5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
22 #ifdef HAVE_SYS_TIME_H
28 #if defined (HOST_WIN32)
31 #if defined (HAVE_WCHAR_H)
35 #include "mono/utils/mono-membar.h"
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/threads.h>
38 #include <mono/metadata/threads-types.h>
39 #include <mono/metadata/threadpool.h>
40 #include <mono/metadata/monitor.h>
41 #include <mono/metadata/reflection.h>
42 #include <mono/metadata/assembly.h>
43 #include <mono/metadata/tabledefs.h>
44 #include <mono/metadata/exception.h>
45 #include <mono/metadata/file-io.h>
46 #include <mono/metadata/console-io.h>
47 #include <mono/metadata/socket-io.h>
48 #include <mono/metadata/mono-endian.h>
49 #include <mono/metadata/tokentype.h>
50 #include <mono/metadata/domain-internals.h>
51 #include <mono/metadata/metadata-internals.h>
52 #include <mono/metadata/class-internals.h>
53 #include <mono/metadata/marshal.h>
54 #include <mono/metadata/gc-internal.h>
55 #include <mono/metadata/mono-gc.h>
56 #include <mono/metadata/rand.h>
57 #include <mono/metadata/sysmath.h>
58 #include <mono/metadata/string-icalls.h>
59 #include <mono/metadata/debug-helpers.h>
60 #include <mono/metadata/process.h>
61 #include <mono/metadata/environment.h>
62 #include <mono/metadata/profiler-private.h>
63 #include <mono/metadata/locales.h>
64 #include <mono/metadata/filewatcher.h>
65 #include <mono/metadata/char-conversions.h>
66 #include <mono/metadata/security.h>
67 #include <mono/metadata/mono-config.h>
68 #include <mono/metadata/cil-coff.h>
69 #include <mono/metadata/number-formatter.h>
70 #include <mono/metadata/security-manager.h>
71 #include <mono/metadata/security-core-clr.h>
72 #include <mono/metadata/mono-perfcounters.h>
73 #include <mono/metadata/mono-debug.h>
74 #include <mono/metadata/mono-ptr-array.h>
75 #include <mono/metadata/verify-internals.h>
76 #include <mono/metadata/runtime.h>
77 #include <mono/io-layer/io-layer.h>
78 #include <mono/utils/strtod.h>
79 #include <mono/utils/monobitset.h>
80 #include <mono/utils/mono-time.h>
81 #include <mono/utils/mono-proclib.h>
82 #include <mono/utils/mono-string.h>
83 #include <mono/utils/mono-error-internals.h>
84 #include <mono/utils/mono-mmap.h>
85 #include <mono/utils/mono-io-portability.h>
86 #include <mono/utils/mono-digest.h>
87 #include <mono/utils/bsearch.h>
88 #include <mono/utils/mono-mutex.h>
89 #include <mono/utils/mono-threads.h>
91 #if defined (HOST_WIN32)
97 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
99 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
102 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
104 static inline MonoBoolean
105 is_generic_parameter (MonoType *type)
107 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
111 mono_class_init_or_throw (MonoClass *klass)
113 if (!mono_class_init (klass))
114 mono_raise_exception (mono_class_get_exception_for_failure (klass));
118 * We expect a pointer to a char, not a string
120 ICALL_EXPORT gboolean
121 mono_double_ParseImpl (char *ptr, double *result)
123 gchar *endptr = NULL;
130 *result = strtod (ptr, &endptr);
133 /* mono_strtod () is not thread-safe */
134 EnterCriticalSection (&mono_strtod_mutex);
135 *result = mono_strtod (ptr, &endptr);
136 LeaveCriticalSection (&mono_strtod_mutex);
140 if (!*ptr || (endptr && *endptr))
146 ICALL_EXPORT MonoObject *
147 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
156 ao = (MonoArray *)this;
157 ac = (MonoClass *)ao->obj.vtable->klass;
159 esize = mono_array_element_size (ac);
160 ea = (gpointer*)((char*)ao->vector + (pos * esize));
162 if (ac->element_class->valuetype)
163 return mono_value_box (this->vtable->domain, ac->element_class, ea);
168 ICALL_EXPORT MonoObject *
169 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
177 MONO_CHECK_ARG_NULL (idxs);
179 io = (MonoArray *)idxs;
180 ic = (MonoClass *)io->obj.vtable->klass;
182 ao = (MonoArray *)this;
183 ac = (MonoClass *)ao->obj.vtable->klass;
185 g_assert (ic->rank == 1);
186 if (io->bounds != NULL || io->max_length != ac->rank)
187 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
189 ind = (gint32 *)io->vector;
191 if (ao->bounds == NULL) {
192 if (*ind < 0 || *ind >= ao->max_length)
193 mono_raise_exception (mono_get_exception_index_out_of_range ());
195 return ves_icall_System_Array_GetValueImpl (this, *ind);
198 for (i = 0; i < ac->rank; i++)
199 if ((ind [i] < ao->bounds [i].lower_bound) ||
200 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
201 mono_raise_exception (mono_get_exception_index_out_of_range ());
203 pos = ind [0] - ao->bounds [0].lower_bound;
204 for (i = 1; i < ac->rank; i++)
205 pos = pos*ao->bounds [i].length + ind [i] -
206 ao->bounds [i].lower_bound;
208 return ves_icall_System_Array_GetValueImpl (this, pos);
212 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
214 MonoClass *ac, *vc, *ec;
226 vc = value->vtable->klass;
230 ac = this->obj.vtable->klass;
231 ec = ac->element_class;
233 esize = mono_array_element_size (ac);
234 ea = (gpointer*)((char*)this->vector + (pos * esize));
235 va = (gpointer*)((char*)value + sizeof (MonoObject));
237 if (mono_class_is_nullable (ec)) {
238 mono_nullable_init ((guint8*)ea, value, ec);
243 mono_gc_bzero (ea, esize);
247 #define NO_WIDENING_CONVERSION G_STMT_START{\
248 mono_raise_exception (mono_get_exception_argument ( \
249 "value", "not a widening conversion")); \
252 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
253 if (esize < vsize + (extra)) \
254 mono_raise_exception (mono_get_exception_argument ( \
255 "value", "not a widening conversion")); \
258 #define INVALID_CAST G_STMT_START{ \
259 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
260 mono_raise_exception (mono_get_exception_invalid_cast ()); \
263 /* Check element (destination) type. */
264 switch (ec->byval_arg.type) {
265 case MONO_TYPE_STRING:
266 switch (vc->byval_arg.type) {
267 case MONO_TYPE_STRING:
273 case MONO_TYPE_BOOLEAN:
274 switch (vc->byval_arg.type) {
275 case MONO_TYPE_BOOLEAN:
288 NO_WIDENING_CONVERSION;
295 if (!ec->valuetype) {
296 if (!mono_object_isinst (value, ec))
298 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
302 if (mono_object_isinst (value, ec)) {
303 if (ec->has_references)
304 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
306 mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
313 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
315 et = ec->byval_arg.type;
316 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
317 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
319 vt = vc->byval_arg.type;
320 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
321 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
323 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
329 case MONO_TYPE_CHAR: \
330 CHECK_WIDENING_CONVERSION(0); \
331 *(etype *) ea = (etype) u64; \
333 /* You can't assign a signed value to an unsigned array. */ \
338 /* You can't assign a floating point number to an integer array. */ \
341 NO_WIDENING_CONVERSION; \
345 #define ASSIGN_SIGNED(etype) G_STMT_START{\
351 CHECK_WIDENING_CONVERSION(0); \
352 *(etype *) ea = (etype) i64; \
354 /* You can assign an unsigned value to a signed array if the array's */ \
355 /* element size is larger than the value size. */ \
360 case MONO_TYPE_CHAR: \
361 CHECK_WIDENING_CONVERSION(1); \
362 *(etype *) ea = (etype) u64; \
364 /* You can't assign a floating point number to an integer array. */ \
367 NO_WIDENING_CONVERSION; \
371 #define ASSIGN_REAL(etype) G_STMT_START{\
375 CHECK_WIDENING_CONVERSION(0); \
376 *(etype *) ea = (etype) r64; \
378 /* All integer values fit into a floating point array, so we don't */ \
379 /* need to CHECK_WIDENING_CONVERSION here. */ \
384 *(etype *) ea = (etype) i64; \
390 case MONO_TYPE_CHAR: \
391 *(etype *) ea = (etype) u64; \
398 u64 = *(guint8 *) va;
401 u64 = *(guint16 *) va;
404 u64 = *(guint32 *) va;
407 u64 = *(guint64 *) va;
413 i64 = *(gint16 *) va;
416 i64 = *(gint32 *) va;
419 i64 = *(gint64 *) va;
422 r64 = *(gfloat *) va;
425 r64 = *(gdouble *) va;
428 u64 = *(guint16 *) va;
430 case MONO_TYPE_BOOLEAN:
431 /* Boolean is only compatible with itself. */
444 NO_WIDENING_CONVERSION;
451 /* If we can't do a direct copy, let's try a widening conversion. */
454 ASSIGN_UNSIGNED (guint16);
456 ASSIGN_UNSIGNED (guint8);
458 ASSIGN_UNSIGNED (guint16);
460 ASSIGN_UNSIGNED (guint32);
462 ASSIGN_UNSIGNED (guint64);
464 ASSIGN_SIGNED (gint8);
466 ASSIGN_SIGNED (gint16);
468 ASSIGN_SIGNED (gint32);
470 ASSIGN_SIGNED (gint64);
472 ASSIGN_REAL (gfloat);
474 ASSIGN_REAL (gdouble);
478 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
482 #undef NO_WIDENING_CONVERSION
483 #undef CHECK_WIDENING_CONVERSION
484 #undef ASSIGN_UNSIGNED
490 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
498 MONO_CHECK_ARG_NULL (idxs);
500 ic = idxs->obj.vtable->klass;
501 ac = this->obj.vtable->klass;
503 g_assert (ic->rank == 1);
504 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
505 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
507 ind = (gint32 *)idxs->vector;
509 if (this->bounds == NULL) {
510 if (*ind < 0 || *ind >= this->max_length)
511 mono_raise_exception (mono_get_exception_index_out_of_range ());
513 ves_icall_System_Array_SetValueImpl (this, value, *ind);
517 for (i = 0; i < ac->rank; i++)
518 if ((ind [i] < this->bounds [i].lower_bound) ||
519 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
520 mono_raise_exception (mono_get_exception_index_out_of_range ());
522 pos = ind [0] - this->bounds [0].lower_bound;
523 for (i = 1; i < ac->rank; i++)
524 pos = pos * this->bounds [i].length + ind [i] -
525 this->bounds [i].lower_bound;
527 ves_icall_System_Array_SetValueImpl (this, value, pos);
530 ICALL_EXPORT MonoArray *
531 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
533 MonoClass *aklass, *klass;
536 gboolean bounded = FALSE;
540 MONO_CHECK_ARG_NULL (type);
541 MONO_CHECK_ARG_NULL (lengths);
543 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
545 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
547 for (i = 0; i < mono_array_length (lengths); i++)
548 if (mono_array_get (lengths, gint32, i) < 0)
549 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
551 klass = mono_class_from_mono_type (type->type);
552 mono_class_init_or_throw (klass);
554 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
555 /* vectors are not the same as one dimensional arrays with no-zero bounds */
560 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
562 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
563 for (i = 0; i < aklass->rank; ++i) {
564 sizes [i] = mono_array_get (lengths, guint32, i);
566 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
568 sizes [i + aklass->rank] = 0;
571 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
576 ICALL_EXPORT MonoArray *
577 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
579 MonoClass *aklass, *klass;
582 gboolean bounded = FALSE;
586 MONO_CHECK_ARG_NULL (type);
587 MONO_CHECK_ARG_NULL (lengths);
589 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
591 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
593 for (i = 0; i < mono_array_length (lengths); i++)
594 if ((mono_array_get (lengths, gint64, i) < 0) ||
595 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
596 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
598 klass = mono_class_from_mono_type (type->type);
599 mono_class_init_or_throw (klass);
601 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
602 /* vectors are not the same as one dimensional arrays with no-zero bounds */
607 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
609 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
610 for (i = 0; i < aklass->rank; ++i) {
611 sizes [i] = mono_array_get (lengths, guint64, i);
613 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
615 sizes [i + aklass->rank] = 0;
618 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
624 ves_icall_System_Array_GetRank (MonoObject *this)
628 return this->vtable->klass->rank;
632 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
634 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
639 if ((dimension < 0) || (dimension >= rank))
640 mono_raise_exception (mono_get_exception_index_out_of_range ());
642 if (this->bounds == NULL)
643 length = this->max_length;
645 length = this->bounds [dimension].length;
647 #ifdef MONO_BIG_ARRAYS
648 if (length > G_MAXINT32)
649 mono_raise_exception (mono_get_exception_overflow ());
655 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
657 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
661 if ((dimension < 0) || (dimension >= rank))
662 mono_raise_exception (mono_get_exception_index_out_of_range ());
664 if (this->bounds == NULL)
665 return this->max_length;
667 return this->bounds [dimension].length;
671 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
673 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
677 if ((dimension < 0) || (dimension >= rank))
678 mono_raise_exception (mono_get_exception_index_out_of_range ());
680 if (this->bounds == NULL)
683 return this->bounds [dimension].lower_bound;
687 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
689 int sz = mono_array_element_size (mono_object_class (arr));
690 mono_gc_bzero (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
693 ICALL_EXPORT gboolean
694 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
699 MonoVTable *src_vtable;
700 MonoVTable *dest_vtable;
701 MonoClass *src_class;
702 MonoClass *dest_class;
704 src_vtable = source->obj.vtable;
705 dest_vtable = dest->obj.vtable;
707 if (src_vtable->rank != dest_vtable->rank)
710 if (source->bounds || dest->bounds)
713 /* there's no integer overflow since mono_array_length returns an unsigned integer */
714 if ((dest_idx + length > mono_array_length_fast (dest)) ||
715 (source_idx + length > mono_array_length_fast (source)))
718 src_class = src_vtable->klass->element_class;
719 dest_class = dest_vtable->klass->element_class;
722 * Handle common cases.
725 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
726 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
728 if (src_class == mono_defaults.object_class && dest_class->valuetype)
731 /* Check if we're copying a char[] <==> (u)short[] */
732 if (src_class != dest_class) {
733 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
736 /* 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. */
737 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
741 if (dest_class->valuetype) {
742 element_size = mono_array_element_size (source->obj.vtable->klass);
743 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
744 if (dest_class->has_references) {
745 mono_value_copy_array (dest, dest_idx, source_addr, length);
747 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
748 mono_gc_memmove (dest_addr, source_addr, element_size * length);
751 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
758 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
767 ao = (MonoArray *)this;
768 ac = (MonoClass *)ao->obj.vtable->klass;
770 esize = mono_array_element_size (ac);
771 ea = (gpointer*)((char*)ao->vector + (pos * esize));
773 mono_gc_memmove (value, ea, esize);
777 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
786 ao = (MonoArray *)this;
787 ac = (MonoClass *)ao->obj.vtable->klass;
788 ec = ac->element_class;
790 esize = mono_array_element_size (ac);
791 ea = (gpointer*)((char*)ao->vector + (pos * esize));
793 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
794 g_assert (esize == sizeof (gpointer));
795 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
797 g_assert (ec->inited);
798 g_assert (esize == mono_class_value_size (ec, NULL));
799 if (ec->has_references)
800 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
802 mono_gc_memmove (ea, value, esize);
807 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
809 MonoClass *klass = array->obj.vtable->klass;
810 guint32 size = mono_array_element_size (klass);
811 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
813 const char *field_data;
815 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
816 MonoException *exc = mono_get_exception_argument("array",
817 "Cannot initialize array of non-primitive type.");
818 mono_raise_exception (exc);
821 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
822 MonoException *exc = mono_get_exception_argument("field_handle",
823 "Field doesn't have an RVA");
824 mono_raise_exception (exc);
827 size *= array->max_length;
828 field_data = mono_field_get_data (field_handle);
830 if (size > mono_type_size (field_handle->type, &align)) {
831 MonoException *exc = mono_get_exception_argument("field_handle",
832 "Field not large enough to fill array");
833 mono_raise_exception (exc);
836 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
838 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
839 guint ## n *src = (guint ## n *) field_data; \
840 guint ## n *end = (guint ## n *)((char*)src + size); \
842 for (; src < end; data++, src++) { \
843 *data = read ## n (src); \
847 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
849 switch (type->type) {
866 memcpy (mono_array_addr (array, char, 0), field_data, size);
870 memcpy (mono_array_addr (array, char, 0), field_data, size);
875 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
879 return offsetof (MonoString, chars);
882 ICALL_EXPORT MonoObject *
883 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
887 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
890 return mono_object_clone (obj);
894 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
899 MONO_CHECK_ARG_NULL (handle);
901 klass = mono_class_from_mono_type (handle);
902 MONO_CHECK_ARG (handle, klass);
904 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
906 /* This will call the type constructor */
907 mono_runtime_class_init (vtable);
911 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
915 mono_image_check_for_module_cctor (image);
916 if (image->has_module_cctor) {
917 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
918 /*It's fine to raise the exception here*/
919 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
923 ICALL_EXPORT MonoBoolean
924 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
929 /* later make this configurable and per-arch */
930 int min_size = 4096 * 4 * sizeof (void*);
931 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
932 /* if we have no info we are optimistic and assume there is enough room */
936 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
940 current = (guint8 *)&stack_addr;
941 if (current > stack_addr) {
942 if ((current - stack_addr) < min_size)
945 if (current - (stack_addr - stack_size) < min_size)
951 ICALL_EXPORT MonoObject *
952 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
956 return mono_object_clone (this);
960 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
963 MonoObject **values = NULL;
966 gint32 result = (int)mono_defaults.int32_class;
967 MonoClassField* field;
972 klass = mono_object_class (this);
974 if (mono_class_num_fields (klass) == 0)
978 * Compute the starting value of the hashcode for fields of primitive
979 * types, and return the remaining fields in an array to the managed side.
980 * This way, we can avoid costly reflection operations in managed code.
983 while ((field = mono_class_get_fields (klass, &iter))) {
984 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
986 if (mono_field_is_deleted (field))
988 /* FIXME: Add more types */
989 switch (field->type->type) {
991 result ^= *(gint32*)((guint8*)this + field->offset);
993 case MONO_TYPE_STRING: {
995 s = *(MonoString**)((guint8*)this + field->offset);
997 result ^= mono_string_hash (s);
1002 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1003 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1004 values [count++] = o;
1010 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1011 for (i = 0; i < count; ++i)
1012 mono_array_setref (*fields, i, values [i]);
1019 ICALL_EXPORT MonoBoolean
1020 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1023 MonoObject **values = NULL;
1025 MonoClassField* field;
1029 MONO_ARCH_SAVE_REGS;
1031 MONO_CHECK_ARG_NULL (that);
1033 if (this->vtable != that->vtable)
1036 klass = mono_object_class (this);
1038 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1039 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1042 * Do the comparison for fields of primitive type and return a result if
1043 * possible. Otherwise, return the remaining fields in an array to the
1044 * managed side. This way, we can avoid costly reflection operations in
1049 while ((field = mono_class_get_fields (klass, &iter))) {
1050 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1052 if (mono_field_is_deleted (field))
1054 /* FIXME: Add more types */
1055 switch (field->type->type) {
1058 case MONO_TYPE_BOOLEAN:
1059 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1064 case MONO_TYPE_CHAR:
1065 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1070 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1075 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1079 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1083 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1088 case MONO_TYPE_STRING: {
1089 MonoString *s1, *s2;
1090 guint32 s1len, s2len;
1091 s1 = *(MonoString**)((guint8*)this + field->offset);
1092 s2 = *(MonoString**)((guint8*)that + field->offset);
1095 if ((s1 == NULL) || (s2 == NULL))
1097 s1len = mono_string_length (s1);
1098 s2len = mono_string_length (s2);
1102 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1108 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1109 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1110 values [count++] = o;
1111 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1112 values [count++] = o;
1115 if (klass->enumtype)
1116 /* enums only have one non-static field */
1122 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1123 for (i = 0; i < count; ++i)
1124 mono_array_setref_fast (*fields, i, values [i]);
1131 ICALL_EXPORT MonoReflectionType *
1132 ves_icall_System_Object_GetType (MonoObject *obj)
1134 MONO_ARCH_SAVE_REGS;
1136 #ifndef DISABLE_REMOTING
1137 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1138 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1141 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1145 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1147 MONO_ARCH_SAVE_REGS;
1149 mtype->type = &obj->vtable->klass->byval_arg;
1150 g_assert (mtype->type->type);
1154 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1156 MONO_ARCH_SAVE_REGS;
1158 MONO_CHECK_ARG_NULL (obj);
1160 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1164 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1165 MonoReflectionMethod *method,
1166 MonoArray *opt_param_types)
1168 MONO_ARCH_SAVE_REGS;
1170 MONO_CHECK_ARG_NULL (method);
1172 return mono_image_create_method_token (
1173 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1177 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1179 MONO_ARCH_SAVE_REGS;
1181 mono_image_create_pefile (mb, file);
1185 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1187 MONO_ARCH_SAVE_REGS;
1189 mono_image_build_metadata (mb);
1193 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1195 MONO_ARCH_SAVE_REGS;
1197 mono_image_register_token (mb->dynamic_image, token, obj);
1201 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1203 MonoMethod **dest = data;
1205 /* skip unmanaged frames */
1221 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1223 MonoMethod **dest = data;
1225 /* skip unmanaged frames */
1230 if (!strcmp (m->klass->name_space, "System.Reflection"))
1239 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1241 MonoMethod **dest = data;
1243 /* skip unmanaged frames */
1247 if (m->wrapper_type != MONO_WRAPPER_NONE)
1250 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1264 static MonoReflectionType *
1265 type_from_name (const char *str, MonoBoolean ignoreCase)
1267 MonoType *type = NULL;
1268 MonoAssembly *assembly = NULL;
1269 MonoTypeNameParse info;
1270 char *temp_str = g_strdup (str);
1271 gboolean type_resolve = FALSE;
1273 MONO_ARCH_SAVE_REGS;
1275 /* mono_reflection_parse_type() mangles the string */
1276 if (!mono_reflection_parse_type (temp_str, &info)) {
1277 mono_reflection_free_type_info (&info);
1282 if (info.assembly.name) {
1283 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1285 MonoMethod *m = mono_method_get_last_managed ();
1286 MonoMethod *dest = m;
1288 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1293 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1294 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1295 * to crash. This only seems to happen in some strange remoting
1296 * scenarios and I was unable to figure out what's happening there.
1297 * Dec 10, 2005 - Martin.
1301 assembly = dest->klass->image->assembly;
1302 type_resolve = TRUE;
1304 g_warning (G_STRLOC);
1309 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1310 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1313 if (!info.assembly.name && !type) /* try mscorlib */
1314 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1316 if (assembly && !type && type_resolve) {
1317 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1318 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1321 mono_reflection_free_type_info (&info);
1327 return mono_type_get_object (mono_domain_get (), type);
1331 MonoReflectionType *
1332 mono_type_get (const char *str)
1334 char *copy = g_strdup (str);
1335 MonoReflectionType *type = type_from_name (copy, FALSE);
1342 ICALL_EXPORT MonoReflectionType*
1343 ves_icall_type_from_name (MonoString *name,
1344 MonoBoolean throwOnError,
1345 MonoBoolean ignoreCase)
1347 char *str = mono_string_to_utf8 (name);
1348 MonoReflectionType *type;
1350 type = type_from_name (str, ignoreCase);
1353 MonoException *e = NULL;
1356 e = mono_get_exception_type_load (name, NULL);
1358 mono_loader_clear_error ();
1360 mono_raise_exception (e);
1367 ICALL_EXPORT MonoReflectionType*
1368 ves_icall_type_from_handle (MonoType *handle)
1370 MonoDomain *domain = mono_domain_get ();
1372 MONO_ARCH_SAVE_REGS;
1374 return mono_type_get_object (domain, handle);
1377 ICALL_EXPORT MonoBoolean
1378 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1380 MONO_ARCH_SAVE_REGS;
1382 if (c && type->type && c->type)
1383 return mono_metadata_type_equal (type->type, c->type);
1385 return (type == c) ? TRUE : FALSE;
1388 /* System.TypeCode */
1407 TYPECODE_STRING = 18
1410 ICALL_EXPORT guint32
1411 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1413 int t = type->type->type;
1415 MONO_ARCH_SAVE_REGS;
1417 if (type->type->byref)
1418 return TYPECODE_OBJECT;
1422 case MONO_TYPE_VOID:
1423 return TYPECODE_OBJECT;
1424 case MONO_TYPE_BOOLEAN:
1425 return TYPECODE_BOOLEAN;
1427 return TYPECODE_BYTE;
1429 return TYPECODE_SBYTE;
1431 return TYPECODE_UINT16;
1433 return TYPECODE_INT16;
1434 case MONO_TYPE_CHAR:
1435 return TYPECODE_CHAR;
1439 return TYPECODE_OBJECT;
1441 return TYPECODE_UINT32;
1443 return TYPECODE_INT32;
1445 return TYPECODE_UINT64;
1447 return TYPECODE_INT64;
1449 return TYPECODE_SINGLE;
1451 return TYPECODE_DOUBLE;
1452 case MONO_TYPE_VALUETYPE: {
1453 MonoClass *klass = type->type->data.klass;
1455 if (klass->enumtype) {
1456 t = mono_class_enum_basetype (klass)->type;
1458 } else if (mono_is_corlib_image (klass->image)) {
1459 if (strcmp (klass->name_space, "System") == 0) {
1460 if (strcmp (klass->name, "Decimal") == 0)
1461 return TYPECODE_DECIMAL;
1462 else if (strcmp (klass->name, "DateTime") == 0)
1463 return TYPECODE_DATETIME;
1466 return TYPECODE_OBJECT;
1468 case MONO_TYPE_STRING:
1469 return TYPECODE_STRING;
1470 case MONO_TYPE_SZARRAY:
1471 case MONO_TYPE_ARRAY:
1472 case MONO_TYPE_OBJECT:
1474 case MONO_TYPE_MVAR:
1475 case MONO_TYPE_TYPEDBYREF:
1476 return TYPECODE_OBJECT;
1477 case MONO_TYPE_CLASS:
1479 MonoClass *klass = type->type->data.klass;
1480 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1481 if (strcmp (klass->name, "DBNull") == 0)
1482 return TYPECODE_DBNULL;
1485 return TYPECODE_OBJECT;
1486 case MONO_TYPE_GENERICINST:
1487 return TYPECODE_OBJECT;
1489 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1494 ICALL_EXPORT guint32
1495 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1501 MONO_ARCH_SAVE_REGS;
1503 g_assert (type != NULL);
1505 domain = ((MonoObject *)type)->vtable->domain;
1507 if (!c) /* FIXME: dont know what do do here */
1510 klass = mono_class_from_mono_type (type->type);
1511 klassc = mono_class_from_mono_type (c->type);
1513 /* Interface check requires a more complex setup so we
1514 * only do for them. Otherwise we simply avoid mono_class_init.
1516 if (check_interfaces) {
1517 mono_class_init_or_throw (klass);
1518 mono_class_init_or_throw (klassc);
1519 } else if (!klass->supertypes || !klassc->supertypes) {
1520 mono_class_setup_supertypes (klass);
1521 mono_class_setup_supertypes (klassc);
1524 if (type->type->byref)
1525 return klassc == mono_defaults.object_class;
1527 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1531 mono_type_is_primitive (MonoType *type)
1533 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1534 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1538 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1540 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1541 return mono_class_enum_basetype (type->data.klass);
1542 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1543 return mono_class_enum_basetype (type->data.generic_class->container_class);
1547 ICALL_EXPORT guint32
1548 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1554 MONO_ARCH_SAVE_REGS;
1556 g_assert (type != NULL);
1558 domain = ((MonoObject *)type)->vtable->domain;
1560 klass = mono_class_from_mono_type (type->type);
1561 klassc = mono_class_from_mono_type (c->type);
1563 if (type->type->byref ^ c->type->byref)
1566 if (type->type->byref) {
1567 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1568 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1570 klass = mono_class_from_mono_type (t);
1571 klassc = mono_class_from_mono_type (ot);
1573 if (mono_type_is_primitive (t)) {
1574 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1575 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1576 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1577 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1578 return t->type == ot->type;
1580 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1583 if (klass->valuetype)
1584 return klass == klassc;
1585 return klass->valuetype == klassc->valuetype;
1588 return mono_class_is_assignable_from (klass, klassc);
1591 ICALL_EXPORT guint32
1592 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1594 MonoClass *klass = mono_class_from_mono_type (type->type);
1595 mono_class_init_or_throw (klass);
1596 return mono_object_isinst (obj, klass) != NULL;
1599 ICALL_EXPORT guint32
1600 ves_icall_get_attributes (MonoReflectionType *type)
1602 MonoClass *klass = mono_class_from_mono_type (type->type);
1603 return klass->flags;
1606 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1607 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1609 MonoClass *klass = field->field->parent;
1610 MonoMarshalType *info;
1613 if (klass->generic_container ||
1614 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1617 info = mono_marshal_load_type_info (klass);
1619 for (i = 0; i < info->num_fields; ++i) {
1620 if (info->fields [i].field == field->field) {
1621 if (!info->fields [i].mspec)
1624 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1631 ICALL_EXPORT MonoReflectionField*
1632 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1634 gboolean found = FALSE;
1641 klass = handle->parent;
1643 klass = mono_class_from_mono_type (type);
1645 /* Check that the field belongs to the class */
1646 for (k = klass; k; k = k->parent) {
1647 if (k == handle->parent) {
1654 /* The managed code will throw the exception */
1658 return mono_field_get_object (mono_domain_get (), klass, handle);
1661 ICALL_EXPORT MonoArray*
1662 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1665 MonoType *type = mono_field_get_type_checked (field->field, &error);
1666 if (!mono_error_ok (&error))
1667 mono_error_raise_exception (&error);
1669 return type_array_from_modifiers (field->field->parent->image, type, optional);
1673 vell_icall_get_method_attributes (MonoMethod *method)
1675 return method->flags;
1679 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1682 MonoDomain *domain = mono_domain_get ();
1683 MonoMethodSignature* sig;
1684 MONO_ARCH_SAVE_REGS;
1686 sig = mono_method_signature_checked (method, &error);
1687 if (!mono_error_ok (&error))
1688 mono_error_raise_exception (&error);
1691 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1692 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1693 info->attrs = method->flags;
1694 info->implattrs = method->iflags;
1695 if (sig->call_convention == MONO_CALL_DEFAULT)
1696 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1698 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1703 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1706 ICALL_EXPORT MonoArray*
1707 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1709 MonoDomain *domain = mono_domain_get ();
1711 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1714 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1715 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1717 MonoDomain *domain = mono_domain_get ();
1718 MonoReflectionMarshalAsAttribute* res = NULL;
1719 MonoMarshalSpec **mspecs;
1722 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1723 mono_method_get_marshal_info (method, mspecs);
1726 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1728 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1730 mono_metadata_free_marshal_spec (mspecs [i]);
1737 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1739 MonoClass *parent = field->field->parent;
1740 if (!parent->size_inited)
1741 mono_class_init (parent);
1743 return field->field->offset - sizeof (MonoObject);
1746 ICALL_EXPORT MonoReflectionType*
1747 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1750 MONO_ARCH_SAVE_REGS;
1752 parent = declaring? field->field->parent: field->klass;
1754 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1757 ICALL_EXPORT MonoObject *
1758 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1760 MonoClass *fklass = field->klass;
1761 MonoClassField *cf = field->field;
1762 MonoDomain *domain = mono_object_domain (field);
1764 if (fklass->image->assembly->ref_only)
1765 mono_raise_exception (mono_get_exception_invalid_operation (
1766 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1768 if (mono_security_core_clr_enabled ())
1769 mono_security_core_clr_ensure_reflection_access_field (cf);
1771 return mono_field_get_value_object (domain, cf, obj);
1775 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1778 MonoClassField *cf = field->field;
1782 MONO_ARCH_SAVE_REGS;
1784 if (field->klass->image->assembly->ref_only)
1785 mono_raise_exception (mono_get_exception_invalid_operation (
1786 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1788 if (mono_security_core_clr_enabled ())
1789 mono_security_core_clr_ensure_reflection_access_field (cf);
1791 type = mono_field_get_type_checked (cf, &error);
1792 if (!mono_error_ok (&error))
1793 mono_error_raise_exception (&error);
1795 v = (gchar *) value;
1797 switch (type->type) {
1800 case MONO_TYPE_BOOLEAN:
1803 case MONO_TYPE_CHAR:
1812 case MONO_TYPE_VALUETYPE:
1815 v += sizeof (MonoObject);
1817 case MONO_TYPE_STRING:
1818 case MONO_TYPE_OBJECT:
1819 case MONO_TYPE_CLASS:
1820 case MONO_TYPE_ARRAY:
1821 case MONO_TYPE_SZARRAY:
1824 case MONO_TYPE_GENERICINST: {
1825 MonoGenericClass *gclass = type->data.generic_class;
1826 g_assert (!gclass->context.class_inst->is_open);
1828 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1829 MonoClass *nklass = mono_class_from_mono_type (type);
1830 MonoObject *nullable;
1833 * Convert the boxed vtype into a Nullable structure.
1834 * This is complicated by the fact that Nullables have
1835 * a variable structure.
1837 nullable = mono_object_new (mono_domain_get (), nklass);
1839 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1841 v = mono_object_unbox (nullable);
1844 if (gclass->container_class->valuetype && (v != NULL))
1845 v += sizeof (MonoObject);
1849 g_error ("type 0x%x not handled in "
1850 "ves_icall_FieldInfo_SetValueInternal", type->type);
1855 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1856 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1857 if (!vtable->initialized)
1858 mono_runtime_class_init (vtable);
1859 mono_field_static_set_value (vtable, cf, v);
1861 mono_field_set_value (obj, cf, v);
1865 ICALL_EXPORT MonoObject *
1866 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1868 MonoObject *o = NULL;
1869 MonoClassField *field = this->field;
1871 MonoDomain *domain = mono_object_domain (this);
1873 MonoTypeEnum def_type;
1874 const char *def_value;
1878 MONO_ARCH_SAVE_REGS;
1880 mono_class_init (field->parent);
1882 t = mono_field_get_type_checked (field, &error);
1883 if (!mono_error_ok (&error))
1884 mono_error_raise_exception (&error);
1886 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1887 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1889 if (field->parent->image->dynamic) {
1891 g_assert_not_reached ();
1894 def_value = mono_class_get_field_default_value (field, &def_type);
1895 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1896 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1898 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1902 case MONO_TYPE_BOOLEAN:
1905 case MONO_TYPE_CHAR:
1913 case MONO_TYPE_R8: {
1916 /* boxed value type */
1917 t = g_new0 (MonoType, 1);
1919 klass = mono_class_from_mono_type (t);
1921 o = mono_object_new (domain, klass);
1922 v = ((gchar *) o) + sizeof (MonoObject);
1923 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1926 case MONO_TYPE_STRING:
1927 case MONO_TYPE_CLASS:
1928 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1931 g_assert_not_reached ();
1937 ICALL_EXPORT MonoReflectionType*
1938 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1941 MonoClassField *field = ref_field->field;
1942 MonoType *type = mono_field_get_type_checked (field, &error);
1943 if (!mono_error_ok (&error))
1944 mono_error_raise_exception (&error);
1945 return mono_type_get_object (mono_object_domain (ref_field), type);
1948 ICALL_EXPORT MonoReflectionType*
1949 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1951 MonoMethod *method = rmethod->method.method;
1953 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1956 /* From MonoProperty.cs */
1958 PInfo_Attributes = 1,
1959 PInfo_GetMethod = 1 << 1,
1960 PInfo_SetMethod = 1 << 2,
1961 PInfo_ReflectedType = 1 << 3,
1962 PInfo_DeclaringType = 1 << 4,
1967 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1969 MonoDomain *domain = mono_object_domain (property);
1971 MONO_ARCH_SAVE_REGS;
1973 if ((req_info & PInfo_ReflectedType) != 0)
1974 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1975 if ((req_info & PInfo_DeclaringType) != 0)
1976 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1978 if ((req_info & PInfo_Name) != 0)
1979 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1981 if ((req_info & PInfo_Attributes) != 0)
1982 info->attrs = property->property->attrs;
1984 if ((req_info & PInfo_GetMethod) != 0)
1985 MONO_STRUCT_SETREF (info, get, property->property->get ?
1986 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1988 if ((req_info & PInfo_SetMethod) != 0)
1989 MONO_STRUCT_SETREF (info, set, property->property->set ?
1990 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1992 * There may be other methods defined for properties, though, it seems they are not exposed
1993 * in the reflection API
1998 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2000 MonoDomain *domain = mono_object_domain (event);
2002 MONO_ARCH_SAVE_REGS;
2004 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2005 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2007 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2008 info->attrs = event->event->attrs;
2009 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2010 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2011 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2013 #ifndef MONO_SMALL_CONFIG
2014 if (event->event->other) {
2016 while (event->event->other [n])
2018 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2020 for (i = 0; i < n; i++)
2021 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2027 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2032 mono_class_setup_interfaces (klass, error);
2033 if (!mono_error_ok (error))
2036 for (i = 0; i < klass->interface_count; i++) {
2037 ic = klass->interfaces [i];
2038 g_hash_table_insert (ifaces, ic, ic);
2040 collect_interfaces (ic, ifaces, error);
2041 if (!mono_error_ok (error))
2047 MonoArray *iface_array;
2048 MonoGenericContext *context;
2052 } FillIfaceArrayData;
2055 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2057 FillIfaceArrayData *data = user_data;
2058 MonoClass *ic = key;
2059 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2061 if (!mono_error_ok (data->error))
2064 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2065 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2066 if (!mono_error_ok (data->error))
2070 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2073 mono_metadata_free_type (inflated);
2076 ICALL_EXPORT MonoArray*
2077 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2080 MonoClass *class = mono_class_from_mono_type (type->type);
2082 FillIfaceArrayData data = { 0 };
2085 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2087 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2088 data.context = mono_class_get_context (class);
2089 class = class->generic_class->container_class;
2092 for (parent = class; parent; parent = parent->parent) {
2093 mono_class_setup_interfaces (parent, &error);
2094 if (!mono_error_ok (&error))
2096 collect_interfaces (parent, iface_hash, &error);
2097 if (!mono_error_ok (&error))
2101 data.error = &error;
2102 data.domain = mono_object_domain (type);
2104 len = g_hash_table_size (iface_hash);
2106 g_hash_table_destroy (iface_hash);
2107 if (!data.domain->empty_types)
2108 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2109 return data.domain->empty_types;
2112 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2113 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2114 if (!mono_error_ok (&error))
2117 g_hash_table_destroy (iface_hash);
2118 return data.iface_array;
2121 g_hash_table_destroy (iface_hash);
2122 mono_error_raise_exception (&error);
2127 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2129 gboolean variance_used;
2130 MonoClass *class = mono_class_from_mono_type (type->type);
2131 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2132 MonoReflectionMethod *member;
2135 int i = 0, len, ioffset;
2138 MONO_ARCH_SAVE_REGS;
2139 mono_class_init_or_throw (class);
2140 mono_class_init_or_throw (iclass);
2142 mono_class_setup_vtable (class);
2144 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2148 len = mono_class_num_methods (iclass);
2149 domain = mono_object_domain (type);
2150 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2151 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2153 while ((method = mono_class_get_methods (iclass, &iter))) {
2154 member = mono_method_get_object (domain, method, iclass);
2155 mono_array_setref (*methods, i, member);
2156 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2157 mono_array_setref (*targets, i, member);
2164 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2166 MonoClass *klass = mono_class_from_mono_type (type->type);
2167 mono_class_init_or_throw (klass);
2169 if (klass->image->dynamic) {
2170 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2171 *packing = tb->packing_size;
2172 *size = tb->class_size;
2174 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2178 ICALL_EXPORT MonoReflectionType*
2179 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2183 MONO_ARCH_SAVE_REGS;
2185 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2186 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2188 class = mono_class_from_mono_type (type->type);
2189 mono_class_init_or_throw (class);
2191 // GetElementType should only return a type for:
2192 // Array Pointer PassedByRef
2193 if (type->type->byref)
2194 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2195 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2196 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2197 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2198 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2203 ICALL_EXPORT MonoReflectionType*
2204 ves_icall_get_type_parent (MonoReflectionType *type)
2206 MonoClass *class = mono_class_from_mono_type (type->type);
2207 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2210 ICALL_EXPORT MonoBoolean
2211 ves_icall_type_ispointer (MonoReflectionType *type)
2213 MONO_ARCH_SAVE_REGS;
2215 return type->type->type == MONO_TYPE_PTR;
2218 ICALL_EXPORT MonoBoolean
2219 ves_icall_type_isprimitive (MonoReflectionType *type)
2221 MONO_ARCH_SAVE_REGS;
2223 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)));
2226 ICALL_EXPORT MonoBoolean
2227 ves_icall_type_isbyref (MonoReflectionType *type)
2229 MONO_ARCH_SAVE_REGS;
2231 return type->type->byref;
2234 ICALL_EXPORT MonoBoolean
2235 ves_icall_type_iscomobject (MonoReflectionType *type)
2237 MonoClass *klass = mono_class_from_mono_type (type->type);
2238 mono_class_init_or_throw (klass);
2240 return mono_class_is_com_object (klass);
2243 ICALL_EXPORT MonoReflectionModule*
2244 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2246 MonoClass *class = mono_class_from_mono_type (type->type);
2247 return mono_module_get_object (mono_object_domain (type), class->image);
2250 ICALL_EXPORT MonoReflectionAssembly*
2251 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2253 MonoDomain *domain = mono_domain_get ();
2254 MonoClass *class = mono_class_from_mono_type (type->type);
2255 return mono_assembly_get_object (domain, class->image->assembly);
2258 ICALL_EXPORT MonoReflectionType*
2259 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2261 MonoDomain *domain = mono_domain_get ();
2264 MONO_ARCH_SAVE_REGS;
2266 if (type->type->byref)
2268 if (type->type->type == MONO_TYPE_VAR)
2269 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2270 else if (type->type->type == MONO_TYPE_MVAR)
2271 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2273 class = mono_class_from_mono_type (type->type)->nested_in;
2275 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2278 ICALL_EXPORT MonoString*
2279 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2281 MonoDomain *domain = mono_domain_get ();
2282 MonoClass *class = mono_class_from_mono_type (type->type);
2284 if (type->type->byref) {
2285 char *n = g_strdup_printf ("%s&", class->name);
2286 MonoString *res = mono_string_new (domain, n);
2292 return mono_string_new (domain, class->name);
2296 ICALL_EXPORT MonoString*
2297 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2299 MonoDomain *domain = mono_domain_get ();
2300 MonoClass *class = mono_class_from_mono_type (type->type);
2302 while (class->nested_in)
2303 class = class->nested_in;
2305 if (class->name_space [0] == '\0')
2308 return mono_string_new (domain, class->name_space);
2312 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2316 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2317 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2319 class = mono_class_from_mono_type (type->type);
2324 ICALL_EXPORT MonoArray*
2325 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2328 MonoClass *klass, *pklass;
2329 MonoDomain *domain = mono_object_domain (type);
2330 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2332 MONO_ARCH_SAVE_REGS;
2334 klass = mono_class_from_mono_type (type->type);
2336 if (klass->generic_container) {
2337 MonoGenericContainer *container = klass->generic_container;
2338 res = mono_array_new_specific (array_vtable, container->type_argc);
2339 for (i = 0; i < container->type_argc; ++i) {
2340 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2341 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2343 } else if (klass->generic_class) {
2344 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2345 res = mono_array_new_specific (array_vtable, inst->type_argc);
2346 for (i = 0; i < inst->type_argc; ++i)
2347 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2349 res = mono_array_new_specific (array_vtable, 0);
2354 ICALL_EXPORT gboolean
2355 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2358 MONO_ARCH_SAVE_REGS;
2360 if (!IS_MONOTYPE (type))
2363 if (type->type->byref)
2366 klass = mono_class_from_mono_type (type->type);
2367 return klass->generic_container != NULL;
2370 ICALL_EXPORT MonoReflectionType*
2371 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2374 MONO_ARCH_SAVE_REGS;
2376 if (type->type->byref)
2379 klass = mono_class_from_mono_type (type->type);
2381 if (klass->generic_container) {
2382 return type; /* check this one */
2384 if (klass->generic_class) {
2385 MonoClass *generic_class = klass->generic_class->container_class;
2388 tb = mono_class_get_ref_info (generic_class);
2390 if (generic_class->wastypebuilder && tb)
2393 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2398 ICALL_EXPORT MonoReflectionType*
2399 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2402 MonoType *geninst, **types;
2405 g_assert (IS_MONOTYPE (type));
2406 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2408 count = mono_array_length (type_array);
2409 types = g_new0 (MonoType *, count);
2411 for (i = 0; i < count; i++) {
2412 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2413 types [i] = t->type;
2416 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2421 class = mono_class_from_mono_type (geninst);
2423 /*we might inflate to the GTD*/
2424 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2425 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2427 return mono_type_get_object (mono_object_domain (type), geninst);
2430 ICALL_EXPORT gboolean
2431 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2434 MONO_ARCH_SAVE_REGS;
2436 if (type->type->byref)
2439 klass = mono_class_from_mono_type (type->type);
2441 return klass->generic_class != NULL;
2444 ICALL_EXPORT gboolean
2445 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2448 MONO_ARCH_SAVE_REGS;
2450 if (!IS_MONOTYPE (type))
2453 if (type->type->byref)
2456 klass = mono_class_from_mono_type (type->type);
2457 return klass->generic_class != NULL || klass->generic_container != NULL;
2461 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2463 MONO_ARCH_SAVE_REGS;
2465 if (!IS_MONOTYPE (type))
2468 if (is_generic_parameter (type->type))
2469 return mono_type_get_generic_param_num (type->type);
2473 ICALL_EXPORT GenericParameterAttributes
2474 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2476 MONO_ARCH_SAVE_REGS;
2478 g_assert (IS_MONOTYPE (type));
2479 g_assert (is_generic_parameter (type->type));
2480 return mono_generic_param_info (type->type->data.generic_param)->flags;
2483 ICALL_EXPORT MonoArray *
2484 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2486 MonoGenericParamInfo *param_info;
2492 MONO_ARCH_SAVE_REGS;
2494 g_assert (IS_MONOTYPE (type));
2496 domain = mono_object_domain (type);
2497 param_info = mono_generic_param_info (type->type->data.generic_param);
2498 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2501 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2502 for (i = 0; i < count; i++)
2503 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2509 ICALL_EXPORT MonoBoolean
2510 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2512 MONO_ARCH_SAVE_REGS;
2513 return is_generic_parameter (type->type);
2516 ICALL_EXPORT MonoBoolean
2517 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2519 MONO_ARCH_SAVE_REGS;
2520 return is_generic_parameter (tb->type.type);
2524 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2525 MonoReflectionType *t)
2527 enumtype->type = t->type;
2530 ICALL_EXPORT MonoReflectionMethod*
2531 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2532 MonoReflectionMethod* generic)
2539 MONO_ARCH_SAVE_REGS;
2541 domain = ((MonoObject *)type)->vtable->domain;
2543 klass = mono_class_from_mono_type (type->type);
2544 mono_class_init_or_throw (klass);
2547 while ((method = mono_class_get_methods (klass, &iter))) {
2548 if (method->token == generic->method->token)
2549 return mono_method_get_object (domain, method, klass);
2557 ICALL_EXPORT MonoReflectionMethod *
2558 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2561 MonoType *type = ref_type->type;
2563 MONO_ARCH_SAVE_REGS;
2565 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2566 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2567 if (type->type == MONO_TYPE_VAR)
2570 method = mono_type_get_generic_param_owner (type)->owner.method;
2572 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2575 ICALL_EXPORT MonoReflectionDllImportAttribute*
2576 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2578 static MonoClass *DllImportAttributeClass = NULL;
2579 MonoDomain *domain = mono_domain_get ();
2580 MonoReflectionDllImportAttribute *attr;
2581 MonoImage *image = method->klass->image;
2582 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2583 MonoTableInfo *tables = image->tables;
2584 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2585 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2586 guint32 im_cols [MONO_IMPLMAP_SIZE];
2587 guint32 scope_token;
2588 const char *import = NULL;
2589 const char *scope = NULL;
2592 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2595 if (!DllImportAttributeClass) {
2596 DllImportAttributeClass =
2597 mono_class_from_name (mono_defaults.corlib,
2598 "System.Runtime.InteropServices", "DllImportAttribute");
2599 g_assert (DllImportAttributeClass);
2602 if (method->klass->image->dynamic) {
2603 MonoReflectionMethodAux *method_aux =
2604 g_hash_table_lookup (
2605 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2607 import = method_aux->dllentry;
2608 scope = method_aux->dll;
2611 if (!import || !scope) {
2612 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2617 if (piinfo->implmap_idx) {
2618 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2620 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2621 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2622 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2623 scope = mono_metadata_string_heap (image, scope_token);
2626 flags = piinfo->piflags;
2628 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2630 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2631 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2632 attr->call_conv = (flags & 0x700) >> 8;
2633 attr->charset = ((flags & 0x6) >> 1) + 1;
2634 if (attr->charset == 1)
2636 attr->exact_spelling = (flags & 0x1) != 0;
2637 attr->set_last_error = (flags & 0x40) != 0;
2638 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2639 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2640 attr->preserve_sig = FALSE;
2645 ICALL_EXPORT MonoReflectionMethod *
2646 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2648 MonoMethodInflated *imethod;
2651 MONO_ARCH_SAVE_REGS;
2653 if (method->method->is_generic)
2656 if (!method->method->is_inflated)
2659 imethod = (MonoMethodInflated *) method->method;
2661 result = imethod->declaring;
2662 /* Not a generic method. */
2663 if (!result->is_generic)
2666 if (method->method->klass->image->dynamic) {
2667 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2668 MonoReflectionMethod *res;
2671 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2672 * the dynamic case as well ?
2674 mono_image_lock ((MonoImage*)image);
2675 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2676 mono_image_unlock ((MonoImage*)image);
2682 if (imethod->context.class_inst) {
2683 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2684 /*Generic methods gets the context of the GTD.*/
2685 if (mono_class_get_context (klass))
2686 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2689 return mono_method_get_object (mono_object_domain (method), result, NULL);
2692 ICALL_EXPORT gboolean
2693 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2695 MONO_ARCH_SAVE_REGS;
2697 return mono_method_signature (method->method)->generic_param_count != 0;
2700 ICALL_EXPORT gboolean
2701 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2703 MONO_ARCH_SAVE_REGS;
2705 return method->method->is_generic;
2708 ICALL_EXPORT MonoArray*
2709 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2714 MONO_ARCH_SAVE_REGS;
2716 domain = mono_object_domain (method);
2718 if (method->method->is_inflated) {
2719 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2722 count = inst->type_argc;
2723 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2725 for (i = 0; i < count; i++)
2726 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2732 count = mono_method_signature (method->method)->generic_param_count;
2733 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2735 for (i = 0; i < count; i++) {
2736 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2737 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2738 MonoClass *pklass = mono_class_from_generic_parameter (
2739 param, method->method->klass->image, TRUE);
2740 mono_array_setref (res, i,
2741 mono_type_get_object (domain, &pklass->byval_arg));
2747 ICALL_EXPORT MonoObject *
2748 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2751 * Invoke from reflection is supposed to always be a virtual call (the API
2752 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2753 * greater flexibility.
2755 MonoMethod *m = method->method;
2756 MonoMethodSignature *sig = mono_method_signature (m);
2761 MONO_ARCH_SAVE_REGS;
2765 if (mono_security_core_clr_enabled ())
2766 mono_security_core_clr_ensure_reflection_access_method (m);
2768 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2769 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2770 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2775 if (!mono_object_isinst (this, m->klass)) {
2776 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2777 char *target_name = mono_type_get_full_name (m->klass);
2778 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2779 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2781 g_free (target_name);
2785 m = mono_object_get_virtual_method (this, m);
2786 /* must pass the pointer to the value for valuetype methods */
2787 if (m->klass->valuetype)
2788 obj = mono_object_unbox (this);
2789 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2790 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2795 if (sig->ret->byref) {
2796 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"));
2800 pcount = params? mono_array_length (params): 0;
2801 if (pcount != sig->param_count) {
2802 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2806 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2807 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."));
2811 image = m->klass->image;
2812 if (image->assembly->ref_only) {
2813 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."));
2817 if (image->dynamic && !((MonoDynamicImage*)image)->run) {
2818 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2822 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2825 intptr_t *lower_bounds;
2826 pcount = mono_array_length (params);
2827 lengths = alloca (sizeof (uintptr_t) * pcount);
2828 /* Note: the synthetized array .ctors have int32 as argument type */
2829 for (i = 0; i < pcount; ++i)
2830 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2832 if (m->klass->rank == pcount) {
2833 /* Only lengths provided. */
2834 lower_bounds = NULL;
2836 g_assert (pcount == (m->klass->rank * 2));
2837 /* lower bounds are first. */
2838 lower_bounds = (intptr_t*)lengths;
2839 lengths += m->klass->rank;
2842 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2844 return mono_runtime_invoke_array (m, obj, params, NULL);
2847 #ifndef DISABLE_REMOTING
2848 ICALL_EXPORT MonoObject *
2849 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2851 MonoDomain *domain = mono_object_domain (method);
2852 MonoMethod *m = method->method;
2853 MonoMethodSignature *sig = mono_method_signature (m);
2854 MonoArray *out_args;
2856 int i, j, outarg_count = 0;
2858 MONO_ARCH_SAVE_REGS;
2860 if (m->klass == mono_defaults.object_class) {
2862 if (!strcmp (m->name, "FieldGetter")) {
2863 MonoClass *k = this->vtable->klass;
2867 /* If this is a proxy, then it must be a CBO */
2868 if (k == mono_defaults.transparent_proxy_class) {
2869 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2870 this = tp->rp->unwrapped_server;
2872 k = this->vtable->klass;
2875 name = mono_array_get (params, MonoString *, 1);
2876 str = mono_string_to_utf8 (name);
2879 MonoClassField* field = mono_class_get_field_from_name (k, str);
2881 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2882 if (field_klass->valuetype)
2883 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2885 result = *((gpointer *)((char *)this + field->offset));
2887 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2888 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2889 mono_array_setref (out_args, 0, result);
2897 g_assert_not_reached ();
2899 } else if (!strcmp (m->name, "FieldSetter")) {
2900 MonoClass *k = this->vtable->klass;
2906 /* If this is a proxy, then it must be a CBO */
2907 if (k == mono_defaults.transparent_proxy_class) {
2908 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2909 this = tp->rp->unwrapped_server;
2911 k = this->vtable->klass;
2914 name = mono_array_get (params, MonoString *, 1);
2915 str = mono_string_to_utf8 (name);
2918 MonoClassField* field = mono_class_get_field_from_name (k, str);
2920 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2921 MonoObject *val = mono_array_get (params, gpointer, 2);
2923 if (field_klass->valuetype) {
2924 size = mono_type_size (field->type, &align);
2925 g_assert (size == mono_class_value_size (field_klass, NULL));
2926 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2928 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2931 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2932 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2942 g_assert_not_reached ();
2947 for (i = 0; i < mono_array_length (params); i++) {
2948 if (sig->params [i]->byref)
2952 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2954 /* handle constructors only for objects already allocated */
2955 if (!strcmp (method->method->name, ".ctor"))
2958 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2959 g_assert (!method->method->klass->valuetype);
2960 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2962 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2963 if (sig->params [i]->byref) {
2965 arg = mono_array_get (params, gpointer, i);
2966 mono_array_setref (out_args, j, arg);
2971 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2978 read_enum_value (char *mem, int type)
2982 return *(guint8*)mem;
2984 return *(gint8*)mem;
2986 return *(guint16*)mem;
2988 return *(gint16*)mem;
2990 return *(guint32*)mem;
2992 return *(gint32*)mem;
2994 return *(guint64*)mem;
2996 return *(gint64*)mem;
2998 g_assert_not_reached ();
3004 write_enum_value (char *mem, int type, guint64 value)
3008 case MONO_TYPE_I1: {
3009 guint8 *p = (guint8*)mem;
3014 case MONO_TYPE_I2: {
3015 guint16 *p = (void*)mem;
3020 case MONO_TYPE_I4: {
3021 guint32 *p = (void*)mem;
3026 case MONO_TYPE_I8: {
3027 guint64 *p = (void*)mem;
3032 g_assert_not_reached ();
3037 ICALL_EXPORT MonoObject *
3038 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3041 MonoClass *enumc, *objc;
3046 MONO_ARCH_SAVE_REGS;
3048 MONO_CHECK_ARG_NULL (enumType);
3049 MONO_CHECK_ARG_NULL (value);
3051 domain = mono_object_domain (enumType);
3052 enumc = mono_class_from_mono_type (enumType->type);
3054 mono_class_init_or_throw (enumc);
3056 objc = value->vtable->klass;
3058 if (!enumc->enumtype)
3059 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3060 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3061 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."));
3063 etype = mono_class_enum_basetype (enumc);
3065 /* MS throws this for typebuilders */
3066 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3068 res = mono_object_new (domain, enumc);
3069 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3070 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3075 ICALL_EXPORT MonoObject *
3076 ves_icall_System_Enum_get_value (MonoObject *this)
3084 MONO_ARCH_SAVE_REGS;
3089 g_assert (this->vtable->klass->enumtype);
3091 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3092 res = mono_object_new (mono_object_domain (this), enumc);
3093 dst = (char *)res + sizeof (MonoObject);
3094 src = (char *)this + sizeof (MonoObject);
3095 size = mono_class_value_size (enumc, NULL);
3097 memcpy (dst, src, size);
3102 ICALL_EXPORT MonoReflectionType *
3103 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3108 MONO_ARCH_SAVE_REGS;
3110 klass = mono_class_from_mono_type (type->type);
3111 mono_class_init_or_throw (klass);
3113 etype = mono_class_enum_basetype (klass);
3115 /* MS throws this for typebuilders */
3116 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3118 return mono_type_get_object (mono_object_domain (type), etype);
3122 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3124 gpointer tdata = (char *)this + sizeof (MonoObject);
3125 gpointer odata = (char *)other + sizeof (MonoObject);
3126 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3127 g_assert (basetype);
3129 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3130 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3131 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3134 return me > other ? 1 : -1; \
3137 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3138 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3139 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3142 return me - other; \
3145 switch (basetype->type) {
3147 COMPARE_ENUM_VALUES (guint8);
3149 COMPARE_ENUM_VALUES (gint8);
3150 case MONO_TYPE_CHAR:
3152 COMPARE_ENUM_VALUES_RANGE (guint16);
3154 COMPARE_ENUM_VALUES (gint16);
3156 COMPARE_ENUM_VALUES (guint32);
3158 COMPARE_ENUM_VALUES (gint32);
3160 COMPARE_ENUM_VALUES (guint64);
3162 COMPARE_ENUM_VALUES (gint64);
3164 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3166 #undef COMPARE_ENUM_VALUES_RANGE
3167 #undef COMPARE_ENUM_VALUES
3172 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3174 gpointer data = (char *)this + sizeof (MonoObject);
3175 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3176 g_assert (basetype);
3178 switch (basetype->type) {
3180 return *((gint8*)data);
3182 return *((guint8*)data);
3183 case MONO_TYPE_CHAR:
3185 return *((guint16*)data);
3188 return *((gint16*)data);
3190 return *((guint32*)data);
3192 return *((gint32*)data);
3194 case MONO_TYPE_I8: {
3195 gint64 value = *((gint64*)data);
3196 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3199 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3205 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3207 MonoDomain *domain = mono_object_domain (type);
3208 MonoClass *enumc = mono_class_from_mono_type (type->type);
3209 guint j = 0, nvalues, crow;
3211 MonoClassField *field;
3213 MONO_ARCH_SAVE_REGS;
3215 mono_class_init_or_throw (enumc);
3217 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3218 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3219 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3220 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3224 while ((field = mono_class_get_fields (enumc, &iter))) {
3227 MonoTypeEnum def_type;
3229 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3231 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3233 if (mono_field_is_deleted (field))
3235 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3237 p = mono_class_get_field_default_value (field, &def_type);
3238 len = mono_metadata_decode_blob_size (p, &p);
3239 switch (mono_class_enum_basetype (enumc)->type) {
3242 mono_array_set (info->values, gchar, j, *p);
3244 case MONO_TYPE_CHAR:
3247 mono_array_set (info->values, gint16, j, read16 (p));
3251 mono_array_set (info->values, gint32, j, read32 (p));
3255 mono_array_set (info->values, gint64, j, read64 (p));
3258 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3265 BFLAGS_IgnoreCase = 1,
3266 BFLAGS_DeclaredOnly = 2,
3267 BFLAGS_Instance = 4,
3269 BFLAGS_Public = 0x10,
3270 BFLAGS_NonPublic = 0x20,
3271 BFLAGS_FlattenHierarchy = 0x40,
3272 BFLAGS_InvokeMethod = 0x100,
3273 BFLAGS_CreateInstance = 0x200,
3274 BFLAGS_GetField = 0x400,
3275 BFLAGS_SetField = 0x800,
3276 BFLAGS_GetProperty = 0x1000,
3277 BFLAGS_SetProperty = 0x2000,
3278 BFLAGS_ExactBinding = 0x10000,
3279 BFLAGS_SuppressChangeType = 0x20000,
3280 BFLAGS_OptionalParamBinding = 0x40000
3283 ICALL_EXPORT MonoReflectionField *
3284 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3287 MonoClass *startklass, *klass;
3289 MonoClassField *field;
3292 int (*compare_func) (const char *s1, const char *s2) = NULL;
3293 domain = ((MonoObject *)type)->vtable->domain;
3294 klass = startklass = mono_class_from_mono_type (type->type);
3297 mono_raise_exception (mono_get_exception_argument_null ("name"));
3298 if (type->type->byref)
3301 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3304 if (klass->exception_type != MONO_EXCEPTION_NONE)
3305 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3308 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3309 guint32 flags = mono_field_get_flags (field);
3312 if (mono_field_is_deleted_with_flags (field, flags))
3314 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3315 if (bflags & BFLAGS_Public)
3317 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3318 if (bflags & BFLAGS_NonPublic) {
3325 if (flags & FIELD_ATTRIBUTE_STATIC) {
3326 if (bflags & BFLAGS_Static)
3327 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3330 if (bflags & BFLAGS_Instance)
3337 utf8_name = mono_string_to_utf8 (name);
3339 if (compare_func (mono_field_get_name (field), utf8_name)) {
3345 return mono_field_get_object (domain, klass, field);
3347 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3353 ICALL_EXPORT MonoArray*
3354 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3357 MonoClass *startklass, *klass, *refklass;
3362 MonoClassField *field;
3363 MonoPtrArray tmp_array;
3365 MONO_ARCH_SAVE_REGS;
3367 domain = ((MonoObject *)type)->vtable->domain;
3368 if (type->type->byref)
3369 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3370 klass = startklass = mono_class_from_mono_type (type->type);
3371 refklass = mono_class_from_mono_type (reftype->type);
3373 mono_ptr_array_init (tmp_array, 2);
3376 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3377 mono_ptr_array_destroy (tmp_array);
3378 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3382 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3383 guint32 flags = mono_field_get_flags (field);
3385 if (mono_field_is_deleted_with_flags (field, flags))
3387 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3388 if (bflags & BFLAGS_Public)
3390 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3391 if (bflags & BFLAGS_NonPublic) {
3398 if (flags & FIELD_ATTRIBUTE_STATIC) {
3399 if (bflags & BFLAGS_Static)
3400 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3403 if (bflags & BFLAGS_Instance)
3409 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3410 mono_ptr_array_append (tmp_array, member);
3412 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3415 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3417 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3418 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3420 mono_ptr_array_destroy (tmp_array);
3426 method_nonpublic (MonoMethod* method, gboolean start_klass)
3428 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3429 case METHOD_ATTRIBUTE_ASSEM:
3430 return (start_klass || mono_defaults.generic_ilist_class);
3431 case METHOD_ATTRIBUTE_PRIVATE:
3433 case METHOD_ATTRIBUTE_PUBLIC:
3441 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3444 MonoClass *startklass;
3447 int len, match, nslots;
3448 /*FIXME, use MonoBitSet*/
3449 guint32 method_slots_default [8];
3450 guint32 *method_slots = NULL;
3451 int (*compare_func) (const char *s1, const char *s2) = NULL;
3453 array = g_ptr_array_new ();
3459 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3461 /* An optimization for calls made from Delegate:CreateDelegate () */
3462 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3463 method = mono_get_delegate_invoke (klass);
3464 if (mono_loader_get_last_error ())
3467 g_ptr_array_add (array, method);
3471 mono_class_setup_vtable (klass);
3472 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3475 if (is_generic_parameter (&klass->byval_arg))
3476 nslots = mono_class_get_vtable_size (klass->parent);
3478 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3479 if (nslots >= sizeof (method_slots_default) * 8) {
3480 method_slots = g_new0 (guint32, nslots / 32 + 1);
3482 method_slots = method_slots_default;
3483 memset (method_slots, 0, sizeof (method_slots_default));
3486 mono_class_setup_vtable (klass);
3487 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3491 while ((method = mono_class_get_methods (klass, &iter))) {
3493 if (method->slot != -1) {
3494 g_assert (method->slot < nslots);
3495 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3497 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3498 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3501 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3503 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3504 if (bflags & BFLAGS_Public)
3506 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3512 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3513 if (bflags & BFLAGS_Static)
3514 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3517 if (bflags & BFLAGS_Instance)
3525 if (compare_func (name, method->name))
3530 g_ptr_array_add (array, method);
3532 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3534 if (method_slots != method_slots_default)
3535 g_free (method_slots);
3540 if (method_slots != method_slots_default)
3541 g_free (method_slots);
3542 g_ptr_array_free (array, TRUE);
3544 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3545 *ex = mono_class_get_exception_for_failure (klass);
3547 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3548 mono_loader_clear_error ();
3553 ICALL_EXPORT MonoArray*
3554 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3556 static MonoClass *MethodInfo_array;
3559 MonoVTable *array_vtable;
3560 MonoException *ex = NULL;
3561 const char *mname = NULL;
3562 GPtrArray *method_array;
3563 MonoClass *klass, *refklass;
3566 if (!MethodInfo_array) {
3567 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3568 mono_memory_barrier ();
3569 MethodInfo_array = klass;
3572 klass = mono_class_from_mono_type (type->type);
3573 refklass = mono_class_from_mono_type (reftype->type);
3574 domain = ((MonoObject *)type)->vtable->domain;
3575 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3576 if (type->type->byref)
3577 return mono_array_new_specific (array_vtable, 0);
3580 mname = mono_string_to_utf8 (name);
3582 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3583 g_free ((char*)mname);
3585 mono_raise_exception (ex);
3587 res = mono_array_new_specific (array_vtable, method_array->len);
3590 for (i = 0; i < method_array->len; ++i) {
3591 MonoMethod *method = g_ptr_array_index (method_array, i);
3592 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3595 g_ptr_array_free (method_array, TRUE);
3599 ICALL_EXPORT MonoArray*
3600 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3603 static MonoClass *System_Reflection_ConstructorInfo;
3604 MonoClass *startklass, *klass, *refklass;
3609 gpointer iter = NULL;
3610 MonoPtrArray tmp_array;
3612 MONO_ARCH_SAVE_REGS;
3614 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3616 domain = ((MonoObject *)type)->vtable->domain;
3617 if (type->type->byref)
3618 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3619 klass = startklass = mono_class_from_mono_type (type->type);
3620 refklass = mono_class_from_mono_type (reftype->type);
3622 if (!System_Reflection_ConstructorInfo)
3623 System_Reflection_ConstructorInfo = mono_class_from_name (
3624 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3627 while ((method = mono_class_get_methods (klass, &iter))) {
3629 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3631 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3632 if (bflags & BFLAGS_Public)
3635 if (bflags & BFLAGS_NonPublic)
3641 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3642 if (bflags & BFLAGS_Static)
3643 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3646 if (bflags & BFLAGS_Instance)
3652 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3654 mono_ptr_array_append (tmp_array, member);
3657 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3659 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3660 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3662 mono_ptr_array_destroy (tmp_array);
3668 property_hash (gconstpointer data)
3670 MonoProperty *prop = (MonoProperty*)data;
3672 return g_str_hash (prop->name);
3676 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3678 // Properties are hide-by-name-and-signature
3679 if (!g_str_equal (prop1->name, prop2->name))
3682 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3684 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3690 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3695 return method_nonpublic (accessor, start_klass);
3698 ICALL_EXPORT MonoArray*
3699 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3703 static MonoClass *System_Reflection_PropertyInfo;
3704 MonoClass *startklass, *klass;
3710 gchar *propname = NULL;
3711 int (*compare_func) (const char *s1, const char *s2) = NULL;
3713 GHashTable *properties = NULL;
3714 MonoPtrArray tmp_array;
3716 MONO_ARCH_SAVE_REGS;
3718 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3720 if (!System_Reflection_PropertyInfo)
3721 System_Reflection_PropertyInfo = mono_class_from_name (
3722 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3724 domain = ((MonoObject *)type)->vtable->domain;
3725 if (type->type->byref)
3726 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3727 klass = startklass = mono_class_from_mono_type (type->type);
3730 propname = mono_string_to_utf8 (name);
3731 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3734 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3736 mono_class_setup_vtable (klass);
3737 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3741 while ((prop = mono_class_get_properties (klass, &iter))) {
3747 flags = method->flags;
3750 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3751 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3752 if (bflags & BFLAGS_Public)
3754 } else if (bflags & BFLAGS_NonPublic) {
3755 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3756 property_accessor_nonpublic(prop->set, startklass == klass)) {
3763 if (flags & METHOD_ATTRIBUTE_STATIC) {
3764 if (bflags & BFLAGS_Static)
3765 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3768 if (bflags & BFLAGS_Instance)
3777 if (compare_func (propname, prop->name))
3781 if (g_hash_table_lookup (properties, prop))
3784 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3786 g_hash_table_insert (properties, prop, prop);
3788 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3791 g_hash_table_destroy (properties);
3794 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3795 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3796 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3798 mono_ptr_array_destroy (tmp_array);
3804 g_hash_table_destroy (properties);
3807 mono_ptr_array_destroy (tmp_array);
3809 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3810 ex = mono_class_get_exception_for_failure (klass);
3812 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3813 mono_loader_clear_error ();
3815 mono_raise_exception (ex);
3819 ICALL_EXPORT MonoReflectionEvent *
3820 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3823 MonoClass *klass, *startklass;
3828 int (*compare_func) (const char *s1, const char *s2);
3830 MONO_ARCH_SAVE_REGS;
3832 event_name = mono_string_to_utf8 (name);
3833 if (type->type->byref)
3835 klass = startklass = mono_class_from_mono_type (type->type);
3836 domain = mono_object_domain (type);
3838 mono_class_init_or_throw (klass);
3840 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3842 if (klass->exception_type != MONO_EXCEPTION_NONE)
3843 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3846 while ((event = mono_class_get_events (klass, &iter))) {
3847 if (compare_func (event->name, event_name))
3850 method = event->add;
3852 method = event->remove;
3854 method = event->raise;
3856 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3857 if (!(bflags & BFLAGS_Public))
3860 if (!(bflags & BFLAGS_NonPublic))
3862 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3866 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3867 if (!(bflags & BFLAGS_Static))
3869 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3872 if (!(bflags & BFLAGS_Instance))
3876 if (!(bflags & BFLAGS_NonPublic))
3879 g_free (event_name);
3880 return mono_event_get_object (domain, startklass, event);
3883 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3886 g_free (event_name);
3891 event_hash (gconstpointer data)
3893 MonoEvent *event = (MonoEvent*)data;
3895 return g_str_hash (event->name);
3899 event_equal (MonoEvent *event1, MonoEvent *event2)
3901 // Events are hide-by-name
3902 return g_str_equal (event1->name, event2->name);
3905 ICALL_EXPORT MonoArray*
3906 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3910 static MonoClass *System_Reflection_EventInfo;
3911 MonoClass *startklass, *klass;
3917 GHashTable *events = NULL;
3918 MonoPtrArray tmp_array;
3920 MONO_ARCH_SAVE_REGS;
3922 mono_ptr_array_init (tmp_array, 4);
3924 if (!System_Reflection_EventInfo)
3925 System_Reflection_EventInfo = mono_class_from_name (
3926 mono_defaults.corlib, "System.Reflection", "EventInfo");
3928 domain = mono_object_domain (type);
3929 if (type->type->byref)
3930 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3931 klass = startklass = mono_class_from_mono_type (type->type);
3933 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3935 mono_class_setup_vtable (klass);
3936 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3940 while ((event = mono_class_get_events (klass, &iter))) {
3942 method = event->add;
3944 method = event->remove;
3946 method = event->raise;
3948 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3949 if (bflags & BFLAGS_Public)
3951 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3952 if (bflags & BFLAGS_NonPublic)
3957 if (bflags & BFLAGS_NonPublic)
3963 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3964 if (bflags & BFLAGS_Static)
3965 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3968 if (bflags & BFLAGS_Instance)
3973 if (bflags & BFLAGS_Instance)
3978 if (g_hash_table_lookup (events, event))
3981 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3983 g_hash_table_insert (events, event, event);
3985 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3988 g_hash_table_destroy (events);
3990 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3992 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3993 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3995 mono_ptr_array_destroy (tmp_array);
4000 mono_ptr_array_destroy (tmp_array);
4001 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4002 ex = mono_class_get_exception_for_failure (klass);
4004 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4005 mono_loader_clear_error ();
4007 mono_raise_exception (ex);
4011 ICALL_EXPORT MonoReflectionType *
4012 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4020 MONO_ARCH_SAVE_REGS;
4023 mono_raise_exception (mono_get_exception_argument_null ("name"));
4025 domain = ((MonoObject *)type)->vtable->domain;
4026 if (type->type->byref)
4028 klass = mono_class_from_mono_type (type->type);
4030 str = mono_string_to_utf8 (name);
4033 if (klass->exception_type != MONO_EXCEPTION_NONE)
4034 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4037 * If a nested type is generic, return its generic type definition.
4038 * Note that this means that the return value is essentially a
4039 * nested type of the generic type definition of @klass.
4041 * A note in MSDN claims that a generic type definition can have
4042 * nested types that aren't generic. In any case, the container of that
4043 * nested type would be the generic type definition.
4045 if (klass->generic_class)
4046 klass = klass->generic_class->container_class;
4049 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4051 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4052 if (bflags & BFLAGS_Public)
4055 if (bflags & BFLAGS_NonPublic)
4060 if (strcmp (nested->name, str) == 0){
4062 return mono_type_get_object (domain, &nested->byval_arg);
4065 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4071 ICALL_EXPORT MonoArray*
4072 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4081 MonoPtrArray tmp_array;
4083 MONO_ARCH_SAVE_REGS;
4085 domain = ((MonoObject *)type)->vtable->domain;
4086 if (type->type->byref)
4087 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4088 klass = mono_class_from_mono_type (type->type);
4091 * If a nested type is generic, return its generic type definition.
4092 * Note that this means that the return value is essentially the set
4093 * of nested types of the generic type definition of @klass.
4095 * A note in MSDN claims that a generic type definition can have
4096 * nested types that aren't generic. In any case, the container of that
4097 * nested type would be the generic type definition.
4099 if (klass->generic_class)
4100 klass = klass->generic_class->container_class;
4102 mono_ptr_array_init (tmp_array, 1);
4104 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4106 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4107 if (bflags & BFLAGS_Public)
4110 if (bflags & BFLAGS_NonPublic)
4115 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4116 mono_ptr_array_append (tmp_array, member);
4119 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4121 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4122 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4124 mono_ptr_array_destroy (tmp_array);
4129 ICALL_EXPORT MonoReflectionType*
4130 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4133 MonoType *type = NULL;
4134 MonoTypeNameParse info;
4135 gboolean type_resolve;
4137 MONO_ARCH_SAVE_REGS;
4139 /* On MS.NET, this does not fire a TypeResolve event */
4140 type_resolve = TRUE;
4141 str = mono_string_to_utf8 (name);
4142 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4143 if (!mono_reflection_parse_type (str, &info)) {
4145 mono_reflection_free_type_info (&info);
4146 if (throwOnError) /* uhm: this is a parse error, though... */
4147 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4148 /*g_print ("failed parse\n");*/
4152 if (info.assembly.name) {
4154 mono_reflection_free_type_info (&info);
4156 /* 1.0 and 2.0 throw different exceptions */
4157 if (mono_defaults.generic_ilist_class)
4158 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4160 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4165 if (module != NULL) {
4167 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4172 if (assembly->assembly->dynamic) {
4173 /* Enumerate all modules */
4174 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4178 if (abuilder->modules) {
4179 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4180 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4181 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4187 if (!type && abuilder->loaded_modules) {
4188 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4189 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4190 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4197 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4199 mono_reflection_free_type_info (&info);
4201 MonoException *e = NULL;
4204 e = mono_get_exception_type_load (name, NULL);
4206 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4207 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4209 mono_loader_clear_error ();
4212 mono_raise_exception (e);
4215 } else if (mono_loader_get_last_error ()) {
4217 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4218 mono_loader_clear_error ();
4221 if (type->type == MONO_TYPE_CLASS) {
4222 MonoClass *klass = mono_type_get_class (type);
4224 if (mono_security_enabled () && !klass->exception_type)
4225 /* Some security problems are detected during generic vtable construction */
4226 mono_class_setup_vtable (klass);
4228 /* need to report exceptions ? */
4229 if (throwOnError && klass->exception_type) {
4230 /* report SecurityException (or others) that occured when loading the assembly */
4231 MonoException *exc = mono_class_get_exception_for_failure (klass);
4232 mono_loader_clear_error ();
4233 mono_raise_exception (exc);
4234 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4239 /* g_print ("got it\n"); */
4240 return mono_type_get_object (mono_object_domain (assembly), type);
4244 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4247 gchar *shadow_ini_file;
4250 /* Check for shadow-copied assembly */
4251 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4252 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4254 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4255 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4261 g_free (shadow_ini_file);
4262 if (content != NULL) {
4265 *filename = content;
4272 ICALL_EXPORT MonoString *
4273 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4275 MonoDomain *domain = mono_object_domain (assembly);
4276 MonoAssembly *mass = assembly->assembly;
4277 MonoString *res = NULL;
4282 MONO_ARCH_SAVE_REGS;
4284 if (g_path_is_absolute (mass->image->name)) {
4285 absolute = g_strdup (mass->image->name);
4286 dirname = g_path_get_dirname (absolute);
4288 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4289 dirname = g_strdup (mass->basedir);
4292 replace_shadow_path (domain, dirname, &absolute);
4297 for (i = strlen (absolute) - 1; i >= 0; i--)
4298 if (absolute [i] == '\\')
4303 uri = g_filename_to_uri (absolute, NULL, NULL);
4305 const char *prepend = "file://";
4307 if (*absolute == '/' && *(absolute + 1) == '/') {
4310 prepend = "file:///";
4313 uri = g_strconcat (prepend, absolute, NULL);
4317 res = mono_string_new (domain, uri);
4324 ICALL_EXPORT MonoBoolean
4325 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4327 MonoAssembly *mass = assembly->assembly;
4329 MONO_ARCH_SAVE_REGS;
4331 return mass->in_gac;
4334 ICALL_EXPORT MonoReflectionAssembly*
4335 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4339 MonoImageOpenStatus status;
4341 MONO_ARCH_SAVE_REGS;
4343 name = mono_string_to_utf8 (mname);
4344 res = mono_assembly_load_with_partial_name (name, &status);
4350 return mono_assembly_get_object (mono_domain_get (), res);
4353 ICALL_EXPORT MonoString *
4354 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4356 MonoDomain *domain = mono_object_domain (assembly);
4359 MONO_ARCH_SAVE_REGS;
4361 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4366 ICALL_EXPORT MonoBoolean
4367 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4369 MONO_ARCH_SAVE_REGS;
4371 return assembly->assembly->ref_only;
4374 ICALL_EXPORT MonoString *
4375 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4377 MonoDomain *domain = mono_object_domain (assembly);
4379 MONO_ARCH_SAVE_REGS;
4381 return mono_string_new (domain, assembly->assembly->image->version);
4384 ICALL_EXPORT MonoReflectionMethod*
4385 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4387 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4389 MONO_ARCH_SAVE_REGS;
4393 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4396 ICALL_EXPORT MonoReflectionModule*
4397 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4399 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4402 ICALL_EXPORT MonoArray*
4403 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4405 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4406 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4410 MONO_ARCH_SAVE_REGS;
4412 for (i = 0; i < table->rows; ++i) {
4413 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4414 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4420 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4422 static MonoClass *System_Version = NULL;
4423 static MonoMethod *create_version = NULL;
4427 if (!System_Version) {
4428 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4429 g_assert (System_Version);
4432 if (!create_version) {
4433 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4434 create_version = mono_method_desc_search_in_class (desc, System_Version);
4435 g_assert (create_version);
4436 mono_method_desc_free (desc);
4442 args [3] = &revision;
4443 result = mono_object_new (domain, System_Version);
4444 mono_runtime_invoke (create_version, result, args, NULL);
4449 ICALL_EXPORT MonoArray*
4450 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4452 static MonoClass *System_Reflection_AssemblyName;
4454 MonoDomain *domain = mono_object_domain (assembly);
4456 static MonoMethod *create_culture = NULL;
4457 MonoImage *image = assembly->assembly->image;
4460 MONO_ARCH_SAVE_REGS;
4462 if (!System_Reflection_AssemblyName)
4463 System_Reflection_AssemblyName = mono_class_from_name (
4464 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4466 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4469 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4471 if (count > 0 && !create_culture) {
4472 MonoMethodDesc *desc = mono_method_desc_new (
4473 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4474 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4475 g_assert (create_culture);
4476 mono_method_desc_free (desc);
4479 for (i = 0; i < count; i++) {
4480 MonoReflectionAssemblyName *aname;
4481 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4483 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4485 aname = (MonoReflectionAssemblyName *) mono_object_new (
4486 domain, System_Reflection_AssemblyName);
4488 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4490 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4491 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4492 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4493 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4494 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4495 aname->versioncompat = 1; /* SameMachine (default) */
4496 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4497 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4499 if (create_culture) {
4501 MonoBoolean assembly_ref = 1;
4502 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4503 args [1] = &assembly_ref;
4504 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4507 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4508 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4509 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4511 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4512 /* public key token isn't copied - the class library will
4513 automatically generate it from the public key if required */
4514 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4515 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4517 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4518 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4521 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4524 /* note: this function doesn't return the codebase on purpose (i.e. it can
4525 be used under partial trust as path information isn't present). */
4527 mono_array_setref (result, i, aname);
4532 /* move this in some file in mono/util/ */
4534 g_concat_dir_and_file (const char *dir, const char *file)
4536 g_return_val_if_fail (dir != NULL, NULL);
4537 g_return_val_if_fail (file != NULL, NULL);
4540 * If the directory name doesn't have a / on the end, we need
4541 * to add one so we get a proper path to the file
4543 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4544 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4546 return g_strconcat (dir, file, NULL);
4550 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4552 char *n = mono_string_to_utf8 (name);
4553 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4555 guint32 cols [MONO_MANIFEST_SIZE];
4556 guint32 impl, file_idx;
4560 MONO_ARCH_SAVE_REGS;
4562 for (i = 0; i < table->rows; ++i) {
4563 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4564 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4565 if (strcmp (val, n) == 0)
4569 if (i == table->rows)
4572 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4575 * this code should only be called after obtaining the
4576 * ResourceInfo and handling the other cases.
4578 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4579 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4581 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4586 module = assembly->assembly->image;
4588 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4590 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4593 ICALL_EXPORT gboolean
4594 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4596 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4598 guint32 cols [MONO_MANIFEST_SIZE];
4599 guint32 file_cols [MONO_FILE_SIZE];
4603 MONO_ARCH_SAVE_REGS;
4605 n = mono_string_to_utf8 (name);
4606 for (i = 0; i < table->rows; ++i) {
4607 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4608 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4609 if (strcmp (val, n) == 0)
4613 if (i == table->rows)
4616 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4617 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4620 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4621 case MONO_IMPLEMENTATION_FILE:
4622 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4623 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4624 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4625 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4626 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4627 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4630 info->location = RESOURCE_LOCATION_EMBEDDED;
4633 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4634 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4635 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4636 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4637 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4638 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4640 mono_raise_exception (ex);
4642 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4644 /* Obtain info recursively */
4645 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4646 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4649 case MONO_IMPLEMENTATION_EXP_TYPE:
4650 g_assert_not_reached ();
4658 ICALL_EXPORT MonoObject*
4659 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4661 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4662 MonoArray *result = NULL;
4667 MONO_ARCH_SAVE_REGS;
4669 /* check hash if needed */
4671 n = mono_string_to_utf8 (name);
4672 for (i = 0; i < table->rows; ++i) {
4673 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4674 if (strcmp (val, n) == 0) {
4677 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4678 fn = mono_string_new (mono_object_domain (assembly), n);
4680 return (MonoObject*)fn;
4688 for (i = 0; i < table->rows; ++i) {
4689 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4693 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4696 for (i = 0; i < table->rows; ++i) {
4697 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4698 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4699 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4700 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4705 return (MonoObject*)result;
4708 ICALL_EXPORT MonoArray*
4709 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4711 MonoDomain *domain = mono_domain_get();
4714 int i, j, file_count = 0;
4715 MonoImage **modules;
4716 guint32 module_count, real_module_count;
4717 MonoTableInfo *table;
4718 guint32 cols [MONO_FILE_SIZE];
4719 MonoImage *image = assembly->assembly->image;
4721 g_assert (image != NULL);
4722 g_assert (!assembly->assembly->dynamic);
4724 table = &image->tables [MONO_TABLE_FILE];
4725 file_count = table->rows;
4727 modules = image->modules;
4728 module_count = image->module_count;
4730 real_module_count = 0;
4731 for (i = 0; i < module_count; ++i)
4733 real_module_count ++;
4735 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4736 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4738 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4740 for (i = 0; i < module_count; ++i)
4742 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4746 for (i = 0; i < file_count; ++i, ++j) {
4747 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4748 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4749 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4751 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4753 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4754 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4756 mono_array_setref (res, j, mono_module_get_object (domain, m));
4763 ICALL_EXPORT MonoReflectionMethod*
4764 ves_icall_GetCurrentMethod (void)
4766 MonoMethod *m = mono_method_get_last_managed ();
4768 while (m->is_inflated)
4769 m = ((MonoMethodInflated*)m)->declaring;
4771 return mono_method_get_object (mono_domain_get (), m, NULL);
4776 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4779 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4780 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4781 //method is inflated, we should inflate it on the other class
4782 MonoGenericContext ctx;
4783 ctx.method_inst = inflated->context.method_inst;
4784 ctx.class_inst = inflated->context.class_inst;
4785 if (klass->generic_class)
4786 ctx.class_inst = klass->generic_class->context.class_inst;
4787 else if (klass->generic_container)
4788 ctx.class_inst = klass->generic_container->context.class_inst;
4789 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4792 mono_class_setup_methods (method->klass);
4793 if (method->klass->exception_type)
4795 for (i = 0; i < method->klass->method.count; ++i) {
4796 if (method->klass->methods [i] == method) {
4801 mono_class_setup_methods (klass);
4802 if (klass->exception_type)
4804 g_assert (offset >= 0 && offset < klass->method.count);
4805 return klass->methods [offset];
4808 ICALL_EXPORT MonoReflectionMethod*
4809 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4813 klass = mono_class_from_mono_type (type);
4814 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4816 if (method->klass != klass) {
4817 method = mono_method_get_equivalent_method (method, klass);
4822 klass = method->klass;
4823 return mono_method_get_object (mono_domain_get (), method, klass);
4826 ICALL_EXPORT MonoReflectionMethod*
4827 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4829 return mono_method_get_object (mono_domain_get (), method, NULL);
4832 ICALL_EXPORT MonoReflectionMethodBody*
4833 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4835 return mono_method_body_get_object (mono_domain_get (), method);
4838 ICALL_EXPORT MonoReflectionAssembly*
4839 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4841 MonoMethod *dest = NULL;
4843 MONO_ARCH_SAVE_REGS;
4845 mono_stack_walk_no_il (get_executing, &dest);
4847 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4851 ICALL_EXPORT MonoReflectionAssembly*
4852 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4854 MonoDomain* domain = mono_domain_get ();
4856 MONO_ARCH_SAVE_REGS;
4858 if (!domain->entry_assembly)
4861 return mono_assembly_get_object (domain, domain->entry_assembly);
4864 ICALL_EXPORT MonoReflectionAssembly*
4865 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4870 MONO_ARCH_SAVE_REGS;
4873 mono_stack_walk_no_il (get_executing, &dest);
4875 mono_stack_walk_no_il (get_caller, &dest);
4878 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4881 ICALL_EXPORT MonoString *
4882 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4883 gboolean assembly_qualified)
4885 MonoDomain *domain = mono_object_domain (object);
4886 MonoTypeNameFormat format;
4891 format = assembly_qualified ?
4892 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4893 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4895 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4897 name = mono_type_get_name_full (object->type, format);
4901 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4906 res = mono_string_new (domain, name);
4913 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4915 MonoClass *klass = mono_class_from_mono_type (this->type);
4916 mono_class_init_or_throw (klass);
4917 return mono_security_core_clr_class_level (klass);
4921 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4923 static MonoMethod *create_culture = NULL;
4926 const char *pkey_ptr;
4928 MonoBoolean assembly_ref = 0;
4930 MONO_ARCH_SAVE_REGS;
4932 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4933 aname->major = name->major;
4934 aname->minor = name->minor;
4935 aname->build = name->build;
4936 aname->flags = name->flags;
4937 aname->revision = name->revision;
4938 aname->hashalg = name->hash_alg;
4939 aname->versioncompat = 1; /* SameMachine (default) */
4940 aname->processor_architecture = name->arch;
4942 if (by_default_version)
4943 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4946 if (absolute != NULL && *absolute != '\0') {
4947 const gchar *prepend = "file://";
4950 codebase = g_strdup (absolute);
4955 for (i = strlen (codebase) - 1; i >= 0; i--)
4956 if (codebase [i] == '\\')
4959 if (*codebase == '/' && *(codebase + 1) == '/') {
4962 prepend = "file:///";
4966 result = g_strconcat (prepend, codebase, NULL);
4972 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4976 if (!create_culture) {
4977 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4978 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4979 g_assert (create_culture);
4980 mono_method_desc_free (desc);
4983 if (name->culture) {
4984 args [0] = mono_string_new (domain, name->culture);
4985 args [1] = &assembly_ref;
4986 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4989 if (name->public_key) {
4990 pkey_ptr = (char*)name->public_key;
4991 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4993 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4994 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4995 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4996 } else if (default_publickey) {
4997 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4998 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5001 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5002 if (name->public_key_token [0]) {
5006 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5007 p = mono_array_addr (aname->keyToken, char, 0);
5009 for (i = 0, j = 0; i < 8; i++) {
5010 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5011 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5014 } else if (default_token) {
5015 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5019 ICALL_EXPORT MonoString *
5020 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5022 MonoDomain *domain = mono_object_domain (assembly);
5023 MonoAssembly *mass = assembly->assembly;
5027 name = mono_stringify_assembly_name (&mass->aname);
5028 res = mono_string_new (domain, name);
5035 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5038 MonoAssembly *mass = assembly->assembly;
5040 MONO_ARCH_SAVE_REGS;
5042 if (g_path_is_absolute (mass->image->name)) {
5043 fill_reflection_assembly_name (mono_object_domain (assembly),
5044 aname, &mass->aname, mass->image->name, TRUE,
5048 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5050 fill_reflection_assembly_name (mono_object_domain (assembly),
5051 aname, &mass->aname, absolute, TRUE, TRUE,
5058 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5061 MonoImageOpenStatus status = MONO_IMAGE_OK;
5064 MonoAssemblyName name;
5067 MONO_ARCH_SAVE_REGS;
5069 filename = mono_string_to_utf8 (fname);
5071 dirname = g_path_get_dirname (filename);
5072 replace_shadow_path (mono_domain_get (), dirname, &filename);
5075 image = mono_image_open (filename, &status);
5081 if (status == MONO_IMAGE_IMAGE_INVALID)
5082 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5084 exc = mono_get_exception_file_not_found2 (NULL, fname);
5085 mono_raise_exception (exc);
5088 res = mono_assembly_fill_assembly_name (image, &name);
5090 mono_image_close (image);
5092 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5095 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5099 mono_image_close (image);
5102 ICALL_EXPORT MonoBoolean
5103 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5104 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5106 MonoBoolean result = FALSE;
5107 MonoDeclSecurityEntry entry;
5109 /* SecurityAction.RequestMinimum */
5110 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5111 *minimum = entry.blob;
5112 *minLength = entry.size;
5115 /* SecurityAction.RequestOptional */
5116 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5117 *optional = entry.blob;
5118 *optLength = entry.size;
5121 /* SecurityAction.RequestRefuse */
5122 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5123 *refused = entry.blob;
5124 *refLength = entry.size;
5132 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5136 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5138 guint32 attrs, visibility;
5140 /* we start the count from 1 because we skip the special type <Module> */
5143 for (i = 1; i < tdef->rows; ++i) {
5144 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5145 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5146 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5150 count = tdef->rows - 1;
5152 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5153 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5155 for (i = 1; i < tdef->rows; ++i) {
5156 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5157 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5158 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5159 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5161 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5163 MonoLoaderError *error;
5166 error = mono_loader_get_last_error ();
5167 g_assert (error != NULL);
5169 ex = mono_loader_error_prepare_exception (error);
5170 mono_array_setref (*exceptions, count, ex);
5172 if (mono_loader_get_last_error ())
5173 mono_loader_clear_error ();
5181 ICALL_EXPORT MonoArray*
5182 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5184 MonoArray *res = NULL;
5185 MonoArray *exceptions = NULL;
5186 MonoImage *image = NULL;
5187 MonoTableInfo *table = NULL;
5190 int i, len, ex_count;
5192 MONO_ARCH_SAVE_REGS;
5194 domain = mono_object_domain (assembly);
5196 g_assert (!assembly->assembly->dynamic);
5197 image = assembly->assembly->image;
5198 table = &image->tables [MONO_TABLE_FILE];
5199 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5201 /* Append data from all modules in the assembly */
5202 for (i = 0; i < table->rows; ++i) {
5203 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5204 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5207 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5208 /* Append the new types to the end of the array */
5209 if (mono_array_length (res2) > 0) {
5211 MonoArray *res3, *ex3;
5213 len1 = mono_array_length (res);
5214 len2 = mono_array_length (res2);
5216 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5217 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5218 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5221 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5222 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5223 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5230 /* the ReflectionTypeLoadException must have all the types (Types property),
5231 * NULL replacing types which throws an exception. The LoaderException must
5232 * contain all exceptions for NULL items.
5235 len = mono_array_length (res);
5238 for (i = 0; i < len; i++) {
5239 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5243 klass = mono_type_get_class (t->type);
5244 if ((klass != NULL) && klass->exception_type) {
5245 /* keep the class in the list */
5246 list = g_list_append (list, klass);
5247 /* and replace Type with NULL */
5248 mono_array_setref (res, i, NULL);
5255 if (list || ex_count) {
5257 MonoException *exc = NULL;
5258 MonoArray *exl = NULL;
5259 int j, length = g_list_length (list) + ex_count;
5261 mono_loader_clear_error ();
5263 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5264 /* Types for which mono_class_get () succeeded */
5265 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5266 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5267 mono_array_setref (exl, i, exc);
5269 /* Types for which it don't */
5270 for (j = 0; j < mono_array_length (exceptions); ++j) {
5271 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5273 g_assert (i < length);
5274 mono_array_setref (exl, i, exc);
5281 exc = mono_get_exception_reflection_type_load (res, exl);
5282 mono_loader_clear_error ();
5283 mono_raise_exception (exc);
5289 ICALL_EXPORT gboolean
5290 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5292 MonoAssemblyName aname;
5293 MonoDomain *domain = mono_object_domain (name);
5295 gboolean is_version_defined;
5296 gboolean is_token_defined;
5298 aname.public_key = NULL;
5299 val = mono_string_to_utf8 (assname);
5300 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5301 g_free ((guint8*) aname.public_key);
5306 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5307 FALSE, is_token_defined);
5309 mono_assembly_name_free (&aname);
5310 g_free ((guint8*) aname.public_key);
5316 ICALL_EXPORT MonoReflectionType*
5317 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5319 MonoDomain *domain = mono_object_domain (module);
5322 MONO_ARCH_SAVE_REGS;
5324 g_assert (module->image);
5326 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5327 /* These images do not have a global type */
5330 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5331 return mono_type_get_object (domain, &klass->byval_arg);
5335 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5337 /*if (module->image)
5338 mono_image_close (module->image);*/
5341 ICALL_EXPORT MonoString*
5342 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5344 MonoDomain *domain = mono_object_domain (module);
5346 MONO_ARCH_SAVE_REGS;
5348 g_assert (module->image);
5349 return mono_string_new (domain, module->image->guid);
5352 ICALL_EXPORT gpointer
5353 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5356 if (module->image && module->image->is_module_handle)
5357 return module->image->raw_data;
5360 return (gpointer) (-1);
5364 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5366 if (image->dynamic) {
5367 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5368 *pe_kind = dyn->pe_kind;
5369 *machine = dyn->machine;
5372 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5373 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5378 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5380 return (image->md_version_major << 16) | (image->md_version_minor);
5383 ICALL_EXPORT MonoArray*
5384 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5386 MonoArray *exceptions;
5389 MONO_ARCH_SAVE_REGS;
5392 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5394 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5395 for (i = 0; i < mono_array_length (exceptions); ++i) {
5396 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5398 mono_raise_exception (ex);
5405 mono_memberref_is_method (MonoImage *image, guint32 token)
5407 if (!image->dynamic) {
5408 guint32 cols [MONO_MEMBERREF_SIZE];
5410 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5411 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5412 mono_metadata_decode_blob_size (sig, &sig);
5413 return (*sig != 0x6);
5415 MonoClass *handle_class;
5417 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5420 return mono_defaults.methodhandle_class == handle_class;
5425 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5428 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5429 mono_array_addr (type_args, MonoType*, 0));
5431 context->class_inst = NULL;
5433 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5434 mono_array_addr (method_args, MonoType*, 0));
5436 context->method_inst = NULL;
5439 ICALL_EXPORT MonoType*
5440 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5443 int table = mono_metadata_token_table (token);
5444 int index = mono_metadata_token_index (token);
5445 MonoGenericContext context;
5447 *error = ResolveTokenError_Other;
5449 /* Validate token */
5450 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5451 (table != MONO_TABLE_TYPESPEC)) {
5452 *error = ResolveTokenError_BadTable;
5456 if (image->dynamic) {
5457 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5458 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5459 return klass ? &klass->byval_arg : NULL;
5462 init_generic_context_from_args (&context, type_args, method_args);
5463 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5464 return klass ? &klass->byval_arg : NULL;
5467 if ((index <= 0) || (index > image->tables [table].rows)) {
5468 *error = ResolveTokenError_OutOfRange;
5472 init_generic_context_from_args (&context, type_args, method_args);
5473 klass = mono_class_get_full (image, token, &context);
5475 if (mono_loader_get_last_error ())
5476 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5479 return &klass->byval_arg;
5484 ICALL_EXPORT MonoMethod*
5485 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5487 int table = mono_metadata_token_table (token);
5488 int index = mono_metadata_token_index (token);
5489 MonoGenericContext context;
5492 *error = ResolveTokenError_Other;
5494 /* Validate token */
5495 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5496 (table != MONO_TABLE_MEMBERREF)) {
5497 *error = ResolveTokenError_BadTable;
5501 if (image->dynamic) {
5502 if (table == MONO_TABLE_METHOD)
5503 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5505 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5506 *error = ResolveTokenError_BadTable;
5510 init_generic_context_from_args (&context, type_args, method_args);
5511 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5514 if ((index <= 0) || (index > image->tables [table].rows)) {
5515 *error = ResolveTokenError_OutOfRange;
5518 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5519 *error = ResolveTokenError_BadTable;
5523 init_generic_context_from_args (&context, type_args, method_args);
5524 method = mono_get_method_full (image, token, NULL, &context);
5526 if (mono_loader_get_last_error ())
5527 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5532 ICALL_EXPORT MonoString*
5533 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5535 int index = mono_metadata_token_index (token);
5537 *error = ResolveTokenError_Other;
5539 /* Validate token */
5540 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5541 *error = ResolveTokenError_BadTable;
5546 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5548 if ((index <= 0) || (index >= image->heap_us.size)) {
5549 *error = ResolveTokenError_OutOfRange;
5553 /* FIXME: What to do if the index points into the middle of a string ? */
5555 return mono_ldstr (mono_domain_get (), image, index);
5558 ICALL_EXPORT MonoClassField*
5559 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5562 int table = mono_metadata_token_table (token);
5563 int index = mono_metadata_token_index (token);
5564 MonoGenericContext context;
5565 MonoClassField *field;
5567 *error = ResolveTokenError_Other;
5569 /* Validate token */
5570 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5571 *error = ResolveTokenError_BadTable;
5575 if (image->dynamic) {
5576 if (table == MONO_TABLE_FIELD)
5577 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5579 if (mono_memberref_is_method (image, token)) {
5580 *error = ResolveTokenError_BadTable;
5584 init_generic_context_from_args (&context, type_args, method_args);
5585 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5588 if ((index <= 0) || (index > image->tables [table].rows)) {
5589 *error = ResolveTokenError_OutOfRange;
5592 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5593 *error = ResolveTokenError_BadTable;
5597 init_generic_context_from_args (&context, type_args, method_args);
5598 field = mono_field_from_token (image, token, &klass, &context);
5600 if (mono_loader_get_last_error ())
5601 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5607 ICALL_EXPORT MonoObject*
5608 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5610 int table = mono_metadata_token_table (token);
5612 *error = ResolveTokenError_Other;
5615 case MONO_TABLE_TYPEDEF:
5616 case MONO_TABLE_TYPEREF:
5617 case MONO_TABLE_TYPESPEC: {
5618 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5620 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5624 case MONO_TABLE_METHOD:
5625 case MONO_TABLE_METHODSPEC: {
5626 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5628 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5632 case MONO_TABLE_FIELD: {
5633 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5635 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5639 case MONO_TABLE_MEMBERREF:
5640 if (mono_memberref_is_method (image, token)) {
5641 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5643 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5648 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5650 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5657 *error = ResolveTokenError_BadTable;
5663 ICALL_EXPORT MonoArray*
5664 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5666 int table = mono_metadata_token_table (token);
5667 int idx = mono_metadata_token_index (token);
5668 MonoTableInfo *tables = image->tables;
5673 *error = ResolveTokenError_OutOfRange;
5675 /* FIXME: Support other tables ? */
5676 if (table != MONO_TABLE_STANDALONESIG)
5682 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5685 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5687 ptr = mono_metadata_blob_heap (image, sig);
5688 len = mono_metadata_decode_blob_size (ptr, &ptr);
5690 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5691 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5695 ICALL_EXPORT MonoReflectionType*
5696 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5699 int isbyref = 0, rank;
5700 char *str = mono_string_to_utf8 (smodifiers);
5703 MONO_ARCH_SAVE_REGS;
5705 klass = mono_class_from_mono_type (tb->type.type);
5707 /* logic taken from mono_reflection_parse_type(): keep in sync */
5711 if (isbyref) { /* only one level allowed by the spec */
5718 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5721 klass = mono_ptr_class_get (&klass->byval_arg);
5722 mono_class_init (klass);
5733 else if (*p != '*') { /* '*' means unknown lower bound */
5744 klass = mono_array_class_get (klass, rank);
5745 mono_class_init (klass);
5752 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5755 ICALL_EXPORT MonoBoolean
5756 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5761 MONO_ARCH_SAVE_REGS;
5764 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5770 check_for_invalid_type (MonoClass *klass)
5774 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5777 name = mono_type_get_full_name (klass);
5778 str = mono_string_new (mono_domain_get (), name);
5780 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5783 ICALL_EXPORT MonoReflectionType *
5784 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5786 MonoClass *klass, *aklass;
5788 MONO_ARCH_SAVE_REGS;
5790 klass = mono_class_from_mono_type (type->type);
5791 check_for_invalid_type (klass);
5793 if (rank == 0) //single dimentional array
5794 aklass = mono_array_class_get (klass, 1);
5796 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5798 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5801 ICALL_EXPORT MonoReflectionType *
5802 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5806 MONO_ARCH_SAVE_REGS;
5808 klass = mono_class_from_mono_type (type->type);
5809 mono_class_init_or_throw (klass);
5810 check_for_invalid_type (klass);
5812 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5815 ICALL_EXPORT MonoReflectionType *
5816 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5818 MonoClass *klass, *pklass;
5820 klass = mono_class_from_mono_type (type->type);
5821 mono_class_init_or_throw (klass);
5822 check_for_invalid_type (klass);
5824 pklass = mono_ptr_class_get (type->type);
5826 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5829 ICALL_EXPORT MonoObject *
5830 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5831 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5833 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5834 MonoObject *delegate;
5836 MonoMethod *method = info->method;
5838 MONO_ARCH_SAVE_REGS;
5840 mono_class_init_or_throw (delegate_class);
5842 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5844 if (mono_security_core_clr_enabled ()) {
5845 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5849 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5851 if (method->dynamic) {
5852 /* Creating a trampoline would leak memory */
5853 func = mono_compile_method (method);
5855 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5856 method = mono_object_get_virtual_method (target, method);
5857 func = mono_create_ftnptr (mono_domain_get (),
5858 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5861 mono_delegate_ctor_with_method (delegate, target, func, method);
5867 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5869 /* Reset the invoke impl to the default one */
5870 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5874 * Magic number to convert a time which is relative to
5875 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5877 #define EPOCH_ADJUST ((guint64)62135596800LL)
5880 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5882 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5885 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5887 convert_to_absolute_date(SYSTEMTIME *date)
5889 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5890 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5891 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5892 /* from the calendar FAQ */
5893 int a = (14 - date->wMonth) / 12;
5894 int y = date->wYear - a;
5895 int m = date->wMonth + 12 * a - 2;
5896 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5898 /* d is now the day of the week for the first of the month (0 == Sunday) */
5900 int day_of_week = date->wDayOfWeek;
5902 /* set day_in_month to the first day in the month which falls on day_of_week */
5903 int day_in_month = 1 + (day_of_week - d);
5904 if (day_in_month <= 0)
5907 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5908 date->wDay = day_in_month + (date->wDay - 1) * 7;
5909 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5916 * Return's the offset from GMT of a local time.
5918 * tm is a local time
5919 * t is the same local time as seconds.
5922 gmt_offset(struct tm *tm, time_t t)
5924 #if defined (HAVE_TM_GMTOFF)
5925 return tm->tm_gmtoff;
5930 g.tm_isdst = tm->tm_isdst;
5932 return (int)difftime(t, t2);
5937 * This is heavily based on zdump.c from glibc 2.2.
5939 * * data[0]: start of daylight saving time (in DateTime ticks).
5940 * * data[1]: end of daylight saving time (in DateTime ticks).
5941 * * data[2]: utcoffset (in TimeSpan ticks).
5942 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5943 * * name[0]: name of this timezone when not daylight saving.
5944 * * name[1]: name of this timezone when daylight saving.
5946 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5947 * the class library allows years between 1 and 9999.
5949 * Returns true on success and zero on failure.
5951 ICALL_EXPORT guint32
5952 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5955 MonoDomain *domain = mono_domain_get ();
5956 struct tm start, tt;
5959 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5960 int day, transitioned;
5963 gmtoff_st = gmtoff_ds = transitioned = 0;
5965 MONO_ARCH_SAVE_REGS;
5967 MONO_CHECK_ARG_NULL (data);
5968 MONO_CHECK_ARG_NULL (names);
5970 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5971 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5974 * no info is better than crashing: we'll need our own tz data
5975 * to make this work properly, anyway. The range is probably
5976 * reduced to 1970 .. 2037 because that is what mktime is
5977 * guaranteed to support (we get into an infinite loop
5981 memset (&start, 0, sizeof (start));
5984 start.tm_year = year-1900;
5986 t = mktime (&start);
5988 if ((year < 1970) || (year > 2037) || (t == -1)) {
5990 tt = *localtime (&t);
5991 strftime (tzone, sizeof (tzone), "%Z", &tt);
5992 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5993 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5997 gmtoff = gmt_offset (&start, t);
5999 /* For each day of the year, calculate the tm_gmtoff. */
6000 for (day = 0; day < 365 && transitioned < 2; day++) {
6003 tt = *localtime (&t);
6005 gmtoff_after = gmt_offset(&tt, t);
6007 /* Daylight saving starts or ends here. */
6008 if (gmtoff_after != gmtoff) {
6012 /* Try to find the exact hour when daylight saving starts/ends. */
6016 tt1 = *localtime (&t1);
6017 } while (gmt_offset (&tt1, t1) != gmtoff);
6019 /* Try to find the exact minute when daylight saving starts/ends. */
6022 tt1 = *localtime (&t1);
6023 } while (gmt_offset (&tt1, t1) == gmtoff);
6025 strftime (tzone, sizeof (tzone), "%Z", &tt);
6027 /* Write data, if we're already in daylight saving, we're done. */
6029 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6030 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6031 if (gmtoff_ds == 0) {
6033 gmtoff_ds = gmtoff_after;
6040 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6041 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6042 if (gmtoff_ds == 0) {
6043 gmtoff_st = gmtoff_after;
6049 /* This is only set once when we enter daylight saving. */
6051 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6052 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6054 gmtoff = gmt_offset (&tt, t);
6058 if (transitioned < 2) {
6059 strftime (tzone, sizeof (tzone), "%Z", &tt);
6060 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6061 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6062 mono_array_set ((*data), gint64, 0, 0);
6063 mono_array_set ((*data), gint64, 1, 0);
6064 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6065 mono_array_set ((*data), gint64, 3, 0);
6070 MonoDomain *domain = mono_domain_get ();
6071 TIME_ZONE_INFORMATION tz_info;
6076 tz_id = GetTimeZoneInformation (&tz_info);
6077 if (tz_id == TIME_ZONE_ID_INVALID)
6080 MONO_CHECK_ARG_NULL (data);
6081 MONO_CHECK_ARG_NULL (names);
6083 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6084 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6086 for (i = 0; i < 32; ++i)
6087 if (!tz_info.DaylightName [i])
6089 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6090 for (i = 0; i < 32; ++i)
6091 if (!tz_info.StandardName [i])
6093 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6095 if ((year <= 1601) || (year > 30827)) {
6097 * According to MSDN, the MS time functions can't handle dates outside
6103 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6104 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6105 tz_info.StandardDate.wYear = year;
6106 convert_to_absolute_date(&tz_info.StandardDate);
6107 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6112 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6113 tz_info.DaylightDate.wYear = year;
6114 convert_to_absolute_date(&tz_info.DaylightDate);
6115 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6120 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6122 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6123 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6129 ICALL_EXPORT gpointer
6130 ves_icall_System_Object_obj_address (MonoObject *this)
6132 MONO_ARCH_SAVE_REGS;
6139 static inline gint32
6140 mono_array_get_byte_length (MonoArray *array)
6146 klass = array->obj.vtable->klass;
6148 if (array->bounds == NULL)
6149 length = array->max_length;
6152 for (i = 0; i < klass->rank; ++ i)
6153 length *= array->bounds [i].length;
6156 switch (klass->element_class->byval_arg.type) {
6159 case MONO_TYPE_BOOLEAN:
6163 case MONO_TYPE_CHAR:
6171 return length * sizeof (gpointer);
6182 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6184 MONO_ARCH_SAVE_REGS;
6186 return mono_array_get_byte_length (array);
6190 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6192 MONO_ARCH_SAVE_REGS;
6194 return mono_array_get (array, gint8, idx);
6198 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6200 MONO_ARCH_SAVE_REGS;
6202 mono_array_set (array, gint8, idx, value);
6205 ICALL_EXPORT MonoBoolean
6206 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6208 guint8 *src_buf, *dest_buf;
6210 MONO_ARCH_SAVE_REGS;
6212 /* This is called directly from the class libraries without going through the managed wrapper */
6213 MONO_CHECK_ARG_NULL (src);
6214 MONO_CHECK_ARG_NULL (dest);
6216 /* watch out for integer overflow */
6217 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6220 src_buf = (guint8 *)src->vector + src_offset;
6221 dest_buf = (guint8 *)dest->vector + dest_offset;
6224 memcpy (dest_buf, src_buf, count);
6226 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6231 #ifndef DISABLE_REMOTING
6232 ICALL_EXPORT MonoObject *
6233 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6235 MonoDomain *domain = mono_object_domain (this);
6237 MonoRealProxy *rp = ((MonoRealProxy *)this);
6238 MonoTransparentProxy *tp;
6242 MONO_ARCH_SAVE_REGS;
6244 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6245 tp = (MonoTransparentProxy*) res;
6247 MONO_OBJECT_SETREF (tp, rp, rp);
6248 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6249 klass = mono_class_from_mono_type (type);
6251 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6252 tp->remote_class = mono_remote_class (domain, class_name, klass);
6254 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6258 ICALL_EXPORT MonoReflectionType *
6259 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6261 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6265 /* System.Environment */
6268 ves_icall_System_Environment_get_UserName (void)
6270 MONO_ARCH_SAVE_REGS;
6272 /* using glib is more portable */
6273 return mono_string_new (mono_domain_get (), g_get_user_name ());
6277 ICALL_EXPORT MonoString *
6278 ves_icall_System_Environment_get_MachineName (void)
6280 #if defined (HOST_WIN32)
6285 len = MAX_COMPUTERNAME_LENGTH + 1;
6286 buf = g_new (gunichar2, len);
6289 if (GetComputerName (buf, (PDWORD) &len))
6290 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6294 #elif !defined(DISABLE_SOCKETS)
6298 if (gethostname (buf, sizeof (buf)) == 0)
6299 result = mono_string_new (mono_domain_get (), buf);
6305 return mono_string_new (mono_domain_get (), "mono");
6310 ves_icall_System_Environment_get_Platform (void)
6312 #if defined (TARGET_WIN32)
6315 #elif defined(__MACH__)
6318 // Notice that the value is hidden from user code, and only exposed
6319 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6320 // define and making assumptions based on Unix/128/4 values before there
6321 // was a MacOS define. Lots of code would assume that not-Unix meant
6322 // Windows, but in this case, it would be OSX.
6331 ICALL_EXPORT MonoString *
6332 ves_icall_System_Environment_get_NewLine (void)
6334 MONO_ARCH_SAVE_REGS;
6336 #if defined (HOST_WIN32)
6337 return mono_string_new (mono_domain_get (), "\r\n");
6339 return mono_string_new (mono_domain_get (), "\n");
6343 ICALL_EXPORT MonoString *
6344 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6349 MONO_ARCH_SAVE_REGS;
6354 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6355 value = g_getenv (utf8_name);
6362 return mono_string_new (mono_domain_get (), value);
6366 * There is no standard way to get at environ.
6369 #ifndef __MINGW32_VERSION
6370 #if defined(__APPLE__) && !defined (__arm__)
6371 /* Apple defines this in crt_externs.h but doesn't provide that header for
6372 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6373 * in fact exist on all implementations (so far)
6375 gchar ***_NSGetEnviron(void);
6376 #define environ (*_NSGetEnviron())
6384 ICALL_EXPORT MonoArray *
6385 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6396 env_strings = GetEnvironmentStrings();
6399 env_string = env_strings;
6400 while (*env_string != '\0') {
6401 /* weird case that MS seems to skip */
6402 if (*env_string != '=')
6404 while (*env_string != '\0')
6410 domain = mono_domain_get ();
6411 names = mono_array_new (domain, mono_defaults.string_class, n);
6415 env_string = env_strings;
6416 while (*env_string != '\0') {
6417 /* weird case that MS seems to skip */
6418 if (*env_string != '=') {
6419 equal_str = wcschr(env_string, '=');
6420 g_assert(equal_str);
6421 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6422 mono_array_setref (names, n, str);
6425 while (*env_string != '\0')
6430 FreeEnvironmentStrings (env_strings);
6442 MONO_ARCH_SAVE_REGS;
6445 for (e = environ; *e != 0; ++ e)
6448 domain = mono_domain_get ();
6449 names = mono_array_new (domain, mono_defaults.string_class, n);
6452 for (e = environ; *e != 0; ++ e) {
6453 parts = g_strsplit (*e, "=", 2);
6455 str = mono_string_new (domain, *parts);
6456 mono_array_setref (names, n, str);
6469 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6471 #if !GLIB_CHECK_VERSION(2,4,0)
6472 #define g_setenv(a,b,c) setenv(a,b,c)
6473 #define g_unsetenv(a) unsetenv(a)
6477 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6482 gunichar2 *utf16_name, *utf16_value;
6484 gchar *utf8_name, *utf8_value;
6487 MONO_ARCH_SAVE_REGS;
6490 utf16_name = mono_string_to_utf16 (name);
6491 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6492 SetEnvironmentVariable (utf16_name, NULL);
6493 g_free (utf16_name);
6497 utf16_value = mono_string_to_utf16 (value);
6499 SetEnvironmentVariable (utf16_name, utf16_value);
6501 g_free (utf16_name);
6502 g_free (utf16_value);
6504 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6506 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6507 g_unsetenv (utf8_name);
6512 utf8_value = mono_string_to_utf8_checked (value, &error);
6513 if (!mono_error_ok (&error)) {
6515 mono_error_raise_exception (&error);
6517 g_setenv (utf8_name, utf8_value, TRUE);
6520 g_free (utf8_value);
6525 ves_icall_System_Environment_Exit (int result)
6527 MONO_ARCH_SAVE_REGS;
6529 mono_environment_exitcode_set (result);
6531 /* FIXME: There are some cleanup hangs that should be worked out, but
6532 * if the program is going to exit, everything will be cleaned up when
6533 * NaCl exits anyway.
6535 #ifndef __native_client__
6536 if (!mono_runtime_try_shutdown ())
6537 mono_thread_exit ();
6539 /* Suspend all managed threads since the runtime is going away */
6540 mono_thread_suspend_all_other_threads ();
6542 mono_runtime_quit ();
6545 /* we may need to do some cleanup here... */
6549 ICALL_EXPORT MonoString*
6550 ves_icall_System_Environment_GetGacPath (void)
6552 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6555 ICALL_EXPORT MonoString*
6556 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6558 #if defined (HOST_WIN32)
6559 #ifndef CSIDL_FLAG_CREATE
6560 #define CSIDL_FLAG_CREATE 0x8000
6563 WCHAR path [MAX_PATH];
6564 /* Create directory if no existing */
6565 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6569 return mono_string_new_utf16 (mono_domain_get (), path, len);
6572 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6574 return mono_string_new (mono_domain_get (), "");
6577 ICALL_EXPORT MonoArray *
6578 ves_icall_System_Environment_GetLogicalDrives (void)
6580 gunichar2 buf [256], *ptr, *dname;
6582 guint initial_size = 127, size = 128;
6585 MonoString *drivestr;
6586 MonoDomain *domain = mono_domain_get ();
6589 MONO_ARCH_SAVE_REGS;
6594 while (size > initial_size) {
6595 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6596 if (size > initial_size) {
6599 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6600 initial_size = size;
6614 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6619 while (*u16) { u16++; len ++; }
6620 drivestr = mono_string_new_utf16 (domain, dname, len);
6621 mono_array_setref (result, ndrives++, drivestr);
6631 ICALL_EXPORT MonoString *
6632 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6634 gunichar2 volume_name [MAX_PATH + 1];
6636 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6638 return mono_string_from_utf16 (volume_name);
6641 ICALL_EXPORT MonoString *
6642 ves_icall_System_Environment_InternalGetHome (void)
6644 MONO_ARCH_SAVE_REGS;
6646 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6649 static const char *encodings [] = {
6651 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6652 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6653 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6655 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6656 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6657 "x_unicode_2_0_utf_7",
6659 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6660 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6662 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6665 "unicodefffe", "utf_16be",
6672 * Returns the internal codepage, if the value of "int_code_page" is
6673 * 1 at entry, and we can not compute a suitable code page number,
6674 * returns the code page as a string
6676 ICALL_EXPORT MonoString*
6677 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6682 char *codepage = NULL;
6684 int want_name = *int_code_page;
6687 *int_code_page = -1;
6688 MONO_ARCH_SAVE_REGS;
6690 g_get_charset (&cset);
6691 c = codepage = strdup (cset);
6692 for (c = codepage; *c; c++){
6693 if (isascii (*c) && isalpha (*c))
6698 /* g_print ("charset: %s\n", cset); */
6700 /* handle some common aliases */
6703 for (i = 0; p != 0; ){
6704 if ((gssize) p < 7){
6706 p = encodings [++i];
6709 if (strcmp (p, codepage) == 0){
6710 *int_code_page = code;
6713 p = encodings [++i];
6716 if (strstr (codepage, "utf_8") != NULL)
6717 *int_code_page |= 0x10000000;
6720 if (want_name && *int_code_page == -1)
6721 return mono_string_new (mono_domain_get (), cset);
6726 ICALL_EXPORT MonoBoolean
6727 ves_icall_System_Environment_get_HasShutdownStarted (void)
6729 if (mono_runtime_is_shutting_down ())
6732 if (mono_domain_is_unloading (mono_domain_get ()))
6739 ves_icall_System_Environment_BroadcastSettingChange (void)
6742 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6747 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6748 MonoReflectionMethod *method,
6749 MonoArray *out_args)
6751 MONO_ARCH_SAVE_REGS;
6753 mono_message_init (mono_object_domain (this), this, method, out_args);
6756 #ifndef DISABLE_REMOTING
6757 ICALL_EXPORT MonoBoolean
6758 ves_icall_IsTransparentProxy (MonoObject *proxy)
6760 MONO_ARCH_SAVE_REGS;
6765 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6771 ICALL_EXPORT MonoReflectionMethod *
6772 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6773 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6777 MonoMethod **vtable;
6778 MonoMethod *res = NULL;
6780 MONO_CHECK_ARG_NULL (rtype);
6781 MONO_CHECK_ARG_NULL (rmethod);
6783 method = rmethod->method;
6784 klass = mono_class_from_mono_type (rtype->type);
6785 mono_class_init_or_throw (klass);
6787 if (MONO_CLASS_IS_INTERFACE (klass))
6790 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6793 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6794 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6800 mono_class_setup_vtable (klass);
6801 vtable = klass->vtable;
6803 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6804 gboolean variance_used = FALSE;
6805 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6806 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6808 res = vtable [offs + method->slot];
6810 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6813 if (method->slot != -1)
6814 res = vtable [method->slot];
6820 return mono_method_get_object (mono_domain_get (), res, NULL);
6824 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6829 MONO_ARCH_SAVE_REGS;
6831 klass = mono_class_from_mono_type (type->type);
6832 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6834 mono_vtable_set_is_remote (vtable, enable);
6837 #else /* DISABLE_REMOTING */
6840 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6842 g_assert_not_reached ();
6847 ICALL_EXPORT MonoObject *
6848 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6853 MONO_ARCH_SAVE_REGS;
6855 domain = mono_object_domain (type);
6856 klass = mono_class_from_mono_type (type->type);
6857 mono_class_init_or_throw (klass);
6859 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6860 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6862 if (klass->rank >= 1) {
6863 g_assert (klass->rank == 1);
6864 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6866 /* Bypass remoting object creation check */
6867 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6871 ICALL_EXPORT MonoString *
6872 ves_icall_System_IO_get_temp_path (void)
6874 MONO_ARCH_SAVE_REGS;
6876 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6879 #ifndef PLATFORM_NO_DRIVEINFO
6880 ICALL_EXPORT MonoBoolean
6881 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6882 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6886 ULARGE_INTEGER wapi_free_bytes_avail;
6887 ULARGE_INTEGER wapi_total_number_of_bytes;
6888 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6890 MONO_ARCH_SAVE_REGS;
6892 *error = ERROR_SUCCESS;
6893 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6894 &wapi_total_number_of_free_bytes);
6897 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6898 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6899 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6901 *free_bytes_avail = 0;
6902 *total_number_of_bytes = 0;
6903 *total_number_of_free_bytes = 0;
6904 *error = GetLastError ();
6910 ICALL_EXPORT guint32
6911 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6913 MONO_ARCH_SAVE_REGS;
6915 return GetDriveType (mono_string_chars (root_path_name));
6919 ICALL_EXPORT gpointer
6920 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6922 MONO_ARCH_SAVE_REGS;
6924 return mono_compile_method (method);
6927 ICALL_EXPORT MonoString *
6928 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6933 MONO_ARCH_SAVE_REGS;
6935 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6937 #if defined (HOST_WIN32)
6938 /* Avoid mixing '/' and '\\' */
6941 for (i = strlen (path) - 1; i >= 0; i--)
6942 if (path [i] == '/')
6946 mcpath = mono_string_new (mono_domain_get (), path);
6953 get_bundled_app_config (void)
6955 const gchar *app_config;
6958 gchar *config_file_name, *config_file_path;
6962 MONO_ARCH_SAVE_REGS;
6964 domain = mono_domain_get ();
6965 file = domain->setup->configuration_file;
6969 // Retrieve config file and remove the extension
6970 config_file_name = mono_string_to_utf8 (file);
6971 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6972 if (!config_file_path)
6973 config_file_path = config_file_name;
6974 len = strlen (config_file_path) - strlen (".config");
6975 module = g_malloc0 (len + 1);
6976 memcpy (module, config_file_path, len);
6977 // Get the config file from the module name
6978 app_config = mono_config_string_for_assembly_file (module);
6981 if (config_file_name != config_file_path)
6982 g_free (config_file_name);
6983 g_free (config_file_path);
6988 return mono_string_new (mono_domain_get (), app_config);
6992 get_bundled_machine_config (void)
6994 const gchar *machine_config;
6996 MONO_ARCH_SAVE_REGS;
6998 machine_config = mono_get_machine_config ();
7000 if (!machine_config)
7003 return mono_string_new (mono_domain_get (), machine_config);
7006 ICALL_EXPORT MonoString *
7007 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7012 MONO_ARCH_SAVE_REGS;
7014 path = g_path_get_dirname (mono_get_config_dir ());
7016 #if defined (HOST_WIN32)
7017 /* Avoid mixing '/' and '\\' */
7020 for (i = strlen (path) - 1; i >= 0; i--)
7021 if (path [i] == '/')
7025 ipath = mono_string_new (mono_domain_get (), path);
7031 ICALL_EXPORT gboolean
7032 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7034 MonoPEResourceDataEntry *entry;
7037 MONO_ARCH_SAVE_REGS;
7039 if (!assembly || !result || !size)
7044 image = assembly->assembly->image;
7045 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7049 *result = mono_image_rva_map (image, entry->rde_data_offset);
7054 *size = entry->rde_size;
7059 ICALL_EXPORT MonoBoolean
7060 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7062 return mono_is_debugger_attached ();
7065 ICALL_EXPORT MonoBoolean
7066 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7068 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7069 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7075 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7077 if (mono_get_runtime_callbacks ()->debug_log)
7078 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7082 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7084 #if defined (HOST_WIN32)
7085 OutputDebugString (mono_string_chars (message));
7087 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7091 /* Only used for value types */
7092 ICALL_EXPORT MonoObject *
7093 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7098 MONO_ARCH_SAVE_REGS;
7100 domain = mono_object_domain (type);
7101 klass = mono_class_from_mono_type (type->type);
7102 mono_class_init_or_throw (klass);
7104 if (mono_class_is_nullable (klass))
7105 /* No arguments -> null */
7108 return mono_object_new (domain, klass);
7111 ICALL_EXPORT MonoReflectionMethod *
7112 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7114 MonoClass *klass, *parent;
7115 MonoMethod *method = m->method;
7116 MonoMethod *result = NULL;
7119 MONO_ARCH_SAVE_REGS;
7121 if (method->klass == NULL)
7124 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7125 MONO_CLASS_IS_INTERFACE (method->klass) ||
7126 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7129 slot = mono_method_get_vtable_slot (method);
7133 klass = method->klass;
7134 if (klass->generic_class)
7135 klass = klass->generic_class->container_class;
7138 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7139 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7140 mono_class_setup_vtable (parent);
7141 if (parent->vtable_size <= slot)
7146 klass = klass->parent;
7151 if (klass == method->klass)
7154 /*This is possible if definition == FALSE.
7155 * Do it here to be really sure we don't read invalid memory.
7157 if (slot >= klass->vtable_size)
7160 mono_class_setup_vtable (klass);
7162 result = klass->vtable [slot];
7163 if (result == NULL) {
7164 /* It is an abstract method */
7165 gpointer iter = NULL;
7166 while ((result = mono_class_get_methods (klass, &iter)))
7167 if (result->slot == slot)
7174 return mono_method_get_object (mono_domain_get (), result, NULL);
7177 ICALL_EXPORT MonoString*
7178 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7180 MonoMethod *method = m->method;
7182 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7187 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7189 MONO_ARCH_SAVE_REGS;
7191 iter->sig = *(MonoMethodSignature**)argsp;
7193 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7194 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7197 /* FIXME: it's not documented what start is exactly... */
7201 iter->args = argsp + sizeof (gpointer);
7203 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7205 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7208 ICALL_EXPORT MonoTypedRef
7209 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7211 guint32 i, arg_size;
7214 MONO_ARCH_SAVE_REGS;
7216 i = iter->sig->sentinelpos + iter->next_arg;
7218 g_assert (i < iter->sig->param_count);
7220 res.type = iter->sig->params [i];
7221 res.klass = mono_class_from_mono_type (res.type);
7222 arg_size = mono_type_stack_size (res.type, &align);
7223 #if defined(__arm__) || defined(__mips__)
7224 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7226 res.value = iter->args;
7227 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7228 /* Values are stored as 8 byte register sized objects, but 'value'
7229 * is dereferenced as a pointer in other routines.
7231 res.value = (char*)res.value + 4;
7233 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7234 if (arg_size <= sizeof (gpointer)) {
7236 int padding = arg_size - mono_type_size (res.type, &dummy);
7237 res.value = (guint8*)res.value + padding;
7240 iter->args = (char*)iter->args + arg_size;
7243 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7248 ICALL_EXPORT MonoTypedRef
7249 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7251 guint32 i, arg_size;
7254 MONO_ARCH_SAVE_REGS;
7256 i = iter->sig->sentinelpos + iter->next_arg;
7258 g_assert (i < iter->sig->param_count);
7260 while (i < iter->sig->param_count) {
7261 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7263 res.type = iter->sig->params [i];
7264 res.klass = mono_class_from_mono_type (res.type);
7265 /* FIXME: endianess issue... */
7266 arg_size = mono_type_stack_size (res.type, &align);
7267 #if defined(__arm__) || defined(__mips__)
7268 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7270 res.value = iter->args;
7271 iter->args = (char*)iter->args + arg_size;
7273 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7276 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7284 ICALL_EXPORT MonoType*
7285 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7288 MONO_ARCH_SAVE_REGS;
7290 i = iter->sig->sentinelpos + iter->next_arg;
7292 g_assert (i < iter->sig->param_count);
7294 return iter->sig->params [i];
7297 ICALL_EXPORT MonoObject*
7298 mono_TypedReference_ToObject (MonoTypedRef tref)
7300 MONO_ARCH_SAVE_REGS;
7302 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7303 MonoObject** objp = tref.value;
7307 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7310 ICALL_EXPORT MonoObject*
7311 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7313 MONO_ARCH_SAVE_REGS;
7315 if (MONO_TYPE_IS_REFERENCE (type)) {
7316 MonoObject** objp = value;
7320 return mono_value_box (mono_domain_get (), klass, value);
7324 prelink_method (MonoMethod *method)
7326 const char *exc_class, *exc_arg;
7327 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7329 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7331 mono_raise_exception(
7332 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7334 /* create the wrapper, too? */
7338 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7340 MONO_ARCH_SAVE_REGS;
7341 prelink_method (method->method);
7345 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7347 MonoClass *klass = mono_class_from_mono_type (type->type);
7349 gpointer iter = NULL;
7350 MONO_ARCH_SAVE_REGS;
7352 mono_class_init_or_throw (klass);
7354 while ((m = mono_class_get_methods (klass, &iter)))
7358 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7360 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7361 gint32 const **exponents,
7362 gunichar2 const **digitLowerTable,
7363 gunichar2 const **digitUpperTable,
7364 gint64 const **tenPowersList,
7365 gint32 const **decHexDigits)
7367 *mantissas = Formatter_MantissaBitsTable;
7368 *exponents = Formatter_TensExponentTable;
7369 *digitLowerTable = Formatter_DigitLowerTable;
7370 *digitUpperTable = Formatter_DigitUpperTable;
7371 *tenPowersList = Formatter_TenPowersList;
7372 *decHexDigits = Formatter_DecHexDigits;
7376 get_category_data (int version,
7377 guint8 const **category_data,
7378 guint16 const **category_astral_index)
7380 *category_astral_index = NULL;
7382 #ifndef DISABLE_NET_4_0
7384 *category_data = CategoryData_v4;
7385 #ifndef DISABLE_ASTRAL
7386 *category_astral_index = CategoryData_v4_astral_index;
7392 *category_data = CategoryData_v2;
7393 #ifndef DISABLE_ASTRAL
7394 *category_astral_index = CategoryData_v2_astral_index;
7398 /* These parameters are "readonly" in corlib/System/Char.cs */
7400 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7401 guint8 const **category_data,
7402 guint16 const **category_astral_index,
7403 guint8 const **numeric_data,
7404 gdouble const **numeric_data_values,
7405 guint16 const **to_lower_data_low,
7406 guint16 const **to_lower_data_high,
7407 guint16 const **to_upper_data_low,
7408 guint16 const **to_upper_data_high)
7410 get_category_data (category_data_version, category_data, category_astral_index);
7411 *numeric_data = NumericData;
7412 *numeric_data_values = NumericDataValues;
7413 *to_lower_data_low = ToLowerDataLow;
7414 *to_lower_data_high = ToLowerDataHigh;
7415 *to_upper_data_low = ToUpperDataLow;
7416 *to_upper_data_high = ToUpperDataHigh;
7420 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7422 return method->method->token;
7426 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7427 * and avoid useless allocations.
7430 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7434 for (i = 0; i < type->num_mods; ++i) {
7435 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7440 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7442 for (i = 0; i < type->num_mods; ++i) {
7443 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7444 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7445 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7452 ICALL_EXPORT MonoArray*
7453 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7455 MonoType *type = param->ClassImpl->type;
7456 MonoClass *member_class = mono_object_class (param->MemberImpl);
7457 MonoMethod *method = NULL;
7460 MonoMethodSignature *sig;
7462 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7463 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7464 method = rmethod->method;
7465 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7466 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7467 if (!(method = prop->property->get))
7468 method = prop->property->set;
7471 char *type_name = mono_type_get_full_name (member_class);
7472 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7473 MonoException *ex = mono_get_exception_not_supported (msg);
7476 mono_raise_exception (ex);
7479 image = method->klass->image;
7480 pos = param->PositionImpl;
7481 sig = mono_method_signature (method);
7485 type = sig->params [pos];
7487 return type_array_from_modifiers (image, type, optional);
7491 get_property_type (MonoProperty *prop)
7493 MonoMethodSignature *sig;
7495 sig = mono_method_signature (prop->get);
7497 } else if (prop->set) {
7498 sig = mono_method_signature (prop->set);
7499 return sig->params [sig->param_count - 1];
7504 ICALL_EXPORT MonoArray*
7505 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7507 MonoType *type = get_property_type (property->property);
7508 MonoImage *image = property->klass->image;
7512 return type_array_from_modifiers (image, type, optional);
7516 *Construct a MonoType suited to be used to decode a constant blob object.
7518 * @type is the target type which will be constructed
7519 * @blob_type is the blob type, for example, that comes from the constant table
7520 * @real_type is the expected constructed type.
7523 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7525 type->type = blob_type;
7526 type->data.klass = NULL;
7527 if (blob_type == MONO_TYPE_CLASS)
7528 type->data.klass = mono_defaults.object_class;
7529 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7530 /* For enums, we need to use the base type */
7531 type->type = MONO_TYPE_VALUETYPE;
7532 type->data.klass = mono_class_from_mono_type (real_type);
7534 type->data.klass = mono_class_from_mono_type (real_type);
7537 ICALL_EXPORT MonoObject*
7538 property_info_get_default_value (MonoReflectionProperty *property)
7541 MonoProperty *prop = property->property;
7542 MonoType *type = get_property_type (prop);
7543 MonoDomain *domain = mono_object_domain (property);
7544 MonoTypeEnum def_type;
7545 const char *def_value;
7548 mono_class_init (prop->parent);
7550 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7551 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7553 def_value = mono_class_get_property_default_value (prop, &def_type);
7555 mono_type_from_blob_type (&blob_type, def_type, type);
7556 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7561 ICALL_EXPORT MonoBoolean
7562 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7564 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7565 MonoCustomAttrInfo *cinfo;
7568 mono_class_init_or_throw (attr_class);
7570 cinfo = mono_reflection_get_custom_attrs_info (obj);
7573 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7575 mono_custom_attrs_free (cinfo);
7579 ICALL_EXPORT MonoArray*
7580 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7582 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7587 mono_class_init_or_throw (attr_class);
7589 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7590 if (!mono_error_ok (&error))
7591 mono_error_raise_exception (&error);
7592 if (mono_loader_get_last_error ()) {
7593 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7594 g_assert_not_reached ();
7602 ICALL_EXPORT MonoString*
7603 ves_icall_Mono_Runtime_GetDisplayName (void)
7606 MonoString *display_name;
7608 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7609 display_name = mono_string_new (mono_domain_get (), info);
7611 return display_name;
7614 ICALL_EXPORT MonoString*
7615 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7617 MonoString *message;
7621 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7622 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7625 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7627 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7635 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7636 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7637 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7638 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7639 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7640 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7641 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7642 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7646 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7651 gunichar2 last, prev_last, prev2_last;
7658 int havePadding = 0;
7660 last = prev_last = 0, prev2_last = 0;
7661 for (i = 0; i < ilength; i++) {
7663 if (c >= sizeof (dbase64)) {
7664 exc = mono_exception_from_name_msg (mono_get_corlib (),
7665 "System", "FormatException",
7666 "Invalid character found.");
7667 mono_raise_exception (exc);
7668 } else if (isspace (c)) {
7670 } else if (havePadding && c != '=') {
7671 exc = mono_exception_from_name_msg (mono_get_corlib (),
7672 "System", "FormatException",
7673 "Invalid character found.");
7674 mono_raise_exception (exc);
7676 if (c == '=') havePadding = 1;
7677 prev2_last = prev_last;
7683 olength = ilength - ignored;
7685 if (allowWhitespaceOnly && olength == 0) {
7686 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7689 if ((olength & 3) != 0 || olength <= 0) {
7690 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7691 "FormatException", "Invalid length.");
7692 mono_raise_exception (exc);
7695 if (prev2_last == '=') {
7696 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7697 mono_raise_exception (exc);
7700 olength = (olength * 3) / 4;
7704 if (prev_last == '=')
7707 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7708 res_ptr = mono_array_addr (result, guchar, 0);
7709 for (i = 0; i < ilength; ) {
7712 for (k = 0; k < 4 && i < ilength;) {
7718 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7719 exc = mono_exception_from_name_msg (mono_get_corlib (),
7720 "System", "FormatException",
7721 "Invalid character found.");
7722 mono_raise_exception (exc);
7727 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7729 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7731 *res_ptr++ = (b [2] << 6) | b [3];
7733 while (i < ilength && isspace (start [i]))
7740 ICALL_EXPORT MonoArray *
7741 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7743 MONO_ARCH_SAVE_REGS;
7745 return base64_to_byte_array (mono_string_chars (str),
7746 mono_string_length (str), allowWhitespaceOnly);
7749 ICALL_EXPORT MonoArray *
7750 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7752 MONO_ARCH_SAVE_REGS;
7754 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7758 #ifndef DISABLE_ICALL_TABLES
7760 #define ICALL_TYPE(id,name,first)
7761 #define ICALL(id,name,func) Icall_ ## id,
7764 #include "metadata/icall-def.h"
7770 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7771 #define ICALL(id,name,func)
7773 #include "metadata/icall-def.h"
7779 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7780 #define ICALL(id,name,func)
7782 guint16 first_icall;
7785 static const IcallTypeDesc
7786 icall_type_descs [] = {
7787 #include "metadata/icall-def.h"
7791 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7794 #define ICALL_TYPE(id,name,first)
7797 #ifdef HAVE_ARRAY_ELEM_INIT
7798 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7799 #define MSGSTRFIELD1(line) str##line
7801 static const struct msgstrtn_t {
7802 #define ICALL(id,name,func)
7804 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7805 #include "metadata/icall-def.h"
7807 } icall_type_names_str = {
7808 #define ICALL_TYPE(id,name,first) (name),
7809 #include "metadata/icall-def.h"
7812 static const guint16 icall_type_names_idx [] = {
7813 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7814 #include "metadata/icall-def.h"
7817 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7819 static const struct msgstr_t {
7821 #define ICALL_TYPE(id,name,first)
7822 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7823 #include "metadata/icall-def.h"
7825 } icall_names_str = {
7826 #define ICALL(id,name,func) (name),
7827 #include "metadata/icall-def.h"
7830 static const guint16 icall_names_idx [] = {
7831 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7832 #include "metadata/icall-def.h"
7835 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7841 #define ICALL_TYPE(id,name,first) name,
7842 #define ICALL(id,name,func)
7843 static const char* const
7844 icall_type_names [] = {
7845 #include "metadata/icall-def.h"
7849 #define icall_type_name_get(id) (icall_type_names [(id)])
7853 #define ICALL_TYPE(id,name,first)
7854 #define ICALL(id,name,func) name,
7855 static const char* const
7857 #include "metadata/icall-def.h"
7860 #define icall_name_get(id) icall_names [(id)]
7862 #endif /* !HAVE_ARRAY_ELEM_INIT */
7866 #define ICALL_TYPE(id,name,first)
7867 #define ICALL(id,name,func) func,
7868 static const gconstpointer
7869 icall_functions [] = {
7870 #include "metadata/icall-def.h"
7874 #ifdef ENABLE_ICALL_SYMBOL_MAP
7877 #define ICALL_TYPE(id,name,first)
7878 #define ICALL(id,name,func) #func,
7879 static const gconstpointer
7880 icall_symbols [] = {
7881 #include "metadata/icall-def.h"
7886 #endif /* DISABLE_ICALL_TABLES */
7888 static mono_mutex_t icall_mutex;
7889 static GHashTable *icall_hash = NULL;
7890 static GHashTable *jit_icall_hash_name = NULL;
7891 static GHashTable *jit_icall_hash_addr = NULL;
7894 mono_icall_init (void)
7896 #ifndef DISABLE_ICALL_TABLES
7899 /* check that tables are sorted: disable in release */
7902 const char *prev_class = NULL;
7903 const char *prev_method;
7905 for (i = 0; i < Icall_type_num; ++i) {
7906 const IcallTypeDesc *desc;
7909 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7910 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7911 prev_class = icall_type_name_get (i);
7912 desc = &icall_type_descs [i];
7913 num_icalls = icall_desc_num_icalls (desc);
7914 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7915 for (j = 0; j < num_icalls; ++j) {
7916 const char *methodn = icall_name_get (desc->first_icall + j);
7917 if (prev_method && strcmp (prev_method, methodn) >= 0)
7918 g_print ("method %s should come before method %s\n", methodn, prev_method);
7919 prev_method = methodn;
7925 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7926 mono_mutex_init (&icall_mutex);
7930 mono_icall_lock (void)
7932 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7936 mono_icall_unlock (void)
7938 mono_locks_mutex_release (&icall_mutex, IcallLock);
7942 mono_icall_cleanup (void)
7944 g_hash_table_destroy (icall_hash);
7945 g_hash_table_destroy (jit_icall_hash_name);
7946 g_hash_table_destroy (jit_icall_hash_addr);
7947 mono_mutex_destroy (&icall_mutex);
7951 mono_add_internal_call (const char *name, gconstpointer method)
7955 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7957 mono_icall_unlock ();
7960 #ifndef DISABLE_ICALL_TABLES
7962 #ifdef HAVE_ARRAY_ELEM_INIT
7964 compare_method_imap (const void *key, const void *elem)
7966 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7967 return strcmp (key, method_name);
7971 find_method_icall (const IcallTypeDesc *imap, const char *name)
7973 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);
7976 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7980 compare_class_imap (const void *key, const void *elem)
7982 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7983 return strcmp (key, class_name);
7986 static const IcallTypeDesc*
7987 find_class_icalls (const char *name)
7989 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7992 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7995 #else /* HAVE_ARRAY_ELEM_INIT */
7998 compare_method_imap (const void *key, const void *elem)
8000 const char** method_name = (const char**)elem;
8001 return strcmp (key, *method_name);
8005 find_method_icall (const IcallTypeDesc *imap, const char *name)
8007 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8010 return (gpointer)icall_functions [(nameslot - icall_names)];
8014 compare_class_imap (const void *key, const void *elem)
8016 const char** class_name = (const char**)elem;
8017 return strcmp (key, *class_name);
8020 static const IcallTypeDesc*
8021 find_class_icalls (const char *name)
8023 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8026 return &icall_type_descs [nameslot - icall_type_names];
8029 #endif /* HAVE_ARRAY_ELEM_INIT */
8031 #endif /* DISABLE_ICALL_TABLES */
8034 * we should probably export this as an helper (handle nested types).
8035 * Returns the number of chars written in buf.
8038 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8040 int nspacelen, cnamelen;
8041 nspacelen = strlen (klass->name_space);
8042 cnamelen = strlen (klass->name);
8043 if (nspacelen + cnamelen + 2 > bufsize)
8046 memcpy (buf, klass->name_space, nspacelen);
8047 buf [nspacelen ++] = '.';
8049 memcpy (buf + nspacelen, klass->name, cnamelen);
8050 buf [nspacelen + cnamelen] = 0;
8051 return nspacelen + cnamelen;
8054 #ifdef DISABLE_ICALL_TABLES
8056 no_icall_table (void)
8058 g_assert_not_reached ();
8063 mono_lookup_internal_call (MonoMethod *method)
8068 int typelen = 0, mlen, siglen;
8070 #ifndef DISABLE_ICALL_TABLES
8071 const IcallTypeDesc *imap = NULL;
8074 g_assert (method != NULL);
8076 if (method->is_inflated)
8077 method = ((MonoMethodInflated *) method)->declaring;
8079 if (method->klass->nested_in) {
8080 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8084 mname [pos++] = '/';
8087 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8093 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8098 #ifndef DISABLE_ICALL_TABLES
8099 imap = find_class_icalls (mname);
8102 mname [typelen] = ':';
8103 mname [typelen + 1] = ':';
8105 mlen = strlen (method->name);
8106 memcpy (mname + typelen + 2, method->name, mlen);
8107 sigstart = mname + typelen + 2 + mlen;
8110 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8111 siglen = strlen (tmpsig);
8112 if (typelen + mlen + siglen + 6 > sizeof (mname))
8115 memcpy (sigstart + 1, tmpsig, siglen);
8116 sigstart [siglen + 1] = ')';
8117 sigstart [siglen + 2] = 0;
8122 res = g_hash_table_lookup (icall_hash, mname);
8124 mono_icall_unlock ();;
8127 /* try without signature */
8129 res = g_hash_table_lookup (icall_hash, mname);
8131 mono_icall_unlock ();
8135 #ifdef DISABLE_ICALL_TABLES
8136 mono_icall_unlock ();
8137 /* Fail only when the result is actually used */
8138 /* mono_marshal_get_native_wrapper () depends on this */
8139 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8140 return ves_icall_System_String_ctor_RedirectToCreateString;
8142 return no_icall_table;
8144 /* it wasn't found in the static call tables */
8146 mono_icall_unlock ();
8149 res = find_method_icall (imap, sigstart - mlen);
8151 mono_icall_unlock ();
8154 /* try _with_ signature */
8156 res = find_method_icall (imap, sigstart - mlen);
8158 mono_icall_unlock ();
8162 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8163 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8164 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8165 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8166 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");
8167 g_print ("If you see other errors or faults after this message they are probably related\n");
8168 g_print ("and you need to fix your mono install first.\n");
8170 mono_icall_unlock ();
8176 #ifdef ENABLE_ICALL_SYMBOL_MAP
8178 func_cmp (gconstpointer key, gconstpointer p)
8180 return (gsize)key - (gsize)*(gsize*)p;
8185 * mono_lookup_icall_symbol:
8187 * Given the icall METHOD, returns its C symbol.
8190 mono_lookup_icall_symbol (MonoMethod *m)
8192 #ifdef DISABLE_ICALL_TABLES
8193 g_assert_not_reached ();
8196 #ifdef ENABLE_ICALL_SYMBOL_MAP
8200 static gconstpointer *functions_sorted;
8201 static const char**symbols_sorted;
8202 static gboolean inited;
8207 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8208 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8209 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8210 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8211 /* Bubble sort the two arrays */
8215 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8216 if (functions_sorted [i] > functions_sorted [i + 1]) {
8219 tmp = functions_sorted [i];
8220 functions_sorted [i] = functions_sorted [i + 1];
8221 functions_sorted [i + 1] = tmp;
8222 tmp = symbols_sorted [i];
8223 symbols_sorted [i] = symbols_sorted [i + 1];
8224 symbols_sorted [i + 1] = tmp;
8231 func = mono_lookup_internal_call (m);
8234 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8238 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8240 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8241 g_assert_not_reached ();
8248 type_from_typename (char *typename)
8250 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8252 if (!strcmp (typename, "int"))
8253 klass = mono_defaults.int_class;
8254 else if (!strcmp (typename, "ptr"))
8255 klass = mono_defaults.int_class;
8256 else if (!strcmp (typename, "void"))
8257 klass = mono_defaults.void_class;
8258 else if (!strcmp (typename, "int32"))
8259 klass = mono_defaults.int32_class;
8260 else if (!strcmp (typename, "uint32"))
8261 klass = mono_defaults.uint32_class;
8262 else if (!strcmp (typename, "int8"))
8263 klass = mono_defaults.sbyte_class;
8264 else if (!strcmp (typename, "uint8"))
8265 klass = mono_defaults.byte_class;
8266 else if (!strcmp (typename, "int16"))
8267 klass = mono_defaults.int16_class;
8268 else if (!strcmp (typename, "uint16"))
8269 klass = mono_defaults.uint16_class;
8270 else if (!strcmp (typename, "long"))
8271 klass = mono_defaults.int64_class;
8272 else if (!strcmp (typename, "ulong"))
8273 klass = mono_defaults.uint64_class;
8274 else if (!strcmp (typename, "float"))
8275 klass = mono_defaults.single_class;
8276 else if (!strcmp (typename, "double"))
8277 klass = mono_defaults.double_class;
8278 else if (!strcmp (typename, "object"))
8279 klass = mono_defaults.object_class;
8280 else if (!strcmp (typename, "obj"))
8281 klass = mono_defaults.object_class;
8282 else if (!strcmp (typename, "string"))
8283 klass = mono_defaults.string_class;
8284 else if (!strcmp (typename, "bool"))
8285 klass = mono_defaults.boolean_class;
8286 else if (!strcmp (typename, "boolean"))
8287 klass = mono_defaults.boolean_class;
8289 g_error ("%s", typename);
8290 g_assert_not_reached ();
8292 return &klass->byval_arg;
8296 * LOCKING: Take the corlib image lock.
8298 MonoMethodSignature*
8299 mono_create_icall_signature (const char *sigstr)
8304 MonoMethodSignature *res, *res2;
8305 MonoImage *corlib = mono_defaults.corlib;
8307 mono_image_lock (corlib);
8308 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8309 mono_image_unlock (corlib);
8314 parts = g_strsplit (sigstr, " ", 256);
8323 res = mono_metadata_signature_alloc (corlib, len - 1);
8328 * Under windows, the default pinvoke calling convention is STDCALL but
8331 res->call_convention = MONO_CALL_C;
8334 res->ret = type_from_typename (parts [0]);
8335 for (i = 1; i < len; ++i) {
8336 res->params [i - 1] = type_from_typename (parts [i]);
8341 mono_image_lock (corlib);
8342 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8344 res = res2; /*Value is allocated in the image pool*/
8346 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8347 mono_image_unlock (corlib);
8353 mono_find_jit_icall_by_name (const char *name)
8355 MonoJitICallInfo *info;
8356 g_assert (jit_icall_hash_name);
8359 info = g_hash_table_lookup (jit_icall_hash_name, name);
8360 mono_icall_unlock ();
8365 mono_find_jit_icall_by_addr (gconstpointer addr)
8367 MonoJitICallInfo *info;
8368 g_assert (jit_icall_hash_addr);
8371 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8372 mono_icall_unlock ();
8378 * mono_get_jit_icall_info:
8380 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8381 * caller should access it while holding the icall lock.
8384 mono_get_jit_icall_info (void)
8386 return jit_icall_hash_name;
8390 * mono_lookup_jit_icall_symbol:
8392 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8395 mono_lookup_jit_icall_symbol (const char *name)
8397 MonoJitICallInfo *info;
8398 const char *res = NULL;
8401 info = g_hash_table_lookup (jit_icall_hash_name, name);
8403 res = info->c_symbol;
8404 mono_icall_unlock ();
8409 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8412 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8413 mono_icall_unlock ();
8417 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8419 MonoJitICallInfo *info;
8426 if (!jit_icall_hash_name) {
8427 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8428 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8431 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8432 g_warning ("jit icall already defined \"%s\"\n", name);
8433 g_assert_not_reached ();
8436 info = g_new0 (MonoJitICallInfo, 1);
8441 info->c_symbol = c_symbol;
8444 info->wrapper = func;
8446 info->wrapper = NULL;
8449 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8450 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8452 mono_icall_unlock ();
8457 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8459 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);