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);
1753 return field->field->offset - sizeof (MonoObject);
1756 ICALL_EXPORT MonoReflectionType*
1757 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1760 MONO_ARCH_SAVE_REGS;
1762 parent = declaring? field->field->parent: field->klass;
1764 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1767 ICALL_EXPORT MonoObject *
1768 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1770 MonoClass *fklass = field->klass;
1771 MonoClassField *cf = field->field;
1772 MonoDomain *domain = mono_object_domain (field);
1774 if (fklass->image->assembly->ref_only)
1775 mono_raise_exception (mono_get_exception_invalid_operation (
1776 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1778 if (mono_security_core_clr_enabled ())
1779 mono_security_core_clr_ensure_reflection_access_field (cf);
1781 return mono_field_get_value_object (domain, cf, obj);
1785 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1788 MonoClassField *cf = field->field;
1792 MONO_ARCH_SAVE_REGS;
1794 if (field->klass->image->assembly->ref_only)
1795 mono_raise_exception (mono_get_exception_invalid_operation (
1796 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1798 if (mono_security_core_clr_enabled ())
1799 mono_security_core_clr_ensure_reflection_access_field (cf);
1801 type = mono_field_get_type_checked (cf, &error);
1802 if (!mono_error_ok (&error))
1803 mono_error_raise_exception (&error);
1805 v = (gchar *) value;
1807 switch (type->type) {
1810 case MONO_TYPE_BOOLEAN:
1813 case MONO_TYPE_CHAR:
1822 case MONO_TYPE_VALUETYPE:
1825 v += sizeof (MonoObject);
1827 case MONO_TYPE_STRING:
1828 case MONO_TYPE_OBJECT:
1829 case MONO_TYPE_CLASS:
1830 case MONO_TYPE_ARRAY:
1831 case MONO_TYPE_SZARRAY:
1834 case MONO_TYPE_GENERICINST: {
1835 MonoGenericClass *gclass = type->data.generic_class;
1836 g_assert (!gclass->context.class_inst->is_open);
1838 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1839 MonoClass *nklass = mono_class_from_mono_type (type);
1840 MonoObject *nullable;
1843 * Convert the boxed vtype into a Nullable structure.
1844 * This is complicated by the fact that Nullables have
1845 * a variable structure.
1847 nullable = mono_object_new (mono_domain_get (), nklass);
1849 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1851 v = mono_object_unbox (nullable);
1854 if (gclass->container_class->valuetype && (v != NULL))
1855 v += sizeof (MonoObject);
1859 g_error ("type 0x%x not handled in "
1860 "ves_icall_FieldInfo_SetValueInternal", type->type);
1865 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1866 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1867 if (!vtable->initialized)
1868 mono_runtime_class_init (vtable);
1869 mono_field_static_set_value (vtable, cf, v);
1871 mono_field_set_value (obj, cf, v);
1875 ICALL_EXPORT MonoObject *
1876 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1878 MonoObject *o = NULL;
1879 MonoClassField *field = this->field;
1881 MonoDomain *domain = mono_object_domain (this);
1883 MonoTypeEnum def_type;
1884 const char *def_value;
1888 MONO_ARCH_SAVE_REGS;
1890 mono_class_init (field->parent);
1892 t = mono_field_get_type_checked (field, &error);
1893 if (!mono_error_ok (&error))
1894 mono_error_raise_exception (&error);
1896 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1897 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1899 if (image_is_dynamic (field->parent->image)) {
1901 g_assert_not_reached ();
1904 def_value = mono_class_get_field_default_value (field, &def_type);
1905 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1906 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1908 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1912 case MONO_TYPE_BOOLEAN:
1915 case MONO_TYPE_CHAR:
1923 case MONO_TYPE_R8: {
1926 /* boxed value type */
1927 t = g_new0 (MonoType, 1);
1929 klass = mono_class_from_mono_type (t);
1931 o = mono_object_new (domain, klass);
1932 v = ((gchar *) o) + sizeof (MonoObject);
1933 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1936 case MONO_TYPE_STRING:
1937 case MONO_TYPE_CLASS:
1938 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1941 g_assert_not_reached ();
1947 ICALL_EXPORT MonoReflectionType*
1948 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1951 MonoClassField *field = ref_field->field;
1952 MonoType *type = mono_field_get_type_checked (field, &error);
1953 if (!mono_error_ok (&error))
1954 mono_error_raise_exception (&error);
1955 return mono_type_get_object (mono_object_domain (ref_field), type);
1958 ICALL_EXPORT MonoReflectionType*
1959 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1961 MonoMethod *method = rmethod->method.method;
1963 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1966 /* From MonoProperty.cs */
1968 PInfo_Attributes = 1,
1969 PInfo_GetMethod = 1 << 1,
1970 PInfo_SetMethod = 1 << 2,
1971 PInfo_ReflectedType = 1 << 3,
1972 PInfo_DeclaringType = 1 << 4,
1977 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1979 MonoDomain *domain = mono_object_domain (property);
1981 MONO_ARCH_SAVE_REGS;
1983 if ((req_info & PInfo_ReflectedType) != 0)
1984 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1985 if ((req_info & PInfo_DeclaringType) != 0)
1986 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1988 if ((req_info & PInfo_Name) != 0)
1989 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1991 if ((req_info & PInfo_Attributes) != 0)
1992 info->attrs = property->property->attrs;
1994 if ((req_info & PInfo_GetMethod) != 0)
1995 MONO_STRUCT_SETREF (info, get, property->property->get ?
1996 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1998 if ((req_info & PInfo_SetMethod) != 0)
1999 MONO_STRUCT_SETREF (info, set, property->property->set ?
2000 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2002 * There may be other methods defined for properties, though, it seems they are not exposed
2003 * in the reflection API
2008 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2010 MonoDomain *domain = mono_object_domain (event);
2012 MONO_ARCH_SAVE_REGS;
2014 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2015 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2017 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2018 info->attrs = event->event->attrs;
2019 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2020 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2021 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2023 #ifndef MONO_SMALL_CONFIG
2024 if (event->event->other) {
2026 while (event->event->other [n])
2028 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2030 for (i = 0; i < n; i++)
2031 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2037 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2042 mono_class_setup_interfaces (klass, error);
2043 if (!mono_error_ok (error))
2046 for (i = 0; i < klass->interface_count; i++) {
2047 ic = klass->interfaces [i];
2048 g_hash_table_insert (ifaces, ic, ic);
2050 collect_interfaces (ic, ifaces, error);
2051 if (!mono_error_ok (error))
2057 MonoArray *iface_array;
2058 MonoGenericContext *context;
2062 } FillIfaceArrayData;
2065 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2067 FillIfaceArrayData *data = user_data;
2068 MonoClass *ic = key;
2069 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2071 if (!mono_error_ok (data->error))
2074 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2075 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2076 if (!mono_error_ok (data->error))
2080 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2083 mono_metadata_free_type (inflated);
2086 ICALL_EXPORT MonoArray*
2087 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2090 MonoClass *class = mono_class_from_mono_type (type->type);
2092 FillIfaceArrayData data = { 0 };
2095 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2097 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2098 data.context = mono_class_get_context (class);
2099 class = class->generic_class->container_class;
2102 for (parent = class; parent; parent = parent->parent) {
2103 mono_class_setup_interfaces (parent, &error);
2104 if (!mono_error_ok (&error))
2106 collect_interfaces (parent, iface_hash, &error);
2107 if (!mono_error_ok (&error))
2111 data.error = &error;
2112 data.domain = mono_object_domain (type);
2114 len = g_hash_table_size (iface_hash);
2116 g_hash_table_destroy (iface_hash);
2117 if (!data.domain->empty_types)
2118 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2119 return data.domain->empty_types;
2122 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2123 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2124 if (!mono_error_ok (&error))
2127 g_hash_table_destroy (iface_hash);
2128 return data.iface_array;
2131 g_hash_table_destroy (iface_hash);
2132 mono_error_raise_exception (&error);
2137 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2139 gboolean variance_used;
2140 MonoClass *class = mono_class_from_mono_type (type->type);
2141 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2142 MonoReflectionMethod *member;
2145 int i = 0, len, ioffset;
2148 MONO_ARCH_SAVE_REGS;
2149 mono_class_init_or_throw (class);
2150 mono_class_init_or_throw (iclass);
2152 mono_class_setup_vtable (class);
2154 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2158 len = mono_class_num_methods (iclass);
2159 domain = mono_object_domain (type);
2160 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2161 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2163 while ((method = mono_class_get_methods (iclass, &iter))) {
2164 member = mono_method_get_object (domain, method, iclass);
2165 mono_array_setref (*methods, i, member);
2166 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2167 mono_array_setref (*targets, i, member);
2174 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2176 MonoClass *klass = mono_class_from_mono_type (type->type);
2177 mono_class_init_or_throw (klass);
2179 if (image_is_dynamic (klass->image)) {
2180 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2181 *packing = tb->packing_size;
2182 *size = tb->class_size;
2184 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2188 ICALL_EXPORT MonoReflectionType*
2189 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2193 MONO_ARCH_SAVE_REGS;
2195 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2196 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2198 class = mono_class_from_mono_type (type->type);
2199 mono_class_init_or_throw (class);
2201 // GetElementType should only return a type for:
2202 // Array Pointer PassedByRef
2203 if (type->type->byref)
2204 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2205 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2206 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2207 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2208 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2213 ICALL_EXPORT MonoReflectionType*
2214 ves_icall_get_type_parent (MonoReflectionType *type)
2216 MonoClass *class = mono_class_from_mono_type (type->type);
2217 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2220 ICALL_EXPORT MonoBoolean
2221 ves_icall_type_ispointer (MonoReflectionType *type)
2223 MONO_ARCH_SAVE_REGS;
2225 return type->type->type == MONO_TYPE_PTR;
2228 ICALL_EXPORT MonoBoolean
2229 ves_icall_type_isprimitive (MonoReflectionType *type)
2231 MONO_ARCH_SAVE_REGS;
2233 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)));
2236 ICALL_EXPORT MonoBoolean
2237 ves_icall_type_isbyref (MonoReflectionType *type)
2239 MONO_ARCH_SAVE_REGS;
2241 return type->type->byref;
2244 ICALL_EXPORT MonoBoolean
2245 ves_icall_type_iscomobject (MonoReflectionType *type)
2247 MonoClass *klass = mono_class_from_mono_type (type->type);
2248 mono_class_init_or_throw (klass);
2250 return mono_class_is_com_object (klass);
2253 ICALL_EXPORT MonoReflectionModule*
2254 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2256 MonoClass *class = mono_class_from_mono_type (type->type);
2257 return mono_module_get_object (mono_object_domain (type), class->image);
2260 ICALL_EXPORT MonoReflectionAssembly*
2261 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2263 MonoDomain *domain = mono_domain_get ();
2264 MonoClass *class = mono_class_from_mono_type (type->type);
2265 return mono_assembly_get_object (domain, class->image->assembly);
2268 ICALL_EXPORT MonoReflectionType*
2269 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2271 MonoDomain *domain = mono_domain_get ();
2274 MONO_ARCH_SAVE_REGS;
2276 if (type->type->byref)
2278 if (type->type->type == MONO_TYPE_VAR) {
2279 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2280 class = param ? param->owner.klass : NULL;
2281 } else if (type->type->type == MONO_TYPE_MVAR) {
2282 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2283 class = param ? param->owner.method->klass : NULL;
2285 class = mono_class_from_mono_type (type->type)->nested_in;
2288 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2291 ICALL_EXPORT MonoString*
2292 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2294 MonoDomain *domain = mono_domain_get ();
2295 MonoClass *class = mono_class_from_mono_type (type->type);
2297 if (type->type->byref) {
2298 char *n = g_strdup_printf ("%s&", class->name);
2299 MonoString *res = mono_string_new (domain, n);
2305 return mono_string_new (domain, class->name);
2309 ICALL_EXPORT MonoString*
2310 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2312 MonoDomain *domain = mono_domain_get ();
2313 MonoClass *class = mono_class_from_mono_type (type->type);
2315 while (class->nested_in)
2316 class = class->nested_in;
2318 if (class->name_space [0] == '\0')
2321 return mono_string_new (domain, class->name_space);
2325 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2329 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2330 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2332 class = mono_class_from_mono_type (type->type);
2337 ICALL_EXPORT MonoArray*
2338 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2341 MonoClass *klass, *pklass;
2342 MonoDomain *domain = mono_object_domain (type);
2343 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2345 MONO_ARCH_SAVE_REGS;
2347 klass = mono_class_from_mono_type (type->type);
2349 if (klass->generic_container) {
2350 MonoGenericContainer *container = klass->generic_container;
2351 res = mono_array_new_specific (array_vtable, container->type_argc);
2352 for (i = 0; i < container->type_argc; ++i) {
2353 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2354 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2356 } else if (klass->generic_class) {
2357 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2358 res = mono_array_new_specific (array_vtable, inst->type_argc);
2359 for (i = 0; i < inst->type_argc; ++i)
2360 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2362 res = mono_array_new_specific (array_vtable, 0);
2367 ICALL_EXPORT gboolean
2368 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2371 MONO_ARCH_SAVE_REGS;
2373 if (!IS_MONOTYPE (type))
2376 if (type->type->byref)
2379 klass = mono_class_from_mono_type (type->type);
2380 return klass->generic_container != NULL;
2383 ICALL_EXPORT MonoReflectionType*
2384 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2387 MONO_ARCH_SAVE_REGS;
2389 if (type->type->byref)
2392 klass = mono_class_from_mono_type (type->type);
2394 if (klass->generic_container) {
2395 return type; /* check this one */
2397 if (klass->generic_class) {
2398 MonoClass *generic_class = klass->generic_class->container_class;
2401 tb = mono_class_get_ref_info (generic_class);
2403 if (generic_class->wastypebuilder && tb)
2406 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2411 ICALL_EXPORT MonoReflectionType*
2412 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2415 MonoType *geninst, **types;
2418 g_assert (IS_MONOTYPE (type));
2419 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2421 count = mono_array_length (type_array);
2422 types = g_new0 (MonoType *, count);
2424 for (i = 0; i < count; i++) {
2425 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2426 types [i] = t->type;
2429 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2434 class = mono_class_from_mono_type (geninst);
2436 /*we might inflate to the GTD*/
2437 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2438 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2440 return mono_type_get_object (mono_object_domain (type), geninst);
2443 ICALL_EXPORT gboolean
2444 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2447 MONO_ARCH_SAVE_REGS;
2449 if (type->type->byref)
2452 klass = mono_class_from_mono_type (type->type);
2454 return klass->generic_class != NULL;
2457 ICALL_EXPORT gboolean
2458 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2461 MONO_ARCH_SAVE_REGS;
2463 if (!IS_MONOTYPE (type))
2466 if (type->type->byref)
2469 klass = mono_class_from_mono_type (type->type);
2470 return klass->generic_class != NULL || klass->generic_container != NULL;
2474 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2476 MONO_ARCH_SAVE_REGS;
2478 if (!IS_MONOTYPE (type))
2481 if (is_generic_parameter (type->type))
2482 return mono_type_get_generic_param_num (type->type);
2486 ICALL_EXPORT GenericParameterAttributes
2487 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2489 MONO_ARCH_SAVE_REGS;
2491 g_assert (IS_MONOTYPE (type));
2492 g_assert (is_generic_parameter (type->type));
2493 return mono_generic_param_info (type->type->data.generic_param)->flags;
2496 ICALL_EXPORT MonoArray *
2497 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2499 MonoGenericParamInfo *param_info;
2505 MONO_ARCH_SAVE_REGS;
2507 g_assert (IS_MONOTYPE (type));
2509 domain = mono_object_domain (type);
2510 param_info = mono_generic_param_info (type->type->data.generic_param);
2511 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2514 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2515 for (i = 0; i < count; i++)
2516 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2522 ICALL_EXPORT MonoBoolean
2523 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2525 MONO_ARCH_SAVE_REGS;
2526 return is_generic_parameter (type->type);
2529 ICALL_EXPORT MonoBoolean
2530 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2532 MONO_ARCH_SAVE_REGS;
2533 return is_generic_parameter (tb->type.type);
2537 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2538 MonoReflectionType *t)
2540 enumtype->type = t->type;
2543 ICALL_EXPORT MonoReflectionMethod*
2544 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2545 MonoReflectionMethod* generic)
2552 MONO_ARCH_SAVE_REGS;
2554 domain = ((MonoObject *)type)->vtable->domain;
2556 klass = mono_class_from_mono_type (type->type);
2557 mono_class_init_or_throw (klass);
2560 while ((method = mono_class_get_methods (klass, &iter))) {
2561 if (method->token == generic->method->token)
2562 return mono_method_get_object (domain, method, klass);
2570 ICALL_EXPORT MonoReflectionMethod *
2571 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2574 MonoType *type = ref_type->type;
2576 MONO_ARCH_SAVE_REGS;
2578 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2579 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2580 if (type->type == MONO_TYPE_VAR)
2583 method = mono_type_get_generic_param_owner (type)->owner.method;
2585 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2588 ICALL_EXPORT MonoReflectionDllImportAttribute*
2589 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2591 static MonoClass *DllImportAttributeClass = NULL;
2592 MonoDomain *domain = mono_domain_get ();
2593 MonoReflectionDllImportAttribute *attr;
2594 MonoImage *image = method->klass->image;
2595 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2596 MonoTableInfo *tables = image->tables;
2597 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2598 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2599 guint32 im_cols [MONO_IMPLMAP_SIZE];
2600 guint32 scope_token;
2601 const char *import = NULL;
2602 const char *scope = NULL;
2605 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2608 if (!DllImportAttributeClass) {
2609 DllImportAttributeClass =
2610 mono_class_from_name (mono_defaults.corlib,
2611 "System.Runtime.InteropServices", "DllImportAttribute");
2612 g_assert (DllImportAttributeClass);
2615 if (image_is_dynamic (method->klass->image)) {
2616 MonoReflectionMethodAux *method_aux =
2617 g_hash_table_lookup (
2618 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2620 import = method_aux->dllentry;
2621 scope = method_aux->dll;
2624 if (!import || !scope) {
2625 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2630 if (piinfo->implmap_idx) {
2631 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2633 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2634 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2635 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2636 scope = mono_metadata_string_heap (image, scope_token);
2639 flags = piinfo->piflags;
2641 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2643 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2644 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2645 attr->call_conv = (flags & 0x700) >> 8;
2646 attr->charset = ((flags & 0x6) >> 1) + 1;
2647 if (attr->charset == 1)
2649 attr->exact_spelling = (flags & 0x1) != 0;
2650 attr->set_last_error = (flags & 0x40) != 0;
2651 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2652 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2653 attr->preserve_sig = FALSE;
2658 ICALL_EXPORT MonoReflectionMethod *
2659 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2661 MonoMethodInflated *imethod;
2664 MONO_ARCH_SAVE_REGS;
2666 if (method->method->is_generic)
2669 if (!method->method->is_inflated)
2672 imethod = (MonoMethodInflated *) method->method;
2674 result = imethod->declaring;
2675 /* Not a generic method. */
2676 if (!result->is_generic)
2679 if (image_is_dynamic (method->method->klass->image)) {
2680 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2681 MonoReflectionMethod *res;
2684 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2685 * the dynamic case as well ?
2687 mono_image_lock ((MonoImage*)image);
2688 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2689 mono_image_unlock ((MonoImage*)image);
2695 if (imethod->context.class_inst) {
2696 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2697 /*Generic methods gets the context of the GTD.*/
2698 if (mono_class_get_context (klass))
2699 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2702 return mono_method_get_object (mono_object_domain (method), result, NULL);
2705 ICALL_EXPORT gboolean
2706 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2708 MONO_ARCH_SAVE_REGS;
2710 return mono_method_signature (method->method)->generic_param_count != 0;
2713 ICALL_EXPORT gboolean
2714 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2716 MONO_ARCH_SAVE_REGS;
2718 return method->method->is_generic;
2721 ICALL_EXPORT MonoArray*
2722 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2727 MONO_ARCH_SAVE_REGS;
2729 domain = mono_object_domain (method);
2731 if (method->method->is_inflated) {
2732 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2735 count = inst->type_argc;
2736 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2738 for (i = 0; i < count; i++)
2739 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2745 count = mono_method_signature (method->method)->generic_param_count;
2746 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2748 for (i = 0; i < count; i++) {
2749 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2750 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2751 MonoClass *pklass = mono_class_from_generic_parameter (
2752 param, method->method->klass->image, TRUE);
2753 mono_array_setref (res, i,
2754 mono_type_get_object (domain, &pklass->byval_arg));
2760 ICALL_EXPORT MonoObject *
2761 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2764 * Invoke from reflection is supposed to always be a virtual call (the API
2765 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2766 * greater flexibility.
2768 MonoMethod *m = method->method;
2769 MonoMethodSignature *sig = mono_method_signature (m);
2774 MONO_ARCH_SAVE_REGS;
2778 if (mono_security_core_clr_enabled ())
2779 mono_security_core_clr_ensure_reflection_access_method (m);
2781 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2782 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2783 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2788 if (!mono_object_isinst (this, m->klass)) {
2789 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2790 char *target_name = mono_type_get_full_name (m->klass);
2791 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2792 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2794 g_free (target_name);
2798 m = mono_object_get_virtual_method (this, m);
2799 /* must pass the pointer to the value for valuetype methods */
2800 if (m->klass->valuetype)
2801 obj = mono_object_unbox (this);
2802 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2803 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2808 if (sig->ret->byref) {
2809 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"));
2813 pcount = params? mono_array_length (params): 0;
2814 if (pcount != sig->param_count) {
2815 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2819 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2820 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."));
2824 image = m->klass->image;
2825 if (image->assembly->ref_only) {
2826 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."));
2830 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2831 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2835 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2838 intptr_t *lower_bounds;
2839 pcount = mono_array_length (params);
2840 lengths = alloca (sizeof (uintptr_t) * pcount);
2841 /* Note: the synthetized array .ctors have int32 as argument type */
2842 for (i = 0; i < pcount; ++i)
2843 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2845 if (m->klass->rank == pcount) {
2846 /* Only lengths provided. */
2847 lower_bounds = NULL;
2849 g_assert (pcount == (m->klass->rank * 2));
2850 /* lower bounds are first. */
2851 lower_bounds = (intptr_t*)lengths;
2852 lengths += m->klass->rank;
2855 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2857 return mono_runtime_invoke_array (m, obj, params, NULL);
2860 #ifndef DISABLE_REMOTING
2861 ICALL_EXPORT MonoObject *
2862 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2864 MonoDomain *domain = mono_object_domain (method);
2865 MonoMethod *m = method->method;
2866 MonoMethodSignature *sig = mono_method_signature (m);
2867 MonoArray *out_args;
2869 int i, j, outarg_count = 0;
2871 MONO_ARCH_SAVE_REGS;
2873 if (m->klass == mono_defaults.object_class) {
2875 if (!strcmp (m->name, "FieldGetter")) {
2876 MonoClass *k = this->vtable->klass;
2880 /* If this is a proxy, then it must be a CBO */
2881 if (k == mono_defaults.transparent_proxy_class) {
2882 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2883 this = tp->rp->unwrapped_server;
2885 k = this->vtable->klass;
2888 name = mono_array_get (params, MonoString *, 1);
2889 str = mono_string_to_utf8 (name);
2892 MonoClassField* field = mono_class_get_field_from_name (k, str);
2894 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2895 if (field_klass->valuetype)
2896 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2898 result = *((gpointer *)((char *)this + field->offset));
2900 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2901 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2902 mono_array_setref (out_args, 0, result);
2910 g_assert_not_reached ();
2912 } else if (!strcmp (m->name, "FieldSetter")) {
2913 MonoClass *k = this->vtable->klass;
2919 /* If this is a proxy, then it must be a CBO */
2920 if (k == mono_defaults.transparent_proxy_class) {
2921 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2922 this = tp->rp->unwrapped_server;
2924 k = this->vtable->klass;
2927 name = mono_array_get (params, MonoString *, 1);
2928 str = mono_string_to_utf8 (name);
2931 MonoClassField* field = mono_class_get_field_from_name (k, str);
2933 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2934 MonoObject *val = mono_array_get (params, gpointer, 2);
2936 if (field_klass->valuetype) {
2937 size = mono_type_size (field->type, &align);
2938 g_assert (size == mono_class_value_size (field_klass, NULL));
2939 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2941 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2944 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2945 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2955 g_assert_not_reached ();
2960 for (i = 0; i < mono_array_length (params); i++) {
2961 if (sig->params [i]->byref)
2965 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2967 /* handle constructors only for objects already allocated */
2968 if (!strcmp (method->method->name, ".ctor"))
2971 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2972 g_assert (!method->method->klass->valuetype);
2973 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2975 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2976 if (sig->params [i]->byref) {
2978 arg = mono_array_get (params, gpointer, i);
2979 mono_array_setref (out_args, j, arg);
2984 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2991 read_enum_value (char *mem, int type)
2995 return *(guint8*)mem;
2997 return *(gint8*)mem;
2999 return *(guint16*)mem;
3001 return *(gint16*)mem;
3003 return *(guint32*)mem;
3005 return *(gint32*)mem;
3007 return *(guint64*)mem;
3009 return *(gint64*)mem;
3011 g_assert_not_reached ();
3017 write_enum_value (char *mem, int type, guint64 value)
3021 case MONO_TYPE_I1: {
3022 guint8 *p = (guint8*)mem;
3027 case MONO_TYPE_I2: {
3028 guint16 *p = (void*)mem;
3033 case MONO_TYPE_I4: {
3034 guint32 *p = (void*)mem;
3039 case MONO_TYPE_I8: {
3040 guint64 *p = (void*)mem;
3045 g_assert_not_reached ();
3050 ICALL_EXPORT MonoObject *
3051 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3054 MonoClass *enumc, *objc;
3059 MONO_ARCH_SAVE_REGS;
3061 MONO_CHECK_ARG_NULL (enumType);
3062 MONO_CHECK_ARG_NULL (value);
3064 domain = mono_object_domain (enumType);
3065 enumc = mono_class_from_mono_type (enumType->type);
3067 mono_class_init_or_throw (enumc);
3069 objc = value->vtable->klass;
3071 if (!enumc->enumtype)
3072 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3073 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3074 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."));
3076 etype = mono_class_enum_basetype (enumc);
3078 /* MS throws this for typebuilders */
3079 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3081 res = mono_object_new (domain, enumc);
3082 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3083 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3088 ICALL_EXPORT MonoObject *
3089 ves_icall_System_Enum_get_value (MonoObject *this)
3097 MONO_ARCH_SAVE_REGS;
3102 g_assert (this->vtable->klass->enumtype);
3104 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3105 res = mono_object_new (mono_object_domain (this), enumc);
3106 dst = (char *)res + sizeof (MonoObject);
3107 src = (char *)this + sizeof (MonoObject);
3108 size = mono_class_value_size (enumc, NULL);
3110 memcpy (dst, src, size);
3115 ICALL_EXPORT MonoReflectionType *
3116 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3121 MONO_ARCH_SAVE_REGS;
3123 klass = mono_class_from_mono_type (type->type);
3124 mono_class_init_or_throw (klass);
3126 etype = mono_class_enum_basetype (klass);
3128 /* MS throws this for typebuilders */
3129 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3131 return mono_type_get_object (mono_object_domain (type), etype);
3135 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3137 gpointer tdata = (char *)this + sizeof (MonoObject);
3138 gpointer odata = (char *)other + sizeof (MonoObject);
3139 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3140 g_assert (basetype);
3142 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3143 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3144 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3147 return me > other ? 1 : -1; \
3150 switch (basetype->type) {
3152 COMPARE_ENUM_VALUES (guint8);
3154 COMPARE_ENUM_VALUES (gint8);
3155 case MONO_TYPE_CHAR:
3157 COMPARE_ENUM_VALUES (guint16);
3159 COMPARE_ENUM_VALUES (gint16);
3161 COMPARE_ENUM_VALUES (guint32);
3163 COMPARE_ENUM_VALUES (gint32);
3165 COMPARE_ENUM_VALUES (guint64);
3167 COMPARE_ENUM_VALUES (gint64);
3169 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3171 #undef COMPARE_ENUM_VALUES
3176 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3178 gpointer data = (char *)this + sizeof (MonoObject);
3179 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3180 g_assert (basetype);
3182 switch (basetype->type) {
3184 return *((gint8*)data);
3186 return *((guint8*)data);
3187 case MONO_TYPE_CHAR:
3189 return *((guint16*)data);
3192 return *((gint16*)data);
3194 return *((guint32*)data);
3196 return *((gint32*)data);
3198 case MONO_TYPE_I8: {
3199 gint64 value = *((gint64*)data);
3200 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3203 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3209 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3211 MonoDomain *domain = mono_object_domain (type);
3212 MonoClass *enumc = mono_class_from_mono_type (type->type);
3213 guint j = 0, nvalues, crow;
3215 MonoClassField *field;
3217 MONO_ARCH_SAVE_REGS;
3219 mono_class_init_or_throw (enumc);
3221 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3222 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3223 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3224 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3228 while ((field = mono_class_get_fields (enumc, &iter))) {
3231 MonoTypeEnum def_type;
3233 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3235 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3237 if (mono_field_is_deleted (field))
3239 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3241 p = mono_class_get_field_default_value (field, &def_type);
3242 len = mono_metadata_decode_blob_size (p, &p);
3243 switch (mono_class_enum_basetype (enumc)->type) {
3246 mono_array_set (info->values, gchar, j, *p);
3248 case MONO_TYPE_CHAR:
3251 mono_array_set (info->values, gint16, j, read16 (p));
3255 mono_array_set (info->values, gint32, j, read32 (p));
3259 mono_array_set (info->values, gint64, j, read64 (p));
3262 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3269 BFLAGS_IgnoreCase = 1,
3270 BFLAGS_DeclaredOnly = 2,
3271 BFLAGS_Instance = 4,
3273 BFLAGS_Public = 0x10,
3274 BFLAGS_NonPublic = 0x20,
3275 BFLAGS_FlattenHierarchy = 0x40,
3276 BFLAGS_InvokeMethod = 0x100,
3277 BFLAGS_CreateInstance = 0x200,
3278 BFLAGS_GetField = 0x400,
3279 BFLAGS_SetField = 0x800,
3280 BFLAGS_GetProperty = 0x1000,
3281 BFLAGS_SetProperty = 0x2000,
3282 BFLAGS_ExactBinding = 0x10000,
3283 BFLAGS_SuppressChangeType = 0x20000,
3284 BFLAGS_OptionalParamBinding = 0x40000
3287 ICALL_EXPORT MonoReflectionField *
3288 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3291 MonoClass *startklass, *klass;
3293 MonoClassField *field;
3296 int (*compare_func) (const char *s1, const char *s2) = NULL;
3297 domain = ((MonoObject *)type)->vtable->domain;
3298 klass = startklass = mono_class_from_mono_type (type->type);
3301 mono_raise_exception (mono_get_exception_argument_null ("name"));
3302 if (type->type->byref)
3305 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3308 if (klass->exception_type != MONO_EXCEPTION_NONE)
3309 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3312 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3313 guint32 flags = mono_field_get_flags (field);
3316 if (mono_field_is_deleted_with_flags (field, flags))
3318 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3319 if (bflags & BFLAGS_Public)
3321 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3322 if (bflags & BFLAGS_NonPublic) {
3329 if (flags & FIELD_ATTRIBUTE_STATIC) {
3330 if (bflags & BFLAGS_Static)
3331 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3334 if (bflags & BFLAGS_Instance)
3341 utf8_name = mono_string_to_utf8 (name);
3343 if (compare_func (mono_field_get_name (field), utf8_name)) {
3349 return mono_field_get_object (domain, klass, field);
3351 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3357 ICALL_EXPORT MonoArray*
3358 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3361 MonoClass *startklass, *klass, *refklass;
3366 MonoClassField *field;
3367 MonoPtrArray tmp_array;
3369 MONO_ARCH_SAVE_REGS;
3371 domain = ((MonoObject *)type)->vtable->domain;
3372 if (type->type->byref)
3373 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3374 klass = startklass = mono_class_from_mono_type (type->type);
3375 refklass = mono_class_from_mono_type (reftype->type);
3377 mono_ptr_array_init (tmp_array, 2);
3380 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3381 mono_ptr_array_destroy (tmp_array);
3382 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3386 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3387 guint32 flags = mono_field_get_flags (field);
3389 if (mono_field_is_deleted_with_flags (field, flags))
3391 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3392 if (bflags & BFLAGS_Public)
3394 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3395 if (bflags & BFLAGS_NonPublic) {
3402 if (flags & FIELD_ATTRIBUTE_STATIC) {
3403 if (bflags & BFLAGS_Static)
3404 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3407 if (bflags & BFLAGS_Instance)
3413 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3414 mono_ptr_array_append (tmp_array, member);
3416 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3419 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3421 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3422 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3424 mono_ptr_array_destroy (tmp_array);
3430 method_nonpublic (MonoMethod* method, gboolean start_klass)
3432 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3433 case METHOD_ATTRIBUTE_ASSEM:
3434 return (start_klass || mono_defaults.generic_ilist_class);
3435 case METHOD_ATTRIBUTE_PRIVATE:
3437 case METHOD_ATTRIBUTE_PUBLIC:
3445 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3448 MonoClass *startklass;
3451 int len, match, nslots;
3452 /*FIXME, use MonoBitSet*/
3453 guint32 method_slots_default [8];
3454 guint32 *method_slots = NULL;
3455 int (*compare_func) (const char *s1, const char *s2) = NULL;
3457 array = g_ptr_array_new ();
3463 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3465 /* An optimization for calls made from Delegate:CreateDelegate () */
3466 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3467 method = mono_get_delegate_invoke (klass);
3468 if (mono_loader_get_last_error ())
3471 g_ptr_array_add (array, method);
3475 mono_class_setup_vtable (klass);
3476 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3479 if (is_generic_parameter (&klass->byval_arg))
3480 nslots = mono_class_get_vtable_size (klass->parent);
3482 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3483 if (nslots >= sizeof (method_slots_default) * 8) {
3484 method_slots = g_new0 (guint32, nslots / 32 + 1);
3486 method_slots = method_slots_default;
3487 memset (method_slots, 0, sizeof (method_slots_default));
3490 mono_class_setup_vtable (klass);
3491 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3495 while ((method = mono_class_get_methods (klass, &iter))) {
3497 if (method->slot != -1) {
3498 g_assert (method->slot < nslots);
3499 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3501 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3502 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3505 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3507 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3508 if (bflags & BFLAGS_Public)
3510 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3516 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3517 if (bflags & BFLAGS_Static)
3518 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3521 if (bflags & BFLAGS_Instance)
3529 if (compare_func (name, method->name))
3534 g_ptr_array_add (array, method);
3536 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3538 if (method_slots != method_slots_default)
3539 g_free (method_slots);
3544 if (method_slots != method_slots_default)
3545 g_free (method_slots);
3546 g_ptr_array_free (array, TRUE);
3548 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3549 *ex = mono_class_get_exception_for_failure (klass);
3551 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3552 mono_loader_clear_error ();
3557 ICALL_EXPORT MonoArray*
3558 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3560 static MonoClass *MethodInfo_array;
3563 MonoVTable *array_vtable;
3564 MonoException *ex = NULL;
3565 const char *mname = NULL;
3566 GPtrArray *method_array;
3567 MonoClass *klass, *refklass;
3570 if (!MethodInfo_array) {
3571 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3572 mono_memory_barrier ();
3573 MethodInfo_array = klass;
3576 klass = mono_class_from_mono_type (type->type);
3577 refklass = mono_class_from_mono_type (reftype->type);
3578 domain = ((MonoObject *)type)->vtable->domain;
3579 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3580 if (type->type->byref)
3581 return mono_array_new_specific (array_vtable, 0);
3584 mname = mono_string_to_utf8 (name);
3586 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3587 g_free ((char*)mname);
3589 mono_raise_exception (ex);
3591 res = mono_array_new_specific (array_vtable, method_array->len);
3594 for (i = 0; i < method_array->len; ++i) {
3595 MonoMethod *method = g_ptr_array_index (method_array, i);
3596 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3599 g_ptr_array_free (method_array, TRUE);
3603 ICALL_EXPORT MonoArray*
3604 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3607 static MonoClass *System_Reflection_ConstructorInfo;
3608 MonoClass *startklass, *klass, *refklass;
3613 gpointer iter = NULL;
3614 MonoPtrArray tmp_array;
3616 MONO_ARCH_SAVE_REGS;
3618 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3620 domain = ((MonoObject *)type)->vtable->domain;
3621 if (type->type->byref)
3622 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3623 klass = startklass = mono_class_from_mono_type (type->type);
3624 refklass = mono_class_from_mono_type (reftype->type);
3626 if (!System_Reflection_ConstructorInfo)
3627 System_Reflection_ConstructorInfo = mono_class_from_name (
3628 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3631 while ((method = mono_class_get_methods (klass, &iter))) {
3633 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3635 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3636 if (bflags & BFLAGS_Public)
3639 if (bflags & BFLAGS_NonPublic)
3645 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3646 if (bflags & BFLAGS_Static)
3647 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3650 if (bflags & BFLAGS_Instance)
3656 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3658 mono_ptr_array_append (tmp_array, member);
3661 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3663 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3664 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3666 mono_ptr_array_destroy (tmp_array);
3672 property_hash (gconstpointer data)
3674 MonoProperty *prop = (MonoProperty*)data;
3676 return g_str_hash (prop->name);
3680 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3682 // Properties are hide-by-name-and-signature
3683 if (!g_str_equal (prop1->name, prop2->name))
3686 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3688 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3694 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3699 return method_nonpublic (accessor, start_klass);
3702 ICALL_EXPORT MonoArray*
3703 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3707 static MonoClass *System_Reflection_PropertyInfo;
3708 MonoClass *startklass, *klass;
3714 gchar *propname = NULL;
3715 int (*compare_func) (const char *s1, const char *s2) = NULL;
3717 GHashTable *properties = NULL;
3718 MonoPtrArray tmp_array;
3720 MONO_ARCH_SAVE_REGS;
3722 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3724 if (!System_Reflection_PropertyInfo)
3725 System_Reflection_PropertyInfo = mono_class_from_name (
3726 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3728 domain = ((MonoObject *)type)->vtable->domain;
3729 if (type->type->byref)
3730 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3731 klass = startklass = mono_class_from_mono_type (type->type);
3734 propname = mono_string_to_utf8 (name);
3735 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3738 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3740 mono_class_setup_vtable (klass);
3741 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3745 while ((prop = mono_class_get_properties (klass, &iter))) {
3751 flags = method->flags;
3754 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3755 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3756 if (bflags & BFLAGS_Public)
3758 } else if (bflags & BFLAGS_NonPublic) {
3759 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3760 property_accessor_nonpublic(prop->set, startklass == klass)) {
3767 if (flags & METHOD_ATTRIBUTE_STATIC) {
3768 if (bflags & BFLAGS_Static)
3769 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3772 if (bflags & BFLAGS_Instance)
3781 if (compare_func (propname, prop->name))
3785 if (g_hash_table_lookup (properties, prop))
3788 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3790 g_hash_table_insert (properties, prop, prop);
3792 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3795 g_hash_table_destroy (properties);
3798 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3799 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3800 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3802 mono_ptr_array_destroy (tmp_array);
3808 g_hash_table_destroy (properties);
3811 mono_ptr_array_destroy (tmp_array);
3813 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3814 ex = mono_class_get_exception_for_failure (klass);
3816 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3817 mono_loader_clear_error ();
3819 mono_raise_exception (ex);
3823 ICALL_EXPORT MonoReflectionEvent *
3824 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3827 MonoClass *klass, *startklass;
3832 int (*compare_func) (const char *s1, const char *s2);
3834 MONO_ARCH_SAVE_REGS;
3836 event_name = mono_string_to_utf8 (name);
3837 if (type->type->byref)
3839 klass = startklass = mono_class_from_mono_type (type->type);
3840 domain = mono_object_domain (type);
3842 mono_class_init_or_throw (klass);
3844 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3846 if (klass->exception_type != MONO_EXCEPTION_NONE)
3847 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3850 while ((event = mono_class_get_events (klass, &iter))) {
3851 if (compare_func (event->name, event_name))
3854 method = event->add;
3856 method = event->remove;
3858 method = event->raise;
3860 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3861 if (!(bflags & BFLAGS_Public))
3864 if (!(bflags & BFLAGS_NonPublic))
3866 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3870 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3871 if (!(bflags & BFLAGS_Static))
3873 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3876 if (!(bflags & BFLAGS_Instance))
3880 if (!(bflags & BFLAGS_NonPublic))
3883 g_free (event_name);
3884 return mono_event_get_object (domain, startklass, event);
3887 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3890 g_free (event_name);
3895 event_hash (gconstpointer data)
3897 MonoEvent *event = (MonoEvent*)data;
3899 return g_str_hash (event->name);
3903 event_equal (MonoEvent *event1, MonoEvent *event2)
3905 // Events are hide-by-name
3906 return g_str_equal (event1->name, event2->name);
3909 ICALL_EXPORT MonoArray*
3910 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3914 static MonoClass *System_Reflection_EventInfo;
3915 MonoClass *startklass, *klass;
3921 GHashTable *events = NULL;
3922 MonoPtrArray tmp_array;
3924 MONO_ARCH_SAVE_REGS;
3926 mono_ptr_array_init (tmp_array, 4);
3928 if (!System_Reflection_EventInfo)
3929 System_Reflection_EventInfo = mono_class_from_name (
3930 mono_defaults.corlib, "System.Reflection", "EventInfo");
3932 domain = mono_object_domain (type);
3933 if (type->type->byref)
3934 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3935 klass = startklass = mono_class_from_mono_type (type->type);
3937 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3939 mono_class_setup_vtable (klass);
3940 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3944 while ((event = mono_class_get_events (klass, &iter))) {
3946 method = event->add;
3948 method = event->remove;
3950 method = event->raise;
3952 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3953 if (bflags & BFLAGS_Public)
3955 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3956 if (bflags & BFLAGS_NonPublic)
3961 if (bflags & BFLAGS_NonPublic)
3967 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3968 if (bflags & BFLAGS_Static)
3969 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3972 if (bflags & BFLAGS_Instance)
3977 if (bflags & BFLAGS_Instance)
3982 if (g_hash_table_lookup (events, event))
3985 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3987 g_hash_table_insert (events, event, event);
3989 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3992 g_hash_table_destroy (events);
3994 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3996 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3997 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3999 mono_ptr_array_destroy (tmp_array);
4004 mono_ptr_array_destroy (tmp_array);
4005 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4006 ex = mono_class_get_exception_for_failure (klass);
4008 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4009 mono_loader_clear_error ();
4011 mono_raise_exception (ex);
4015 ICALL_EXPORT MonoReflectionType *
4016 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4024 MONO_ARCH_SAVE_REGS;
4027 mono_raise_exception (mono_get_exception_argument_null ("name"));
4029 domain = ((MonoObject *)type)->vtable->domain;
4030 if (type->type->byref)
4032 klass = mono_class_from_mono_type (type->type);
4034 str = mono_string_to_utf8 (name);
4037 if (klass->exception_type != MONO_EXCEPTION_NONE)
4038 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4041 * If a nested type is generic, return its generic type definition.
4042 * Note that this means that the return value is essentially a
4043 * nested type of the generic type definition of @klass.
4045 * A note in MSDN claims that a generic type definition can have
4046 * nested types that aren't generic. In any case, the container of that
4047 * nested type would be the generic type definition.
4049 if (klass->generic_class)
4050 klass = klass->generic_class->container_class;
4053 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4055 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4056 if (bflags & BFLAGS_Public)
4059 if (bflags & BFLAGS_NonPublic)
4064 if (strcmp (nested->name, str) == 0){
4066 return mono_type_get_object (domain, &nested->byval_arg);
4069 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4075 ICALL_EXPORT MonoArray*
4076 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4085 MonoPtrArray tmp_array;
4087 MONO_ARCH_SAVE_REGS;
4089 domain = ((MonoObject *)type)->vtable->domain;
4090 if (type->type->byref)
4091 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4092 klass = mono_class_from_mono_type (type->type);
4095 * If a nested type is generic, return its generic type definition.
4096 * Note that this means that the return value is essentially the set
4097 * of nested types of the generic type definition of @klass.
4099 * A note in MSDN claims that a generic type definition can have
4100 * nested types that aren't generic. In any case, the container of that
4101 * nested type would be the generic type definition.
4103 if (klass->generic_class)
4104 klass = klass->generic_class->container_class;
4106 mono_ptr_array_init (tmp_array, 1);
4108 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4110 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4111 if (bflags & BFLAGS_Public)
4114 if (bflags & BFLAGS_NonPublic)
4119 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4120 mono_ptr_array_append (tmp_array, member);
4123 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4125 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4126 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4128 mono_ptr_array_destroy (tmp_array);
4133 ICALL_EXPORT MonoReflectionType*
4134 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4137 MonoType *type = NULL;
4138 MonoTypeNameParse info;
4139 gboolean type_resolve;
4141 MONO_ARCH_SAVE_REGS;
4143 /* On MS.NET, this does not fire a TypeResolve event */
4144 type_resolve = TRUE;
4145 str = mono_string_to_utf8 (name);
4146 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4147 if (!mono_reflection_parse_type (str, &info)) {
4149 mono_reflection_free_type_info (&info);
4150 if (throwOnError) /* uhm: this is a parse error, though... */
4151 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4152 /*g_print ("failed parse\n");*/
4156 if (info.assembly.name) {
4158 mono_reflection_free_type_info (&info);
4160 /* 1.0 and 2.0 throw different exceptions */
4161 if (mono_defaults.generic_ilist_class)
4162 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4164 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4169 if (module != NULL) {
4171 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4176 if (assembly_is_dynamic (assembly->assembly)) {
4177 /* Enumerate all modules */
4178 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4182 if (abuilder->modules) {
4183 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4184 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4185 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4191 if (!type && abuilder->loaded_modules) {
4192 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4193 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4194 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4201 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4203 mono_reflection_free_type_info (&info);
4205 MonoException *e = NULL;
4208 e = mono_get_exception_type_load (name, NULL);
4210 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4211 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4213 mono_loader_clear_error ();
4216 mono_raise_exception (e);
4219 } else if (mono_loader_get_last_error ()) {
4221 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4222 mono_loader_clear_error ();
4225 if (type->type == MONO_TYPE_CLASS) {
4226 MonoClass *klass = mono_type_get_class (type);
4228 if (mono_security_enabled () && !klass->exception_type)
4229 /* Some security problems are detected during generic vtable construction */
4230 mono_class_setup_vtable (klass);
4232 /* need to report exceptions ? */
4233 if (throwOnError && klass->exception_type) {
4234 /* report SecurityException (or others) that occured when loading the assembly */
4235 MonoException *exc = mono_class_get_exception_for_failure (klass);
4236 mono_loader_clear_error ();
4237 mono_raise_exception (exc);
4238 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4243 /* g_print ("got it\n"); */
4244 return mono_type_get_object (mono_object_domain (assembly), type);
4248 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4251 gchar *shadow_ini_file;
4254 /* Check for shadow-copied assembly */
4255 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4256 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4258 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4259 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4265 g_free (shadow_ini_file);
4266 if (content != NULL) {
4269 *filename = content;
4276 ICALL_EXPORT MonoString *
4277 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4279 MonoDomain *domain = mono_object_domain (assembly);
4280 MonoAssembly *mass = assembly->assembly;
4281 MonoString *res = NULL;
4286 MONO_ARCH_SAVE_REGS;
4288 if (g_path_is_absolute (mass->image->name)) {
4289 absolute = g_strdup (mass->image->name);
4290 dirname = g_path_get_dirname (absolute);
4292 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4293 dirname = g_strdup (mass->basedir);
4296 replace_shadow_path (domain, dirname, &absolute);
4301 for (i = strlen (absolute) - 1; i >= 0; i--)
4302 if (absolute [i] == '\\')
4307 uri = g_filename_to_uri (absolute, NULL, NULL);
4309 const char *prepend = "file://";
4311 if (*absolute == '/' && *(absolute + 1) == '/') {
4314 prepend = "file:///";
4317 uri = g_strconcat (prepend, absolute, NULL);
4321 res = mono_string_new (domain, uri);
4328 ICALL_EXPORT MonoBoolean
4329 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4331 MonoAssembly *mass = assembly->assembly;
4333 MONO_ARCH_SAVE_REGS;
4335 return mass->in_gac;
4338 ICALL_EXPORT MonoReflectionAssembly*
4339 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4343 MonoImageOpenStatus status;
4345 MONO_ARCH_SAVE_REGS;
4347 name = mono_string_to_utf8 (mname);
4348 res = mono_assembly_load_with_partial_name (name, &status);
4354 return mono_assembly_get_object (mono_domain_get (), res);
4357 ICALL_EXPORT MonoString *
4358 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4360 MonoDomain *domain = mono_object_domain (assembly);
4363 MONO_ARCH_SAVE_REGS;
4365 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4370 ICALL_EXPORT MonoBoolean
4371 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4373 MONO_ARCH_SAVE_REGS;
4375 return assembly->assembly->ref_only;
4378 ICALL_EXPORT MonoString *
4379 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4381 MonoDomain *domain = mono_object_domain (assembly);
4383 MONO_ARCH_SAVE_REGS;
4385 return mono_string_new (domain, assembly->assembly->image->version);
4388 ICALL_EXPORT MonoReflectionMethod*
4389 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4391 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4393 MONO_ARCH_SAVE_REGS;
4397 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4400 ICALL_EXPORT MonoReflectionModule*
4401 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4403 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4406 ICALL_EXPORT MonoArray*
4407 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4409 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4410 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4414 MONO_ARCH_SAVE_REGS;
4416 for (i = 0; i < table->rows; ++i) {
4417 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4418 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4424 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4426 static MonoClass *System_Version = NULL;
4427 static MonoMethod *create_version = NULL;
4431 if (!System_Version) {
4432 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4433 g_assert (System_Version);
4436 if (!create_version) {
4437 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4438 create_version = mono_method_desc_search_in_class (desc, System_Version);
4439 g_assert (create_version);
4440 mono_method_desc_free (desc);
4446 args [3] = &revision;
4447 result = mono_object_new (domain, System_Version);
4448 mono_runtime_invoke (create_version, result, args, NULL);
4453 ICALL_EXPORT MonoArray*
4454 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4456 static MonoClass *System_Reflection_AssemblyName;
4458 MonoDomain *domain = mono_object_domain (assembly);
4460 static MonoMethod *create_culture = NULL;
4461 MonoImage *image = assembly->assembly->image;
4464 MONO_ARCH_SAVE_REGS;
4466 if (!System_Reflection_AssemblyName)
4467 System_Reflection_AssemblyName = mono_class_from_name (
4468 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4470 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4473 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4475 if (count > 0 && !create_culture) {
4476 MonoMethodDesc *desc = mono_method_desc_new (
4477 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4478 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4479 g_assert (create_culture);
4480 mono_method_desc_free (desc);
4483 for (i = 0; i < count; i++) {
4484 MonoReflectionAssemblyName *aname;
4485 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4487 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4489 aname = (MonoReflectionAssemblyName *) mono_object_new (
4490 domain, System_Reflection_AssemblyName);
4492 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4494 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4495 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4496 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4497 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4498 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4499 aname->versioncompat = 1; /* SameMachine (default) */
4500 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4501 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4503 if (create_culture) {
4505 MonoBoolean assembly_ref = 1;
4506 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4507 args [1] = &assembly_ref;
4508 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4511 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4512 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4513 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4515 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4516 /* public key token isn't copied - the class library will
4517 automatically generate it from the public key if required */
4518 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4519 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4521 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4522 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4525 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4528 /* note: this function doesn't return the codebase on purpose (i.e. it can
4529 be used under partial trust as path information isn't present). */
4531 mono_array_setref (result, i, aname);
4536 /* move this in some file in mono/util/ */
4538 g_concat_dir_and_file (const char *dir, const char *file)
4540 g_return_val_if_fail (dir != NULL, NULL);
4541 g_return_val_if_fail (file != NULL, NULL);
4544 * If the directory name doesn't have a / on the end, we need
4545 * to add one so we get a proper path to the file
4547 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4548 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4550 return g_strconcat (dir, file, NULL);
4554 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4556 char *n = mono_string_to_utf8 (name);
4557 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4559 guint32 cols [MONO_MANIFEST_SIZE];
4560 guint32 impl, file_idx;
4564 MONO_ARCH_SAVE_REGS;
4566 for (i = 0; i < table->rows; ++i) {
4567 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4568 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4569 if (strcmp (val, n) == 0)
4573 if (i == table->rows)
4576 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4579 * this code should only be called after obtaining the
4580 * ResourceInfo and handling the other cases.
4582 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4583 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4585 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4590 module = assembly->assembly->image;
4592 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4594 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4597 ICALL_EXPORT gboolean
4598 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4600 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4602 guint32 cols [MONO_MANIFEST_SIZE];
4603 guint32 file_cols [MONO_FILE_SIZE];
4607 MONO_ARCH_SAVE_REGS;
4609 n = mono_string_to_utf8 (name);
4610 for (i = 0; i < table->rows; ++i) {
4611 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4612 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4613 if (strcmp (val, n) == 0)
4617 if (i == table->rows)
4620 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4621 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4624 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4625 case MONO_IMPLEMENTATION_FILE:
4626 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4627 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4628 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4629 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4630 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4631 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4634 info->location = RESOURCE_LOCATION_EMBEDDED;
4637 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4638 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4639 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4640 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4641 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4642 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4644 mono_raise_exception (ex);
4646 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4648 /* Obtain info recursively */
4649 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4650 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4653 case MONO_IMPLEMENTATION_EXP_TYPE:
4654 g_assert_not_reached ();
4662 ICALL_EXPORT MonoObject*
4663 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4665 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4666 MonoArray *result = NULL;
4671 MONO_ARCH_SAVE_REGS;
4673 /* check hash if needed */
4675 n = mono_string_to_utf8 (name);
4676 for (i = 0; i < table->rows; ++i) {
4677 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4678 if (strcmp (val, n) == 0) {
4681 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4682 fn = mono_string_new (mono_object_domain (assembly), n);
4684 return (MonoObject*)fn;
4692 for (i = 0; i < table->rows; ++i) {
4693 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4697 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4700 for (i = 0; i < table->rows; ++i) {
4701 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4702 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4703 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4704 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4709 return (MonoObject*)result;
4712 ICALL_EXPORT MonoArray*
4713 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4715 MonoDomain *domain = mono_domain_get();
4718 int i, j, file_count = 0;
4719 MonoImage **modules;
4720 guint32 module_count, real_module_count;
4721 MonoTableInfo *table;
4722 guint32 cols [MONO_FILE_SIZE];
4723 MonoImage *image = assembly->assembly->image;
4725 g_assert (image != NULL);
4726 g_assert (!assembly_is_dynamic (assembly->assembly));
4728 table = &image->tables [MONO_TABLE_FILE];
4729 file_count = table->rows;
4731 modules = image->modules;
4732 module_count = image->module_count;
4734 real_module_count = 0;
4735 for (i = 0; i < module_count; ++i)
4737 real_module_count ++;
4739 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4740 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4742 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4744 for (i = 0; i < module_count; ++i)
4746 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4750 for (i = 0; i < file_count; ++i, ++j) {
4751 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4752 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4753 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4755 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4757 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4758 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4760 mono_array_setref (res, j, mono_module_get_object (domain, m));
4767 ICALL_EXPORT MonoReflectionMethod*
4768 ves_icall_GetCurrentMethod (void)
4770 MonoMethod *m = mono_method_get_last_managed ();
4772 while (m->is_inflated)
4773 m = ((MonoMethodInflated*)m)->declaring;
4775 return mono_method_get_object (mono_domain_get (), m, NULL);
4780 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4783 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4784 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4785 //method is inflated, we should inflate it on the other class
4786 MonoGenericContext ctx;
4787 ctx.method_inst = inflated->context.method_inst;
4788 ctx.class_inst = inflated->context.class_inst;
4789 if (klass->generic_class)
4790 ctx.class_inst = klass->generic_class->context.class_inst;
4791 else if (klass->generic_container)
4792 ctx.class_inst = klass->generic_container->context.class_inst;
4793 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4796 mono_class_setup_methods (method->klass);
4797 if (method->klass->exception_type)
4799 for (i = 0; i < method->klass->method.count; ++i) {
4800 if (method->klass->methods [i] == method) {
4805 mono_class_setup_methods (klass);
4806 if (klass->exception_type)
4808 g_assert (offset >= 0 && offset < klass->method.count);
4809 return klass->methods [offset];
4812 ICALL_EXPORT MonoReflectionMethod*
4813 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4817 klass = mono_class_from_mono_type (type);
4818 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4820 if (method->klass != klass) {
4821 method = mono_method_get_equivalent_method (method, klass);
4826 klass = method->klass;
4827 return mono_method_get_object (mono_domain_get (), method, klass);
4830 ICALL_EXPORT MonoReflectionMethod*
4831 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4833 return mono_method_get_object (mono_domain_get (), method, NULL);
4836 ICALL_EXPORT MonoReflectionMethodBody*
4837 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4839 return mono_method_body_get_object (mono_domain_get (), method);
4842 ICALL_EXPORT MonoReflectionAssembly*
4843 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4845 MonoMethod *dest = NULL;
4847 MONO_ARCH_SAVE_REGS;
4849 mono_stack_walk_no_il (get_executing, &dest);
4851 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4855 ICALL_EXPORT MonoReflectionAssembly*
4856 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4858 MonoDomain* domain = mono_domain_get ();
4860 MONO_ARCH_SAVE_REGS;
4862 if (!domain->entry_assembly)
4865 return mono_assembly_get_object (domain, domain->entry_assembly);
4868 ICALL_EXPORT MonoReflectionAssembly*
4869 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4874 MONO_ARCH_SAVE_REGS;
4877 mono_stack_walk_no_il (get_executing, &dest);
4879 mono_stack_walk_no_il (get_caller, &dest);
4882 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4885 ICALL_EXPORT MonoString *
4886 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4887 gboolean assembly_qualified)
4889 MonoDomain *domain = mono_object_domain (object);
4890 MonoTypeNameFormat format;
4895 format = assembly_qualified ?
4896 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4897 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4899 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4901 name = mono_type_get_name_full (object->type, format);
4905 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4910 res = mono_string_new (domain, name);
4917 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4919 MonoClass *klass = mono_class_from_mono_type (this->type);
4920 mono_class_init_or_throw (klass);
4921 return mono_security_core_clr_class_level (klass);
4925 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4927 static MonoMethod *create_culture = NULL;
4930 const char *pkey_ptr;
4932 MonoBoolean assembly_ref = 0;
4934 MONO_ARCH_SAVE_REGS;
4936 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4937 aname->major = name->major;
4938 aname->minor = name->minor;
4939 aname->build = name->build;
4940 aname->flags = name->flags;
4941 aname->revision = name->revision;
4942 aname->hashalg = name->hash_alg;
4943 aname->versioncompat = 1; /* SameMachine (default) */
4944 aname->processor_architecture = name->arch;
4946 if (by_default_version)
4947 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4950 if (absolute != NULL && *absolute != '\0') {
4951 const gchar *prepend = "file://";
4954 codebase = g_strdup (absolute);
4959 for (i = strlen (codebase) - 1; i >= 0; i--)
4960 if (codebase [i] == '\\')
4963 if (*codebase == '/' && *(codebase + 1) == '/') {
4966 prepend = "file:///";
4970 result = g_strconcat (prepend, codebase, NULL);
4976 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4980 if (!create_culture) {
4981 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4982 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4983 g_assert (create_culture);
4984 mono_method_desc_free (desc);
4987 if (name->culture) {
4988 args [0] = mono_string_new (domain, name->culture);
4989 args [1] = &assembly_ref;
4990 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4993 if (name->public_key) {
4994 pkey_ptr = (char*)name->public_key;
4995 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4997 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4998 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4999 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5000 } else if (default_publickey) {
5001 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5002 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5005 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5006 if (name->public_key_token [0]) {
5010 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5011 p = mono_array_addr (aname->keyToken, char, 0);
5013 for (i = 0, j = 0; i < 8; i++) {
5014 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5015 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5018 } else if (default_token) {
5019 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5023 ICALL_EXPORT MonoString *
5024 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5026 MonoDomain *domain = mono_object_domain (assembly);
5027 MonoAssembly *mass = assembly->assembly;
5031 name = mono_stringify_assembly_name (&mass->aname);
5032 res = mono_string_new (domain, name);
5039 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5042 MonoAssembly *mass = assembly->assembly;
5044 MONO_ARCH_SAVE_REGS;
5046 if (g_path_is_absolute (mass->image->name)) {
5047 fill_reflection_assembly_name (mono_object_domain (assembly),
5048 aname, &mass->aname, mass->image->name, TRUE,
5052 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5054 fill_reflection_assembly_name (mono_object_domain (assembly),
5055 aname, &mass->aname, absolute, TRUE, TRUE,
5062 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5065 MonoImageOpenStatus status = MONO_IMAGE_OK;
5068 MonoAssemblyName name;
5071 MONO_ARCH_SAVE_REGS;
5073 filename = mono_string_to_utf8 (fname);
5075 dirname = g_path_get_dirname (filename);
5076 replace_shadow_path (mono_domain_get (), dirname, &filename);
5079 image = mono_image_open (filename, &status);
5085 if (status == MONO_IMAGE_IMAGE_INVALID)
5086 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5088 exc = mono_get_exception_file_not_found2 (NULL, fname);
5089 mono_raise_exception (exc);
5092 res = mono_assembly_fill_assembly_name (image, &name);
5094 mono_image_close (image);
5096 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5099 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5103 mono_image_close (image);
5106 ICALL_EXPORT MonoBoolean
5107 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5108 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5110 MonoBoolean result = FALSE;
5111 MonoDeclSecurityEntry entry;
5113 /* SecurityAction.RequestMinimum */
5114 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5115 *minimum = entry.blob;
5116 *minLength = entry.size;
5119 /* SecurityAction.RequestOptional */
5120 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5121 *optional = entry.blob;
5122 *optLength = entry.size;
5125 /* SecurityAction.RequestRefuse */
5126 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5127 *refused = entry.blob;
5128 *refLength = entry.size;
5136 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5140 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5142 guint32 attrs, visibility;
5144 /* we start the count from 1 because we skip the special type <Module> */
5147 for (i = 1; i < tdef->rows; ++i) {
5148 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5149 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5150 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5154 count = tdef->rows - 1;
5156 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5157 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5159 for (i = 1; i < tdef->rows; ++i) {
5160 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5161 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5162 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5163 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5165 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5167 MonoLoaderError *error;
5170 error = mono_loader_get_last_error ();
5171 g_assert (error != NULL);
5173 ex = mono_loader_error_prepare_exception (error);
5174 mono_array_setref (*exceptions, count, ex);
5176 if (mono_loader_get_last_error ())
5177 mono_loader_clear_error ();
5185 ICALL_EXPORT MonoArray*
5186 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5188 MonoArray *res = NULL;
5189 MonoArray *exceptions = NULL;
5190 MonoImage *image = NULL;
5191 MonoTableInfo *table = NULL;
5194 int i, len, ex_count;
5196 MONO_ARCH_SAVE_REGS;
5198 domain = mono_object_domain (assembly);
5200 g_assert (!assembly_is_dynamic (assembly->assembly));
5201 image = assembly->assembly->image;
5202 table = &image->tables [MONO_TABLE_FILE];
5203 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5205 /* Append data from all modules in the assembly */
5206 for (i = 0; i < table->rows; ++i) {
5207 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5208 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5211 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5212 /* Append the new types to the end of the array */
5213 if (mono_array_length (res2) > 0) {
5215 MonoArray *res3, *ex3;
5217 len1 = mono_array_length (res);
5218 len2 = mono_array_length (res2);
5220 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5221 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5222 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5225 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5226 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5227 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5234 /* the ReflectionTypeLoadException must have all the types (Types property),
5235 * NULL replacing types which throws an exception. The LoaderException must
5236 * contain all exceptions for NULL items.
5239 len = mono_array_length (res);
5242 for (i = 0; i < len; i++) {
5243 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5247 klass = mono_type_get_class (t->type);
5248 if ((klass != NULL) && klass->exception_type) {
5249 /* keep the class in the list */
5250 list = g_list_append (list, klass);
5251 /* and replace Type with NULL */
5252 mono_array_setref (res, i, NULL);
5259 if (list || ex_count) {
5261 MonoException *exc = NULL;
5262 MonoArray *exl = NULL;
5263 int j, length = g_list_length (list) + ex_count;
5265 mono_loader_clear_error ();
5267 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5268 /* Types for which mono_class_get () succeeded */
5269 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5270 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5271 mono_array_setref (exl, i, exc);
5273 /* Types for which it don't */
5274 for (j = 0; j < mono_array_length (exceptions); ++j) {
5275 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5277 g_assert (i < length);
5278 mono_array_setref (exl, i, exc);
5285 exc = mono_get_exception_reflection_type_load (res, exl);
5286 mono_loader_clear_error ();
5287 mono_raise_exception (exc);
5293 ICALL_EXPORT gboolean
5294 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5296 MonoAssemblyName aname;
5297 MonoDomain *domain = mono_object_domain (name);
5299 gboolean is_version_defined;
5300 gboolean is_token_defined;
5302 aname.public_key = NULL;
5303 val = mono_string_to_utf8 (assname);
5304 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5305 g_free ((guint8*) aname.public_key);
5310 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5311 FALSE, is_token_defined);
5313 mono_assembly_name_free (&aname);
5314 g_free ((guint8*) aname.public_key);
5320 ICALL_EXPORT MonoReflectionType*
5321 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5323 MonoDomain *domain = mono_object_domain (module);
5326 MONO_ARCH_SAVE_REGS;
5328 g_assert (module->image);
5330 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5331 /* These images do not have a global type */
5334 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5335 return mono_type_get_object (domain, &klass->byval_arg);
5339 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5341 /*if (module->image)
5342 mono_image_close (module->image);*/
5345 ICALL_EXPORT MonoString*
5346 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5348 MonoDomain *domain = mono_object_domain (module);
5350 MONO_ARCH_SAVE_REGS;
5352 g_assert (module->image);
5353 return mono_string_new (domain, module->image->guid);
5356 ICALL_EXPORT gpointer
5357 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5360 if (module->image && module->image->is_module_handle)
5361 return module->image->raw_data;
5364 return (gpointer) (-1);
5368 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5370 if (image_is_dynamic (image)) {
5371 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5372 *pe_kind = dyn->pe_kind;
5373 *machine = dyn->machine;
5376 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5377 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5382 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5384 return (image->md_version_major << 16) | (image->md_version_minor);
5387 ICALL_EXPORT MonoArray*
5388 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5390 MonoArray *exceptions;
5393 MONO_ARCH_SAVE_REGS;
5396 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5398 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5399 for (i = 0; i < mono_array_length (exceptions); ++i) {
5400 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5402 mono_raise_exception (ex);
5409 mono_memberref_is_method (MonoImage *image, guint32 token)
5411 if (!image_is_dynamic (image)) {
5412 guint32 cols [MONO_MEMBERREF_SIZE];
5414 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5415 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5416 mono_metadata_decode_blob_size (sig, &sig);
5417 return (*sig != 0x6);
5419 MonoClass *handle_class;
5421 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5424 return mono_defaults.methodhandle_class == handle_class;
5429 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5432 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5433 mono_array_addr (type_args, MonoType*, 0));
5435 context->class_inst = NULL;
5437 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5438 mono_array_addr (method_args, MonoType*, 0));
5440 context->method_inst = NULL;
5443 ICALL_EXPORT MonoType*
5444 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5447 int table = mono_metadata_token_table (token);
5448 int index = mono_metadata_token_index (token);
5449 MonoGenericContext context;
5451 *error = ResolveTokenError_Other;
5453 /* Validate token */
5454 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5455 (table != MONO_TABLE_TYPESPEC)) {
5456 *error = ResolveTokenError_BadTable;
5460 if (image_is_dynamic (image)) {
5461 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5462 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5463 return klass ? &klass->byval_arg : NULL;
5466 init_generic_context_from_args (&context, type_args, method_args);
5467 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5468 return klass ? &klass->byval_arg : NULL;
5471 if ((index <= 0) || (index > image->tables [table].rows)) {
5472 *error = ResolveTokenError_OutOfRange;
5476 init_generic_context_from_args (&context, type_args, method_args);
5477 klass = mono_class_get_full (image, token, &context);
5479 if (mono_loader_get_last_error ())
5480 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5483 return &klass->byval_arg;
5488 ICALL_EXPORT MonoMethod*
5489 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5491 int table = mono_metadata_token_table (token);
5492 int index = mono_metadata_token_index (token);
5493 MonoGenericContext context;
5496 *error = ResolveTokenError_Other;
5498 /* Validate token */
5499 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5500 (table != MONO_TABLE_MEMBERREF)) {
5501 *error = ResolveTokenError_BadTable;
5505 if (image_is_dynamic (image)) {
5506 if (table == MONO_TABLE_METHOD)
5507 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5509 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5510 *error = ResolveTokenError_BadTable;
5514 init_generic_context_from_args (&context, type_args, method_args);
5515 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5518 if ((index <= 0) || (index > image->tables [table].rows)) {
5519 *error = ResolveTokenError_OutOfRange;
5522 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5523 *error = ResolveTokenError_BadTable;
5527 init_generic_context_from_args (&context, type_args, method_args);
5528 method = mono_get_method_full (image, token, NULL, &context);
5530 if (mono_loader_get_last_error ())
5531 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5536 ICALL_EXPORT MonoString*
5537 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5539 int index = mono_metadata_token_index (token);
5541 *error = ResolveTokenError_Other;
5543 /* Validate token */
5544 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5545 *error = ResolveTokenError_BadTable;
5549 if (image_is_dynamic (image))
5550 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5552 if ((index <= 0) || (index >= image->heap_us.size)) {
5553 *error = ResolveTokenError_OutOfRange;
5557 /* FIXME: What to do if the index points into the middle of a string ? */
5559 return mono_ldstr (mono_domain_get (), image, index);
5562 ICALL_EXPORT MonoClassField*
5563 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5566 int table = mono_metadata_token_table (token);
5567 int index = mono_metadata_token_index (token);
5568 MonoGenericContext context;
5569 MonoClassField *field;
5571 *error = ResolveTokenError_Other;
5573 /* Validate token */
5574 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5575 *error = ResolveTokenError_BadTable;
5579 if (image_is_dynamic (image)) {
5580 if (table == MONO_TABLE_FIELD)
5581 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5583 if (mono_memberref_is_method (image, token)) {
5584 *error = ResolveTokenError_BadTable;
5588 init_generic_context_from_args (&context, type_args, method_args);
5589 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5592 if ((index <= 0) || (index > image->tables [table].rows)) {
5593 *error = ResolveTokenError_OutOfRange;
5596 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5597 *error = ResolveTokenError_BadTable;
5601 init_generic_context_from_args (&context, type_args, method_args);
5602 field = mono_field_from_token (image, token, &klass, &context);
5604 if (mono_loader_get_last_error ())
5605 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5611 ICALL_EXPORT MonoObject*
5612 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5614 int table = mono_metadata_token_table (token);
5616 *error = ResolveTokenError_Other;
5619 case MONO_TABLE_TYPEDEF:
5620 case MONO_TABLE_TYPEREF:
5621 case MONO_TABLE_TYPESPEC: {
5622 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5624 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5628 case MONO_TABLE_METHOD:
5629 case MONO_TABLE_METHODSPEC: {
5630 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5632 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5636 case MONO_TABLE_FIELD: {
5637 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5639 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5643 case MONO_TABLE_MEMBERREF:
5644 if (mono_memberref_is_method (image, token)) {
5645 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5647 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5652 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5654 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5661 *error = ResolveTokenError_BadTable;
5667 ICALL_EXPORT MonoArray*
5668 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5670 int table = mono_metadata_token_table (token);
5671 int idx = mono_metadata_token_index (token);
5672 MonoTableInfo *tables = image->tables;
5677 *error = ResolveTokenError_OutOfRange;
5679 /* FIXME: Support other tables ? */
5680 if (table != MONO_TABLE_STANDALONESIG)
5683 if (image_is_dynamic (image))
5686 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5689 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5691 ptr = mono_metadata_blob_heap (image, sig);
5692 len = mono_metadata_decode_blob_size (ptr, &ptr);
5694 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5695 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5699 ICALL_EXPORT MonoReflectionType*
5700 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5703 int isbyref = 0, rank;
5704 char *str = mono_string_to_utf8 (smodifiers);
5707 MONO_ARCH_SAVE_REGS;
5709 klass = mono_class_from_mono_type (tb->type.type);
5711 /* logic taken from mono_reflection_parse_type(): keep in sync */
5715 if (isbyref) { /* only one level allowed by the spec */
5722 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5725 klass = mono_ptr_class_get (&klass->byval_arg);
5726 mono_class_init (klass);
5737 else if (*p != '*') { /* '*' means unknown lower bound */
5748 klass = mono_array_class_get (klass, rank);
5749 mono_class_init (klass);
5756 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5759 ICALL_EXPORT MonoBoolean
5760 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5765 MONO_ARCH_SAVE_REGS;
5768 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5774 check_for_invalid_type (MonoClass *klass)
5778 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5781 name = mono_type_get_full_name (klass);
5782 str = mono_string_new (mono_domain_get (), name);
5784 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5787 ICALL_EXPORT MonoReflectionType *
5788 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5790 MonoClass *klass, *aklass;
5792 MONO_ARCH_SAVE_REGS;
5794 klass = mono_class_from_mono_type (type->type);
5795 check_for_invalid_type (klass);
5797 if (rank == 0) //single dimentional array
5798 aklass = mono_array_class_get (klass, 1);
5800 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5802 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5805 ICALL_EXPORT MonoReflectionType *
5806 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5810 MONO_ARCH_SAVE_REGS;
5812 klass = mono_class_from_mono_type (type->type);
5813 mono_class_init_or_throw (klass);
5814 check_for_invalid_type (klass);
5816 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5819 ICALL_EXPORT MonoReflectionType *
5820 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5822 MonoClass *klass, *pklass;
5824 klass = mono_class_from_mono_type (type->type);
5825 mono_class_init_or_throw (klass);
5826 check_for_invalid_type (klass);
5828 pklass = mono_ptr_class_get (type->type);
5830 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5833 ICALL_EXPORT MonoObject *
5834 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5835 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5837 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5838 MonoObject *delegate;
5840 MonoMethod *method = info->method;
5842 MONO_ARCH_SAVE_REGS;
5844 mono_class_init_or_throw (delegate_class);
5846 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5848 if (mono_security_core_clr_enabled ()) {
5849 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5853 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5855 if (method_is_dynamic (method)) {
5856 /* Creating a trampoline would leak memory */
5857 func = mono_compile_method (method);
5859 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5860 method = mono_object_get_virtual_method (target, method);
5861 func = mono_create_ftnptr (mono_domain_get (),
5862 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5865 mono_delegate_ctor_with_method (delegate, target, func, method);
5871 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5873 /* Reset the invoke impl to the default one */
5874 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5878 * Magic number to convert a time which is relative to
5879 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5881 #define EPOCH_ADJUST ((guint64)62135596800LL)
5884 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5886 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5889 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5891 convert_to_absolute_date(SYSTEMTIME *date)
5893 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5894 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5895 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5896 /* from the calendar FAQ */
5897 int a = (14 - date->wMonth) / 12;
5898 int y = date->wYear - a;
5899 int m = date->wMonth + 12 * a - 2;
5900 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5902 /* d is now the day of the week for the first of the month (0 == Sunday) */
5904 int day_of_week = date->wDayOfWeek;
5906 /* set day_in_month to the first day in the month which falls on day_of_week */
5907 int day_in_month = 1 + (day_of_week - d);
5908 if (day_in_month <= 0)
5911 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5912 date->wDay = day_in_month + (date->wDay - 1) * 7;
5913 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5920 * Return's the offset from GMT of a local time.
5922 * tm is a local time
5923 * t is the same local time as seconds.
5926 gmt_offset(struct tm *tm, time_t t)
5928 #if defined (HAVE_TM_GMTOFF)
5929 return tm->tm_gmtoff;
5934 g.tm_isdst = tm->tm_isdst;
5936 return (int)difftime(t, t2);
5941 * This is heavily based on zdump.c from glibc 2.2.
5943 * * data[0]: start of daylight saving time (in DateTime ticks).
5944 * * data[1]: end of daylight saving time (in DateTime ticks).
5945 * * data[2]: utcoffset (in TimeSpan ticks).
5946 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5947 * * name[0]: name of this timezone when not daylight saving.
5948 * * name[1]: name of this timezone when daylight saving.
5950 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5951 * the class library allows years between 1 and 9999.
5953 * Returns true on success and zero on failure.
5955 ICALL_EXPORT guint32
5956 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5959 MonoDomain *domain = mono_domain_get ();
5960 struct tm start, tt;
5963 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5964 int day, transitioned;
5967 gmtoff_st = gmtoff_ds = transitioned = 0;
5969 MONO_ARCH_SAVE_REGS;
5971 MONO_CHECK_ARG_NULL (data);
5972 MONO_CHECK_ARG_NULL (names);
5974 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5975 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5978 * no info is better than crashing: we'll need our own tz data
5979 * to make this work properly, anyway. The range is probably
5980 * reduced to 1970 .. 2037 because that is what mktime is
5981 * guaranteed to support (we get into an infinite loop
5985 memset (&start, 0, sizeof (start));
5988 start.tm_year = year-1900;
5990 t = mktime (&start);
5992 if ((year < 1970) || (year > 2037) || (t == -1)) {
5994 tt = *localtime (&t);
5995 strftime (tzone, sizeof (tzone), "%Z", &tt);
5996 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5997 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6001 gmtoff = gmt_offset (&start, t);
6003 /* For each day of the year, calculate the tm_gmtoff. */
6004 for (day = 0; day < 365 && transitioned < 2; day++) {
6007 tt = *localtime (&t);
6009 gmtoff_after = gmt_offset(&tt, t);
6011 /* Daylight saving starts or ends here. */
6012 if (gmtoff_after != gmtoff) {
6016 /* Try to find the exact hour when daylight saving starts/ends. */
6020 tt1 = *localtime (&t1);
6021 } while (gmt_offset (&tt1, t1) != gmtoff);
6023 /* Try to find the exact minute when daylight saving starts/ends. */
6026 tt1 = *localtime (&t1);
6027 } while (gmt_offset (&tt1, t1) == gmtoff);
6029 strftime (tzone, sizeof (tzone), "%Z", &tt);
6031 /* Write data, if we're already in daylight saving, we're done. */
6033 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6034 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6035 if (gmtoff_ds == 0) {
6037 gmtoff_ds = gmtoff_after;
6044 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6045 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6046 if (gmtoff_ds == 0) {
6047 gmtoff_st = gmtoff_after;
6053 /* This is only set once when we enter daylight saving. */
6055 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6056 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6058 gmtoff = gmt_offset (&tt, t);
6062 if (transitioned < 2) {
6063 strftime (tzone, sizeof (tzone), "%Z", &tt);
6064 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6065 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6066 mono_array_set ((*data), gint64, 0, 0);
6067 mono_array_set ((*data), gint64, 1, 0);
6068 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6069 mono_array_set ((*data), gint64, 3, 0);
6074 MonoDomain *domain = mono_domain_get ();
6075 TIME_ZONE_INFORMATION tz_info;
6080 tz_id = GetTimeZoneInformation (&tz_info);
6081 if (tz_id == TIME_ZONE_ID_INVALID)
6084 MONO_CHECK_ARG_NULL (data);
6085 MONO_CHECK_ARG_NULL (names);
6087 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6088 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6090 for (i = 0; i < 32; ++i)
6091 if (!tz_info.DaylightName [i])
6093 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6094 for (i = 0; i < 32; ++i)
6095 if (!tz_info.StandardName [i])
6097 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6099 if ((year <= 1601) || (year > 30827)) {
6101 * According to MSDN, the MS time functions can't handle dates outside
6107 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6108 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6109 tz_info.StandardDate.wYear = year;
6110 convert_to_absolute_date(&tz_info.StandardDate);
6111 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6116 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6117 tz_info.DaylightDate.wYear = year;
6118 convert_to_absolute_date(&tz_info.DaylightDate);
6119 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6124 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6126 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6127 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6135 static inline gint32
6136 mono_array_get_byte_length (MonoArray *array)
6142 klass = array->obj.vtable->klass;
6144 if (array->bounds == NULL)
6145 length = array->max_length;
6148 for (i = 0; i < klass->rank; ++ i)
6149 length *= array->bounds [i].length;
6152 switch (klass->element_class->byval_arg.type) {
6155 case MONO_TYPE_BOOLEAN:
6159 case MONO_TYPE_CHAR:
6167 return length * sizeof (gpointer);
6178 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6180 MONO_ARCH_SAVE_REGS;
6182 return mono_array_get_byte_length (array);
6186 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6188 MONO_ARCH_SAVE_REGS;
6190 return mono_array_get (array, gint8, idx);
6194 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6196 MONO_ARCH_SAVE_REGS;
6198 mono_array_set (array, gint8, idx, value);
6201 ICALL_EXPORT MonoBoolean
6202 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6204 guint8 *src_buf, *dest_buf;
6206 MONO_ARCH_SAVE_REGS;
6208 /* This is called directly from the class libraries without going through the managed wrapper */
6209 MONO_CHECK_ARG_NULL (src);
6210 MONO_CHECK_ARG_NULL (dest);
6212 /* watch out for integer overflow */
6213 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6216 src_buf = (guint8 *)src->vector + src_offset;
6217 dest_buf = (guint8 *)dest->vector + dest_offset;
6220 memcpy (dest_buf, src_buf, count);
6222 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6227 #ifndef DISABLE_REMOTING
6228 ICALL_EXPORT MonoObject *
6229 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6231 MonoDomain *domain = mono_object_domain (this);
6233 MonoRealProxy *rp = ((MonoRealProxy *)this);
6234 MonoTransparentProxy *tp;
6238 MONO_ARCH_SAVE_REGS;
6240 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6241 tp = (MonoTransparentProxy*) res;
6243 MONO_OBJECT_SETREF (tp, rp, rp);
6244 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6245 klass = mono_class_from_mono_type (type);
6247 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6248 tp->remote_class = mono_remote_class (domain, class_name, klass);
6250 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6254 ICALL_EXPORT MonoReflectionType *
6255 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6257 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6261 /* System.Environment */
6264 ves_icall_System_Environment_get_UserName (void)
6266 MONO_ARCH_SAVE_REGS;
6268 /* using glib is more portable */
6269 return mono_string_new (mono_domain_get (), g_get_user_name ());
6273 ICALL_EXPORT MonoString *
6274 ves_icall_System_Environment_get_MachineName (void)
6276 #if defined (HOST_WIN32)
6281 len = MAX_COMPUTERNAME_LENGTH + 1;
6282 buf = g_new (gunichar2, len);
6285 if (GetComputerName (buf, (PDWORD) &len))
6286 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6290 #elif !defined(DISABLE_SOCKETS)
6294 if (gethostname (buf, sizeof (buf)) == 0)
6295 result = mono_string_new (mono_domain_get (), buf);
6301 return mono_string_new (mono_domain_get (), "mono");
6306 ves_icall_System_Environment_get_Platform (void)
6308 #if defined (TARGET_WIN32)
6311 #elif defined(__MACH__)
6314 // Notice that the value is hidden from user code, and only exposed
6315 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6316 // define and making assumptions based on Unix/128/4 values before there
6317 // was a MacOS define. Lots of code would assume that not-Unix meant
6318 // Windows, but in this case, it would be OSX.
6327 ICALL_EXPORT MonoString *
6328 ves_icall_System_Environment_get_NewLine (void)
6330 MONO_ARCH_SAVE_REGS;
6332 #if defined (HOST_WIN32)
6333 return mono_string_new (mono_domain_get (), "\r\n");
6335 return mono_string_new (mono_domain_get (), "\n");
6339 ICALL_EXPORT MonoString *
6340 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6345 MONO_ARCH_SAVE_REGS;
6350 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6351 value = g_getenv (utf8_name);
6358 return mono_string_new (mono_domain_get (), value);
6362 * There is no standard way to get at environ.
6365 #ifndef __MINGW32_VERSION
6366 #if defined(__APPLE__) && !defined (__arm__)
6367 /* Apple defines this in crt_externs.h but doesn't provide that header for
6368 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6369 * in fact exist on all implementations (so far)
6371 gchar ***_NSGetEnviron(void);
6372 #define environ (*_NSGetEnviron())
6380 ICALL_EXPORT MonoArray *
6381 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6392 env_strings = GetEnvironmentStrings();
6395 env_string = env_strings;
6396 while (*env_string != '\0') {
6397 /* weird case that MS seems to skip */
6398 if (*env_string != '=')
6400 while (*env_string != '\0')
6406 domain = mono_domain_get ();
6407 names = mono_array_new (domain, mono_defaults.string_class, n);
6411 env_string = env_strings;
6412 while (*env_string != '\0') {
6413 /* weird case that MS seems to skip */
6414 if (*env_string != '=') {
6415 equal_str = wcschr(env_string, '=');
6416 g_assert(equal_str);
6417 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6418 mono_array_setref (names, n, str);
6421 while (*env_string != '\0')
6426 FreeEnvironmentStrings (env_strings);
6438 MONO_ARCH_SAVE_REGS;
6441 for (e = environ; *e != 0; ++ e)
6444 domain = mono_domain_get ();
6445 names = mono_array_new (domain, mono_defaults.string_class, n);
6448 for (e = environ; *e != 0; ++ e) {
6449 parts = g_strsplit (*e, "=", 2);
6451 str = mono_string_new (domain, *parts);
6452 mono_array_setref (names, n, str);
6465 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6467 #if !GLIB_CHECK_VERSION(2,4,0)
6468 #define g_setenv(a,b,c) setenv(a,b,c)
6469 #define g_unsetenv(a) unsetenv(a)
6473 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6476 gunichar2 *utf16_name, *utf16_value;
6478 gchar *utf8_name, *utf8_value;
6482 MONO_ARCH_SAVE_REGS;
6485 utf16_name = mono_string_to_utf16 (name);
6486 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6487 SetEnvironmentVariable (utf16_name, NULL);
6488 g_free (utf16_name);
6492 utf16_value = mono_string_to_utf16 (value);
6494 SetEnvironmentVariable (utf16_name, utf16_value);
6496 g_free (utf16_name);
6497 g_free (utf16_value);
6499 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6501 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6502 g_unsetenv (utf8_name);
6507 utf8_value = mono_string_to_utf8_checked (value, &error);
6508 if (!mono_error_ok (&error)) {
6510 mono_error_raise_exception (&error);
6512 g_setenv (utf8_name, utf8_value, TRUE);
6515 g_free (utf8_value);
6520 ves_icall_System_Environment_Exit (int result)
6522 MONO_ARCH_SAVE_REGS;
6524 mono_environment_exitcode_set (result);
6526 /* FIXME: There are some cleanup hangs that should be worked out, but
6527 * if the program is going to exit, everything will be cleaned up when
6528 * NaCl exits anyway.
6530 #ifndef __native_client__
6531 if (!mono_runtime_try_shutdown ())
6532 mono_thread_exit ();
6534 /* Suspend all managed threads since the runtime is going away */
6535 mono_thread_suspend_all_other_threads ();
6537 mono_runtime_quit ();
6540 /* we may need to do some cleanup here... */
6544 ICALL_EXPORT MonoString*
6545 ves_icall_System_Environment_GetGacPath (void)
6547 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6550 ICALL_EXPORT MonoString*
6551 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6553 #if defined (HOST_WIN32)
6554 #ifndef CSIDL_FLAG_CREATE
6555 #define CSIDL_FLAG_CREATE 0x8000
6558 WCHAR path [MAX_PATH];
6559 /* Create directory if no existing */
6560 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6564 return mono_string_new_utf16 (mono_domain_get (), path, len);
6567 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6569 return mono_string_new (mono_domain_get (), "");
6572 ICALL_EXPORT MonoArray *
6573 ves_icall_System_Environment_GetLogicalDrives (void)
6575 gunichar2 buf [256], *ptr, *dname;
6577 guint initial_size = 127, size = 128;
6580 MonoString *drivestr;
6581 MonoDomain *domain = mono_domain_get ();
6584 MONO_ARCH_SAVE_REGS;
6589 while (size > initial_size) {
6590 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6591 if (size > initial_size) {
6594 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6595 initial_size = size;
6609 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6614 while (*u16) { u16++; len ++; }
6615 drivestr = mono_string_new_utf16 (domain, dname, len);
6616 mono_array_setref (result, ndrives++, drivestr);
6626 ICALL_EXPORT MonoString *
6627 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6629 gunichar2 volume_name [MAX_PATH + 1];
6631 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6633 return mono_string_from_utf16 (volume_name);
6636 ICALL_EXPORT MonoString *
6637 ves_icall_System_Environment_InternalGetHome (void)
6639 MONO_ARCH_SAVE_REGS;
6641 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6644 static const char *encodings [] = {
6646 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6647 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6648 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6650 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6651 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6652 "x_unicode_2_0_utf_7",
6654 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6655 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6657 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6660 "unicodefffe", "utf_16be",
6667 * Returns the internal codepage, if the value of "int_code_page" is
6668 * 1 at entry, and we can not compute a suitable code page number,
6669 * returns the code page as a string
6671 ICALL_EXPORT MonoString*
6672 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6677 char *codepage = NULL;
6679 int want_name = *int_code_page;
6682 *int_code_page = -1;
6683 MONO_ARCH_SAVE_REGS;
6685 g_get_charset (&cset);
6686 c = codepage = strdup (cset);
6687 for (c = codepage; *c; c++){
6688 if (isascii (*c) && isalpha (*c))
6693 /* g_print ("charset: %s\n", cset); */
6695 /* handle some common aliases */
6698 for (i = 0; p != 0; ){
6699 if ((gssize) p < 7){
6701 p = encodings [++i];
6704 if (strcmp (p, codepage) == 0){
6705 *int_code_page = code;
6708 p = encodings [++i];
6711 if (strstr (codepage, "utf_8") != NULL)
6712 *int_code_page |= 0x10000000;
6715 if (want_name && *int_code_page == -1)
6716 return mono_string_new (mono_domain_get (), cset);
6721 ICALL_EXPORT MonoBoolean
6722 ves_icall_System_Environment_get_HasShutdownStarted (void)
6724 if (mono_runtime_is_shutting_down ())
6727 if (mono_domain_is_unloading (mono_domain_get ()))
6734 ves_icall_System_Environment_BroadcastSettingChange (void)
6737 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6742 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6743 MonoReflectionMethod *method,
6744 MonoArray *out_args)
6746 MONO_ARCH_SAVE_REGS;
6748 mono_message_init (mono_object_domain (this), this, method, out_args);
6751 #ifndef DISABLE_REMOTING
6752 ICALL_EXPORT MonoBoolean
6753 ves_icall_IsTransparentProxy (MonoObject *proxy)
6755 MONO_ARCH_SAVE_REGS;
6760 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6766 ICALL_EXPORT MonoReflectionMethod *
6767 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6768 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6772 MonoMethod **vtable;
6773 MonoMethod *res = NULL;
6775 MONO_CHECK_ARG_NULL (rtype);
6776 MONO_CHECK_ARG_NULL (rmethod);
6778 method = rmethod->method;
6779 klass = mono_class_from_mono_type (rtype->type);
6780 mono_class_init_or_throw (klass);
6782 if (MONO_CLASS_IS_INTERFACE (klass))
6785 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6788 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6789 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6795 mono_class_setup_vtable (klass);
6796 vtable = klass->vtable;
6798 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6799 gboolean variance_used = FALSE;
6800 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6801 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6803 res = vtable [offs + method->slot];
6805 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6808 if (method->slot != -1)
6809 res = vtable [method->slot];
6815 return mono_method_get_object (mono_domain_get (), res, NULL);
6819 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6824 MONO_ARCH_SAVE_REGS;
6826 klass = mono_class_from_mono_type (type->type);
6827 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6829 mono_vtable_set_is_remote (vtable, enable);
6832 #else /* DISABLE_REMOTING */
6835 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6837 g_assert_not_reached ();
6842 ICALL_EXPORT MonoObject *
6843 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6848 MONO_ARCH_SAVE_REGS;
6850 domain = mono_object_domain (type);
6851 klass = mono_class_from_mono_type (type->type);
6852 mono_class_init_or_throw (klass);
6854 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6855 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6857 if (klass->rank >= 1) {
6858 g_assert (klass->rank == 1);
6859 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6861 /* Bypass remoting object creation check */
6862 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6866 ICALL_EXPORT MonoString *
6867 ves_icall_System_IO_get_temp_path (void)
6869 MONO_ARCH_SAVE_REGS;
6871 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6874 #ifndef PLATFORM_NO_DRIVEINFO
6875 ICALL_EXPORT MonoBoolean
6876 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6877 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6881 ULARGE_INTEGER wapi_free_bytes_avail;
6882 ULARGE_INTEGER wapi_total_number_of_bytes;
6883 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6885 MONO_ARCH_SAVE_REGS;
6887 *error = ERROR_SUCCESS;
6888 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6889 &wapi_total_number_of_free_bytes);
6892 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6893 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6894 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6896 *free_bytes_avail = 0;
6897 *total_number_of_bytes = 0;
6898 *total_number_of_free_bytes = 0;
6899 *error = GetLastError ();
6905 ICALL_EXPORT guint32
6906 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6908 MONO_ARCH_SAVE_REGS;
6910 return GetDriveType (mono_string_chars (root_path_name));
6914 ICALL_EXPORT gpointer
6915 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6917 MONO_ARCH_SAVE_REGS;
6919 return mono_compile_method (method);
6922 ICALL_EXPORT MonoString *
6923 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6928 MONO_ARCH_SAVE_REGS;
6930 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6932 #if defined (HOST_WIN32)
6933 /* Avoid mixing '/' and '\\' */
6936 for (i = strlen (path) - 1; i >= 0; i--)
6937 if (path [i] == '/')
6941 mcpath = mono_string_new (mono_domain_get (), path);
6948 get_bundled_app_config (void)
6950 const gchar *app_config;
6953 gchar *config_file_name, *config_file_path;
6957 MONO_ARCH_SAVE_REGS;
6959 domain = mono_domain_get ();
6960 file = domain->setup->configuration_file;
6964 // Retrieve config file and remove the extension
6965 config_file_name = mono_string_to_utf8 (file);
6966 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6967 if (!config_file_path)
6968 config_file_path = config_file_name;
6969 len = strlen (config_file_path) - strlen (".config");
6970 module = g_malloc0 (len + 1);
6971 memcpy (module, config_file_path, len);
6972 // Get the config file from the module name
6973 app_config = mono_config_string_for_assembly_file (module);
6976 if (config_file_name != config_file_path)
6977 g_free (config_file_name);
6978 g_free (config_file_path);
6983 return mono_string_new (mono_domain_get (), app_config);
6987 get_bundled_machine_config (void)
6989 const gchar *machine_config;
6991 MONO_ARCH_SAVE_REGS;
6993 machine_config = mono_get_machine_config ();
6995 if (!machine_config)
6998 return mono_string_new (mono_domain_get (), machine_config);
7001 ICALL_EXPORT MonoString *
7002 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7007 MONO_ARCH_SAVE_REGS;
7009 path = g_path_get_dirname (mono_get_config_dir ());
7011 #if defined (HOST_WIN32)
7012 /* Avoid mixing '/' and '\\' */
7015 for (i = strlen (path) - 1; i >= 0; i--)
7016 if (path [i] == '/')
7020 ipath = mono_string_new (mono_domain_get (), path);
7026 ICALL_EXPORT gboolean
7027 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7029 MonoPEResourceDataEntry *entry;
7032 MONO_ARCH_SAVE_REGS;
7034 if (!assembly || !result || !size)
7039 image = assembly->assembly->image;
7040 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7044 *result = mono_image_rva_map (image, entry->rde_data_offset);
7049 *size = entry->rde_size;
7054 ICALL_EXPORT MonoBoolean
7055 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7057 return mono_is_debugger_attached ();
7060 ICALL_EXPORT MonoBoolean
7061 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7063 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7064 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7070 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7072 if (mono_get_runtime_callbacks ()->debug_log)
7073 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7077 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7079 #if defined (HOST_WIN32)
7080 OutputDebugString (mono_string_chars (message));
7082 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7086 /* Only used for value types */
7087 ICALL_EXPORT MonoObject *
7088 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7093 MONO_ARCH_SAVE_REGS;
7095 domain = mono_object_domain (type);
7096 klass = mono_class_from_mono_type (type->type);
7097 mono_class_init_or_throw (klass);
7099 if (mono_class_is_nullable (klass))
7100 /* No arguments -> null */
7103 return mono_object_new (domain, klass);
7106 ICALL_EXPORT MonoReflectionMethod *
7107 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7109 MonoClass *klass, *parent;
7110 MonoMethod *method = m->method;
7111 MonoMethod *result = NULL;
7114 MONO_ARCH_SAVE_REGS;
7116 if (method->klass == NULL)
7119 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7120 MONO_CLASS_IS_INTERFACE (method->klass) ||
7121 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7124 slot = mono_method_get_vtable_slot (method);
7128 klass = method->klass;
7129 if (klass->generic_class)
7130 klass = klass->generic_class->container_class;
7133 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7134 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7135 mono_class_setup_vtable (parent);
7136 if (parent->vtable_size <= slot)
7141 klass = klass->parent;
7146 if (klass == method->klass)
7149 /*This is possible if definition == FALSE.
7150 * Do it here to be really sure we don't read invalid memory.
7152 if (slot >= klass->vtable_size)
7155 mono_class_setup_vtable (klass);
7157 result = klass->vtable [slot];
7158 if (result == NULL) {
7159 /* It is an abstract method */
7160 gpointer iter = NULL;
7161 while ((result = mono_class_get_methods (klass, &iter)))
7162 if (result->slot == slot)
7169 return mono_method_get_object (mono_domain_get (), result, NULL);
7172 ICALL_EXPORT MonoString*
7173 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7175 MonoMethod *method = m->method;
7177 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7182 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7184 MONO_ARCH_SAVE_REGS;
7186 iter->sig = *(MonoMethodSignature**)argsp;
7188 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7189 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7192 /* FIXME: it's not documented what start is exactly... */
7196 iter->args = argsp + sizeof (gpointer);
7198 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7200 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7203 ICALL_EXPORT MonoTypedRef
7204 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7206 guint32 i, arg_size;
7209 MONO_ARCH_SAVE_REGS;
7211 i = iter->sig->sentinelpos + iter->next_arg;
7213 g_assert (i < iter->sig->param_count);
7215 res.type = iter->sig->params [i];
7216 res.klass = mono_class_from_mono_type (res.type);
7217 arg_size = mono_type_stack_size (res.type, &align);
7218 #if defined(__arm__) || defined(__mips__)
7219 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7221 res.value = iter->args;
7222 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7223 /* Values are stored as 8 byte register sized objects, but 'value'
7224 * is dereferenced as a pointer in other routines.
7226 res.value = (char*)res.value + 4;
7228 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7229 if (arg_size <= sizeof (gpointer)) {
7231 int padding = arg_size - mono_type_size (res.type, &dummy);
7232 res.value = (guint8*)res.value + padding;
7235 iter->args = (char*)iter->args + arg_size;
7238 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7243 ICALL_EXPORT MonoTypedRef
7244 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7246 guint32 i, arg_size;
7249 MONO_ARCH_SAVE_REGS;
7251 i = iter->sig->sentinelpos + iter->next_arg;
7253 g_assert (i < iter->sig->param_count);
7255 while (i < iter->sig->param_count) {
7256 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7258 res.type = iter->sig->params [i];
7259 res.klass = mono_class_from_mono_type (res.type);
7260 /* FIXME: endianess issue... */
7261 arg_size = mono_type_stack_size (res.type, &align);
7262 #if defined(__arm__) || defined(__mips__)
7263 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7265 res.value = iter->args;
7266 iter->args = (char*)iter->args + arg_size;
7268 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7271 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7279 ICALL_EXPORT MonoType*
7280 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7283 MONO_ARCH_SAVE_REGS;
7285 i = iter->sig->sentinelpos + iter->next_arg;
7287 g_assert (i < iter->sig->param_count);
7289 return iter->sig->params [i];
7292 ICALL_EXPORT MonoObject*
7293 mono_TypedReference_ToObject (MonoTypedRef tref)
7295 MONO_ARCH_SAVE_REGS;
7297 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7298 MonoObject** objp = tref.value;
7302 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7305 ICALL_EXPORT MonoObject*
7306 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7308 MONO_ARCH_SAVE_REGS;
7310 if (MONO_TYPE_IS_REFERENCE (type)) {
7311 MonoObject** objp = value;
7315 return mono_value_box (mono_domain_get (), klass, value);
7319 prelink_method (MonoMethod *method)
7321 const char *exc_class, *exc_arg;
7322 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7324 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7326 mono_raise_exception(
7327 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7329 /* create the wrapper, too? */
7333 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7335 MONO_ARCH_SAVE_REGS;
7336 prelink_method (method->method);
7340 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7342 MonoClass *klass = mono_class_from_mono_type (type->type);
7344 gpointer iter = NULL;
7345 MONO_ARCH_SAVE_REGS;
7347 mono_class_init_or_throw (klass);
7349 while ((m = mono_class_get_methods (klass, &iter)))
7353 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7355 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7356 gint32 const **exponents,
7357 gunichar2 const **digitLowerTable,
7358 gunichar2 const **digitUpperTable,
7359 gint64 const **tenPowersList,
7360 gint32 const **decHexDigits)
7362 *mantissas = Formatter_MantissaBitsTable;
7363 *exponents = Formatter_TensExponentTable;
7364 *digitLowerTable = Formatter_DigitLowerTable;
7365 *digitUpperTable = Formatter_DigitUpperTable;
7366 *tenPowersList = Formatter_TenPowersList;
7367 *decHexDigits = Formatter_DecHexDigits;
7371 get_category_data (int version,
7372 guint8 const **category_data,
7373 guint16 const **category_astral_index)
7375 *category_astral_index = NULL;
7377 #ifndef DISABLE_NET_4_0
7379 *category_data = CategoryData_v4;
7380 #ifndef DISABLE_ASTRAL
7381 *category_astral_index = CategoryData_v4_astral_index;
7387 *category_data = CategoryData_v2;
7388 #ifndef DISABLE_ASTRAL
7389 *category_astral_index = CategoryData_v2_astral_index;
7393 /* These parameters are "readonly" in corlib/System/Char.cs */
7395 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7396 guint8 const **category_data,
7397 guint16 const **category_astral_index,
7398 guint8 const **numeric_data,
7399 gdouble const **numeric_data_values,
7400 guint16 const **to_lower_data_low,
7401 guint16 const **to_lower_data_high,
7402 guint16 const **to_upper_data_low,
7403 guint16 const **to_upper_data_high)
7405 get_category_data (category_data_version, category_data, category_astral_index);
7406 *numeric_data = NumericData;
7407 *numeric_data_values = NumericDataValues;
7408 *to_lower_data_low = ToLowerDataLow;
7409 *to_lower_data_high = ToLowerDataHigh;
7410 *to_upper_data_low = ToUpperDataLow;
7411 *to_upper_data_high = ToUpperDataHigh;
7415 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7417 return method->method->token;
7421 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7422 * and avoid useless allocations.
7425 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7429 for (i = 0; i < type->num_mods; ++i) {
7430 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7435 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7437 for (i = 0; i < type->num_mods; ++i) {
7438 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7439 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7440 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7447 ICALL_EXPORT MonoArray*
7448 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7450 MonoType *type = param->ClassImpl->type;
7451 MonoClass *member_class = mono_object_class (param->MemberImpl);
7452 MonoMethod *method = NULL;
7455 MonoMethodSignature *sig;
7457 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7458 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7459 method = rmethod->method;
7460 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7461 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7462 if (!(method = prop->property->get))
7463 method = prop->property->set;
7466 char *type_name = mono_type_get_full_name (member_class);
7467 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7468 MonoException *ex = mono_get_exception_not_supported (msg);
7471 mono_raise_exception (ex);
7474 image = method->klass->image;
7475 pos = param->PositionImpl;
7476 sig = mono_method_signature (method);
7480 type = sig->params [pos];
7482 return type_array_from_modifiers (image, type, optional);
7486 get_property_type (MonoProperty *prop)
7488 MonoMethodSignature *sig;
7490 sig = mono_method_signature (prop->get);
7492 } else if (prop->set) {
7493 sig = mono_method_signature (prop->set);
7494 return sig->params [sig->param_count - 1];
7499 ICALL_EXPORT MonoArray*
7500 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7502 MonoType *type = get_property_type (property->property);
7503 MonoImage *image = property->klass->image;
7507 return type_array_from_modifiers (image, type, optional);
7511 *Construct a MonoType suited to be used to decode a constant blob object.
7513 * @type is the target type which will be constructed
7514 * @blob_type is the blob type, for example, that comes from the constant table
7515 * @real_type is the expected constructed type.
7518 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7520 type->type = blob_type;
7521 type->data.klass = NULL;
7522 if (blob_type == MONO_TYPE_CLASS)
7523 type->data.klass = mono_defaults.object_class;
7524 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7525 /* For enums, we need to use the base type */
7526 type->type = MONO_TYPE_VALUETYPE;
7527 type->data.klass = mono_class_from_mono_type (real_type);
7529 type->data.klass = mono_class_from_mono_type (real_type);
7532 ICALL_EXPORT MonoObject*
7533 property_info_get_default_value (MonoReflectionProperty *property)
7536 MonoProperty *prop = property->property;
7537 MonoType *type = get_property_type (prop);
7538 MonoDomain *domain = mono_object_domain (property);
7539 MonoTypeEnum def_type;
7540 const char *def_value;
7543 mono_class_init (prop->parent);
7545 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7546 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7548 def_value = mono_class_get_property_default_value (prop, &def_type);
7550 mono_type_from_blob_type (&blob_type, def_type, type);
7551 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7556 ICALL_EXPORT MonoBoolean
7557 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7559 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7560 MonoCustomAttrInfo *cinfo;
7563 mono_class_init_or_throw (attr_class);
7565 cinfo = mono_reflection_get_custom_attrs_info (obj);
7568 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7570 mono_custom_attrs_free (cinfo);
7574 ICALL_EXPORT MonoArray*
7575 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7577 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7582 mono_class_init_or_throw (attr_class);
7584 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7585 mono_error_raise_exception (&error);
7587 if (mono_loader_get_last_error ()) {
7588 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7589 g_assert_not_reached ();
7597 ICALL_EXPORT MonoString*
7598 ves_icall_Mono_Runtime_GetDisplayName (void)
7601 MonoString *display_name;
7603 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7604 display_name = mono_string_new (mono_domain_get (), info);
7606 return display_name;
7609 ICALL_EXPORT MonoString*
7610 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7612 MonoString *message;
7616 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7617 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7620 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7622 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7630 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
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, 62, 128, 128, 128, 63,
7633 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7634 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7635 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7636 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7637 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7641 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7646 gunichar2 last, prev_last, prev2_last;
7653 int havePadding = 0;
7655 last = prev_last = 0, prev2_last = 0;
7656 for (i = 0; i < ilength; i++) {
7658 if (c >= sizeof (dbase64)) {
7659 exc = mono_exception_from_name_msg (mono_get_corlib (),
7660 "System", "FormatException",
7661 "Invalid character found.");
7662 mono_raise_exception (exc);
7663 } else if (isspace (c)) {
7665 } else if (havePadding && c != '=') {
7666 exc = mono_exception_from_name_msg (mono_get_corlib (),
7667 "System", "FormatException",
7668 "Invalid character found.");
7669 mono_raise_exception (exc);
7671 if (c == '=') havePadding = 1;
7672 prev2_last = prev_last;
7678 olength = ilength - ignored;
7680 if (allowWhitespaceOnly && olength == 0) {
7681 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7684 if ((olength & 3) != 0 || olength <= 0) {
7685 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7686 "FormatException", "Invalid length.");
7687 mono_raise_exception (exc);
7690 if (prev2_last == '=') {
7691 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7692 mono_raise_exception (exc);
7695 olength = (olength * 3) / 4;
7699 if (prev_last == '=')
7702 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7703 res_ptr = mono_array_addr (result, guchar, 0);
7704 for (i = 0; i < ilength; ) {
7707 for (k = 0; k < 4 && i < ilength;) {
7713 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7714 exc = mono_exception_from_name_msg (mono_get_corlib (),
7715 "System", "FormatException",
7716 "Invalid character found.");
7717 mono_raise_exception (exc);
7722 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7724 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7726 *res_ptr++ = (b [2] << 6) | b [3];
7728 while (i < ilength && isspace (start [i]))
7735 ICALL_EXPORT MonoArray *
7736 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7738 MONO_ARCH_SAVE_REGS;
7740 return base64_to_byte_array (mono_string_chars (str),
7741 mono_string_length (str), allowWhitespaceOnly);
7744 ICALL_EXPORT MonoArray *
7745 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7747 MONO_ARCH_SAVE_REGS;
7749 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7753 #ifndef DISABLE_ICALL_TABLES
7755 #define ICALL_TYPE(id,name,first)
7756 #define ICALL(id,name,func) Icall_ ## id,
7759 #include "metadata/icall-def.h"
7765 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7766 #define ICALL(id,name,func)
7768 #include "metadata/icall-def.h"
7774 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7775 #define ICALL(id,name,func)
7777 guint16 first_icall;
7780 static const IcallTypeDesc
7781 icall_type_descs [] = {
7782 #include "metadata/icall-def.h"
7786 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7789 #define ICALL_TYPE(id,name,first)
7792 #ifdef HAVE_ARRAY_ELEM_INIT
7793 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7794 #define MSGSTRFIELD1(line) str##line
7796 static const struct msgstrtn_t {
7797 #define ICALL(id,name,func)
7799 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7800 #include "metadata/icall-def.h"
7802 } icall_type_names_str = {
7803 #define ICALL_TYPE(id,name,first) (name),
7804 #include "metadata/icall-def.h"
7807 static const guint16 icall_type_names_idx [] = {
7808 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7809 #include "metadata/icall-def.h"
7812 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7814 static const struct msgstr_t {
7816 #define ICALL_TYPE(id,name,first)
7817 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7818 #include "metadata/icall-def.h"
7820 } icall_names_str = {
7821 #define ICALL(id,name,func) (name),
7822 #include "metadata/icall-def.h"
7825 static const guint16 icall_names_idx [] = {
7826 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7827 #include "metadata/icall-def.h"
7830 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7836 #define ICALL_TYPE(id,name,first) name,
7837 #define ICALL(id,name,func)
7838 static const char* const
7839 icall_type_names [] = {
7840 #include "metadata/icall-def.h"
7844 #define icall_type_name_get(id) (icall_type_names [(id)])
7848 #define ICALL_TYPE(id,name,first)
7849 #define ICALL(id,name,func) name,
7850 static const char* const
7852 #include "metadata/icall-def.h"
7855 #define icall_name_get(id) icall_names [(id)]
7857 #endif /* !HAVE_ARRAY_ELEM_INIT */
7861 #define ICALL_TYPE(id,name,first)
7862 #define ICALL(id,name,func) func,
7863 static const gconstpointer
7864 icall_functions [] = {
7865 #include "metadata/icall-def.h"
7869 #ifdef ENABLE_ICALL_SYMBOL_MAP
7872 #define ICALL_TYPE(id,name,first)
7873 #define ICALL(id,name,func) #func,
7874 static const gconstpointer
7875 icall_symbols [] = {
7876 #include "metadata/icall-def.h"
7881 #endif /* DISABLE_ICALL_TABLES */
7883 static mono_mutex_t icall_mutex;
7884 static GHashTable *icall_hash = NULL;
7885 static GHashTable *jit_icall_hash_name = NULL;
7886 static GHashTable *jit_icall_hash_addr = NULL;
7889 mono_icall_init (void)
7891 #ifndef DISABLE_ICALL_TABLES
7894 /* check that tables are sorted: disable in release */
7897 const char *prev_class = NULL;
7898 const char *prev_method;
7900 for (i = 0; i < Icall_type_num; ++i) {
7901 const IcallTypeDesc *desc;
7904 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7905 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7906 prev_class = icall_type_name_get (i);
7907 desc = &icall_type_descs [i];
7908 num_icalls = icall_desc_num_icalls (desc);
7909 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7910 for (j = 0; j < num_icalls; ++j) {
7911 const char *methodn = icall_name_get (desc->first_icall + j);
7912 if (prev_method && strcmp (prev_method, methodn) >= 0)
7913 g_print ("method %s should come before method %s\n", methodn, prev_method);
7914 prev_method = methodn;
7920 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7921 mono_mutex_init (&icall_mutex);
7925 mono_icall_lock (void)
7927 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7931 mono_icall_unlock (void)
7933 mono_locks_mutex_release (&icall_mutex, IcallLock);
7937 mono_icall_cleanup (void)
7939 g_hash_table_destroy (icall_hash);
7940 g_hash_table_destroy (jit_icall_hash_name);
7941 g_hash_table_destroy (jit_icall_hash_addr);
7942 mono_mutex_destroy (&icall_mutex);
7946 mono_add_internal_call (const char *name, gconstpointer method)
7950 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7952 mono_icall_unlock ();
7955 #ifndef DISABLE_ICALL_TABLES
7957 #ifdef HAVE_ARRAY_ELEM_INIT
7959 compare_method_imap (const void *key, const void *elem)
7961 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7962 return strcmp (key, method_name);
7966 find_method_icall (const IcallTypeDesc *imap, const char *name)
7968 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);
7971 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7975 compare_class_imap (const void *key, const void *elem)
7977 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7978 return strcmp (key, class_name);
7981 static const IcallTypeDesc*
7982 find_class_icalls (const char *name)
7984 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7987 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7990 #else /* HAVE_ARRAY_ELEM_INIT */
7993 compare_method_imap (const void *key, const void *elem)
7995 const char** method_name = (const char**)elem;
7996 return strcmp (key, *method_name);
8000 find_method_icall (const IcallTypeDesc *imap, const char *name)
8002 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8005 return (gpointer)icall_functions [(nameslot - icall_names)];
8009 compare_class_imap (const void *key, const void *elem)
8011 const char** class_name = (const char**)elem;
8012 return strcmp (key, *class_name);
8015 static const IcallTypeDesc*
8016 find_class_icalls (const char *name)
8018 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8021 return &icall_type_descs [nameslot - icall_type_names];
8024 #endif /* HAVE_ARRAY_ELEM_INIT */
8026 #endif /* DISABLE_ICALL_TABLES */
8029 * we should probably export this as an helper (handle nested types).
8030 * Returns the number of chars written in buf.
8033 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8035 int nspacelen, cnamelen;
8036 nspacelen = strlen (klass->name_space);
8037 cnamelen = strlen (klass->name);
8038 if (nspacelen + cnamelen + 2 > bufsize)
8041 memcpy (buf, klass->name_space, nspacelen);
8042 buf [nspacelen ++] = '.';
8044 memcpy (buf + nspacelen, klass->name, cnamelen);
8045 buf [nspacelen + cnamelen] = 0;
8046 return nspacelen + cnamelen;
8049 #ifdef DISABLE_ICALL_TABLES
8051 no_icall_table (void)
8053 g_assert_not_reached ();
8058 mono_lookup_internal_call (MonoMethod *method)
8063 int typelen = 0, mlen, siglen;
8065 #ifndef DISABLE_ICALL_TABLES
8066 const IcallTypeDesc *imap = NULL;
8069 g_assert (method != NULL);
8071 if (method->is_inflated)
8072 method = ((MonoMethodInflated *) method)->declaring;
8074 if (method->klass->nested_in) {
8075 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8079 mname [pos++] = '/';
8082 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8088 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8093 #ifndef DISABLE_ICALL_TABLES
8094 imap = find_class_icalls (mname);
8097 mname [typelen] = ':';
8098 mname [typelen + 1] = ':';
8100 mlen = strlen (method->name);
8101 memcpy (mname + typelen + 2, method->name, mlen);
8102 sigstart = mname + typelen + 2 + mlen;
8105 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8106 siglen = strlen (tmpsig);
8107 if (typelen + mlen + siglen + 6 > sizeof (mname))
8110 memcpy (sigstart + 1, tmpsig, siglen);
8111 sigstart [siglen + 1] = ')';
8112 sigstart [siglen + 2] = 0;
8117 res = g_hash_table_lookup (icall_hash, mname);
8119 mono_icall_unlock ();;
8122 /* try without signature */
8124 res = g_hash_table_lookup (icall_hash, mname);
8126 mono_icall_unlock ();
8130 #ifdef DISABLE_ICALL_TABLES
8131 mono_icall_unlock ();
8132 /* Fail only when the result is actually used */
8133 /* mono_marshal_get_native_wrapper () depends on this */
8134 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8135 return ves_icall_System_String_ctor_RedirectToCreateString;
8137 return no_icall_table;
8139 /* it wasn't found in the static call tables */
8141 mono_icall_unlock ();
8144 res = find_method_icall (imap, sigstart - mlen);
8146 mono_icall_unlock ();
8149 /* try _with_ signature */
8151 res = find_method_icall (imap, sigstart - mlen);
8153 mono_icall_unlock ();
8157 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8158 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8159 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8160 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8161 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");
8162 g_print ("If you see other errors or faults after this message they are probably related\n");
8163 g_print ("and you need to fix your mono install first.\n");
8165 mono_icall_unlock ();
8171 #ifdef ENABLE_ICALL_SYMBOL_MAP
8173 func_cmp (gconstpointer key, gconstpointer p)
8175 return (gsize)key - (gsize)*(gsize*)p;
8180 * mono_lookup_icall_symbol:
8182 * Given the icall METHOD, returns its C symbol.
8185 mono_lookup_icall_symbol (MonoMethod *m)
8187 #ifdef DISABLE_ICALL_TABLES
8188 g_assert_not_reached ();
8191 #ifdef ENABLE_ICALL_SYMBOL_MAP
8195 static gconstpointer *functions_sorted;
8196 static const char**symbols_sorted;
8197 static gboolean inited;
8202 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8203 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8204 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8205 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8206 /* Bubble sort the two arrays */
8210 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8211 if (functions_sorted [i] > functions_sorted [i + 1]) {
8214 tmp = functions_sorted [i];
8215 functions_sorted [i] = functions_sorted [i + 1];
8216 functions_sorted [i + 1] = tmp;
8217 tmp = symbols_sorted [i];
8218 symbols_sorted [i] = symbols_sorted [i + 1];
8219 symbols_sorted [i + 1] = tmp;
8226 func = mono_lookup_internal_call (m);
8229 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8233 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8235 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8236 g_assert_not_reached ();
8243 type_from_typename (char *typename)
8245 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8247 if (!strcmp (typename, "int"))
8248 klass = mono_defaults.int_class;
8249 else if (!strcmp (typename, "ptr"))
8250 klass = mono_defaults.int_class;
8251 else if (!strcmp (typename, "void"))
8252 klass = mono_defaults.void_class;
8253 else if (!strcmp (typename, "int32"))
8254 klass = mono_defaults.int32_class;
8255 else if (!strcmp (typename, "uint32"))
8256 klass = mono_defaults.uint32_class;
8257 else if (!strcmp (typename, "int8"))
8258 klass = mono_defaults.sbyte_class;
8259 else if (!strcmp (typename, "uint8"))
8260 klass = mono_defaults.byte_class;
8261 else if (!strcmp (typename, "int16"))
8262 klass = mono_defaults.int16_class;
8263 else if (!strcmp (typename, "uint16"))
8264 klass = mono_defaults.uint16_class;
8265 else if (!strcmp (typename, "long"))
8266 klass = mono_defaults.int64_class;
8267 else if (!strcmp (typename, "ulong"))
8268 klass = mono_defaults.uint64_class;
8269 else if (!strcmp (typename, "float"))
8270 klass = mono_defaults.single_class;
8271 else if (!strcmp (typename, "double"))
8272 klass = mono_defaults.double_class;
8273 else if (!strcmp (typename, "object"))
8274 klass = mono_defaults.object_class;
8275 else if (!strcmp (typename, "obj"))
8276 klass = mono_defaults.object_class;
8277 else if (!strcmp (typename, "string"))
8278 klass = mono_defaults.string_class;
8279 else if (!strcmp (typename, "bool"))
8280 klass = mono_defaults.boolean_class;
8281 else if (!strcmp (typename, "boolean"))
8282 klass = mono_defaults.boolean_class;
8284 g_error ("%s", typename);
8285 g_assert_not_reached ();
8287 return &klass->byval_arg;
8291 * LOCKING: Take the corlib image lock.
8293 MonoMethodSignature*
8294 mono_create_icall_signature (const char *sigstr)
8299 MonoMethodSignature *res, *res2;
8300 MonoImage *corlib = mono_defaults.corlib;
8302 mono_image_lock (corlib);
8303 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8304 mono_image_unlock (corlib);
8309 parts = g_strsplit (sigstr, " ", 256);
8318 res = mono_metadata_signature_alloc (corlib, len - 1);
8323 * Under windows, the default pinvoke calling convention is STDCALL but
8326 res->call_convention = MONO_CALL_C;
8329 res->ret = type_from_typename (parts [0]);
8330 for (i = 1; i < len; ++i) {
8331 res->params [i - 1] = type_from_typename (parts [i]);
8336 mono_image_lock (corlib);
8337 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8339 res = res2; /*Value is allocated in the image pool*/
8341 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8342 mono_image_unlock (corlib);
8348 mono_find_jit_icall_by_name (const char *name)
8350 MonoJitICallInfo *info;
8351 g_assert (jit_icall_hash_name);
8354 info = g_hash_table_lookup (jit_icall_hash_name, name);
8355 mono_icall_unlock ();
8360 mono_find_jit_icall_by_addr (gconstpointer addr)
8362 MonoJitICallInfo *info;
8363 g_assert (jit_icall_hash_addr);
8366 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8367 mono_icall_unlock ();
8373 * mono_get_jit_icall_info:
8375 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8376 * caller should access it while holding the icall lock.
8379 mono_get_jit_icall_info (void)
8381 return jit_icall_hash_name;
8385 * mono_lookup_jit_icall_symbol:
8387 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8390 mono_lookup_jit_icall_symbol (const char *name)
8392 MonoJitICallInfo *info;
8393 const char *res = NULL;
8396 info = g_hash_table_lookup (jit_icall_hash_name, name);
8398 res = info->c_symbol;
8399 mono_icall_unlock ();
8404 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8407 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8408 mono_icall_unlock ();
8412 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8414 MonoJitICallInfo *info;
8421 if (!jit_icall_hash_name) {
8422 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8423 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8426 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8427 g_warning ("jit icall already defined \"%s\"\n", name);
8428 g_assert_not_reached ();
8431 info = g_new0 (MonoJitICallInfo, 1);
8436 info->c_symbol = c_symbol;
8439 info->wrapper = func;
8441 info->wrapper = NULL;
8444 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8445 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8447 mono_icall_unlock ();
8452 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8454 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);