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 EnterCriticalSection (&mono_strtod_mutex);
133 *result = mono_strtod (ptr, &endptr);
134 LeaveCriticalSection (&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 (image, MONO_TOKEN_TYPE_DEF | 1);
915 /*It's fine to raise the exception here*/
916 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
920 ICALL_EXPORT MonoBoolean
921 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
926 /* later make this configurable and per-arch */
927 int min_size = 4096 * 4 * sizeof (void*);
928 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
929 /* if we have no info we are optimistic and assume there is enough room */
933 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
937 current = (guint8 *)&stack_addr;
938 if (current > stack_addr) {
939 if ((current - stack_addr) < min_size)
942 if (current - (stack_addr - stack_size) < min_size)
948 ICALL_EXPORT MonoObject *
949 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
953 return mono_object_clone (this);
957 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
960 MonoObject **values = NULL;
963 gint32 result = (int)(gsize)mono_defaults.int32_class;
964 MonoClassField* field;
969 klass = mono_object_class (this);
971 if (mono_class_num_fields (klass) == 0)
975 * Compute the starting value of the hashcode for fields of primitive
976 * types, and return the remaining fields in an array to the managed side.
977 * This way, we can avoid costly reflection operations in managed code.
980 while ((field = mono_class_get_fields (klass, &iter))) {
981 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
983 if (mono_field_is_deleted (field))
985 /* FIXME: Add more types */
986 switch (field->type->type) {
988 result ^= *(gint32*)((guint8*)this + field->offset);
990 case MONO_TYPE_STRING: {
992 s = *(MonoString**)((guint8*)this + field->offset);
994 result ^= mono_string_hash (s);
999 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1000 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1001 values [count++] = o;
1007 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1008 for (i = 0; i < count; ++i)
1009 mono_array_setref (*fields, i, values [i]);
1016 ICALL_EXPORT MonoBoolean
1017 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1020 MonoObject **values = NULL;
1022 MonoClassField* field;
1026 MONO_ARCH_SAVE_REGS;
1028 MONO_CHECK_ARG_NULL (that);
1030 if (this->vtable != that->vtable)
1033 klass = mono_object_class (this);
1035 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1036 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1039 * Do the comparison for fields of primitive type and return a result if
1040 * possible. Otherwise, return the remaining fields in an array to the
1041 * managed side. This way, we can avoid costly reflection operations in
1046 while ((field = mono_class_get_fields (klass, &iter))) {
1047 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1049 if (mono_field_is_deleted (field))
1051 /* FIXME: Add more types */
1052 switch (field->type->type) {
1055 case MONO_TYPE_BOOLEAN:
1056 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1061 case MONO_TYPE_CHAR:
1062 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1067 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1072 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1076 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1080 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1085 case MONO_TYPE_STRING: {
1086 MonoString *s1, *s2;
1087 guint32 s1len, s2len;
1088 s1 = *(MonoString**)((guint8*)this + field->offset);
1089 s2 = *(MonoString**)((guint8*)that + field->offset);
1092 if ((s1 == NULL) || (s2 == NULL))
1094 s1len = mono_string_length (s1);
1095 s2len = mono_string_length (s2);
1099 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1105 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1106 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1107 values [count++] = o;
1108 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1109 values [count++] = o;
1112 if (klass->enumtype)
1113 /* enums only have one non-static field */
1119 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1120 for (i = 0; i < count; ++i)
1121 mono_array_setref_fast (*fields, i, values [i]);
1128 ICALL_EXPORT MonoReflectionType *
1129 ves_icall_System_Object_GetType (MonoObject *obj)
1131 MONO_ARCH_SAVE_REGS;
1133 #ifndef DISABLE_REMOTING
1134 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1135 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1138 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1142 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1144 MONO_ARCH_SAVE_REGS;
1146 mtype->type = &obj->vtable->klass->byval_arg;
1147 g_assert (mtype->type->type);
1151 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1153 MONO_ARCH_SAVE_REGS;
1155 MONO_CHECK_ARG_NULL (obj);
1157 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1161 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1162 MonoReflectionMethod *method,
1163 MonoArray *opt_param_types)
1165 MONO_ARCH_SAVE_REGS;
1167 MONO_CHECK_ARG_NULL (method);
1169 return mono_image_create_method_token (
1170 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1174 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1176 MONO_ARCH_SAVE_REGS;
1178 mono_image_create_pefile (mb, file);
1182 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1184 MONO_ARCH_SAVE_REGS;
1186 mono_image_build_metadata (mb);
1190 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1192 MONO_ARCH_SAVE_REGS;
1194 mono_image_register_token (mb->dynamic_image, token, obj);
1198 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1200 MonoMethod **dest = data;
1202 /* skip unmanaged frames */
1218 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1220 MonoMethod **dest = data;
1222 /* skip unmanaged frames */
1227 if (!strcmp (m->klass->name_space, "System.Reflection"))
1236 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1238 MonoMethod **dest = data;
1240 /* skip unmanaged frames */
1244 if (m->wrapper_type != MONO_WRAPPER_NONE)
1247 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1261 static MonoReflectionType *
1262 type_from_name (const char *str, MonoBoolean ignoreCase)
1264 MonoMethod *m, *dest;
1266 MonoType *type = NULL;
1267 MonoAssembly *assembly = NULL;
1268 MonoTypeNameParse info;
1269 char *temp_str = g_strdup (str);
1270 gboolean type_resolve = FALSE;
1272 MONO_ARCH_SAVE_REGS;
1274 /* mono_reflection_parse_type() mangles the string */
1275 if (!mono_reflection_parse_type (temp_str, &info)) {
1276 mono_reflection_free_type_info (&info);
1283 * We must compute the calling assembly as type loading must happen under a metadata context.
1284 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1285 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1287 m = mono_method_get_last_managed ();
1290 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1295 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1296 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1297 * to crash. This only seems to happen in some strange remoting
1298 * scenarios and I was unable to figure out what's happening there.
1299 * Dec 10, 2005 - Martin.
1303 assembly = dest->klass->image->assembly;
1304 type_resolve = TRUE;
1306 g_warning (G_STRLOC);
1309 if (info.assembly.name)
1310 assembly = mono_assembly_load (&info.assembly, assembly ? assembly->basedir : NULL, NULL);
1314 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1315 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1318 if (!info.assembly.name && !type) /* try mscorlib */
1319 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1321 if (assembly && !type && type_resolve) {
1322 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1323 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1326 mono_reflection_free_type_info (&info);
1332 return mono_type_get_object (mono_domain_get (), type);
1336 MonoReflectionType *
1337 mono_type_get (const char *str)
1339 char *copy = g_strdup (str);
1340 MonoReflectionType *type = type_from_name (copy, FALSE);
1347 ICALL_EXPORT MonoReflectionType*
1348 ves_icall_type_from_name (MonoString *name,
1349 MonoBoolean throwOnError,
1350 MonoBoolean ignoreCase)
1352 char *str = mono_string_to_utf8 (name);
1353 MonoReflectionType *type;
1355 type = type_from_name (str, ignoreCase);
1358 MonoException *e = NULL;
1361 e = mono_get_exception_type_load (name, NULL);
1363 mono_loader_clear_error ();
1365 mono_raise_exception (e);
1372 ICALL_EXPORT MonoReflectionType*
1373 ves_icall_type_from_handle (MonoType *handle)
1375 MonoDomain *domain = mono_domain_get ();
1377 MONO_ARCH_SAVE_REGS;
1379 return mono_type_get_object (domain, handle);
1382 ICALL_EXPORT MonoBoolean
1383 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1385 MONO_ARCH_SAVE_REGS;
1387 if (c && type->type && c->type)
1388 return mono_metadata_type_equal (type->type, c->type);
1390 return (type == c) ? TRUE : FALSE;
1393 /* System.TypeCode */
1412 TYPECODE_STRING = 18
1415 ICALL_EXPORT guint32
1416 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1418 int t = type->type->type;
1420 MONO_ARCH_SAVE_REGS;
1422 if (type->type->byref)
1423 return TYPECODE_OBJECT;
1427 case MONO_TYPE_VOID:
1428 return TYPECODE_OBJECT;
1429 case MONO_TYPE_BOOLEAN:
1430 return TYPECODE_BOOLEAN;
1432 return TYPECODE_BYTE;
1434 return TYPECODE_SBYTE;
1436 return TYPECODE_UINT16;
1438 return TYPECODE_INT16;
1439 case MONO_TYPE_CHAR:
1440 return TYPECODE_CHAR;
1444 return TYPECODE_OBJECT;
1446 return TYPECODE_UINT32;
1448 return TYPECODE_INT32;
1450 return TYPECODE_UINT64;
1452 return TYPECODE_INT64;
1454 return TYPECODE_SINGLE;
1456 return TYPECODE_DOUBLE;
1457 case MONO_TYPE_VALUETYPE: {
1458 MonoClass *klass = type->type->data.klass;
1460 if (klass->enumtype) {
1461 t = mono_class_enum_basetype (klass)->type;
1463 } else if (mono_is_corlib_image (klass->image)) {
1464 if (strcmp (klass->name_space, "System") == 0) {
1465 if (strcmp (klass->name, "Decimal") == 0)
1466 return TYPECODE_DECIMAL;
1467 else if (strcmp (klass->name, "DateTime") == 0)
1468 return TYPECODE_DATETIME;
1471 return TYPECODE_OBJECT;
1473 case MONO_TYPE_STRING:
1474 return TYPECODE_STRING;
1475 case MONO_TYPE_SZARRAY:
1476 case MONO_TYPE_ARRAY:
1477 case MONO_TYPE_OBJECT:
1479 case MONO_TYPE_MVAR:
1480 case MONO_TYPE_TYPEDBYREF:
1481 return TYPECODE_OBJECT;
1482 case MONO_TYPE_CLASS:
1484 MonoClass *klass = type->type->data.klass;
1485 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1486 if (strcmp (klass->name, "DBNull") == 0)
1487 return TYPECODE_DBNULL;
1490 return TYPECODE_OBJECT;
1491 case MONO_TYPE_GENERICINST:
1492 return TYPECODE_OBJECT;
1494 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1499 ICALL_EXPORT guint32
1500 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1506 MONO_ARCH_SAVE_REGS;
1508 g_assert (type != NULL);
1510 domain = ((MonoObject *)type)->vtable->domain;
1512 if (!c) /* FIXME: dont know what do do here */
1515 klass = mono_class_from_mono_type (type->type);
1516 klassc = mono_class_from_mono_type (c->type);
1518 /* Interface check requires a more complex setup so we
1519 * only do for them. Otherwise we simply avoid mono_class_init.
1521 if (check_interfaces) {
1522 mono_class_init_or_throw (klass);
1523 mono_class_init_or_throw (klassc);
1524 } else if (!klass->supertypes || !klassc->supertypes) {
1525 mono_class_setup_supertypes (klass);
1526 mono_class_setup_supertypes (klassc);
1529 if (type->type->byref)
1530 return klassc == mono_defaults.object_class;
1532 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1536 mono_type_is_primitive (MonoType *type)
1538 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1539 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1543 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1545 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1546 return mono_class_enum_basetype (type->data.klass);
1547 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1548 return mono_class_enum_basetype (type->data.generic_class->container_class);
1552 ICALL_EXPORT guint32
1553 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1559 MONO_ARCH_SAVE_REGS;
1561 g_assert (type != NULL);
1563 domain = ((MonoObject *)type)->vtable->domain;
1565 klass = mono_class_from_mono_type (type->type);
1566 klassc = mono_class_from_mono_type (c->type);
1568 if (type->type->byref ^ c->type->byref)
1571 if (type->type->byref) {
1572 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1573 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1575 klass = mono_class_from_mono_type (t);
1576 klassc = mono_class_from_mono_type (ot);
1578 if (mono_type_is_primitive (t)) {
1579 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1580 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1581 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1582 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1583 return t->type == ot->type;
1585 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1588 if (klass->valuetype)
1589 return klass == klassc;
1590 return klass->valuetype == klassc->valuetype;
1593 return mono_class_is_assignable_from (klass, klassc);
1596 ICALL_EXPORT guint32
1597 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1599 MonoClass *klass = mono_class_from_mono_type (type->type);
1600 mono_class_init_or_throw (klass);
1601 return mono_object_isinst (obj, klass) != NULL;
1604 ICALL_EXPORT guint32
1605 ves_icall_get_attributes (MonoReflectionType *type)
1607 MonoClass *klass = mono_class_from_mono_type (type->type);
1608 return klass->flags;
1611 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1612 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1614 MonoClass *klass = field->field->parent;
1615 MonoMarshalType *info;
1619 if (klass->generic_container ||
1620 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1623 ftype = mono_field_get_type (field->field);
1624 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1627 info = mono_marshal_load_type_info (klass);
1629 for (i = 0; i < info->num_fields; ++i) {
1630 if (info->fields [i].field == field->field) {
1631 if (!info->fields [i].mspec)
1634 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1641 ICALL_EXPORT MonoReflectionField*
1642 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1644 gboolean found = FALSE;
1651 klass = handle->parent;
1653 klass = mono_class_from_mono_type (type);
1655 /* Check that the field belongs to the class */
1656 for (k = klass; k; k = k->parent) {
1657 if (k == handle->parent) {
1664 /* The managed code will throw the exception */
1668 return mono_field_get_object (mono_domain_get (), klass, handle);
1671 ICALL_EXPORT MonoArray*
1672 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1675 MonoType *type = mono_field_get_type_checked (field->field, &error);
1676 if (!mono_error_ok (&error))
1677 mono_error_raise_exception (&error);
1679 return type_array_from_modifiers (field->field->parent->image, type, optional);
1683 vell_icall_get_method_attributes (MonoMethod *method)
1685 return method->flags;
1689 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1692 MonoDomain *domain = mono_domain_get ();
1693 MonoMethodSignature* sig;
1694 MONO_ARCH_SAVE_REGS;
1696 sig = mono_method_signature_checked (method, &error);
1697 if (!mono_error_ok (&error))
1698 mono_error_raise_exception (&error);
1701 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1702 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1703 info->attrs = method->flags;
1704 info->implattrs = method->iflags;
1705 if (sig->call_convention == MONO_CALL_DEFAULT)
1706 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1708 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1713 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1716 ICALL_EXPORT MonoArray*
1717 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1719 MonoDomain *domain = mono_domain_get ();
1721 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1724 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1725 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1727 MonoDomain *domain = mono_domain_get ();
1728 MonoReflectionMarshalAsAttribute* res = NULL;
1729 MonoMarshalSpec **mspecs;
1732 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1733 mono_method_get_marshal_info (method, mspecs);
1736 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1738 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1740 mono_metadata_free_marshal_spec (mspecs [i]);
1747 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1749 MonoClass *parent = field->field->parent;
1750 if (!parent->size_inited)
1751 mono_class_init (parent);
1752 mono_class_setup_fields_locking (parent);
1754 return field->field->offset - sizeof (MonoObject);
1757 ICALL_EXPORT MonoReflectionType*
1758 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1761 MONO_ARCH_SAVE_REGS;
1763 parent = declaring? field->field->parent: field->klass;
1765 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1768 ICALL_EXPORT MonoObject *
1769 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1771 MonoClass *fklass = field->klass;
1772 MonoClassField *cf = field->field;
1773 MonoDomain *domain = mono_object_domain (field);
1775 if (fklass->image->assembly->ref_only)
1776 mono_raise_exception (mono_get_exception_invalid_operation (
1777 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1779 if (mono_security_core_clr_enabled ())
1780 mono_security_core_clr_ensure_reflection_access_field (cf);
1782 return mono_field_get_value_object (domain, cf, obj);
1786 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1789 MonoClassField *cf = field->field;
1793 MONO_ARCH_SAVE_REGS;
1795 if (field->klass->image->assembly->ref_only)
1796 mono_raise_exception (mono_get_exception_invalid_operation (
1797 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1799 if (mono_security_core_clr_enabled ())
1800 mono_security_core_clr_ensure_reflection_access_field (cf);
1802 type = mono_field_get_type_checked (cf, &error);
1803 if (!mono_error_ok (&error))
1804 mono_error_raise_exception (&error);
1806 v = (gchar *) value;
1808 switch (type->type) {
1811 case MONO_TYPE_BOOLEAN:
1814 case MONO_TYPE_CHAR:
1823 case MONO_TYPE_VALUETYPE:
1826 v += sizeof (MonoObject);
1828 case MONO_TYPE_STRING:
1829 case MONO_TYPE_OBJECT:
1830 case MONO_TYPE_CLASS:
1831 case MONO_TYPE_ARRAY:
1832 case MONO_TYPE_SZARRAY:
1835 case MONO_TYPE_GENERICINST: {
1836 MonoGenericClass *gclass = type->data.generic_class;
1837 g_assert (!gclass->context.class_inst->is_open);
1839 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1840 MonoClass *nklass = mono_class_from_mono_type (type);
1841 MonoObject *nullable;
1844 * Convert the boxed vtype into a Nullable structure.
1845 * This is complicated by the fact that Nullables have
1846 * a variable structure.
1848 nullable = mono_object_new (mono_domain_get (), nklass);
1850 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1852 v = mono_object_unbox (nullable);
1855 if (gclass->container_class->valuetype && (v != NULL))
1856 v += sizeof (MonoObject);
1860 g_error ("type 0x%x not handled in "
1861 "ves_icall_FieldInfo_SetValueInternal", type->type);
1866 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1867 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1868 if (!vtable->initialized)
1869 mono_runtime_class_init (vtable);
1870 mono_field_static_set_value (vtable, cf, v);
1872 mono_field_set_value (obj, cf, v);
1876 ICALL_EXPORT MonoObject *
1877 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1879 MonoObject *o = NULL;
1880 MonoClassField *field = this->field;
1882 MonoDomain *domain = mono_object_domain (this);
1884 MonoTypeEnum def_type;
1885 const char *def_value;
1889 MONO_ARCH_SAVE_REGS;
1891 mono_class_init (field->parent);
1893 t = mono_field_get_type_checked (field, &error);
1894 if (!mono_error_ok (&error))
1895 mono_error_raise_exception (&error);
1897 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1898 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1900 if (image_is_dynamic (field->parent->image)) {
1902 g_assert_not_reached ();
1905 def_value = mono_class_get_field_default_value (field, &def_type);
1906 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1907 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1909 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1913 case MONO_TYPE_BOOLEAN:
1916 case MONO_TYPE_CHAR:
1924 case MONO_TYPE_R8: {
1927 /* boxed value type */
1928 t = g_new0 (MonoType, 1);
1930 klass = mono_class_from_mono_type (t);
1932 o = mono_object_new (domain, klass);
1933 v = ((gchar *) o) + sizeof (MonoObject);
1934 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1937 case MONO_TYPE_STRING:
1938 case MONO_TYPE_CLASS:
1939 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1942 g_assert_not_reached ();
1948 ICALL_EXPORT MonoReflectionType*
1949 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1952 MonoClassField *field = ref_field->field;
1953 MonoType *type = mono_field_get_type_checked (field, &error);
1954 if (!mono_error_ok (&error))
1955 mono_error_raise_exception (&error);
1956 return mono_type_get_object (mono_object_domain (ref_field), type);
1959 ICALL_EXPORT MonoReflectionType*
1960 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1962 MonoMethod *method = rmethod->method.method;
1964 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1967 /* From MonoProperty.cs */
1969 PInfo_Attributes = 1,
1970 PInfo_GetMethod = 1 << 1,
1971 PInfo_SetMethod = 1 << 2,
1972 PInfo_ReflectedType = 1 << 3,
1973 PInfo_DeclaringType = 1 << 4,
1978 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1980 MonoDomain *domain = mono_object_domain (property);
1982 MONO_ARCH_SAVE_REGS;
1984 if ((req_info & PInfo_ReflectedType) != 0)
1985 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1986 if ((req_info & PInfo_DeclaringType) != 0)
1987 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1989 if ((req_info & PInfo_Name) != 0)
1990 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1992 if ((req_info & PInfo_Attributes) != 0)
1993 info->attrs = property->property->attrs;
1995 if ((req_info & PInfo_GetMethod) != 0)
1996 MONO_STRUCT_SETREF (info, get, property->property->get ?
1997 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1999 if ((req_info & PInfo_SetMethod) != 0)
2000 MONO_STRUCT_SETREF (info, set, property->property->set ?
2001 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2003 * There may be other methods defined for properties, though, it seems they are not exposed
2004 * in the reflection API
2009 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2011 MonoDomain *domain = mono_object_domain (event);
2013 MONO_ARCH_SAVE_REGS;
2015 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2016 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2018 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2019 info->attrs = event->event->attrs;
2020 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2021 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2022 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2024 #ifndef MONO_SMALL_CONFIG
2025 if (event->event->other) {
2027 while (event->event->other [n])
2029 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2031 for (i = 0; i < n; i++)
2032 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2038 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2043 mono_class_setup_interfaces (klass, error);
2044 if (!mono_error_ok (error))
2047 for (i = 0; i < klass->interface_count; i++) {
2048 ic = klass->interfaces [i];
2049 g_hash_table_insert (ifaces, ic, ic);
2051 collect_interfaces (ic, ifaces, error);
2052 if (!mono_error_ok (error))
2058 MonoArray *iface_array;
2059 MonoGenericContext *context;
2063 } FillIfaceArrayData;
2066 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2068 FillIfaceArrayData *data = user_data;
2069 MonoClass *ic = key;
2070 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2072 if (!mono_error_ok (data->error))
2075 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2076 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2077 if (!mono_error_ok (data->error))
2081 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2084 mono_metadata_free_type (inflated);
2087 ICALL_EXPORT MonoArray*
2088 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2091 MonoClass *class = mono_class_from_mono_type (type->type);
2093 FillIfaceArrayData data = { 0 };
2096 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2098 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2099 data.context = mono_class_get_context (class);
2100 class = class->generic_class->container_class;
2103 for (parent = class; parent; parent = parent->parent) {
2104 mono_class_setup_interfaces (parent, &error);
2105 if (!mono_error_ok (&error))
2107 collect_interfaces (parent, iface_hash, &error);
2108 if (!mono_error_ok (&error))
2112 data.error = &error;
2113 data.domain = mono_object_domain (type);
2115 len = g_hash_table_size (iface_hash);
2117 g_hash_table_destroy (iface_hash);
2118 if (!data.domain->empty_types)
2119 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2120 return data.domain->empty_types;
2123 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2124 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2125 if (!mono_error_ok (&error))
2128 g_hash_table_destroy (iface_hash);
2129 return data.iface_array;
2132 g_hash_table_destroy (iface_hash);
2133 mono_error_raise_exception (&error);
2138 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2140 gboolean variance_used;
2141 MonoClass *class = mono_class_from_mono_type (type->type);
2142 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2143 MonoReflectionMethod *member;
2146 int i = 0, len, ioffset;
2149 MONO_ARCH_SAVE_REGS;
2150 mono_class_init_or_throw (class);
2151 mono_class_init_or_throw (iclass);
2153 mono_class_setup_vtable (class);
2155 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2159 len = mono_class_num_methods (iclass);
2160 domain = mono_object_domain (type);
2161 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2162 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2164 while ((method = mono_class_get_methods (iclass, &iter))) {
2165 member = mono_method_get_object (domain, method, iclass);
2166 mono_array_setref (*methods, i, member);
2167 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2168 mono_array_setref (*targets, i, member);
2175 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2177 MonoClass *klass = mono_class_from_mono_type (type->type);
2178 mono_class_init_or_throw (klass);
2180 if (image_is_dynamic (klass->image)) {
2181 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2182 *packing = tb->packing_size;
2183 *size = tb->class_size;
2185 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2189 ICALL_EXPORT MonoReflectionType*
2190 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2194 MONO_ARCH_SAVE_REGS;
2196 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2197 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2199 class = mono_class_from_mono_type (type->type);
2200 mono_class_init_or_throw (class);
2202 // GetElementType should only return a type for:
2203 // Array Pointer PassedByRef
2204 if (type->type->byref)
2205 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2206 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2207 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2208 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2209 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2214 ICALL_EXPORT MonoReflectionType*
2215 ves_icall_get_type_parent (MonoReflectionType *type)
2217 MonoClass *class = mono_class_from_mono_type (type->type);
2218 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2221 ICALL_EXPORT MonoBoolean
2222 ves_icall_type_ispointer (MonoReflectionType *type)
2224 MONO_ARCH_SAVE_REGS;
2226 return type->type->type == MONO_TYPE_PTR;
2229 ICALL_EXPORT MonoBoolean
2230 ves_icall_type_isprimitive (MonoReflectionType *type)
2232 MONO_ARCH_SAVE_REGS;
2234 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2237 ICALL_EXPORT MonoBoolean
2238 ves_icall_type_isbyref (MonoReflectionType *type)
2240 MONO_ARCH_SAVE_REGS;
2242 return type->type->byref;
2245 ICALL_EXPORT MonoBoolean
2246 ves_icall_type_iscomobject (MonoReflectionType *type)
2248 MonoClass *klass = mono_class_from_mono_type (type->type);
2249 mono_class_init_or_throw (klass);
2251 return mono_class_is_com_object (klass);
2254 ICALL_EXPORT MonoReflectionModule*
2255 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2257 MonoClass *class = mono_class_from_mono_type (type->type);
2258 return mono_module_get_object (mono_object_domain (type), class->image);
2261 ICALL_EXPORT MonoReflectionAssembly*
2262 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2264 MonoDomain *domain = mono_domain_get ();
2265 MonoClass *class = mono_class_from_mono_type (type->type);
2266 return mono_assembly_get_object (domain, class->image->assembly);
2269 ICALL_EXPORT MonoReflectionType*
2270 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2272 MonoDomain *domain = mono_domain_get ();
2275 MONO_ARCH_SAVE_REGS;
2277 if (type->type->byref)
2279 if (type->type->type == MONO_TYPE_VAR) {
2280 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2281 class = param ? param->owner.klass : NULL;
2282 } else if (type->type->type == MONO_TYPE_MVAR) {
2283 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2284 class = param ? param->owner.method->klass : NULL;
2286 class = mono_class_from_mono_type (type->type)->nested_in;
2289 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2292 ICALL_EXPORT MonoString*
2293 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2295 MonoDomain *domain = mono_domain_get ();
2296 MonoClass *class = mono_class_from_mono_type (type->type);
2298 if (type->type->byref) {
2299 char *n = g_strdup_printf ("%s&", class->name);
2300 MonoString *res = mono_string_new (domain, n);
2306 return mono_string_new (domain, class->name);
2310 ICALL_EXPORT MonoString*
2311 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2313 MonoDomain *domain = mono_domain_get ();
2314 MonoClass *class = mono_class_from_mono_type (type->type);
2316 while (class->nested_in)
2317 class = class->nested_in;
2319 if (class->name_space [0] == '\0')
2322 return mono_string_new (domain, class->name_space);
2326 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2330 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2331 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2333 class = mono_class_from_mono_type (type->type);
2338 ICALL_EXPORT MonoArray*
2339 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2342 MonoClass *klass, *pklass;
2343 MonoDomain *domain = mono_object_domain (type);
2344 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2346 MONO_ARCH_SAVE_REGS;
2348 klass = mono_class_from_mono_type (type->type);
2350 if (klass->generic_container) {
2351 MonoGenericContainer *container = klass->generic_container;
2352 res = mono_array_new_specific (array_vtable, container->type_argc);
2353 for (i = 0; i < container->type_argc; ++i) {
2354 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2355 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2357 } else if (klass->generic_class) {
2358 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2359 res = mono_array_new_specific (array_vtable, inst->type_argc);
2360 for (i = 0; i < inst->type_argc; ++i)
2361 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2363 res = mono_array_new_specific (array_vtable, 0);
2368 ICALL_EXPORT gboolean
2369 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2372 MONO_ARCH_SAVE_REGS;
2374 if (!IS_MONOTYPE (type))
2377 if (type->type->byref)
2380 klass = mono_class_from_mono_type (type->type);
2381 return klass->generic_container != NULL;
2384 ICALL_EXPORT MonoReflectionType*
2385 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2388 MONO_ARCH_SAVE_REGS;
2390 if (type->type->byref)
2393 klass = mono_class_from_mono_type (type->type);
2395 if (klass->generic_container) {
2396 return type; /* check this one */
2398 if (klass->generic_class) {
2399 MonoClass *generic_class = klass->generic_class->container_class;
2402 tb = mono_class_get_ref_info (generic_class);
2404 if (generic_class->wastypebuilder && tb)
2407 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2412 ICALL_EXPORT MonoReflectionType*
2413 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2416 MonoType *geninst, **types;
2419 g_assert (IS_MONOTYPE (type));
2420 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2422 count = mono_array_length (type_array);
2423 types = g_new0 (MonoType *, count);
2425 for (i = 0; i < count; i++) {
2426 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2427 types [i] = t->type;
2430 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2435 class = mono_class_from_mono_type (geninst);
2437 /*we might inflate to the GTD*/
2438 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2439 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2441 return mono_type_get_object (mono_object_domain (type), geninst);
2444 ICALL_EXPORT gboolean
2445 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2448 MONO_ARCH_SAVE_REGS;
2450 if (type->type->byref)
2453 klass = mono_class_from_mono_type (type->type);
2455 return klass->generic_class != NULL;
2458 ICALL_EXPORT gboolean
2459 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2462 MONO_ARCH_SAVE_REGS;
2464 if (!IS_MONOTYPE (type))
2467 if (type->type->byref)
2470 klass = mono_class_from_mono_type (type->type);
2471 return klass->generic_class != NULL || klass->generic_container != NULL;
2475 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2477 MONO_ARCH_SAVE_REGS;
2479 if (!IS_MONOTYPE (type))
2482 if (is_generic_parameter (type->type))
2483 return mono_type_get_generic_param_num (type->type);
2487 ICALL_EXPORT GenericParameterAttributes
2488 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2490 MONO_ARCH_SAVE_REGS;
2492 g_assert (IS_MONOTYPE (type));
2493 g_assert (is_generic_parameter (type->type));
2494 return mono_generic_param_info (type->type->data.generic_param)->flags;
2497 ICALL_EXPORT MonoArray *
2498 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2500 MonoGenericParamInfo *param_info;
2506 MONO_ARCH_SAVE_REGS;
2508 g_assert (IS_MONOTYPE (type));
2510 domain = mono_object_domain (type);
2511 param_info = mono_generic_param_info (type->type->data.generic_param);
2512 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2515 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2516 for (i = 0; i < count; i++)
2517 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2523 ICALL_EXPORT MonoBoolean
2524 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2526 MONO_ARCH_SAVE_REGS;
2527 return is_generic_parameter (type->type);
2530 ICALL_EXPORT MonoBoolean
2531 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2533 MONO_ARCH_SAVE_REGS;
2534 return is_generic_parameter (tb->type.type);
2538 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2539 MonoReflectionType *t)
2541 enumtype->type = t->type;
2544 ICALL_EXPORT MonoReflectionMethod*
2545 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2546 MonoReflectionMethod* generic)
2553 MONO_ARCH_SAVE_REGS;
2555 domain = ((MonoObject *)type)->vtable->domain;
2557 klass = mono_class_from_mono_type (type->type);
2558 mono_class_init_or_throw (klass);
2561 while ((method = mono_class_get_methods (klass, &iter))) {
2562 if (method->token == generic->method->token)
2563 return mono_method_get_object (domain, method, klass);
2571 ICALL_EXPORT MonoReflectionMethod *
2572 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2575 MonoType *type = ref_type->type;
2577 MONO_ARCH_SAVE_REGS;
2579 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2580 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2581 if (type->type == MONO_TYPE_VAR)
2584 method = mono_type_get_generic_param_owner (type)->owner.method;
2586 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2589 ICALL_EXPORT MonoReflectionDllImportAttribute*
2590 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2592 static MonoClass *DllImportAttributeClass = NULL;
2593 MonoDomain *domain = mono_domain_get ();
2594 MonoReflectionDllImportAttribute *attr;
2595 MonoImage *image = method->klass->image;
2596 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2597 MonoTableInfo *tables = image->tables;
2598 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2599 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2600 guint32 im_cols [MONO_IMPLMAP_SIZE];
2601 guint32 scope_token;
2602 const char *import = NULL;
2603 const char *scope = NULL;
2606 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2609 if (!DllImportAttributeClass) {
2610 DllImportAttributeClass =
2611 mono_class_from_name (mono_defaults.corlib,
2612 "System.Runtime.InteropServices", "DllImportAttribute");
2613 g_assert (DllImportAttributeClass);
2616 if (image_is_dynamic (method->klass->image)) {
2617 MonoReflectionMethodAux *method_aux =
2618 g_hash_table_lookup (
2619 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2621 import = method_aux->dllentry;
2622 scope = method_aux->dll;
2625 if (!import || !scope) {
2626 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2631 if (piinfo->implmap_idx) {
2632 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2634 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2635 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2636 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2637 scope = mono_metadata_string_heap (image, scope_token);
2640 flags = piinfo->piflags;
2642 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2644 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2645 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2646 attr->call_conv = (flags & 0x700) >> 8;
2647 attr->charset = ((flags & 0x6) >> 1) + 1;
2648 if (attr->charset == 1)
2650 attr->exact_spelling = (flags & 0x1) != 0;
2651 attr->set_last_error = (flags & 0x40) != 0;
2652 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2653 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2654 attr->preserve_sig = FALSE;
2659 ICALL_EXPORT MonoReflectionMethod *
2660 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2662 MonoMethodInflated *imethod;
2665 MONO_ARCH_SAVE_REGS;
2667 if (method->method->is_generic)
2670 if (!method->method->is_inflated)
2673 imethod = (MonoMethodInflated *) method->method;
2675 result = imethod->declaring;
2676 /* Not a generic method. */
2677 if (!result->is_generic)
2680 if (image_is_dynamic (method->method->klass->image)) {
2681 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2682 MonoReflectionMethod *res;
2685 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2686 * the dynamic case as well ?
2688 mono_image_lock ((MonoImage*)image);
2689 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2690 mono_image_unlock ((MonoImage*)image);
2696 if (imethod->context.class_inst) {
2697 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2698 /*Generic methods gets the context of the GTD.*/
2699 if (mono_class_get_context (klass))
2700 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2703 return mono_method_get_object (mono_object_domain (method), result, NULL);
2706 ICALL_EXPORT gboolean
2707 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2709 MONO_ARCH_SAVE_REGS;
2711 return mono_method_signature (method->method)->generic_param_count != 0;
2714 ICALL_EXPORT gboolean
2715 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2717 MONO_ARCH_SAVE_REGS;
2719 return method->method->is_generic;
2722 ICALL_EXPORT MonoArray*
2723 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2728 MONO_ARCH_SAVE_REGS;
2730 domain = mono_object_domain (method);
2732 if (method->method->is_inflated) {
2733 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2736 count = inst->type_argc;
2737 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2739 for (i = 0; i < count; i++)
2740 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2746 count = mono_method_signature (method->method)->generic_param_count;
2747 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2749 for (i = 0; i < count; i++) {
2750 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2751 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2752 MonoClass *pklass = mono_class_from_generic_parameter (
2753 param, method->method->klass->image, TRUE);
2754 mono_array_setref (res, i,
2755 mono_type_get_object (domain, &pklass->byval_arg));
2761 ICALL_EXPORT MonoObject *
2762 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2765 * Invoke from reflection is supposed to always be a virtual call (the API
2766 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2767 * greater flexibility.
2769 MonoMethod *m = method->method;
2770 MonoMethodSignature *sig = mono_method_signature (m);
2775 MONO_ARCH_SAVE_REGS;
2779 if (mono_security_core_clr_enabled ())
2780 mono_security_core_clr_ensure_reflection_access_method (m);
2782 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2783 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2784 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2789 if (!mono_object_isinst (this, m->klass)) {
2790 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2791 char *target_name = mono_type_get_full_name (m->klass);
2792 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2793 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2795 g_free (target_name);
2799 m = mono_object_get_virtual_method (this, m);
2800 /* must pass the pointer to the value for valuetype methods */
2801 if (m->klass->valuetype)
2802 obj = mono_object_unbox (this);
2803 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2804 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2809 if (sig->ret->byref) {
2810 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
2814 pcount = params? mono_array_length (params): 0;
2815 if (pcount != sig->param_count) {
2816 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2820 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2821 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2825 image = m->klass->image;
2826 if (image->assembly->ref_only) {
2827 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2831 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2832 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2836 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2839 intptr_t *lower_bounds;
2840 pcount = mono_array_length (params);
2841 lengths = alloca (sizeof (uintptr_t) * pcount);
2842 /* Note: the synthetized array .ctors have int32 as argument type */
2843 for (i = 0; i < pcount; ++i)
2844 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2846 if (m->klass->rank == pcount) {
2847 /* Only lengths provided. */
2848 lower_bounds = NULL;
2850 g_assert (pcount == (m->klass->rank * 2));
2851 /* lower bounds are first. */
2852 lower_bounds = (intptr_t*)lengths;
2853 lengths += m->klass->rank;
2856 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2858 return mono_runtime_invoke_array (m, obj, params, NULL);
2861 #ifndef DISABLE_REMOTING
2862 ICALL_EXPORT MonoObject *
2863 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2865 MonoDomain *domain = mono_object_domain (method);
2866 MonoMethod *m = method->method;
2867 MonoMethodSignature *sig = mono_method_signature (m);
2868 MonoArray *out_args;
2870 int i, j, outarg_count = 0;
2872 MONO_ARCH_SAVE_REGS;
2874 if (m->klass == mono_defaults.object_class) {
2876 if (!strcmp (m->name, "FieldGetter")) {
2877 MonoClass *k = this->vtable->klass;
2881 /* If this is a proxy, then it must be a CBO */
2882 if (k == mono_defaults.transparent_proxy_class) {
2883 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2884 this = tp->rp->unwrapped_server;
2886 k = this->vtable->klass;
2889 name = mono_array_get (params, MonoString *, 1);
2890 str = mono_string_to_utf8 (name);
2893 MonoClassField* field = mono_class_get_field_from_name (k, str);
2895 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2896 if (field_klass->valuetype)
2897 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2899 result = *((gpointer *)((char *)this + field->offset));
2901 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2902 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2903 mono_array_setref (out_args, 0, result);
2911 g_assert_not_reached ();
2913 } else if (!strcmp (m->name, "FieldSetter")) {
2914 MonoClass *k = this->vtable->klass;
2920 /* If this is a proxy, then it must be a CBO */
2921 if (k == mono_defaults.transparent_proxy_class) {
2922 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2923 this = tp->rp->unwrapped_server;
2925 k = this->vtable->klass;
2928 name = mono_array_get (params, MonoString *, 1);
2929 str = mono_string_to_utf8 (name);
2932 MonoClassField* field = mono_class_get_field_from_name (k, str);
2934 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2935 MonoObject *val = mono_array_get (params, gpointer, 2);
2937 if (field_klass->valuetype) {
2938 size = mono_type_size (field->type, &align);
2939 g_assert (size == mono_class_value_size (field_klass, NULL));
2940 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2942 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2945 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2946 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2956 g_assert_not_reached ();
2961 for (i = 0; i < mono_array_length (params); i++) {
2962 if (sig->params [i]->byref)
2966 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2968 /* handle constructors only for objects already allocated */
2969 if (!strcmp (method->method->name, ".ctor"))
2972 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2973 g_assert (!method->method->klass->valuetype);
2974 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2976 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2977 if (sig->params [i]->byref) {
2979 arg = mono_array_get (params, gpointer, i);
2980 mono_array_setref (out_args, j, arg);
2985 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2992 read_enum_value (char *mem, int type)
2996 return *(guint8*)mem;
2998 return *(gint8*)mem;
3000 return *(guint16*)mem;
3002 return *(gint16*)mem;
3004 return *(guint32*)mem;
3006 return *(gint32*)mem;
3008 return *(guint64*)mem;
3010 return *(gint64*)mem;
3012 g_assert_not_reached ();
3018 write_enum_value (char *mem, int type, guint64 value)
3022 case MONO_TYPE_I1: {
3023 guint8 *p = (guint8*)mem;
3028 case MONO_TYPE_I2: {
3029 guint16 *p = (void*)mem;
3034 case MONO_TYPE_I4: {
3035 guint32 *p = (void*)mem;
3040 case MONO_TYPE_I8: {
3041 guint64 *p = (void*)mem;
3046 g_assert_not_reached ();
3051 ICALL_EXPORT MonoObject *
3052 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3055 MonoClass *enumc, *objc;
3060 MONO_ARCH_SAVE_REGS;
3062 MONO_CHECK_ARG_NULL (enumType);
3063 MONO_CHECK_ARG_NULL (value);
3065 domain = mono_object_domain (enumType);
3066 enumc = mono_class_from_mono_type (enumType->type);
3068 mono_class_init_or_throw (enumc);
3070 objc = value->vtable->klass;
3072 if (!enumc->enumtype)
3073 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3074 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3075 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."));
3077 etype = mono_class_enum_basetype (enumc);
3079 /* MS throws this for typebuilders */
3080 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3082 res = mono_object_new (domain, enumc);
3083 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3084 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3089 ICALL_EXPORT MonoObject *
3090 ves_icall_System_Enum_get_value (MonoObject *this)
3098 MONO_ARCH_SAVE_REGS;
3103 g_assert (this->vtable->klass->enumtype);
3105 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3106 res = mono_object_new (mono_object_domain (this), enumc);
3107 dst = (char *)res + sizeof (MonoObject);
3108 src = (char *)this + sizeof (MonoObject);
3109 size = mono_class_value_size (enumc, NULL);
3111 memcpy (dst, src, size);
3116 ICALL_EXPORT MonoReflectionType *
3117 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3122 MONO_ARCH_SAVE_REGS;
3124 klass = mono_class_from_mono_type (type->type);
3125 mono_class_init_or_throw (klass);
3127 etype = mono_class_enum_basetype (klass);
3129 /* MS throws this for typebuilders */
3130 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3132 return mono_type_get_object (mono_object_domain (type), etype);
3136 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3138 gpointer tdata = (char *)this + sizeof (MonoObject);
3139 gpointer odata = (char *)other + sizeof (MonoObject);
3140 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3141 g_assert (basetype);
3143 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3144 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3145 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3148 return me > other ? 1 : -1; \
3151 switch (basetype->type) {
3153 COMPARE_ENUM_VALUES (guint8);
3155 COMPARE_ENUM_VALUES (gint8);
3156 case MONO_TYPE_CHAR:
3158 COMPARE_ENUM_VALUES (guint16);
3160 COMPARE_ENUM_VALUES (gint16);
3162 COMPARE_ENUM_VALUES (guint32);
3164 COMPARE_ENUM_VALUES (gint32);
3166 COMPARE_ENUM_VALUES (guint64);
3168 COMPARE_ENUM_VALUES (gint64);
3170 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3172 #undef COMPARE_ENUM_VALUES
3177 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3179 gpointer data = (char *)this + sizeof (MonoObject);
3180 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3181 g_assert (basetype);
3183 switch (basetype->type) {
3185 return *((gint8*)data);
3187 return *((guint8*)data);
3188 case MONO_TYPE_CHAR:
3190 return *((guint16*)data);
3193 return *((gint16*)data);
3195 return *((guint32*)data);
3197 return *((gint32*)data);
3199 case MONO_TYPE_I8: {
3200 gint64 value = *((gint64*)data);
3201 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3204 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3210 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3212 MonoDomain *domain = mono_object_domain (type);
3213 MonoClass *enumc = mono_class_from_mono_type (type->type);
3214 guint j = 0, nvalues, crow;
3216 MonoClassField *field;
3218 MONO_ARCH_SAVE_REGS;
3220 mono_class_init_or_throw (enumc);
3222 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3223 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3224 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3225 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3229 while ((field = mono_class_get_fields (enumc, &iter))) {
3232 MonoTypeEnum def_type;
3234 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3236 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3238 if (mono_field_is_deleted (field))
3240 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3242 p = mono_class_get_field_default_value (field, &def_type);
3243 len = mono_metadata_decode_blob_size (p, &p);
3244 switch (mono_class_enum_basetype (enumc)->type) {
3247 mono_array_set (info->values, gchar, j, *p);
3249 case MONO_TYPE_CHAR:
3252 mono_array_set (info->values, gint16, j, read16 (p));
3256 mono_array_set (info->values, gint32, j, read32 (p));
3260 mono_array_set (info->values, gint64, j, read64 (p));
3263 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3270 BFLAGS_IgnoreCase = 1,
3271 BFLAGS_DeclaredOnly = 2,
3272 BFLAGS_Instance = 4,
3274 BFLAGS_Public = 0x10,
3275 BFLAGS_NonPublic = 0x20,
3276 BFLAGS_FlattenHierarchy = 0x40,
3277 BFLAGS_InvokeMethod = 0x100,
3278 BFLAGS_CreateInstance = 0x200,
3279 BFLAGS_GetField = 0x400,
3280 BFLAGS_SetField = 0x800,
3281 BFLAGS_GetProperty = 0x1000,
3282 BFLAGS_SetProperty = 0x2000,
3283 BFLAGS_ExactBinding = 0x10000,
3284 BFLAGS_SuppressChangeType = 0x20000,
3285 BFLAGS_OptionalParamBinding = 0x40000
3288 ICALL_EXPORT MonoReflectionField *
3289 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3292 MonoClass *startklass, *klass;
3294 MonoClassField *field;
3297 int (*compare_func) (const char *s1, const char *s2) = NULL;
3298 domain = ((MonoObject *)type)->vtable->domain;
3299 klass = startklass = mono_class_from_mono_type (type->type);
3302 mono_raise_exception (mono_get_exception_argument_null ("name"));
3303 if (type->type->byref)
3306 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3309 if (klass->exception_type != MONO_EXCEPTION_NONE)
3310 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3313 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3314 guint32 flags = mono_field_get_flags (field);
3317 if (mono_field_is_deleted_with_flags (field, flags))
3319 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3320 if (bflags & BFLAGS_Public)
3322 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3323 if (bflags & BFLAGS_NonPublic) {
3330 if (flags & FIELD_ATTRIBUTE_STATIC) {
3331 if (bflags & BFLAGS_Static)
3332 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3335 if (bflags & BFLAGS_Instance)
3342 utf8_name = mono_string_to_utf8 (name);
3344 if (compare_func (mono_field_get_name (field), utf8_name)) {
3350 return mono_field_get_object (domain, klass, field);
3352 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3358 ICALL_EXPORT MonoArray*
3359 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3362 MonoClass *startklass, *klass, *refklass;
3367 MonoClassField *field;
3368 MonoPtrArray tmp_array;
3370 MONO_ARCH_SAVE_REGS;
3372 domain = ((MonoObject *)type)->vtable->domain;
3373 if (type->type->byref)
3374 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3375 klass = startklass = mono_class_from_mono_type (type->type);
3376 refklass = mono_class_from_mono_type (reftype->type);
3378 mono_ptr_array_init (tmp_array, 2);
3381 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3382 mono_ptr_array_destroy (tmp_array);
3383 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3387 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3388 guint32 flags = mono_field_get_flags (field);
3390 if (mono_field_is_deleted_with_flags (field, flags))
3392 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3393 if (bflags & BFLAGS_Public)
3395 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3396 if (bflags & BFLAGS_NonPublic) {
3403 if (flags & FIELD_ATTRIBUTE_STATIC) {
3404 if (bflags & BFLAGS_Static)
3405 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3408 if (bflags & BFLAGS_Instance)
3414 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3415 mono_ptr_array_append (tmp_array, member);
3417 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3420 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3422 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3423 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3425 mono_ptr_array_destroy (tmp_array);
3431 method_nonpublic (MonoMethod* method, gboolean start_klass)
3433 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3434 case METHOD_ATTRIBUTE_ASSEM:
3435 return (start_klass || mono_defaults.generic_ilist_class);
3436 case METHOD_ATTRIBUTE_PRIVATE:
3438 case METHOD_ATTRIBUTE_PUBLIC:
3446 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3449 MonoClass *startklass;
3452 int len, match, nslots;
3453 /*FIXME, use MonoBitSet*/
3454 guint32 method_slots_default [8];
3455 guint32 *method_slots = NULL;
3456 int (*compare_func) (const char *s1, const char *s2) = NULL;
3458 array = g_ptr_array_new ();
3464 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3466 /* An optimization for calls made from Delegate:CreateDelegate () */
3467 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3468 method = mono_get_delegate_invoke (klass);
3469 if (mono_loader_get_last_error ())
3472 g_ptr_array_add (array, method);
3476 mono_class_setup_vtable (klass);
3477 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3480 if (is_generic_parameter (&klass->byval_arg))
3481 nslots = mono_class_get_vtable_size (klass->parent);
3483 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3484 if (nslots >= sizeof (method_slots_default) * 8) {
3485 method_slots = g_new0 (guint32, nslots / 32 + 1);
3487 method_slots = method_slots_default;
3488 memset (method_slots, 0, sizeof (method_slots_default));
3491 mono_class_setup_vtable (klass);
3492 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3496 while ((method = mono_class_get_methods (klass, &iter))) {
3498 if (method->slot != -1) {
3499 g_assert (method->slot < nslots);
3500 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3502 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3503 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3506 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3508 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3509 if (bflags & BFLAGS_Public)
3511 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3517 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3518 if (bflags & BFLAGS_Static)
3519 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3522 if (bflags & BFLAGS_Instance)
3530 if (compare_func (name, method->name))
3535 g_ptr_array_add (array, method);
3537 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3539 if (method_slots != method_slots_default)
3540 g_free (method_slots);
3545 if (method_slots != method_slots_default)
3546 g_free (method_slots);
3547 g_ptr_array_free (array, TRUE);
3549 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3550 *ex = mono_class_get_exception_for_failure (klass);
3552 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3553 mono_loader_clear_error ();
3558 ICALL_EXPORT MonoArray*
3559 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3561 static MonoClass *MethodInfo_array;
3564 MonoVTable *array_vtable;
3565 MonoException *ex = NULL;
3566 const char *mname = NULL;
3567 GPtrArray *method_array;
3568 MonoClass *klass, *refklass;
3571 if (!MethodInfo_array) {
3572 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3573 mono_memory_barrier ();
3574 MethodInfo_array = klass;
3577 klass = mono_class_from_mono_type (type->type);
3578 refklass = mono_class_from_mono_type (reftype->type);
3579 domain = ((MonoObject *)type)->vtable->domain;
3580 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3581 if (type->type->byref)
3582 return mono_array_new_specific (array_vtable, 0);
3585 mname = mono_string_to_utf8 (name);
3587 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3588 g_free ((char*)mname);
3590 mono_raise_exception (ex);
3592 res = mono_array_new_specific (array_vtable, method_array->len);
3595 for (i = 0; i < method_array->len; ++i) {
3596 MonoMethod *method = g_ptr_array_index (method_array, i);
3597 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3600 g_ptr_array_free (method_array, TRUE);
3604 ICALL_EXPORT MonoArray*
3605 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3608 static MonoClass *System_Reflection_ConstructorInfo;
3609 MonoClass *startklass, *klass, *refklass;
3614 gpointer iter = NULL;
3615 MonoPtrArray tmp_array;
3617 MONO_ARCH_SAVE_REGS;
3619 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3621 domain = ((MonoObject *)type)->vtable->domain;
3622 if (type->type->byref)
3623 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3624 klass = startklass = mono_class_from_mono_type (type->type);
3625 refklass = mono_class_from_mono_type (reftype->type);
3627 if (!System_Reflection_ConstructorInfo)
3628 System_Reflection_ConstructorInfo = mono_class_from_name (
3629 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3632 while ((method = mono_class_get_methods (klass, &iter))) {
3634 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3636 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3637 if (bflags & BFLAGS_Public)
3640 if (bflags & BFLAGS_NonPublic)
3646 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3647 if (bflags & BFLAGS_Static)
3648 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3651 if (bflags & BFLAGS_Instance)
3657 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3659 mono_ptr_array_append (tmp_array, member);
3662 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3664 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3665 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3667 mono_ptr_array_destroy (tmp_array);
3673 property_hash (gconstpointer data)
3675 MonoProperty *prop = (MonoProperty*)data;
3677 return g_str_hash (prop->name);
3681 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3683 // Properties are hide-by-name-and-signature
3684 if (!g_str_equal (prop1->name, prop2->name))
3687 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3689 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3695 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3700 return method_nonpublic (accessor, start_klass);
3703 ICALL_EXPORT MonoArray*
3704 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3708 static MonoClass *System_Reflection_PropertyInfo;
3709 MonoClass *startklass, *klass;
3715 gchar *propname = NULL;
3716 int (*compare_func) (const char *s1, const char *s2) = NULL;
3718 GHashTable *properties = NULL;
3719 MonoPtrArray tmp_array;
3721 MONO_ARCH_SAVE_REGS;
3723 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3725 if (!System_Reflection_PropertyInfo)
3726 System_Reflection_PropertyInfo = mono_class_from_name (
3727 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3729 domain = ((MonoObject *)type)->vtable->domain;
3730 if (type->type->byref)
3731 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3732 klass = startklass = mono_class_from_mono_type (type->type);
3735 propname = mono_string_to_utf8 (name);
3736 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3739 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3741 mono_class_setup_vtable (klass);
3742 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3746 while ((prop = mono_class_get_properties (klass, &iter))) {
3752 flags = method->flags;
3755 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3756 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3757 if (bflags & BFLAGS_Public)
3759 } else if (bflags & BFLAGS_NonPublic) {
3760 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3761 property_accessor_nonpublic(prop->set, startklass == klass)) {
3768 if (flags & METHOD_ATTRIBUTE_STATIC) {
3769 if (bflags & BFLAGS_Static)
3770 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3773 if (bflags & BFLAGS_Instance)
3782 if (compare_func (propname, prop->name))
3786 if (g_hash_table_lookup (properties, prop))
3789 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3791 g_hash_table_insert (properties, prop, prop);
3793 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3796 g_hash_table_destroy (properties);
3799 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3800 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3801 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3803 mono_ptr_array_destroy (tmp_array);
3809 g_hash_table_destroy (properties);
3812 mono_ptr_array_destroy (tmp_array);
3814 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3815 ex = mono_class_get_exception_for_failure (klass);
3817 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3818 mono_loader_clear_error ();
3820 mono_raise_exception (ex);
3824 ICALL_EXPORT MonoReflectionEvent *
3825 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3828 MonoClass *klass, *startklass;
3833 int (*compare_func) (const char *s1, const char *s2);
3835 MONO_ARCH_SAVE_REGS;
3837 event_name = mono_string_to_utf8 (name);
3838 if (type->type->byref)
3840 klass = startklass = mono_class_from_mono_type (type->type);
3841 domain = mono_object_domain (type);
3843 mono_class_init_or_throw (klass);
3845 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3847 if (klass->exception_type != MONO_EXCEPTION_NONE)
3848 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3851 while ((event = mono_class_get_events (klass, &iter))) {
3852 if (compare_func (event->name, event_name))
3855 method = event->add;
3857 method = event->remove;
3859 method = event->raise;
3861 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3862 if (!(bflags & BFLAGS_Public))
3865 if (!(bflags & BFLAGS_NonPublic))
3867 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3871 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3872 if (!(bflags & BFLAGS_Static))
3874 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3877 if (!(bflags & BFLAGS_Instance))
3881 if (!(bflags & BFLAGS_NonPublic))
3884 g_free (event_name);
3885 return mono_event_get_object (domain, startklass, event);
3888 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3891 g_free (event_name);
3896 event_hash (gconstpointer data)
3898 MonoEvent *event = (MonoEvent*)data;
3900 return g_str_hash (event->name);
3904 event_equal (MonoEvent *event1, MonoEvent *event2)
3906 // Events are hide-by-name
3907 return g_str_equal (event1->name, event2->name);
3910 ICALL_EXPORT MonoArray*
3911 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3915 static MonoClass *System_Reflection_EventInfo;
3916 MonoClass *startklass, *klass;
3922 GHashTable *events = NULL;
3923 MonoPtrArray tmp_array;
3925 MONO_ARCH_SAVE_REGS;
3927 mono_ptr_array_init (tmp_array, 4);
3929 if (!System_Reflection_EventInfo)
3930 System_Reflection_EventInfo = mono_class_from_name (
3931 mono_defaults.corlib, "System.Reflection", "EventInfo");
3933 domain = mono_object_domain (type);
3934 if (type->type->byref)
3935 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3936 klass = startklass = mono_class_from_mono_type (type->type);
3938 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3940 mono_class_setup_vtable (klass);
3941 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3945 while ((event = mono_class_get_events (klass, &iter))) {
3947 method = event->add;
3949 method = event->remove;
3951 method = event->raise;
3953 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3954 if (bflags & BFLAGS_Public)
3956 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3957 if (bflags & BFLAGS_NonPublic)
3962 if (bflags & BFLAGS_NonPublic)
3968 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3969 if (bflags & BFLAGS_Static)
3970 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3973 if (bflags & BFLAGS_Instance)
3978 if (bflags & BFLAGS_Instance)
3983 if (g_hash_table_lookup (events, event))
3986 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3988 g_hash_table_insert (events, event, event);
3990 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3993 g_hash_table_destroy (events);
3995 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3997 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3998 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4000 mono_ptr_array_destroy (tmp_array);
4005 mono_ptr_array_destroy (tmp_array);
4006 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4007 ex = mono_class_get_exception_for_failure (klass);
4009 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4010 mono_loader_clear_error ();
4012 mono_raise_exception (ex);
4016 ICALL_EXPORT MonoReflectionType *
4017 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4025 MONO_ARCH_SAVE_REGS;
4028 mono_raise_exception (mono_get_exception_argument_null ("name"));
4030 domain = ((MonoObject *)type)->vtable->domain;
4031 if (type->type->byref)
4033 klass = mono_class_from_mono_type (type->type);
4035 str = mono_string_to_utf8 (name);
4038 if (klass->exception_type != MONO_EXCEPTION_NONE)
4039 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4042 * If a nested type is generic, return its generic type definition.
4043 * Note that this means that the return value is essentially a
4044 * nested type of the generic type definition of @klass.
4046 * A note in MSDN claims that a generic type definition can have
4047 * nested types that aren't generic. In any case, the container of that
4048 * nested type would be the generic type definition.
4050 if (klass->generic_class)
4051 klass = klass->generic_class->container_class;
4054 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4056 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4057 if (bflags & BFLAGS_Public)
4060 if (bflags & BFLAGS_NonPublic)
4065 if (strcmp (nested->name, str) == 0){
4067 return mono_type_get_object (domain, &nested->byval_arg);
4070 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4076 ICALL_EXPORT MonoArray*
4077 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4086 MonoPtrArray tmp_array;
4088 MONO_ARCH_SAVE_REGS;
4090 domain = ((MonoObject *)type)->vtable->domain;
4091 if (type->type->byref)
4092 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4093 klass = mono_class_from_mono_type (type->type);
4096 * If a nested type is generic, return its generic type definition.
4097 * Note that this means that the return value is essentially the set
4098 * of nested types of the generic type definition of @klass.
4100 * A note in MSDN claims that a generic type definition can have
4101 * nested types that aren't generic. In any case, the container of that
4102 * nested type would be the generic type definition.
4104 if (klass->generic_class)
4105 klass = klass->generic_class->container_class;
4107 mono_ptr_array_init (tmp_array, 1);
4109 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4111 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4112 if (bflags & BFLAGS_Public)
4115 if (bflags & BFLAGS_NonPublic)
4120 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4121 mono_ptr_array_append (tmp_array, member);
4124 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4126 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4127 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4129 mono_ptr_array_destroy (tmp_array);
4134 ICALL_EXPORT MonoReflectionType*
4135 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4138 MonoType *type = NULL;
4139 MonoTypeNameParse info;
4140 gboolean type_resolve;
4142 MONO_ARCH_SAVE_REGS;
4144 /* On MS.NET, this does not fire a TypeResolve event */
4145 type_resolve = TRUE;
4146 str = mono_string_to_utf8 (name);
4147 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4148 if (!mono_reflection_parse_type (str, &info)) {
4150 mono_reflection_free_type_info (&info);
4151 if (throwOnError) /* uhm: this is a parse error, though... */
4152 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4153 /*g_print ("failed parse\n");*/
4157 if (info.assembly.name) {
4159 mono_reflection_free_type_info (&info);
4161 /* 1.0 and 2.0 throw different exceptions */
4162 if (mono_defaults.generic_ilist_class)
4163 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4165 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4170 if (module != NULL) {
4172 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4177 if (assembly_is_dynamic (assembly->assembly)) {
4178 /* Enumerate all modules */
4179 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4183 if (abuilder->modules) {
4184 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4185 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4186 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4192 if (!type && abuilder->loaded_modules) {
4193 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4194 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4195 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4202 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4204 mono_reflection_free_type_info (&info);
4206 MonoException *e = NULL;
4209 e = mono_get_exception_type_load (name, NULL);
4211 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4212 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4214 mono_loader_clear_error ();
4217 mono_raise_exception (e);
4220 } else if (mono_loader_get_last_error ()) {
4222 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4223 mono_loader_clear_error ();
4226 if (type->type == MONO_TYPE_CLASS) {
4227 MonoClass *klass = mono_type_get_class (type);
4229 if (mono_security_enabled () && !klass->exception_type)
4230 /* Some security problems are detected during generic vtable construction */
4231 mono_class_setup_vtable (klass);
4233 /* need to report exceptions ? */
4234 if (throwOnError && klass->exception_type) {
4235 /* report SecurityException (or others) that occured when loading the assembly */
4236 MonoException *exc = mono_class_get_exception_for_failure (klass);
4237 mono_loader_clear_error ();
4238 mono_raise_exception (exc);
4239 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4244 /* g_print ("got it\n"); */
4245 return mono_type_get_object (mono_object_domain (assembly), type);
4249 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4252 gchar *shadow_ini_file;
4255 /* Check for shadow-copied assembly */
4256 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4257 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4259 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4260 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4266 g_free (shadow_ini_file);
4267 if (content != NULL) {
4270 *filename = content;
4277 ICALL_EXPORT MonoString *
4278 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4280 MonoDomain *domain = mono_object_domain (assembly);
4281 MonoAssembly *mass = assembly->assembly;
4282 MonoString *res = NULL;
4287 MONO_ARCH_SAVE_REGS;
4289 if (g_path_is_absolute (mass->image->name)) {
4290 absolute = g_strdup (mass->image->name);
4291 dirname = g_path_get_dirname (absolute);
4293 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4294 dirname = g_strdup (mass->basedir);
4297 replace_shadow_path (domain, dirname, &absolute);
4302 for (i = strlen (absolute) - 1; i >= 0; i--)
4303 if (absolute [i] == '\\')
4308 uri = g_filename_to_uri (absolute, NULL, NULL);
4310 const char *prepend = "file://";
4312 if (*absolute == '/' && *(absolute + 1) == '/') {
4315 prepend = "file:///";
4318 uri = g_strconcat (prepend, absolute, NULL);
4322 res = mono_string_new (domain, uri);
4329 ICALL_EXPORT MonoBoolean
4330 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4332 MonoAssembly *mass = assembly->assembly;
4334 MONO_ARCH_SAVE_REGS;
4336 return mass->in_gac;
4339 ICALL_EXPORT MonoReflectionAssembly*
4340 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4344 MonoImageOpenStatus status;
4346 MONO_ARCH_SAVE_REGS;
4348 name = mono_string_to_utf8 (mname);
4349 res = mono_assembly_load_with_partial_name (name, &status);
4355 return mono_assembly_get_object (mono_domain_get (), res);
4358 ICALL_EXPORT MonoString *
4359 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4361 MonoDomain *domain = mono_object_domain (assembly);
4364 MONO_ARCH_SAVE_REGS;
4366 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4371 ICALL_EXPORT MonoBoolean
4372 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4374 MONO_ARCH_SAVE_REGS;
4376 return assembly->assembly->ref_only;
4379 ICALL_EXPORT MonoString *
4380 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4382 MonoDomain *domain = mono_object_domain (assembly);
4384 MONO_ARCH_SAVE_REGS;
4386 return mono_string_new (domain, assembly->assembly->image->version);
4389 ICALL_EXPORT MonoReflectionMethod*
4390 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4392 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4394 MONO_ARCH_SAVE_REGS;
4398 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4401 ICALL_EXPORT MonoReflectionModule*
4402 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4404 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4407 ICALL_EXPORT MonoArray*
4408 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4410 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4411 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4415 MONO_ARCH_SAVE_REGS;
4417 for (i = 0; i < table->rows; ++i) {
4418 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4419 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4425 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4427 static MonoClass *System_Version = NULL;
4428 static MonoMethod *create_version = NULL;
4432 if (!System_Version) {
4433 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4434 g_assert (System_Version);
4437 if (!create_version) {
4438 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4439 create_version = mono_method_desc_search_in_class (desc, System_Version);
4440 g_assert (create_version);
4441 mono_method_desc_free (desc);
4447 args [3] = &revision;
4448 result = mono_object_new (domain, System_Version);
4449 mono_runtime_invoke (create_version, result, args, NULL);
4454 ICALL_EXPORT MonoArray*
4455 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4457 static MonoClass *System_Reflection_AssemblyName;
4459 MonoDomain *domain = mono_object_domain (assembly);
4461 static MonoMethod *create_culture = NULL;
4462 MonoImage *image = assembly->assembly->image;
4465 MONO_ARCH_SAVE_REGS;
4467 if (!System_Reflection_AssemblyName)
4468 System_Reflection_AssemblyName = mono_class_from_name (
4469 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4471 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4474 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4476 if (count > 0 && !create_culture) {
4477 MonoMethodDesc *desc = mono_method_desc_new (
4478 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4479 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4480 g_assert (create_culture);
4481 mono_method_desc_free (desc);
4484 for (i = 0; i < count; i++) {
4485 MonoReflectionAssemblyName *aname;
4486 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4488 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4490 aname = (MonoReflectionAssemblyName *) mono_object_new (
4491 domain, System_Reflection_AssemblyName);
4493 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4495 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4496 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4497 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4498 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4499 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4500 aname->versioncompat = 1; /* SameMachine (default) */
4501 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4502 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4504 if (create_culture) {
4506 MonoBoolean assembly_ref = 1;
4507 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4508 args [1] = &assembly_ref;
4509 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4512 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4513 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4514 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4516 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4517 /* public key token isn't copied - the class library will
4518 automatically generate it from the public key if required */
4519 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4520 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4522 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4523 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4526 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4529 /* note: this function doesn't return the codebase on purpose (i.e. it can
4530 be used under partial trust as path information isn't present). */
4532 mono_array_setref (result, i, aname);
4537 /* move this in some file in mono/util/ */
4539 g_concat_dir_and_file (const char *dir, const char *file)
4541 g_return_val_if_fail (dir != NULL, NULL);
4542 g_return_val_if_fail (file != NULL, NULL);
4545 * If the directory name doesn't have a / on the end, we need
4546 * to add one so we get a proper path to the file
4548 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4549 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4551 return g_strconcat (dir, file, NULL);
4555 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4557 char *n = mono_string_to_utf8 (name);
4558 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4560 guint32 cols [MONO_MANIFEST_SIZE];
4561 guint32 impl, file_idx;
4565 MONO_ARCH_SAVE_REGS;
4567 for (i = 0; i < table->rows; ++i) {
4568 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4569 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4570 if (strcmp (val, n) == 0)
4574 if (i == table->rows)
4577 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4580 * this code should only be called after obtaining the
4581 * ResourceInfo and handling the other cases.
4583 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4584 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4586 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4591 module = assembly->assembly->image;
4593 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4595 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4598 ICALL_EXPORT gboolean
4599 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4601 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4603 guint32 cols [MONO_MANIFEST_SIZE];
4604 guint32 file_cols [MONO_FILE_SIZE];
4608 MONO_ARCH_SAVE_REGS;
4610 n = mono_string_to_utf8 (name);
4611 for (i = 0; i < table->rows; ++i) {
4612 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4613 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4614 if (strcmp (val, n) == 0)
4618 if (i == table->rows)
4621 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4622 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4625 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4626 case MONO_IMPLEMENTATION_FILE:
4627 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4628 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4629 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4630 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4631 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4632 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4635 info->location = RESOURCE_LOCATION_EMBEDDED;
4638 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4639 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4640 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4641 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4642 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4643 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4645 mono_raise_exception (ex);
4647 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4649 /* Obtain info recursively */
4650 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4651 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4654 case MONO_IMPLEMENTATION_EXP_TYPE:
4655 g_assert_not_reached ();
4663 ICALL_EXPORT MonoObject*
4664 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4666 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4667 MonoArray *result = NULL;
4672 MONO_ARCH_SAVE_REGS;
4674 /* check hash if needed */
4676 n = mono_string_to_utf8 (name);
4677 for (i = 0; i < table->rows; ++i) {
4678 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4679 if (strcmp (val, n) == 0) {
4682 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4683 fn = mono_string_new (mono_object_domain (assembly), n);
4685 return (MonoObject*)fn;
4693 for (i = 0; i < table->rows; ++i) {
4694 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4698 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4701 for (i = 0; i < table->rows; ++i) {
4702 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4703 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4704 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4705 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4710 return (MonoObject*)result;
4713 ICALL_EXPORT MonoArray*
4714 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4716 MonoDomain *domain = mono_domain_get();
4719 int i, j, file_count = 0;
4720 MonoImage **modules;
4721 guint32 module_count, real_module_count;
4722 MonoTableInfo *table;
4723 guint32 cols [MONO_FILE_SIZE];
4724 MonoImage *image = assembly->assembly->image;
4726 g_assert (image != NULL);
4727 g_assert (!assembly_is_dynamic (assembly->assembly));
4729 table = &image->tables [MONO_TABLE_FILE];
4730 file_count = table->rows;
4732 modules = image->modules;
4733 module_count = image->module_count;
4735 real_module_count = 0;
4736 for (i = 0; i < module_count; ++i)
4738 real_module_count ++;
4740 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4741 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4743 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4745 for (i = 0; i < module_count; ++i)
4747 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4751 for (i = 0; i < file_count; ++i, ++j) {
4752 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4753 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4754 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4756 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4758 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4759 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4761 mono_array_setref (res, j, mono_module_get_object (domain, m));
4768 ICALL_EXPORT MonoReflectionMethod*
4769 ves_icall_GetCurrentMethod (void)
4771 MonoMethod *m = mono_method_get_last_managed ();
4773 while (m->is_inflated)
4774 m = ((MonoMethodInflated*)m)->declaring;
4776 return mono_method_get_object (mono_domain_get (), m, NULL);
4781 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4784 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4785 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4786 //method is inflated, we should inflate it on the other class
4787 MonoGenericContext ctx;
4788 ctx.method_inst = inflated->context.method_inst;
4789 ctx.class_inst = inflated->context.class_inst;
4790 if (klass->generic_class)
4791 ctx.class_inst = klass->generic_class->context.class_inst;
4792 else if (klass->generic_container)
4793 ctx.class_inst = klass->generic_container->context.class_inst;
4794 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4797 mono_class_setup_methods (method->klass);
4798 if (method->klass->exception_type)
4800 for (i = 0; i < method->klass->method.count; ++i) {
4801 if (method->klass->methods [i] == method) {
4806 mono_class_setup_methods (klass);
4807 if (klass->exception_type)
4809 g_assert (offset >= 0 && offset < klass->method.count);
4810 return klass->methods [offset];
4813 ICALL_EXPORT MonoReflectionMethod*
4814 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4818 klass = mono_class_from_mono_type (type);
4819 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4821 if (method->klass != klass) {
4822 method = mono_method_get_equivalent_method (method, klass);
4827 klass = method->klass;
4828 return mono_method_get_object (mono_domain_get (), method, klass);
4831 ICALL_EXPORT MonoReflectionMethod*
4832 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4834 return mono_method_get_object (mono_domain_get (), method, NULL);
4837 ICALL_EXPORT MonoReflectionMethodBody*
4838 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4840 return mono_method_body_get_object (mono_domain_get (), method);
4843 ICALL_EXPORT MonoReflectionAssembly*
4844 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4846 MonoMethod *dest = NULL;
4848 MONO_ARCH_SAVE_REGS;
4850 mono_stack_walk_no_il (get_executing, &dest);
4852 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4856 ICALL_EXPORT MonoReflectionAssembly*
4857 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4859 MonoDomain* domain = mono_domain_get ();
4861 MONO_ARCH_SAVE_REGS;
4863 if (!domain->entry_assembly)
4866 return mono_assembly_get_object (domain, domain->entry_assembly);
4869 ICALL_EXPORT MonoReflectionAssembly*
4870 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4875 MONO_ARCH_SAVE_REGS;
4878 mono_stack_walk_no_il (get_executing, &dest);
4880 mono_stack_walk_no_il (get_caller, &dest);
4883 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4886 ICALL_EXPORT MonoString *
4887 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4888 gboolean assembly_qualified)
4890 MonoDomain *domain = mono_object_domain (object);
4891 MonoTypeNameFormat format;
4896 format = assembly_qualified ?
4897 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4898 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4900 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4902 name = mono_type_get_name_full (object->type, format);
4906 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4911 res = mono_string_new (domain, name);
4918 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4920 MonoClass *klass = mono_class_from_mono_type (this->type);
4921 mono_class_init_or_throw (klass);
4922 return mono_security_core_clr_class_level (klass);
4926 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4928 static MonoMethod *create_culture = NULL;
4931 const char *pkey_ptr;
4933 MonoBoolean assembly_ref = 0;
4935 MONO_ARCH_SAVE_REGS;
4937 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4938 aname->major = name->major;
4939 aname->minor = name->minor;
4940 aname->build = name->build;
4941 aname->flags = name->flags;
4942 aname->revision = name->revision;
4943 aname->hashalg = name->hash_alg;
4944 aname->versioncompat = 1; /* SameMachine (default) */
4945 aname->processor_architecture = name->arch;
4947 if (by_default_version)
4948 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4951 if (absolute != NULL && *absolute != '\0') {
4952 const gchar *prepend = "file://";
4955 codebase = g_strdup (absolute);
4960 for (i = strlen (codebase) - 1; i >= 0; i--)
4961 if (codebase [i] == '\\')
4964 if (*codebase == '/' && *(codebase + 1) == '/') {
4967 prepend = "file:///";
4971 result = g_strconcat (prepend, codebase, NULL);
4977 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4981 if (!create_culture) {
4982 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4983 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4984 g_assert (create_culture);
4985 mono_method_desc_free (desc);
4988 if (name->culture) {
4989 args [0] = mono_string_new (domain, name->culture);
4990 args [1] = &assembly_ref;
4991 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4994 if (name->public_key) {
4995 pkey_ptr = (char*)name->public_key;
4996 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4998 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4999 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5000 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5001 } else if (default_publickey) {
5002 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5003 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5006 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5007 if (name->public_key_token [0]) {
5011 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5012 p = mono_array_addr (aname->keyToken, char, 0);
5014 for (i = 0, j = 0; i < 8; i++) {
5015 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5016 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5019 } else if (default_token) {
5020 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5024 ICALL_EXPORT MonoString *
5025 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5027 MonoDomain *domain = mono_object_domain (assembly);
5028 MonoAssembly *mass = assembly->assembly;
5032 name = mono_stringify_assembly_name (&mass->aname);
5033 res = mono_string_new (domain, name);
5040 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5043 MonoAssembly *mass = assembly->assembly;
5045 MONO_ARCH_SAVE_REGS;
5047 if (g_path_is_absolute (mass->image->name)) {
5048 fill_reflection_assembly_name (mono_object_domain (assembly),
5049 aname, &mass->aname, mass->image->name, TRUE,
5053 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5055 fill_reflection_assembly_name (mono_object_domain (assembly),
5056 aname, &mass->aname, absolute, TRUE, TRUE,
5063 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5066 MonoImageOpenStatus status = MONO_IMAGE_OK;
5069 MonoAssemblyName name;
5072 MONO_ARCH_SAVE_REGS;
5074 filename = mono_string_to_utf8 (fname);
5076 dirname = g_path_get_dirname (filename);
5077 replace_shadow_path (mono_domain_get (), dirname, &filename);
5080 image = mono_image_open (filename, &status);
5086 if (status == MONO_IMAGE_IMAGE_INVALID)
5087 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5089 exc = mono_get_exception_file_not_found2 (NULL, fname);
5090 mono_raise_exception (exc);
5093 res = mono_assembly_fill_assembly_name (image, &name);
5095 mono_image_close (image);
5097 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5100 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5104 mono_image_close (image);
5107 ICALL_EXPORT MonoBoolean
5108 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5109 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5111 MonoBoolean result = FALSE;
5112 MonoDeclSecurityEntry entry;
5114 /* SecurityAction.RequestMinimum */
5115 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5116 *minimum = entry.blob;
5117 *minLength = entry.size;
5120 /* SecurityAction.RequestOptional */
5121 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5122 *optional = entry.blob;
5123 *optLength = entry.size;
5126 /* SecurityAction.RequestRefuse */
5127 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5128 *refused = entry.blob;
5129 *refLength = entry.size;
5137 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5141 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5143 guint32 attrs, visibility;
5145 /* we start the count from 1 because we skip the special type <Module> */
5148 for (i = 1; i < tdef->rows; ++i) {
5149 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5150 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5151 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5155 count = tdef->rows - 1;
5157 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5158 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5160 for (i = 1; i < tdef->rows; ++i) {
5161 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5162 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5163 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5164 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5166 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5168 MonoLoaderError *error;
5171 error = mono_loader_get_last_error ();
5172 g_assert (error != NULL);
5174 ex = mono_loader_error_prepare_exception (error);
5175 mono_array_setref (*exceptions, count, ex);
5177 if (mono_loader_get_last_error ())
5178 mono_loader_clear_error ();
5186 ICALL_EXPORT MonoArray*
5187 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5189 MonoArray *res = NULL;
5190 MonoArray *exceptions = NULL;
5191 MonoImage *image = NULL;
5192 MonoTableInfo *table = NULL;
5195 int i, len, ex_count;
5197 MONO_ARCH_SAVE_REGS;
5199 domain = mono_object_domain (assembly);
5201 g_assert (!assembly_is_dynamic (assembly->assembly));
5202 image = assembly->assembly->image;
5203 table = &image->tables [MONO_TABLE_FILE];
5204 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5206 /* Append data from all modules in the assembly */
5207 for (i = 0; i < table->rows; ++i) {
5208 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5209 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5212 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5213 /* Append the new types to the end of the array */
5214 if (mono_array_length (res2) > 0) {
5216 MonoArray *res3, *ex3;
5218 len1 = mono_array_length (res);
5219 len2 = mono_array_length (res2);
5221 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5222 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5223 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5226 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5227 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5228 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5235 /* the ReflectionTypeLoadException must have all the types (Types property),
5236 * NULL replacing types which throws an exception. The LoaderException must
5237 * contain all exceptions for NULL items.
5240 len = mono_array_length (res);
5243 for (i = 0; i < len; i++) {
5244 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5248 klass = mono_type_get_class (t->type);
5249 if ((klass != NULL) && klass->exception_type) {
5250 /* keep the class in the list */
5251 list = g_list_append (list, klass);
5252 /* and replace Type with NULL */
5253 mono_array_setref (res, i, NULL);
5260 if (list || ex_count) {
5262 MonoException *exc = NULL;
5263 MonoArray *exl = NULL;
5264 int j, length = g_list_length (list) + ex_count;
5266 mono_loader_clear_error ();
5268 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5269 /* Types for which mono_class_get () succeeded */
5270 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5271 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5272 mono_array_setref (exl, i, exc);
5274 /* Types for which it don't */
5275 for (j = 0; j < mono_array_length (exceptions); ++j) {
5276 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5278 g_assert (i < length);
5279 mono_array_setref (exl, i, exc);
5286 exc = mono_get_exception_reflection_type_load (res, exl);
5287 mono_loader_clear_error ();
5288 mono_raise_exception (exc);
5294 ICALL_EXPORT gboolean
5295 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5297 MonoAssemblyName aname;
5298 MonoDomain *domain = mono_object_domain (name);
5300 gboolean is_version_defined;
5301 gboolean is_token_defined;
5303 aname.public_key = NULL;
5304 val = mono_string_to_utf8 (assname);
5305 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5306 g_free ((guint8*) aname.public_key);
5311 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5312 FALSE, is_token_defined);
5314 mono_assembly_name_free (&aname);
5315 g_free ((guint8*) aname.public_key);
5321 ICALL_EXPORT MonoReflectionType*
5322 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5324 MonoDomain *domain = mono_object_domain (module);
5327 MONO_ARCH_SAVE_REGS;
5329 g_assert (module->image);
5331 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5332 /* These images do not have a global type */
5335 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5336 return mono_type_get_object (domain, &klass->byval_arg);
5340 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5342 /*if (module->image)
5343 mono_image_close (module->image);*/
5346 ICALL_EXPORT MonoString*
5347 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5349 MonoDomain *domain = mono_object_domain (module);
5351 MONO_ARCH_SAVE_REGS;
5353 g_assert (module->image);
5354 return mono_string_new (domain, module->image->guid);
5357 ICALL_EXPORT gpointer
5358 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5361 if (module->image && module->image->is_module_handle)
5362 return module->image->raw_data;
5365 return (gpointer) (-1);
5369 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5371 if (image_is_dynamic (image)) {
5372 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5373 *pe_kind = dyn->pe_kind;
5374 *machine = dyn->machine;
5377 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5378 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5383 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5385 return (image->md_version_major << 16) | (image->md_version_minor);
5388 ICALL_EXPORT MonoArray*
5389 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5391 MonoArray *exceptions;
5394 MONO_ARCH_SAVE_REGS;
5397 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5399 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5400 for (i = 0; i < mono_array_length (exceptions); ++i) {
5401 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5403 mono_raise_exception (ex);
5410 mono_memberref_is_method (MonoImage *image, guint32 token)
5412 if (!image_is_dynamic (image)) {
5413 guint32 cols [MONO_MEMBERREF_SIZE];
5415 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5416 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5417 mono_metadata_decode_blob_size (sig, &sig);
5418 return (*sig != 0x6);
5420 MonoClass *handle_class;
5422 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5425 return mono_defaults.methodhandle_class == handle_class;
5430 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5433 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5434 mono_array_addr (type_args, MonoType*, 0));
5436 context->class_inst = NULL;
5438 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5439 mono_array_addr (method_args, MonoType*, 0));
5441 context->method_inst = NULL;
5444 ICALL_EXPORT MonoType*
5445 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5448 int table = mono_metadata_token_table (token);
5449 int index = mono_metadata_token_index (token);
5450 MonoGenericContext context;
5452 *error = ResolveTokenError_Other;
5454 /* Validate token */
5455 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5456 (table != MONO_TABLE_TYPESPEC)) {
5457 *error = ResolveTokenError_BadTable;
5461 if (image_is_dynamic (image)) {
5462 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5463 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5464 return klass ? &klass->byval_arg : NULL;
5467 init_generic_context_from_args (&context, type_args, method_args);
5468 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5469 return klass ? &klass->byval_arg : NULL;
5472 if ((index <= 0) || (index > image->tables [table].rows)) {
5473 *error = ResolveTokenError_OutOfRange;
5477 init_generic_context_from_args (&context, type_args, method_args);
5478 klass = mono_class_get_full (image, token, &context);
5480 if (mono_loader_get_last_error ())
5481 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5484 return &klass->byval_arg;
5489 ICALL_EXPORT MonoMethod*
5490 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5492 int table = mono_metadata_token_table (token);
5493 int index = mono_metadata_token_index (token);
5494 MonoGenericContext context;
5497 *error = ResolveTokenError_Other;
5499 /* Validate token */
5500 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5501 (table != MONO_TABLE_MEMBERREF)) {
5502 *error = ResolveTokenError_BadTable;
5506 if (image_is_dynamic (image)) {
5507 if (table == MONO_TABLE_METHOD)
5508 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5510 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5511 *error = ResolveTokenError_BadTable;
5515 init_generic_context_from_args (&context, type_args, method_args);
5516 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5519 if ((index <= 0) || (index > image->tables [table].rows)) {
5520 *error = ResolveTokenError_OutOfRange;
5523 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5524 *error = ResolveTokenError_BadTable;
5528 init_generic_context_from_args (&context, type_args, method_args);
5529 method = mono_get_method_full (image, token, NULL, &context);
5531 if (mono_loader_get_last_error ())
5532 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5537 ICALL_EXPORT MonoString*
5538 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5540 int index = mono_metadata_token_index (token);
5542 *error = ResolveTokenError_Other;
5544 /* Validate token */
5545 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5546 *error = ResolveTokenError_BadTable;
5550 if (image_is_dynamic (image))
5551 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5553 if ((index <= 0) || (index >= image->heap_us.size)) {
5554 *error = ResolveTokenError_OutOfRange;
5558 /* FIXME: What to do if the index points into the middle of a string ? */
5560 return mono_ldstr (mono_domain_get (), image, index);
5563 ICALL_EXPORT MonoClassField*
5564 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5567 int table = mono_metadata_token_table (token);
5568 int index = mono_metadata_token_index (token);
5569 MonoGenericContext context;
5570 MonoClassField *field;
5572 *error = ResolveTokenError_Other;
5574 /* Validate token */
5575 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5576 *error = ResolveTokenError_BadTable;
5580 if (image_is_dynamic (image)) {
5581 if (table == MONO_TABLE_FIELD)
5582 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5584 if (mono_memberref_is_method (image, token)) {
5585 *error = ResolveTokenError_BadTable;
5589 init_generic_context_from_args (&context, type_args, method_args);
5590 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5593 if ((index <= 0) || (index > image->tables [table].rows)) {
5594 *error = ResolveTokenError_OutOfRange;
5597 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5598 *error = ResolveTokenError_BadTable;
5602 init_generic_context_from_args (&context, type_args, method_args);
5603 field = mono_field_from_token (image, token, &klass, &context);
5605 if (mono_loader_get_last_error ())
5606 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5612 ICALL_EXPORT MonoObject*
5613 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5615 int table = mono_metadata_token_table (token);
5617 *error = ResolveTokenError_Other;
5620 case MONO_TABLE_TYPEDEF:
5621 case MONO_TABLE_TYPEREF:
5622 case MONO_TABLE_TYPESPEC: {
5623 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5625 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5629 case MONO_TABLE_METHOD:
5630 case MONO_TABLE_METHODSPEC: {
5631 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5633 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5637 case MONO_TABLE_FIELD: {
5638 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5640 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5644 case MONO_TABLE_MEMBERREF:
5645 if (mono_memberref_is_method (image, token)) {
5646 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5648 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5653 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5655 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5662 *error = ResolveTokenError_BadTable;
5668 ICALL_EXPORT MonoArray*
5669 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5671 int table = mono_metadata_token_table (token);
5672 int idx = mono_metadata_token_index (token);
5673 MonoTableInfo *tables = image->tables;
5678 *error = ResolveTokenError_OutOfRange;
5680 /* FIXME: Support other tables ? */
5681 if (table != MONO_TABLE_STANDALONESIG)
5684 if (image_is_dynamic (image))
5687 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5690 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5692 ptr = mono_metadata_blob_heap (image, sig);
5693 len = mono_metadata_decode_blob_size (ptr, &ptr);
5695 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5696 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5700 ICALL_EXPORT MonoReflectionType*
5701 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5704 int isbyref = 0, rank;
5705 char *str = mono_string_to_utf8 (smodifiers);
5708 MONO_ARCH_SAVE_REGS;
5710 klass = mono_class_from_mono_type (tb->type.type);
5712 /* logic taken from mono_reflection_parse_type(): keep in sync */
5716 if (isbyref) { /* only one level allowed by the spec */
5723 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5726 klass = mono_ptr_class_get (&klass->byval_arg);
5727 mono_class_init (klass);
5738 else if (*p != '*') { /* '*' means unknown lower bound */
5749 klass = mono_array_class_get (klass, rank);
5750 mono_class_init (klass);
5757 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5760 ICALL_EXPORT MonoBoolean
5761 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5766 MONO_ARCH_SAVE_REGS;
5769 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5775 check_for_invalid_type (MonoClass *klass)
5779 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5782 name = mono_type_get_full_name (klass);
5783 str = mono_string_new (mono_domain_get (), name);
5785 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5788 ICALL_EXPORT MonoReflectionType *
5789 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5791 MonoClass *klass, *aklass;
5793 MONO_ARCH_SAVE_REGS;
5795 klass = mono_class_from_mono_type (type->type);
5796 check_for_invalid_type (klass);
5798 if (rank == 0) //single dimentional array
5799 aklass = mono_array_class_get (klass, 1);
5801 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5803 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5806 ICALL_EXPORT MonoReflectionType *
5807 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5811 MONO_ARCH_SAVE_REGS;
5813 klass = mono_class_from_mono_type (type->type);
5814 mono_class_init_or_throw (klass);
5815 check_for_invalid_type (klass);
5817 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5820 ICALL_EXPORT MonoReflectionType *
5821 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5823 MonoClass *klass, *pklass;
5825 klass = mono_class_from_mono_type (type->type);
5826 mono_class_init_or_throw (klass);
5827 check_for_invalid_type (klass);
5829 pklass = mono_ptr_class_get (type->type);
5831 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5834 ICALL_EXPORT MonoObject *
5835 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5836 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5838 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5839 MonoObject *delegate;
5841 MonoMethod *method = info->method;
5843 MONO_ARCH_SAVE_REGS;
5845 mono_class_init_or_throw (delegate_class);
5847 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5849 if (mono_security_core_clr_enabled ()) {
5850 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5854 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5856 if (method_is_dynamic (method)) {
5857 /* Creating a trampoline would leak memory */
5858 func = mono_compile_method (method);
5860 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5861 method = mono_object_get_virtual_method (target, method);
5862 func = mono_create_ftnptr (mono_domain_get (),
5863 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5866 mono_delegate_ctor_with_method (delegate, target, func, method);
5872 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5874 /* Reset the invoke impl to the default one */
5875 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5879 * Magic number to convert a time which is relative to
5880 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5882 #define EPOCH_ADJUST ((guint64)62135596800LL)
5885 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5887 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5890 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5892 convert_to_absolute_date(SYSTEMTIME *date)
5894 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5895 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5896 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5897 /* from the calendar FAQ */
5898 int a = (14 - date->wMonth) / 12;
5899 int y = date->wYear - a;
5900 int m = date->wMonth + 12 * a - 2;
5901 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5903 /* d is now the day of the week for the first of the month (0 == Sunday) */
5905 int day_of_week = date->wDayOfWeek;
5907 /* set day_in_month to the first day in the month which falls on day_of_week */
5908 int day_in_month = 1 + (day_of_week - d);
5909 if (day_in_month <= 0)
5912 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5913 date->wDay = day_in_month + (date->wDay - 1) * 7;
5914 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5921 * Return's the offset from GMT of a local time.
5923 * tm is a local time
5924 * t is the same local time as seconds.
5927 gmt_offset(struct tm *tm, time_t t)
5929 #if defined (HAVE_TM_GMTOFF)
5930 return tm->tm_gmtoff;
5935 g.tm_isdst = tm->tm_isdst;
5937 return (int)difftime(t, t2);
5942 * This is heavily based on zdump.c from glibc 2.2.
5944 * * data[0]: start of daylight saving time (in DateTime ticks).
5945 * * data[1]: end of daylight saving time (in DateTime ticks).
5946 * * data[2]: utcoffset (in TimeSpan ticks).
5947 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5948 * * name[0]: name of this timezone when not daylight saving.
5949 * * name[1]: name of this timezone when daylight saving.
5951 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5952 * the class library allows years between 1 and 9999.
5954 * Returns true on success and zero on failure.
5956 ICALL_EXPORT guint32
5957 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5960 MonoDomain *domain = mono_domain_get ();
5961 struct tm start, tt;
5964 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5965 int day, transitioned;
5968 gmtoff_st = gmtoff_ds = transitioned = 0;
5970 MONO_ARCH_SAVE_REGS;
5972 MONO_CHECK_ARG_NULL (data);
5973 MONO_CHECK_ARG_NULL (names);
5975 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5976 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5979 * no info is better than crashing: we'll need our own tz data
5980 * to make this work properly, anyway. The range is probably
5981 * reduced to 1970 .. 2037 because that is what mktime is
5982 * guaranteed to support (we get into an infinite loop
5986 memset (&start, 0, sizeof (start));
5989 start.tm_year = year-1900;
5991 t = mktime (&start);
5993 if ((year < 1970) || (year > 2037) || (t == -1)) {
5995 tt = *localtime (&t);
5996 strftime (tzone, sizeof (tzone), "%Z", &tt);
5997 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5998 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6002 gmtoff = gmt_offset (&start, t);
6004 /* For each day of the year, calculate the tm_gmtoff. */
6005 for (day = 0; day < 365 && transitioned < 2; day++) {
6008 tt = *localtime (&t);
6010 gmtoff_after = gmt_offset(&tt, t);
6012 /* Daylight saving starts or ends here. */
6013 if (gmtoff_after != gmtoff) {
6017 /* Try to find the exact hour when daylight saving starts/ends. */
6021 tt1 = *localtime (&t1);
6022 } while (gmt_offset (&tt1, t1) != gmtoff);
6024 /* Try to find the exact minute when daylight saving starts/ends. */
6027 tt1 = *localtime (&t1);
6028 } while (gmt_offset (&tt1, t1) == gmtoff);
6030 strftime (tzone, sizeof (tzone), "%Z", &tt);
6032 /* Write data, if we're already in daylight saving, we're done. */
6034 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6035 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6036 if (gmtoff_ds == 0) {
6038 gmtoff_ds = gmtoff_after;
6045 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6046 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6047 if (gmtoff_ds == 0) {
6048 gmtoff_st = gmtoff_after;
6054 /* This is only set once when we enter daylight saving. */
6056 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6057 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6059 gmtoff = gmt_offset (&tt, t);
6063 if (transitioned < 2) {
6064 strftime (tzone, sizeof (tzone), "%Z", &tt);
6065 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6066 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6067 mono_array_set ((*data), gint64, 0, 0);
6068 mono_array_set ((*data), gint64, 1, 0);
6069 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6070 mono_array_set ((*data), gint64, 3, 0);
6075 MonoDomain *domain = mono_domain_get ();
6076 TIME_ZONE_INFORMATION tz_info;
6081 tz_id = GetTimeZoneInformation (&tz_info);
6082 if (tz_id == TIME_ZONE_ID_INVALID)
6085 MONO_CHECK_ARG_NULL (data);
6086 MONO_CHECK_ARG_NULL (names);
6088 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6089 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6091 for (i = 0; i < 32; ++i)
6092 if (!tz_info.DaylightName [i])
6094 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6095 for (i = 0; i < 32; ++i)
6096 if (!tz_info.StandardName [i])
6098 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6100 if ((year <= 1601) || (year > 30827)) {
6102 * According to MSDN, the MS time functions can't handle dates outside
6108 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6109 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6110 tz_info.StandardDate.wYear = year;
6111 convert_to_absolute_date(&tz_info.StandardDate);
6112 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6117 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6118 tz_info.DaylightDate.wYear = year;
6119 convert_to_absolute_date(&tz_info.DaylightDate);
6120 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6125 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6127 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6128 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6136 static inline gint32
6137 mono_array_get_byte_length (MonoArray *array)
6143 klass = array->obj.vtable->klass;
6145 if (array->bounds == NULL)
6146 length = array->max_length;
6149 for (i = 0; i < klass->rank; ++ i)
6150 length *= array->bounds [i].length;
6153 switch (klass->element_class->byval_arg.type) {
6156 case MONO_TYPE_BOOLEAN:
6160 case MONO_TYPE_CHAR:
6168 return length * sizeof (gpointer);
6179 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6181 MONO_ARCH_SAVE_REGS;
6183 return mono_array_get_byte_length (array);
6187 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6189 MONO_ARCH_SAVE_REGS;
6191 return mono_array_get (array, gint8, idx);
6195 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6197 MONO_ARCH_SAVE_REGS;
6199 mono_array_set (array, gint8, idx, value);
6202 ICALL_EXPORT MonoBoolean
6203 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6205 guint8 *src_buf, *dest_buf;
6207 MONO_ARCH_SAVE_REGS;
6209 /* This is called directly from the class libraries without going through the managed wrapper */
6210 MONO_CHECK_ARG_NULL (src);
6211 MONO_CHECK_ARG_NULL (dest);
6213 /* watch out for integer overflow */
6214 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6217 src_buf = (guint8 *)src->vector + src_offset;
6218 dest_buf = (guint8 *)dest->vector + dest_offset;
6221 memcpy (dest_buf, src_buf, count);
6223 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6228 #ifndef DISABLE_REMOTING
6229 ICALL_EXPORT MonoObject *
6230 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6232 MonoDomain *domain = mono_object_domain (this);
6234 MonoRealProxy *rp = ((MonoRealProxy *)this);
6235 MonoTransparentProxy *tp;
6239 MONO_ARCH_SAVE_REGS;
6241 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6242 tp = (MonoTransparentProxy*) res;
6244 MONO_OBJECT_SETREF (tp, rp, rp);
6245 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6246 klass = mono_class_from_mono_type (type);
6248 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6249 tp->remote_class = mono_remote_class (domain, class_name, klass);
6251 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6255 ICALL_EXPORT MonoReflectionType *
6256 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6258 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6262 /* System.Environment */
6265 ves_icall_System_Environment_get_UserName (void)
6267 MONO_ARCH_SAVE_REGS;
6269 /* using glib is more portable */
6270 return mono_string_new (mono_domain_get (), g_get_user_name ());
6274 ICALL_EXPORT MonoString *
6275 ves_icall_System_Environment_get_MachineName (void)
6277 #if defined (HOST_WIN32)
6282 len = MAX_COMPUTERNAME_LENGTH + 1;
6283 buf = g_new (gunichar2, len);
6286 if (GetComputerName (buf, (PDWORD) &len))
6287 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6291 #elif !defined(DISABLE_SOCKETS)
6295 if (gethostname (buf, sizeof (buf)) == 0)
6296 result = mono_string_new (mono_domain_get (), buf);
6302 return mono_string_new (mono_domain_get (), "mono");
6307 ves_icall_System_Environment_get_Platform (void)
6309 #if defined (TARGET_WIN32)
6312 #elif defined(__MACH__)
6315 // Notice that the value is hidden from user code, and only exposed
6316 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6317 // define and making assumptions based on Unix/128/4 values before there
6318 // was a MacOS define. Lots of code would assume that not-Unix meant
6319 // Windows, but in this case, it would be OSX.
6328 ICALL_EXPORT MonoString *
6329 ves_icall_System_Environment_get_NewLine (void)
6331 MONO_ARCH_SAVE_REGS;
6333 #if defined (HOST_WIN32)
6334 return mono_string_new (mono_domain_get (), "\r\n");
6336 return mono_string_new (mono_domain_get (), "\n");
6340 ICALL_EXPORT MonoString *
6341 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6346 MONO_ARCH_SAVE_REGS;
6351 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6352 value = g_getenv (utf8_name);
6359 return mono_string_new (mono_domain_get (), value);
6363 * There is no standard way to get at environ.
6366 #ifndef __MINGW32_VERSION
6367 #if defined(__APPLE__) && !defined (__arm__)
6368 /* Apple defines this in crt_externs.h but doesn't provide that header for
6369 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6370 * in fact exist on all implementations (so far)
6372 gchar ***_NSGetEnviron(void);
6373 #define environ (*_NSGetEnviron())
6381 ICALL_EXPORT MonoArray *
6382 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6393 env_strings = GetEnvironmentStrings();
6396 env_string = env_strings;
6397 while (*env_string != '\0') {
6398 /* weird case that MS seems to skip */
6399 if (*env_string != '=')
6401 while (*env_string != '\0')
6407 domain = mono_domain_get ();
6408 names = mono_array_new (domain, mono_defaults.string_class, n);
6412 env_string = env_strings;
6413 while (*env_string != '\0') {
6414 /* weird case that MS seems to skip */
6415 if (*env_string != '=') {
6416 equal_str = wcschr(env_string, '=');
6417 g_assert(equal_str);
6418 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6419 mono_array_setref (names, n, str);
6422 while (*env_string != '\0')
6427 FreeEnvironmentStrings (env_strings);
6439 MONO_ARCH_SAVE_REGS;
6442 for (e = environ; *e != 0; ++ e)
6445 domain = mono_domain_get ();
6446 names = mono_array_new (domain, mono_defaults.string_class, n);
6449 for (e = environ; *e != 0; ++ e) {
6450 parts = g_strsplit (*e, "=", 2);
6452 str = mono_string_new (domain, *parts);
6453 mono_array_setref (names, n, str);
6466 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6468 #if !GLIB_CHECK_VERSION(2,4,0)
6469 #define g_setenv(a,b,c) setenv(a,b,c)
6470 #define g_unsetenv(a) unsetenv(a)
6474 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6477 gunichar2 *utf16_name, *utf16_value;
6479 gchar *utf8_name, *utf8_value;
6483 MONO_ARCH_SAVE_REGS;
6486 utf16_name = mono_string_to_utf16 (name);
6487 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6488 SetEnvironmentVariable (utf16_name, NULL);
6489 g_free (utf16_name);
6493 utf16_value = mono_string_to_utf16 (value);
6495 SetEnvironmentVariable (utf16_name, utf16_value);
6497 g_free (utf16_name);
6498 g_free (utf16_value);
6500 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6502 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6503 g_unsetenv (utf8_name);
6508 utf8_value = mono_string_to_utf8_checked (value, &error);
6509 if (!mono_error_ok (&error)) {
6511 mono_error_raise_exception (&error);
6513 g_setenv (utf8_name, utf8_value, TRUE);
6516 g_free (utf8_value);
6521 ves_icall_System_Environment_Exit (int result)
6523 MONO_ARCH_SAVE_REGS;
6525 mono_environment_exitcode_set (result);
6527 /* FIXME: There are some cleanup hangs that should be worked out, but
6528 * if the program is going to exit, everything will be cleaned up when
6529 * NaCl exits anyway.
6531 #ifndef __native_client__
6532 if (!mono_runtime_try_shutdown ())
6533 mono_thread_exit ();
6535 /* Suspend all managed threads since the runtime is going away */
6536 mono_thread_suspend_all_other_threads ();
6538 mono_runtime_quit ();
6541 /* we may need to do some cleanup here... */
6545 ICALL_EXPORT MonoString*
6546 ves_icall_System_Environment_GetGacPath (void)
6548 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6551 ICALL_EXPORT MonoString*
6552 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6554 #if defined (HOST_WIN32)
6555 #ifndef CSIDL_FLAG_CREATE
6556 #define CSIDL_FLAG_CREATE 0x8000
6559 WCHAR path [MAX_PATH];
6560 /* Create directory if no existing */
6561 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6565 return mono_string_new_utf16 (mono_domain_get (), path, len);
6568 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6570 return mono_string_new (mono_domain_get (), "");
6573 ICALL_EXPORT MonoArray *
6574 ves_icall_System_Environment_GetLogicalDrives (void)
6576 gunichar2 buf [256], *ptr, *dname;
6578 guint initial_size = 127, size = 128;
6581 MonoString *drivestr;
6582 MonoDomain *domain = mono_domain_get ();
6585 MONO_ARCH_SAVE_REGS;
6590 while (size > initial_size) {
6591 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6592 if (size > initial_size) {
6595 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6596 initial_size = size;
6610 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6615 while (*u16) { u16++; len ++; }
6616 drivestr = mono_string_new_utf16 (domain, dname, len);
6617 mono_array_setref (result, ndrives++, drivestr);
6627 ICALL_EXPORT MonoString *
6628 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6630 gunichar2 volume_name [MAX_PATH + 1];
6632 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6634 return mono_string_from_utf16 (volume_name);
6637 ICALL_EXPORT MonoString *
6638 ves_icall_System_Environment_InternalGetHome (void)
6640 MONO_ARCH_SAVE_REGS;
6642 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6645 static const char *encodings [] = {
6647 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6648 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6649 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6651 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6652 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6653 "x_unicode_2_0_utf_7",
6655 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6656 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6658 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6661 "unicodefffe", "utf_16be",
6668 * Returns the internal codepage, if the value of "int_code_page" is
6669 * 1 at entry, and we can not compute a suitable code page number,
6670 * returns the code page as a string
6672 ICALL_EXPORT MonoString*
6673 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6678 char *codepage = NULL;
6680 int want_name = *int_code_page;
6683 *int_code_page = -1;
6684 MONO_ARCH_SAVE_REGS;
6686 g_get_charset (&cset);
6687 c = codepage = strdup (cset);
6688 for (c = codepage; *c; c++){
6689 if (isascii (*c) && isalpha (*c))
6694 /* g_print ("charset: %s\n", cset); */
6696 /* handle some common aliases */
6699 for (i = 0; p != 0; ){
6700 if ((gssize) p < 7){
6702 p = encodings [++i];
6705 if (strcmp (p, codepage) == 0){
6706 *int_code_page = code;
6709 p = encodings [++i];
6712 if (strstr (codepage, "utf_8") != NULL)
6713 *int_code_page |= 0x10000000;
6716 if (want_name && *int_code_page == -1)
6717 return mono_string_new (mono_domain_get (), cset);
6722 ICALL_EXPORT MonoBoolean
6723 ves_icall_System_Environment_get_HasShutdownStarted (void)
6725 if (mono_runtime_is_shutting_down ())
6728 if (mono_domain_is_unloading (mono_domain_get ()))
6735 ves_icall_System_Environment_BroadcastSettingChange (void)
6738 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6743 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6744 MonoReflectionMethod *method,
6745 MonoArray *out_args)
6747 MONO_ARCH_SAVE_REGS;
6749 mono_message_init (mono_object_domain (this), this, method, out_args);
6752 #ifndef DISABLE_REMOTING
6753 ICALL_EXPORT MonoBoolean
6754 ves_icall_IsTransparentProxy (MonoObject *proxy)
6756 MONO_ARCH_SAVE_REGS;
6761 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6767 ICALL_EXPORT MonoReflectionMethod *
6768 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6769 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6773 MonoMethod **vtable;
6774 MonoMethod *res = NULL;
6776 MONO_CHECK_ARG_NULL (rtype);
6777 MONO_CHECK_ARG_NULL (rmethod);
6779 method = rmethod->method;
6780 klass = mono_class_from_mono_type (rtype->type);
6781 mono_class_init_or_throw (klass);
6783 if (MONO_CLASS_IS_INTERFACE (klass))
6786 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6789 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6790 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6796 mono_class_setup_vtable (klass);
6797 vtable = klass->vtable;
6799 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6800 gboolean variance_used = FALSE;
6801 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6802 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6804 res = vtable [offs + method->slot];
6806 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6809 if (method->slot != -1)
6810 res = vtable [method->slot];
6816 return mono_method_get_object (mono_domain_get (), res, NULL);
6820 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6825 MONO_ARCH_SAVE_REGS;
6827 klass = mono_class_from_mono_type (type->type);
6828 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6830 mono_vtable_set_is_remote (vtable, enable);
6833 #else /* DISABLE_REMOTING */
6836 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6838 g_assert_not_reached ();
6843 ICALL_EXPORT MonoObject *
6844 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6849 MONO_ARCH_SAVE_REGS;
6851 domain = mono_object_domain (type);
6852 klass = mono_class_from_mono_type (type->type);
6853 mono_class_init_or_throw (klass);
6855 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6856 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6858 if (klass->rank >= 1) {
6859 g_assert (klass->rank == 1);
6860 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6862 /* Bypass remoting object creation check */
6863 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6867 ICALL_EXPORT MonoString *
6868 ves_icall_System_IO_get_temp_path (void)
6870 MONO_ARCH_SAVE_REGS;
6872 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6875 #ifndef PLATFORM_NO_DRIVEINFO
6876 ICALL_EXPORT MonoBoolean
6877 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6878 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6882 ULARGE_INTEGER wapi_free_bytes_avail;
6883 ULARGE_INTEGER wapi_total_number_of_bytes;
6884 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6886 MONO_ARCH_SAVE_REGS;
6888 *error = ERROR_SUCCESS;
6889 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6890 &wapi_total_number_of_free_bytes);
6893 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6894 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6895 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6897 *free_bytes_avail = 0;
6898 *total_number_of_bytes = 0;
6899 *total_number_of_free_bytes = 0;
6900 *error = GetLastError ();
6906 ICALL_EXPORT guint32
6907 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6909 MONO_ARCH_SAVE_REGS;
6911 return GetDriveType (mono_string_chars (root_path_name));
6915 ICALL_EXPORT gpointer
6916 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6918 MONO_ARCH_SAVE_REGS;
6920 return mono_compile_method (method);
6923 ICALL_EXPORT MonoString *
6924 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6929 MONO_ARCH_SAVE_REGS;
6931 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6933 #if defined (HOST_WIN32)
6934 /* Avoid mixing '/' and '\\' */
6937 for (i = strlen (path) - 1; i >= 0; i--)
6938 if (path [i] == '/')
6942 mcpath = mono_string_new (mono_domain_get (), path);
6949 get_bundled_app_config (void)
6951 const gchar *app_config;
6954 gchar *config_file_name, *config_file_path;
6958 MONO_ARCH_SAVE_REGS;
6960 domain = mono_domain_get ();
6961 file = domain->setup->configuration_file;
6965 // Retrieve config file and remove the extension
6966 config_file_name = mono_string_to_utf8 (file);
6967 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6968 if (!config_file_path)
6969 config_file_path = config_file_name;
6970 len = strlen (config_file_path) - strlen (".config");
6971 module = g_malloc0 (len + 1);
6972 memcpy (module, config_file_path, len);
6973 // Get the config file from the module name
6974 app_config = mono_config_string_for_assembly_file (module);
6977 if (config_file_name != config_file_path)
6978 g_free (config_file_name);
6979 g_free (config_file_path);
6984 return mono_string_new (mono_domain_get (), app_config);
6988 get_bundled_machine_config (void)
6990 const gchar *machine_config;
6992 MONO_ARCH_SAVE_REGS;
6994 machine_config = mono_get_machine_config ();
6996 if (!machine_config)
6999 return mono_string_new (mono_domain_get (), machine_config);
7002 ICALL_EXPORT MonoString *
7003 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7008 MONO_ARCH_SAVE_REGS;
7010 path = g_path_get_dirname (mono_get_config_dir ());
7012 #if defined (HOST_WIN32)
7013 /* Avoid mixing '/' and '\\' */
7016 for (i = strlen (path) - 1; i >= 0; i--)
7017 if (path [i] == '/')
7021 ipath = mono_string_new (mono_domain_get (), path);
7027 ICALL_EXPORT gboolean
7028 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7030 MonoPEResourceDataEntry *entry;
7033 MONO_ARCH_SAVE_REGS;
7035 if (!assembly || !result || !size)
7040 image = assembly->assembly->image;
7041 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7045 *result = mono_image_rva_map (image, entry->rde_data_offset);
7050 *size = entry->rde_size;
7055 ICALL_EXPORT MonoBoolean
7056 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7058 return mono_is_debugger_attached ();
7061 ICALL_EXPORT MonoBoolean
7062 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7064 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7065 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7071 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7073 if (mono_get_runtime_callbacks ()->debug_log)
7074 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7078 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7080 #if defined (HOST_WIN32)
7081 OutputDebugString (mono_string_chars (message));
7083 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7087 /* Only used for value types */
7088 ICALL_EXPORT MonoObject *
7089 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7094 MONO_ARCH_SAVE_REGS;
7096 domain = mono_object_domain (type);
7097 klass = mono_class_from_mono_type (type->type);
7098 mono_class_init_or_throw (klass);
7100 if (mono_class_is_nullable (klass))
7101 /* No arguments -> null */
7104 return mono_object_new (domain, klass);
7107 ICALL_EXPORT MonoReflectionMethod *
7108 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7110 MonoClass *klass, *parent;
7111 MonoMethod *method = m->method;
7112 MonoMethod *result = NULL;
7115 MONO_ARCH_SAVE_REGS;
7117 if (method->klass == NULL)
7120 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7121 MONO_CLASS_IS_INTERFACE (method->klass) ||
7122 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7125 slot = mono_method_get_vtable_slot (method);
7129 klass = method->klass;
7130 if (klass->generic_class)
7131 klass = klass->generic_class->container_class;
7134 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7135 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7136 mono_class_setup_vtable (parent);
7137 if (parent->vtable_size <= slot)
7142 klass = klass->parent;
7147 if (klass == method->klass)
7150 /*This is possible if definition == FALSE.
7151 * Do it here to be really sure we don't read invalid memory.
7153 if (slot >= klass->vtable_size)
7156 mono_class_setup_vtable (klass);
7158 result = klass->vtable [slot];
7159 if (result == NULL) {
7160 /* It is an abstract method */
7161 gpointer iter = NULL;
7162 while ((result = mono_class_get_methods (klass, &iter)))
7163 if (result->slot == slot)
7170 return mono_method_get_object (mono_domain_get (), result, NULL);
7173 ICALL_EXPORT MonoString*
7174 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7176 MonoMethod *method = m->method;
7178 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7183 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7185 MONO_ARCH_SAVE_REGS;
7187 iter->sig = *(MonoMethodSignature**)argsp;
7189 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7190 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7193 /* FIXME: it's not documented what start is exactly... */
7197 iter->args = argsp + sizeof (gpointer);
7199 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7201 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7204 ICALL_EXPORT MonoTypedRef
7205 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7207 guint32 i, arg_size;
7210 MONO_ARCH_SAVE_REGS;
7212 i = iter->sig->sentinelpos + iter->next_arg;
7214 g_assert (i < iter->sig->param_count);
7216 res.type = iter->sig->params [i];
7217 res.klass = mono_class_from_mono_type (res.type);
7218 arg_size = mono_type_stack_size (res.type, &align);
7219 #if defined(__arm__) || defined(__mips__)
7220 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7222 res.value = iter->args;
7223 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7224 /* Values are stored as 8 byte register sized objects, but 'value'
7225 * is dereferenced as a pointer in other routines.
7227 res.value = (char*)res.value + 4;
7229 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7230 if (arg_size <= sizeof (gpointer)) {
7232 int padding = arg_size - mono_type_size (res.type, &dummy);
7233 res.value = (guint8*)res.value + padding;
7236 iter->args = (char*)iter->args + arg_size;
7239 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7244 ICALL_EXPORT MonoTypedRef
7245 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7247 guint32 i, arg_size;
7250 MONO_ARCH_SAVE_REGS;
7252 i = iter->sig->sentinelpos + iter->next_arg;
7254 g_assert (i < iter->sig->param_count);
7256 while (i < iter->sig->param_count) {
7257 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7259 res.type = iter->sig->params [i];
7260 res.klass = mono_class_from_mono_type (res.type);
7261 /* FIXME: endianess issue... */
7262 arg_size = mono_type_stack_size (res.type, &align);
7263 #if defined(__arm__) || defined(__mips__)
7264 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7266 res.value = iter->args;
7267 iter->args = (char*)iter->args + arg_size;
7269 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7272 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7280 ICALL_EXPORT MonoType*
7281 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7284 MONO_ARCH_SAVE_REGS;
7286 i = iter->sig->sentinelpos + iter->next_arg;
7288 g_assert (i < iter->sig->param_count);
7290 return iter->sig->params [i];
7293 ICALL_EXPORT MonoObject*
7294 mono_TypedReference_ToObject (MonoTypedRef tref)
7296 MONO_ARCH_SAVE_REGS;
7298 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7299 MonoObject** objp = tref.value;
7303 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7306 ICALL_EXPORT MonoObject*
7307 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7309 MONO_ARCH_SAVE_REGS;
7311 if (MONO_TYPE_IS_REFERENCE (type)) {
7312 MonoObject** objp = value;
7316 return mono_value_box (mono_domain_get (), klass, value);
7320 prelink_method (MonoMethod *method)
7322 const char *exc_class, *exc_arg;
7323 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7325 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7327 mono_raise_exception(
7328 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7330 /* create the wrapper, too? */
7334 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7336 MONO_ARCH_SAVE_REGS;
7337 prelink_method (method->method);
7341 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7343 MonoClass *klass = mono_class_from_mono_type (type->type);
7345 gpointer iter = NULL;
7346 MONO_ARCH_SAVE_REGS;
7348 mono_class_init_or_throw (klass);
7350 while ((m = mono_class_get_methods (klass, &iter)))
7354 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7356 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7357 gint32 const **exponents,
7358 gunichar2 const **digitLowerTable,
7359 gunichar2 const **digitUpperTable,
7360 gint64 const **tenPowersList,
7361 gint32 const **decHexDigits)
7363 *mantissas = Formatter_MantissaBitsTable;
7364 *exponents = Formatter_TensExponentTable;
7365 *digitLowerTable = Formatter_DigitLowerTable;
7366 *digitUpperTable = Formatter_DigitUpperTable;
7367 *tenPowersList = Formatter_TenPowersList;
7368 *decHexDigits = Formatter_DecHexDigits;
7372 get_category_data (int version,
7373 guint8 const **category_data,
7374 guint16 const **category_astral_index)
7376 *category_astral_index = NULL;
7378 #ifndef DISABLE_NET_4_0
7380 *category_data = CategoryData_v4;
7381 #ifndef DISABLE_ASTRAL
7382 *category_astral_index = CategoryData_v4_astral_index;
7388 *category_data = CategoryData_v2;
7389 #ifndef DISABLE_ASTRAL
7390 *category_astral_index = CategoryData_v2_astral_index;
7394 /* These parameters are "readonly" in corlib/System/Char.cs */
7396 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7397 guint8 const **category_data,
7398 guint16 const **category_astral_index,
7399 guint8 const **numeric_data,
7400 gdouble const **numeric_data_values,
7401 guint16 const **to_lower_data_low,
7402 guint16 const **to_lower_data_high,
7403 guint16 const **to_upper_data_low,
7404 guint16 const **to_upper_data_high)
7406 get_category_data (category_data_version, category_data, category_astral_index);
7407 *numeric_data = NumericData;
7408 *numeric_data_values = NumericDataValues;
7409 *to_lower_data_low = ToLowerDataLow;
7410 *to_lower_data_high = ToLowerDataHigh;
7411 *to_upper_data_low = ToUpperDataLow;
7412 *to_upper_data_high = ToUpperDataHigh;
7416 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7418 return method->method->token;
7422 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7423 * and avoid useless allocations.
7426 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7430 for (i = 0; i < type->num_mods; ++i) {
7431 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7436 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7438 for (i = 0; i < type->num_mods; ++i) {
7439 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7440 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7441 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7448 ICALL_EXPORT MonoArray*
7449 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7451 MonoType *type = param->ClassImpl->type;
7452 MonoClass *member_class = mono_object_class (param->MemberImpl);
7453 MonoMethod *method = NULL;
7456 MonoMethodSignature *sig;
7458 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7459 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7460 method = rmethod->method;
7461 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7462 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7463 if (!(method = prop->property->get))
7464 method = prop->property->set;
7467 char *type_name = mono_type_get_full_name (member_class);
7468 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7469 MonoException *ex = mono_get_exception_not_supported (msg);
7472 mono_raise_exception (ex);
7475 image = method->klass->image;
7476 pos = param->PositionImpl;
7477 sig = mono_method_signature (method);
7481 type = sig->params [pos];
7483 return type_array_from_modifiers (image, type, optional);
7487 get_property_type (MonoProperty *prop)
7489 MonoMethodSignature *sig;
7491 sig = mono_method_signature (prop->get);
7493 } else if (prop->set) {
7494 sig = mono_method_signature (prop->set);
7495 return sig->params [sig->param_count - 1];
7500 ICALL_EXPORT MonoArray*
7501 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7503 MonoType *type = get_property_type (property->property);
7504 MonoImage *image = property->klass->image;
7508 return type_array_from_modifiers (image, type, optional);
7512 *Construct a MonoType suited to be used to decode a constant blob object.
7514 * @type is the target type which will be constructed
7515 * @blob_type is the blob type, for example, that comes from the constant table
7516 * @real_type is the expected constructed type.
7519 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7521 type->type = blob_type;
7522 type->data.klass = NULL;
7523 if (blob_type == MONO_TYPE_CLASS)
7524 type->data.klass = mono_defaults.object_class;
7525 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7526 /* For enums, we need to use the base type */
7527 type->type = MONO_TYPE_VALUETYPE;
7528 type->data.klass = mono_class_from_mono_type (real_type);
7530 type->data.klass = mono_class_from_mono_type (real_type);
7533 ICALL_EXPORT MonoObject*
7534 property_info_get_default_value (MonoReflectionProperty *property)
7537 MonoProperty *prop = property->property;
7538 MonoType *type = get_property_type (prop);
7539 MonoDomain *domain = mono_object_domain (property);
7540 MonoTypeEnum def_type;
7541 const char *def_value;
7544 mono_class_init (prop->parent);
7546 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7547 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7549 def_value = mono_class_get_property_default_value (prop, &def_type);
7551 mono_type_from_blob_type (&blob_type, def_type, type);
7552 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7557 ICALL_EXPORT MonoBoolean
7558 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7560 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7561 MonoCustomAttrInfo *cinfo;
7564 mono_class_init_or_throw (attr_class);
7566 cinfo = mono_reflection_get_custom_attrs_info (obj);
7569 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7571 mono_custom_attrs_free (cinfo);
7575 ICALL_EXPORT MonoArray*
7576 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7578 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7583 mono_class_init_or_throw (attr_class);
7585 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7586 mono_error_raise_exception (&error);
7588 if (mono_loader_get_last_error ()) {
7589 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7590 g_assert_not_reached ();
7598 ICALL_EXPORT MonoString*
7599 ves_icall_Mono_Runtime_GetDisplayName (void)
7602 MonoString *display_name;
7604 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7605 display_name = mono_string_new (mono_domain_get (), info);
7607 return display_name;
7610 ICALL_EXPORT MonoString*
7611 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7613 MonoString *message;
7617 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7618 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7621 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7623 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7631 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7632 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7633 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7634 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7635 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7636 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7637 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7638 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7642 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7647 gunichar2 last, prev_last, prev2_last;
7654 int havePadding = 0;
7656 last = prev_last = 0, prev2_last = 0;
7657 for (i = 0; i < ilength; i++) {
7659 if (c >= sizeof (dbase64)) {
7660 exc = mono_exception_from_name_msg (mono_get_corlib (),
7661 "System", "FormatException",
7662 "Invalid character found.");
7663 mono_raise_exception (exc);
7664 } else if (isspace (c)) {
7666 } else if (havePadding && c != '=') {
7667 exc = mono_exception_from_name_msg (mono_get_corlib (),
7668 "System", "FormatException",
7669 "Invalid character found.");
7670 mono_raise_exception (exc);
7672 if (c == '=') havePadding = 1;
7673 prev2_last = prev_last;
7679 olength = ilength - ignored;
7681 if (allowWhitespaceOnly && olength == 0) {
7682 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7685 if ((olength & 3) != 0 || olength <= 0) {
7686 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7687 "FormatException", "Invalid length.");
7688 mono_raise_exception (exc);
7691 if (prev2_last == '=') {
7692 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7693 mono_raise_exception (exc);
7696 olength = (olength * 3) / 4;
7700 if (prev_last == '=')
7703 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7704 res_ptr = mono_array_addr (result, guchar, 0);
7705 for (i = 0; i < ilength; ) {
7708 for (k = 0; k < 4 && i < ilength;) {
7714 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7715 exc = mono_exception_from_name_msg (mono_get_corlib (),
7716 "System", "FormatException",
7717 "Invalid character found.");
7718 mono_raise_exception (exc);
7723 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7725 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7727 *res_ptr++ = (b [2] << 6) | b [3];
7729 while (i < ilength && isspace (start [i]))
7736 ICALL_EXPORT MonoArray *
7737 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7739 MONO_ARCH_SAVE_REGS;
7741 return base64_to_byte_array (mono_string_chars (str),
7742 mono_string_length (str), allowWhitespaceOnly);
7745 ICALL_EXPORT MonoArray *
7746 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7748 MONO_ARCH_SAVE_REGS;
7750 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7754 #ifndef DISABLE_ICALL_TABLES
7756 #define ICALL_TYPE(id,name,first)
7757 #define ICALL(id,name,func) Icall_ ## id,
7760 #include "metadata/icall-def.h"
7766 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7767 #define ICALL(id,name,func)
7769 #include "metadata/icall-def.h"
7775 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7776 #define ICALL(id,name,func)
7778 guint16 first_icall;
7781 static const IcallTypeDesc
7782 icall_type_descs [] = {
7783 #include "metadata/icall-def.h"
7787 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7790 #define ICALL_TYPE(id,name,first)
7793 #ifdef HAVE_ARRAY_ELEM_INIT
7794 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7795 #define MSGSTRFIELD1(line) str##line
7797 static const struct msgstrtn_t {
7798 #define ICALL(id,name,func)
7800 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7801 #include "metadata/icall-def.h"
7803 } icall_type_names_str = {
7804 #define ICALL_TYPE(id,name,first) (name),
7805 #include "metadata/icall-def.h"
7808 static const guint16 icall_type_names_idx [] = {
7809 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7810 #include "metadata/icall-def.h"
7813 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7815 static const struct msgstr_t {
7817 #define ICALL_TYPE(id,name,first)
7818 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7819 #include "metadata/icall-def.h"
7821 } icall_names_str = {
7822 #define ICALL(id,name,func) (name),
7823 #include "metadata/icall-def.h"
7826 static const guint16 icall_names_idx [] = {
7827 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7828 #include "metadata/icall-def.h"
7831 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7837 #define ICALL_TYPE(id,name,first) name,
7838 #define ICALL(id,name,func)
7839 static const char* const
7840 icall_type_names [] = {
7841 #include "metadata/icall-def.h"
7845 #define icall_type_name_get(id) (icall_type_names [(id)])
7849 #define ICALL_TYPE(id,name,first)
7850 #define ICALL(id,name,func) name,
7851 static const char* const
7853 #include "metadata/icall-def.h"
7856 #define icall_name_get(id) icall_names [(id)]
7858 #endif /* !HAVE_ARRAY_ELEM_INIT */
7862 #define ICALL_TYPE(id,name,first)
7863 #define ICALL(id,name,func) func,
7864 static const gconstpointer
7865 icall_functions [] = {
7866 #include "metadata/icall-def.h"
7870 #ifdef ENABLE_ICALL_SYMBOL_MAP
7873 #define ICALL_TYPE(id,name,first)
7874 #define ICALL(id,name,func) #func,
7875 static const gconstpointer
7876 icall_symbols [] = {
7877 #include "metadata/icall-def.h"
7882 #endif /* DISABLE_ICALL_TABLES */
7884 static mono_mutex_t icall_mutex;
7885 static GHashTable *icall_hash = NULL;
7886 static GHashTable *jit_icall_hash_name = NULL;
7887 static GHashTable *jit_icall_hash_addr = NULL;
7890 mono_icall_init (void)
7892 #ifndef DISABLE_ICALL_TABLES
7895 /* check that tables are sorted: disable in release */
7898 const char *prev_class = NULL;
7899 const char *prev_method;
7901 for (i = 0; i < Icall_type_num; ++i) {
7902 const IcallTypeDesc *desc;
7905 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7906 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7907 prev_class = icall_type_name_get (i);
7908 desc = &icall_type_descs [i];
7909 num_icalls = icall_desc_num_icalls (desc);
7910 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7911 for (j = 0; j < num_icalls; ++j) {
7912 const char *methodn = icall_name_get (desc->first_icall + j);
7913 if (prev_method && strcmp (prev_method, methodn) >= 0)
7914 g_print ("method %s should come before method %s\n", methodn, prev_method);
7915 prev_method = methodn;
7921 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7922 mono_mutex_init (&icall_mutex);
7926 mono_icall_lock (void)
7928 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7932 mono_icall_unlock (void)
7934 mono_locks_mutex_release (&icall_mutex, IcallLock);
7938 mono_icall_cleanup (void)
7940 g_hash_table_destroy (icall_hash);
7941 g_hash_table_destroy (jit_icall_hash_name);
7942 g_hash_table_destroy (jit_icall_hash_addr);
7943 mono_mutex_destroy (&icall_mutex);
7947 mono_add_internal_call (const char *name, gconstpointer method)
7951 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7953 mono_icall_unlock ();
7956 #ifndef DISABLE_ICALL_TABLES
7958 #ifdef HAVE_ARRAY_ELEM_INIT
7960 compare_method_imap (const void *key, const void *elem)
7962 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7963 return strcmp (key, method_name);
7967 find_method_icall (const IcallTypeDesc *imap, const char *name)
7969 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);
7972 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7976 compare_class_imap (const void *key, const void *elem)
7978 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7979 return strcmp (key, class_name);
7982 static const IcallTypeDesc*
7983 find_class_icalls (const char *name)
7985 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7988 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7991 #else /* HAVE_ARRAY_ELEM_INIT */
7994 compare_method_imap (const void *key, const void *elem)
7996 const char** method_name = (const char**)elem;
7997 return strcmp (key, *method_name);
8001 find_method_icall (const IcallTypeDesc *imap, const char *name)
8003 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8006 return (gpointer)icall_functions [(nameslot - icall_names)];
8010 compare_class_imap (const void *key, const void *elem)
8012 const char** class_name = (const char**)elem;
8013 return strcmp (key, *class_name);
8016 static const IcallTypeDesc*
8017 find_class_icalls (const char *name)
8019 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8022 return &icall_type_descs [nameslot - icall_type_names];
8025 #endif /* HAVE_ARRAY_ELEM_INIT */
8027 #endif /* DISABLE_ICALL_TABLES */
8030 * we should probably export this as an helper (handle nested types).
8031 * Returns the number of chars written in buf.
8034 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8036 int nspacelen, cnamelen;
8037 nspacelen = strlen (klass->name_space);
8038 cnamelen = strlen (klass->name);
8039 if (nspacelen + cnamelen + 2 > bufsize)
8042 memcpy (buf, klass->name_space, nspacelen);
8043 buf [nspacelen ++] = '.';
8045 memcpy (buf + nspacelen, klass->name, cnamelen);
8046 buf [nspacelen + cnamelen] = 0;
8047 return nspacelen + cnamelen;
8050 #ifdef DISABLE_ICALL_TABLES
8052 no_icall_table (void)
8054 g_assert_not_reached ();
8059 mono_lookup_internal_call (MonoMethod *method)
8064 int typelen = 0, mlen, siglen;
8066 #ifndef DISABLE_ICALL_TABLES
8067 const IcallTypeDesc *imap = NULL;
8070 g_assert (method != NULL);
8072 if (method->is_inflated)
8073 method = ((MonoMethodInflated *) method)->declaring;
8075 if (method->klass->nested_in) {
8076 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8080 mname [pos++] = '/';
8083 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8089 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8094 #ifndef DISABLE_ICALL_TABLES
8095 imap = find_class_icalls (mname);
8098 mname [typelen] = ':';
8099 mname [typelen + 1] = ':';
8101 mlen = strlen (method->name);
8102 memcpy (mname + typelen + 2, method->name, mlen);
8103 sigstart = mname + typelen + 2 + mlen;
8106 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8107 siglen = strlen (tmpsig);
8108 if (typelen + mlen + siglen + 6 > sizeof (mname))
8111 memcpy (sigstart + 1, tmpsig, siglen);
8112 sigstart [siglen + 1] = ')';
8113 sigstart [siglen + 2] = 0;
8118 res = g_hash_table_lookup (icall_hash, mname);
8120 mono_icall_unlock ();;
8123 /* try without signature */
8125 res = g_hash_table_lookup (icall_hash, mname);
8127 mono_icall_unlock ();
8131 #ifdef DISABLE_ICALL_TABLES
8132 mono_icall_unlock ();
8133 /* Fail only when the result is actually used */
8134 /* mono_marshal_get_native_wrapper () depends on this */
8135 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8136 return ves_icall_System_String_ctor_RedirectToCreateString;
8138 return no_icall_table;
8140 /* it wasn't found in the static call tables */
8142 mono_icall_unlock ();
8145 res = find_method_icall (imap, sigstart - mlen);
8147 mono_icall_unlock ();
8150 /* try _with_ signature */
8152 res = find_method_icall (imap, sigstart - mlen);
8154 mono_icall_unlock ();
8158 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8159 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8160 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8161 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8162 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");
8163 g_print ("If you see other errors or faults after this message they are probably related\n");
8164 g_print ("and you need to fix your mono install first.\n");
8166 mono_icall_unlock ();
8172 #ifdef ENABLE_ICALL_SYMBOL_MAP
8174 func_cmp (gconstpointer key, gconstpointer p)
8176 return (gsize)key - (gsize)*(gsize*)p;
8181 * mono_lookup_icall_symbol:
8183 * Given the icall METHOD, returns its C symbol.
8186 mono_lookup_icall_symbol (MonoMethod *m)
8188 #ifdef DISABLE_ICALL_TABLES
8189 g_assert_not_reached ();
8192 #ifdef ENABLE_ICALL_SYMBOL_MAP
8196 static gconstpointer *functions_sorted;
8197 static const char**symbols_sorted;
8198 static gboolean inited;
8203 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8204 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8205 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8206 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8207 /* Bubble sort the two arrays */
8211 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8212 if (functions_sorted [i] > functions_sorted [i + 1]) {
8215 tmp = functions_sorted [i];
8216 functions_sorted [i] = functions_sorted [i + 1];
8217 functions_sorted [i + 1] = tmp;
8218 tmp = symbols_sorted [i];
8219 symbols_sorted [i] = symbols_sorted [i + 1];
8220 symbols_sorted [i + 1] = tmp;
8227 func = mono_lookup_internal_call (m);
8230 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8234 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8236 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8237 g_assert_not_reached ();
8244 type_from_typename (char *typename)
8246 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8248 if (!strcmp (typename, "int"))
8249 klass = mono_defaults.int_class;
8250 else if (!strcmp (typename, "ptr"))
8251 klass = mono_defaults.int_class;
8252 else if (!strcmp (typename, "void"))
8253 klass = mono_defaults.void_class;
8254 else if (!strcmp (typename, "int32"))
8255 klass = mono_defaults.int32_class;
8256 else if (!strcmp (typename, "uint32"))
8257 klass = mono_defaults.uint32_class;
8258 else if (!strcmp (typename, "int8"))
8259 klass = mono_defaults.sbyte_class;
8260 else if (!strcmp (typename, "uint8"))
8261 klass = mono_defaults.byte_class;
8262 else if (!strcmp (typename, "int16"))
8263 klass = mono_defaults.int16_class;
8264 else if (!strcmp (typename, "uint16"))
8265 klass = mono_defaults.uint16_class;
8266 else if (!strcmp (typename, "long"))
8267 klass = mono_defaults.int64_class;
8268 else if (!strcmp (typename, "ulong"))
8269 klass = mono_defaults.uint64_class;
8270 else if (!strcmp (typename, "float"))
8271 klass = mono_defaults.single_class;
8272 else if (!strcmp (typename, "double"))
8273 klass = mono_defaults.double_class;
8274 else if (!strcmp (typename, "object"))
8275 klass = mono_defaults.object_class;
8276 else if (!strcmp (typename, "obj"))
8277 klass = mono_defaults.object_class;
8278 else if (!strcmp (typename, "string"))
8279 klass = mono_defaults.string_class;
8280 else if (!strcmp (typename, "bool"))
8281 klass = mono_defaults.boolean_class;
8282 else if (!strcmp (typename, "boolean"))
8283 klass = mono_defaults.boolean_class;
8285 g_error ("%s", typename);
8286 g_assert_not_reached ();
8288 return &klass->byval_arg;
8292 * LOCKING: Take the corlib image lock.
8294 MonoMethodSignature*
8295 mono_create_icall_signature (const char *sigstr)
8300 MonoMethodSignature *res, *res2;
8301 MonoImage *corlib = mono_defaults.corlib;
8303 mono_image_lock (corlib);
8304 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8305 mono_image_unlock (corlib);
8310 parts = g_strsplit (sigstr, " ", 256);
8319 res = mono_metadata_signature_alloc (corlib, len - 1);
8324 * Under windows, the default pinvoke calling convention is STDCALL but
8327 res->call_convention = MONO_CALL_C;
8330 res->ret = type_from_typename (parts [0]);
8331 for (i = 1; i < len; ++i) {
8332 res->params [i - 1] = type_from_typename (parts [i]);
8337 mono_image_lock (corlib);
8338 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8340 res = res2; /*Value is allocated in the image pool*/
8342 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8343 mono_image_unlock (corlib);
8349 mono_find_jit_icall_by_name (const char *name)
8351 MonoJitICallInfo *info;
8352 g_assert (jit_icall_hash_name);
8355 info = g_hash_table_lookup (jit_icall_hash_name, name);
8356 mono_icall_unlock ();
8361 mono_find_jit_icall_by_addr (gconstpointer addr)
8363 MonoJitICallInfo *info;
8364 g_assert (jit_icall_hash_addr);
8367 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8368 mono_icall_unlock ();
8374 * mono_get_jit_icall_info:
8376 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8377 * caller should access it while holding the icall lock.
8380 mono_get_jit_icall_info (void)
8382 return jit_icall_hash_name;
8386 * mono_lookup_jit_icall_symbol:
8388 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8391 mono_lookup_jit_icall_symbol (const char *name)
8393 MonoJitICallInfo *info;
8394 const char *res = NULL;
8397 info = g_hash_table_lookup (jit_icall_hash_name, name);
8399 res = info->c_symbol;
8400 mono_icall_unlock ();
8405 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8408 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8409 mono_icall_unlock ();
8413 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8415 MonoJitICallInfo *info;
8422 if (!jit_icall_hash_name) {
8423 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8424 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8427 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8428 g_warning ("jit icall already defined \"%s\"\n", name);
8429 g_assert_not_reached ();
8432 info = g_new0 (MonoJitICallInfo, 1);
8437 info->c_symbol = c_symbol;
8440 info->wrapper = func;
8442 info->wrapper = NULL;
8445 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8446 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8448 mono_icall_unlock ();
8453 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8455 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);