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 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/io-layer/io-layer.h>
77 #include <mono/utils/strtod.h>
78 #include <mono/utils/monobitset.h>
79 #include <mono/utils/mono-time.h>
80 #include <mono/utils/mono-proclib.h>
81 #include <mono/utils/mono-string.h>
82 #include <mono/utils/mono-error-internals.h>
83 #include <mono/utils/mono-mmap.h>
84 #include <mono/utils/mono-io-portability.h>
86 #if defined (HOST_WIN32)
92 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
94 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
97 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
99 static inline MonoBoolean
100 is_generic_parameter (MonoType *type)
102 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
106 mono_class_init_or_throw (MonoClass *klass)
108 if (!mono_class_init (klass))
109 mono_raise_exception (mono_class_get_exception_for_failure (klass));
113 * We expect a pointer to a char, not a string
116 mono_double_ParseImpl (char *ptr, double *result)
118 gchar *endptr = NULL;
125 *result = strtod (ptr, &endptr);
128 /* mono_strtod () is not thread-safe */
129 EnterCriticalSection (&mono_strtod_mutex);
130 *result = mono_strtod (ptr, &endptr);
131 LeaveCriticalSection (&mono_strtod_mutex);
135 if (!*ptr || (endptr && *endptr))
142 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
151 ao = (MonoArray *)this;
152 ac = (MonoClass *)ao->obj.vtable->klass;
154 esize = mono_array_element_size (ac);
155 ea = (gpointer*)((char*)ao->vector + (pos * esize));
157 if (ac->element_class->valuetype)
158 return mono_value_box (this->vtable->domain, ac->element_class, ea);
164 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
172 MONO_CHECK_ARG_NULL (idxs);
174 io = (MonoArray *)idxs;
175 ic = (MonoClass *)io->obj.vtable->klass;
177 ao = (MonoArray *)this;
178 ac = (MonoClass *)ao->obj.vtable->klass;
180 g_assert (ic->rank == 1);
181 if (io->bounds != NULL || io->max_length != ac->rank)
182 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
184 ind = (gint32 *)io->vector;
186 if (ao->bounds == NULL) {
187 if (*ind < 0 || *ind >= ao->max_length)
188 mono_raise_exception (mono_get_exception_index_out_of_range ());
190 return ves_icall_System_Array_GetValueImpl (this, *ind);
193 for (i = 0; i < ac->rank; i++)
194 if ((ind [i] < ao->bounds [i].lower_bound) ||
195 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
196 mono_raise_exception (mono_get_exception_index_out_of_range ());
198 pos = ind [0] - ao->bounds [0].lower_bound;
199 for (i = 1; i < ac->rank; i++)
200 pos = pos*ao->bounds [i].length + ind [i] -
201 ao->bounds [i].lower_bound;
203 return ves_icall_System_Array_GetValueImpl (this, pos);
207 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
209 MonoClass *ac, *vc, *ec;
221 vc = value->vtable->klass;
225 ac = this->obj.vtable->klass;
226 ec = ac->element_class;
228 esize = mono_array_element_size (ac);
229 ea = (gpointer*)((char*)this->vector + (pos * esize));
230 va = (gpointer*)((char*)value + sizeof (MonoObject));
232 if (mono_class_is_nullable (ec)) {
233 mono_nullable_init ((guint8*)ea, value, ec);
238 mono_gc_bzero (ea, esize);
242 #define NO_WIDENING_CONVERSION G_STMT_START{\
243 mono_raise_exception (mono_get_exception_argument ( \
244 "value", "not a widening conversion")); \
247 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
248 if (esize < vsize + (extra)) \
249 mono_raise_exception (mono_get_exception_argument ( \
250 "value", "not a widening conversion")); \
253 #define INVALID_CAST G_STMT_START{ \
254 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
255 mono_raise_exception (mono_get_exception_invalid_cast ()); \
258 /* Check element (destination) type. */
259 switch (ec->byval_arg.type) {
260 case MONO_TYPE_STRING:
261 switch (vc->byval_arg.type) {
262 case MONO_TYPE_STRING:
268 case MONO_TYPE_BOOLEAN:
269 switch (vc->byval_arg.type) {
270 case MONO_TYPE_BOOLEAN:
283 NO_WIDENING_CONVERSION;
290 if (!ec->valuetype) {
291 if (!mono_object_isinst (value, ec))
293 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
297 if (mono_object_isinst (value, ec)) {
298 if (ec->has_references)
299 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
301 mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
308 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
310 et = ec->byval_arg.type;
311 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
312 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
314 vt = vc->byval_arg.type;
315 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
316 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
318 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
324 case MONO_TYPE_CHAR: \
325 CHECK_WIDENING_CONVERSION(0); \
326 *(etype *) ea = (etype) u64; \
328 /* You can't assign a signed value to an unsigned array. */ \
333 /* You can't assign a floating point number to an integer array. */ \
336 NO_WIDENING_CONVERSION; \
340 #define ASSIGN_SIGNED(etype) G_STMT_START{\
346 CHECK_WIDENING_CONVERSION(0); \
347 *(etype *) ea = (etype) i64; \
349 /* You can assign an unsigned value to a signed array if the array's */ \
350 /* element size is larger than the value size. */ \
355 case MONO_TYPE_CHAR: \
356 CHECK_WIDENING_CONVERSION(1); \
357 *(etype *) ea = (etype) u64; \
359 /* You can't assign a floating point number to an integer array. */ \
362 NO_WIDENING_CONVERSION; \
366 #define ASSIGN_REAL(etype) G_STMT_START{\
370 CHECK_WIDENING_CONVERSION(0); \
371 *(etype *) ea = (etype) r64; \
373 /* All integer values fit into a floating point array, so we don't */ \
374 /* need to CHECK_WIDENING_CONVERSION here. */ \
379 *(etype *) ea = (etype) i64; \
385 case MONO_TYPE_CHAR: \
386 *(etype *) ea = (etype) u64; \
393 u64 = *(guint8 *) va;
396 u64 = *(guint16 *) va;
399 u64 = *(guint32 *) va;
402 u64 = *(guint64 *) va;
408 i64 = *(gint16 *) va;
411 i64 = *(gint32 *) va;
414 i64 = *(gint64 *) va;
417 r64 = *(gfloat *) va;
420 r64 = *(gdouble *) va;
423 u64 = *(guint16 *) va;
425 case MONO_TYPE_BOOLEAN:
426 /* Boolean is only compatible with itself. */
439 NO_WIDENING_CONVERSION;
446 /* If we can't do a direct copy, let's try a widening conversion. */
449 ASSIGN_UNSIGNED (guint16);
451 ASSIGN_UNSIGNED (guint8);
453 ASSIGN_UNSIGNED (guint16);
455 ASSIGN_UNSIGNED (guint32);
457 ASSIGN_UNSIGNED (guint64);
459 ASSIGN_SIGNED (gint8);
461 ASSIGN_SIGNED (gint16);
463 ASSIGN_SIGNED (gint32);
465 ASSIGN_SIGNED (gint64);
467 ASSIGN_REAL (gfloat);
469 ASSIGN_REAL (gdouble);
473 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
477 #undef NO_WIDENING_CONVERSION
478 #undef CHECK_WIDENING_CONVERSION
479 #undef ASSIGN_UNSIGNED
485 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
493 MONO_CHECK_ARG_NULL (idxs);
495 ic = idxs->obj.vtable->klass;
496 ac = this->obj.vtable->klass;
498 g_assert (ic->rank == 1);
499 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
500 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
502 ind = (gint32 *)idxs->vector;
504 if (this->bounds == NULL) {
505 if (*ind < 0 || *ind >= this->max_length)
506 mono_raise_exception (mono_get_exception_index_out_of_range ());
508 ves_icall_System_Array_SetValueImpl (this, value, *ind);
512 for (i = 0; i < ac->rank; i++)
513 if ((ind [i] < this->bounds [i].lower_bound) ||
514 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
515 mono_raise_exception (mono_get_exception_index_out_of_range ());
517 pos = ind [0] - this->bounds [0].lower_bound;
518 for (i = 1; i < ac->rank; i++)
519 pos = pos * this->bounds [i].length + ind [i] -
520 this->bounds [i].lower_bound;
522 ves_icall_System_Array_SetValueImpl (this, value, pos);
526 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
528 MonoClass *aklass, *klass;
531 gboolean bounded = FALSE;
535 MONO_CHECK_ARG_NULL (type);
536 MONO_CHECK_ARG_NULL (lengths);
538 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
540 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
542 for (i = 0; i < mono_array_length (lengths); i++)
543 if (mono_array_get (lengths, gint32, i) < 0)
544 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
546 klass = mono_class_from_mono_type (type->type);
547 mono_class_init_or_throw (klass);
549 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
550 /* vectors are not the same as one dimensional arrays with no-zero bounds */
555 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
557 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
558 for (i = 0; i < aklass->rank; ++i) {
559 sizes [i] = mono_array_get (lengths, guint32, i);
561 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
563 sizes [i + aklass->rank] = 0;
566 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
572 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
574 MonoClass *aklass, *klass;
577 gboolean bounded = FALSE;
581 MONO_CHECK_ARG_NULL (type);
582 MONO_CHECK_ARG_NULL (lengths);
584 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
586 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
588 for (i = 0; i < mono_array_length (lengths); i++)
589 if ((mono_array_get (lengths, gint64, i) < 0) ||
590 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
591 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
593 klass = mono_class_from_mono_type (type->type);
594 mono_class_init_or_throw (klass);
596 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
597 /* vectors are not the same as one dimensional arrays with no-zero bounds */
602 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
604 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
605 for (i = 0; i < aklass->rank; ++i) {
606 sizes [i] = mono_array_get (lengths, guint64, i);
608 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
610 sizes [i + aklass->rank] = 0;
613 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
619 ves_icall_System_Array_GetRank (MonoObject *this)
623 return this->vtable->klass->rank;
627 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
629 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
634 if ((dimension < 0) || (dimension >= rank))
635 mono_raise_exception (mono_get_exception_index_out_of_range ());
637 if (this->bounds == NULL)
638 length = this->max_length;
640 length = this->bounds [dimension].length;
642 #ifdef MONO_BIG_ARRAYS
643 if (length > G_MAXINT32)
644 mono_raise_exception (mono_get_exception_overflow ());
650 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
652 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
656 if ((dimension < 0) || (dimension >= rank))
657 mono_raise_exception (mono_get_exception_index_out_of_range ());
659 if (this->bounds == NULL)
660 return this->max_length;
662 return this->bounds [dimension].length;
666 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
668 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
672 if ((dimension < 0) || (dimension >= rank))
673 mono_raise_exception (mono_get_exception_index_out_of_range ());
675 if (this->bounds == NULL)
678 return this->bounds [dimension].lower_bound;
682 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
684 int sz = mono_array_element_size (mono_object_class (arr));
685 mono_gc_bzero (mono_array_addr_with_size (arr, sz, idx), length * sz);
689 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
694 MonoClass *src_class;
695 MonoClass *dest_class;
699 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
702 if (source->bounds || dest->bounds)
705 /* there's no integer overflow since mono_array_length returns an unsigned integer */
706 if ((dest_idx + length > mono_array_length (dest)) ||
707 (source_idx + length > mono_array_length (source)))
710 src_class = source->obj.vtable->klass->element_class;
711 dest_class = dest->obj.vtable->klass->element_class;
714 * Handle common cases.
717 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
718 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
719 // FIXME: This is racy
723 int has_refs = dest_class->has_references;
724 for (i = source_idx; i < source_idx + length; ++i) {
725 MonoObject *elem = mono_array_get (source, MonoObject*, i);
726 if (elem && !mono_object_isinst (elem, dest_class))
730 element_size = mono_array_element_size (dest->obj.vtable->klass);
731 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
732 for (i = 0; i < length; ++i) {
733 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
734 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
738 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
740 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
746 /* Check if we're copying a char[] <==> (u)short[] */
747 if (src_class != dest_class) {
748 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
751 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
753 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
754 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
755 // FIXME: This is racy
759 for (i = source_idx; i < source_idx + length; ++i) {
760 MonoObject *elem = mono_array_get (source, MonoObject*, i);
761 if (elem && !mono_object_isinst (elem, dest_class))
769 if (dest_class->valuetype) {
770 element_size = mono_array_element_size (source->obj.vtable->klass);
771 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
772 if (dest_class->has_references) {
773 mono_value_copy_array (dest, dest_idx, source_addr, length);
775 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
776 mono_gc_memmove (dest_addr, source_addr, element_size * length);
779 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
786 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
795 ao = (MonoArray *)this;
796 ac = (MonoClass *)ao->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)ao->vector + (pos * esize));
801 mono_gc_memmove (value, ea, esize);
805 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
814 ao = (MonoArray *)this;
815 ac = (MonoClass *)ao->obj.vtable->klass;
816 ec = ac->element_class;
818 esize = mono_array_element_size (ac);
819 ea = (gpointer*)((char*)ao->vector + (pos * esize));
821 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
822 g_assert (esize == sizeof (gpointer));
823 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
825 g_assert (ec->inited);
826 g_assert (esize == mono_class_value_size (ec, NULL));
827 if (ec->has_references)
828 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
830 mono_gc_memmove (ea, value, esize);
835 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
837 MonoClass *klass = array->obj.vtable->klass;
838 guint32 size = mono_array_element_size (klass);
839 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
841 const char *field_data;
843 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
844 MonoException *exc = mono_get_exception_argument("array",
845 "Cannot initialize array of non-primitive type.");
846 mono_raise_exception (exc);
849 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
850 MonoException *exc = mono_get_exception_argument("field_handle",
851 "Field doesn't have an RVA");
852 mono_raise_exception (exc);
855 size *= array->max_length;
856 field_data = mono_field_get_data (field_handle);
858 if (size > mono_type_size (field_handle->type, &align)) {
859 MonoException *exc = mono_get_exception_argument("field_handle",
860 "Field not large enough to fill array");
861 mono_raise_exception (exc);
864 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
866 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
867 guint ## n *src = (guint ## n *) field_data; \
868 guint ## n *end = (guint ## n *)((char*)src + size); \
870 for (; src < end; data++, src++) { \
871 *data = read ## n (src); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
900 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
903 double *data = (double*)mono_array_addr (array, double, 0);
905 for (i = 0; i < size; i++, data++) {
915 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
919 return offsetof (MonoString, chars);
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
927 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
930 return mono_object_clone (obj);
934 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
939 MONO_CHECK_ARG_NULL (handle);
941 klass = mono_class_from_mono_type (handle);
942 MONO_CHECK_ARG (handle, klass);
944 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
946 /* This will call the type constructor */
947 mono_runtime_class_init (vtable);
951 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
955 mono_image_check_for_module_cctor (image);
956 if (image->has_module_cctor) {
957 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
958 /*It's fine to raise the exception here*/
959 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
964 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
969 /* later make this configurable and per-arch */
970 int min_size = 4096 * 4 * sizeof (void*);
971 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
972 /* if we have no info we are optimistic and assume there is enough room */
975 current = (guint8 *)&stack_addr;
976 if (current > stack_addr) {
977 if ((current - stack_addr) < min_size)
980 if (current - (stack_addr - stack_size) < min_size)
987 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
991 return mono_object_clone (this);
995 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
998 MonoObject **values = NULL;
1002 MonoClassField* field;
1005 MONO_ARCH_SAVE_REGS;
1007 klass = mono_object_class (this);
1009 if (mono_class_num_fields (klass) == 0)
1010 return mono_object_hash (this);
1013 * Compute the starting value of the hashcode for fields of primitive
1014 * types, and return the remaining fields in an array to the managed side.
1015 * This way, we can avoid costly reflection operations in managed code.
1018 while ((field = mono_class_get_fields (klass, &iter))) {
1019 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1021 if (mono_field_is_deleted (field))
1023 /* FIXME: Add more types */
1024 switch (field->type->type) {
1026 result ^= *(gint32*)((guint8*)this + field->offset);
1028 case MONO_TYPE_STRING: {
1030 s = *(MonoString**)((guint8*)this + field->offset);
1032 result ^= mono_string_hash (s);
1037 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1038 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1039 values [count++] = o;
1045 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1046 for (i = 0; i < count; ++i)
1047 mono_array_setref (*fields, i, values [i]);
1055 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1058 MonoObject **values = NULL;
1060 MonoClassField* field;
1064 MONO_ARCH_SAVE_REGS;
1066 MONO_CHECK_ARG_NULL (that);
1068 if (this->vtable != that->vtable)
1071 klass = mono_object_class (this);
1073 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1074 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1077 * Do the comparison for fields of primitive type and return a result if
1078 * possible. Otherwise, return the remaining fields in an array to the
1079 * managed side. This way, we can avoid costly reflection operations in
1084 while ((field = mono_class_get_fields (klass, &iter))) {
1085 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1087 if (mono_field_is_deleted (field))
1089 /* FIXME: Add more types */
1090 switch (field->type->type) {
1093 case MONO_TYPE_BOOLEAN:
1094 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1099 case MONO_TYPE_CHAR:
1100 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1105 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1110 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1114 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1118 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1123 case MONO_TYPE_STRING: {
1124 MonoString *s1, *s2;
1125 guint32 s1len, s2len;
1126 s1 = *(MonoString**)((guint8*)this + field->offset);
1127 s2 = *(MonoString**)((guint8*)that + field->offset);
1130 if ((s1 == NULL) || (s2 == NULL))
1132 s1len = mono_string_length (s1);
1133 s2len = mono_string_length (s2);
1137 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1143 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1144 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1145 values [count++] = o;
1146 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1147 values [count++] = o;
1150 if (klass->enumtype)
1151 /* enums only have one non-static field */
1157 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1158 for (i = 0; i < count; ++i)
1159 mono_array_setref (*fields, i, values [i]);
1166 static MonoReflectionType *
1167 ves_icall_System_Object_GetType (MonoObject *obj)
1169 MONO_ARCH_SAVE_REGS;
1171 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1172 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1174 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1178 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1180 MONO_ARCH_SAVE_REGS;
1182 mtype->type = &obj->vtable->klass->byval_arg;
1183 g_assert (mtype->type->type);
1187 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1189 MONO_ARCH_SAVE_REGS;
1191 MONO_CHECK_ARG_NULL (obj);
1193 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1197 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1198 MonoReflectionMethod *method,
1199 MonoArray *opt_param_types)
1201 MONO_ARCH_SAVE_REGS;
1203 MONO_CHECK_ARG_NULL (method);
1205 return mono_image_create_method_token (
1206 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1210 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1212 MONO_ARCH_SAVE_REGS;
1214 mono_image_create_pefile (mb, file);
1218 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1220 MONO_ARCH_SAVE_REGS;
1222 mono_image_build_metadata (mb);
1226 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1228 MONO_ARCH_SAVE_REGS;
1230 mono_image_register_token (mb->dynamic_image, token, obj);
1234 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1236 MonoMethod **dest = data;
1238 /* skip unmanaged frames */
1254 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1256 MonoMethod **dest = data;
1258 /* skip unmanaged frames */
1263 if (!strcmp (m->klass->name_space, "System.Reflection"))
1272 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1274 MonoMethod **dest = data;
1276 /* skip unmanaged frames */
1280 if (m->wrapper_type != MONO_WRAPPER_NONE)
1283 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1297 static MonoReflectionType *
1298 type_from_name (const char *str, MonoBoolean ignoreCase)
1300 MonoType *type = NULL;
1301 MonoAssembly *assembly = NULL;
1302 MonoTypeNameParse info;
1303 char *temp_str = g_strdup (str);
1304 gboolean type_resolve = FALSE;
1306 MONO_ARCH_SAVE_REGS;
1308 /* mono_reflection_parse_type() mangles the string */
1309 if (!mono_reflection_parse_type (temp_str, &info)) {
1310 mono_reflection_free_type_info (&info);
1315 if (info.assembly.name) {
1316 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1318 MonoMethod *m = mono_method_get_last_managed ();
1319 MonoMethod *dest = m;
1321 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1326 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1327 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1328 * to crash. This only seems to happen in some strange remoting
1329 * scenarios and I was unable to figure out what's happening there.
1330 * Dec 10, 2005 - Martin.
1334 assembly = dest->klass->image->assembly;
1335 type_resolve = TRUE;
1337 g_warning (G_STRLOC);
1342 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1343 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1346 if (!info.assembly.name && !type) /* try mscorlib */
1347 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1349 if (assembly && !type && type_resolve) {
1350 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1351 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1354 mono_reflection_free_type_info (&info);
1360 return mono_type_get_object (mono_domain_get (), type);
1364 MonoReflectionType *
1365 mono_type_get (const char *str)
1367 char *copy = g_strdup (str);
1368 MonoReflectionType *type = type_from_name (copy, FALSE);
1375 static MonoReflectionType*
1376 ves_icall_type_from_name (MonoString *name,
1377 MonoBoolean throwOnError,
1378 MonoBoolean ignoreCase)
1380 char *str = mono_string_to_utf8 (name);
1381 MonoReflectionType *type;
1383 type = type_from_name (str, ignoreCase);
1386 MonoException *e = NULL;
1389 e = mono_get_exception_type_load (name, NULL);
1391 mono_loader_clear_error ();
1393 mono_raise_exception (e);
1400 static MonoReflectionType*
1401 ves_icall_type_from_handle (MonoType *handle)
1403 MonoDomain *domain = mono_domain_get ();
1405 MONO_ARCH_SAVE_REGS;
1407 return mono_type_get_object (domain, handle);
1411 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1413 MONO_ARCH_SAVE_REGS;
1415 if (c && type->type && c->type)
1416 return mono_metadata_type_equal (type->type, c->type);
1418 return (type == c) ? TRUE : FALSE;
1421 /* System.TypeCode */
1440 TYPECODE_STRING = 18
1444 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1446 int t = type->type->type;
1448 MONO_ARCH_SAVE_REGS;
1450 if (type->type->byref)
1451 return TYPECODE_OBJECT;
1455 case MONO_TYPE_VOID:
1456 return TYPECODE_OBJECT;
1457 case MONO_TYPE_BOOLEAN:
1458 return TYPECODE_BOOLEAN;
1460 return TYPECODE_BYTE;
1462 return TYPECODE_SBYTE;
1464 return TYPECODE_UINT16;
1466 return TYPECODE_INT16;
1467 case MONO_TYPE_CHAR:
1468 return TYPECODE_CHAR;
1472 return TYPECODE_OBJECT;
1474 return TYPECODE_UINT32;
1476 return TYPECODE_INT32;
1478 return TYPECODE_UINT64;
1480 return TYPECODE_INT64;
1482 return TYPECODE_SINGLE;
1484 return TYPECODE_DOUBLE;
1485 case MONO_TYPE_VALUETYPE: {
1486 MonoClass *klass = type->type->data.klass;
1488 if (klass->enumtype) {
1489 t = mono_class_enum_basetype (klass)->type;
1491 } else if (mono_is_corlib_image (klass->image)) {
1492 if (strcmp (klass->name_space, "System") == 0) {
1493 if (strcmp (klass->name, "Decimal") == 0)
1494 return TYPECODE_DECIMAL;
1495 else if (strcmp (klass->name, "DateTime") == 0)
1496 return TYPECODE_DATETIME;
1499 return TYPECODE_OBJECT;
1501 case MONO_TYPE_STRING:
1502 return TYPECODE_STRING;
1503 case MONO_TYPE_SZARRAY:
1504 case MONO_TYPE_ARRAY:
1505 case MONO_TYPE_OBJECT:
1507 case MONO_TYPE_MVAR:
1508 case MONO_TYPE_TYPEDBYREF:
1509 return TYPECODE_OBJECT;
1510 case MONO_TYPE_CLASS:
1512 MonoClass *klass = type->type->data.klass;
1513 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1514 if (strcmp (klass->name, "DBNull") == 0)
1515 return TYPECODE_DBNULL;
1518 return TYPECODE_OBJECT;
1519 case MONO_TYPE_GENERICINST:
1520 return TYPECODE_OBJECT;
1522 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1528 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1534 MONO_ARCH_SAVE_REGS;
1536 g_assert (type != NULL);
1538 domain = ((MonoObject *)type)->vtable->domain;
1540 if (!c) /* FIXME: dont know what do do here */
1543 klass = mono_class_from_mono_type (type->type);
1544 klassc = mono_class_from_mono_type (c->type);
1546 /* Interface check requires a more complex setup so we
1547 * only do for them. Otherwise we simply avoid mono_class_init.
1549 if (check_interfaces) {
1550 mono_class_init_or_throw (klass);
1551 mono_class_init_or_throw (klassc);
1552 } else if (!klass->supertypes || !klassc->supertypes) {
1553 mono_loader_lock ();
1554 mono_class_setup_supertypes (klass);
1555 mono_class_setup_supertypes (klassc);
1556 mono_loader_unlock ();
1559 if (type->type->byref)
1560 return klassc == mono_defaults.object_class;
1562 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1566 mono_type_is_primitive (MonoType *type)
1568 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1569 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1573 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1575 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1576 return mono_class_enum_basetype (type->data.klass);
1577 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1578 return mono_class_enum_basetype (type->data.generic_class->container_class);
1583 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1589 MONO_ARCH_SAVE_REGS;
1591 g_assert (type != NULL);
1593 domain = ((MonoObject *)type)->vtable->domain;
1595 klass = mono_class_from_mono_type (type->type);
1596 klassc = mono_class_from_mono_type (c->type);
1598 mono_class_init_or_throw (klass);
1599 mono_class_init_or_throw (klassc);
1601 if (type->type->byref ^ c->type->byref)
1604 if (type->type->byref) {
1605 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1606 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1608 klass = mono_class_from_mono_type (t);
1609 klassc = mono_class_from_mono_type (ot);
1611 if (mono_type_is_primitive (t)) {
1612 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1613 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1614 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1615 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1616 return t->type == ot->type;
1618 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1621 if (klass->valuetype)
1622 return klass == klassc;
1623 return klass->valuetype == klassc->valuetype;
1626 return mono_class_is_assignable_from (klass, klassc);
1630 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1632 MonoClass *klass = mono_class_from_mono_type (type->type);
1633 mono_class_init_or_throw (klass);
1634 return mono_object_isinst (obj, klass) != NULL;
1638 ves_icall_get_attributes (MonoReflectionType *type)
1640 MonoClass *klass = mono_class_from_mono_type (type->type);
1641 return klass->flags;
1644 static MonoReflectionMarshal*
1645 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1647 MonoClass *klass = field->field->parent;
1648 MonoMarshalType *info;
1651 if (klass->generic_container ||
1652 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1655 info = mono_marshal_load_type_info (klass);
1657 for (i = 0; i < info->num_fields; ++i) {
1658 if (info->fields [i].field == field->field) {
1659 if (!info->fields [i].mspec)
1662 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1669 static MonoReflectionField*
1670 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1672 gboolean found = FALSE;
1679 klass = handle->parent;
1681 klass = mono_class_from_mono_type (type);
1683 /* Check that the field belongs to the class */
1684 for (k = klass; k; k = k->parent) {
1685 if (k == handle->parent) {
1692 /* The managed code will throw the exception */
1696 return mono_field_get_object (mono_domain_get (), klass, handle);
1700 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1703 MonoType *type = mono_field_get_type_checked (field->field, &error);
1704 if (!mono_error_ok (&error))
1705 mono_error_raise_exception (&error);
1707 return type_array_from_modifiers (field->field->parent->image, type, optional);
1711 vell_icall_get_method_attributes (MonoMethod *method)
1713 return method->flags;
1717 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1720 MonoDomain *domain = mono_domain_get ();
1721 MonoMethodSignature* sig;
1722 MONO_ARCH_SAVE_REGS;
1724 sig = mono_method_signature_checked (method, &error);
1725 if (!mono_error_ok (&error))
1726 mono_error_raise_exception (&error);
1729 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1730 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1731 info->attrs = method->flags;
1732 info->implattrs = method->iflags;
1733 if (sig->call_convention == MONO_CALL_DEFAULT)
1734 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1736 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1741 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1745 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1747 MonoDomain *domain = mono_domain_get ();
1749 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1752 static MonoReflectionMarshal*
1753 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1755 MonoDomain *domain = mono_domain_get ();
1756 MonoReflectionMarshal* res = NULL;
1757 MonoMarshalSpec **mspecs;
1760 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1761 mono_method_get_marshal_info (method, mspecs);
1764 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1766 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1768 mono_metadata_free_marshal_spec (mspecs [i]);
1775 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1777 MonoClass *parent = field->field->parent;
1778 if (!parent->size_inited)
1779 mono_class_init (parent);
1781 return field->field->offset - sizeof (MonoObject);
1784 static MonoReflectionType*
1785 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1788 MONO_ARCH_SAVE_REGS;
1790 parent = declaring? field->field->parent: field->klass;
1792 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1796 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1798 MonoClass *fklass = field->klass;
1799 MonoClassField *cf = field->field;
1800 MonoDomain *domain = mono_object_domain (field);
1802 if (fklass->image->assembly->ref_only)
1803 mono_raise_exception (mono_get_exception_invalid_operation (
1804 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1806 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1807 mono_security_core_clr_ensure_reflection_access_field (cf);
1809 return mono_field_get_value_object (domain, cf, obj);
1813 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1816 MonoClassField *cf = field->field;
1820 MONO_ARCH_SAVE_REGS;
1822 if (field->klass->image->assembly->ref_only)
1823 mono_raise_exception (mono_get_exception_invalid_operation (
1824 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1826 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1827 mono_security_core_clr_ensure_reflection_access_field (cf);
1829 type = mono_field_get_type_checked (cf, &error);
1830 if (!mono_error_ok (&error))
1831 mono_error_raise_exception (&error);
1833 v = (gchar *) value;
1835 switch (type->type) {
1838 case MONO_TYPE_BOOLEAN:
1841 case MONO_TYPE_CHAR:
1850 case MONO_TYPE_VALUETYPE:
1853 v += sizeof (MonoObject);
1855 case MONO_TYPE_STRING:
1856 case MONO_TYPE_OBJECT:
1857 case MONO_TYPE_CLASS:
1858 case MONO_TYPE_ARRAY:
1859 case MONO_TYPE_SZARRAY:
1862 case MONO_TYPE_GENERICINST: {
1863 MonoGenericClass *gclass = type->data.generic_class;
1864 g_assert (!gclass->context.class_inst->is_open);
1866 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1867 MonoClass *nklass = mono_class_from_mono_type (type);
1868 MonoObject *nullable;
1871 * Convert the boxed vtype into a Nullable structure.
1872 * This is complicated by the fact that Nullables have
1873 * a variable structure.
1875 nullable = mono_object_new (mono_domain_get (), nklass);
1877 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1879 v = mono_object_unbox (nullable);
1882 if (gclass->container_class->valuetype && (v != NULL))
1883 v += sizeof (MonoObject);
1887 g_error ("type 0x%x not handled in "
1888 "ves_icall_FieldInfo_SetValueInternal", type->type);
1893 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1894 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1895 if (!vtable->initialized)
1896 mono_runtime_class_init (vtable);
1897 mono_field_static_set_value (vtable, cf, v);
1899 mono_field_set_value (obj, cf, v);
1904 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1906 MonoObject *o = NULL;
1907 MonoClassField *field = this->field;
1909 MonoDomain *domain = mono_object_domain (this);
1911 MonoTypeEnum def_type;
1912 const char *def_value;
1916 MONO_ARCH_SAVE_REGS;
1918 mono_class_init (field->parent);
1920 t = mono_field_get_type_checked (field, &error);
1921 if (!mono_error_ok (&error))
1922 mono_error_raise_exception (&error);
1924 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1925 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1927 if (field->parent->image->dynamic) {
1929 g_assert_not_reached ();
1932 def_value = mono_class_get_field_default_value (field, &def_type);
1933 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1934 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1936 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1940 case MONO_TYPE_BOOLEAN:
1943 case MONO_TYPE_CHAR:
1951 case MONO_TYPE_R8: {
1954 /* boxed value type */
1955 t = g_new0 (MonoType, 1);
1957 klass = mono_class_from_mono_type (t);
1959 o = mono_object_new (domain, klass);
1960 v = ((gchar *) o) + sizeof (MonoObject);
1961 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1964 case MONO_TYPE_STRING:
1965 case MONO_TYPE_CLASS:
1966 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1969 g_assert_not_reached ();
1975 static MonoReflectionType*
1976 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1979 MonoClassField *field = ref_field->field;
1980 MonoType *type = mono_field_get_type_checked (field, &error);
1981 if (!mono_error_ok (&error))
1982 mono_error_raise_exception (&error);
1983 return mono_type_get_object (mono_object_domain (ref_field), type);
1986 static MonoReflectionType*
1987 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1989 MonoMethod *method = rmethod->method.method;
1991 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1994 /* From MonoProperty.cs */
1996 PInfo_Attributes = 1,
1997 PInfo_GetMethod = 1 << 1,
1998 PInfo_SetMethod = 1 << 2,
1999 PInfo_ReflectedType = 1 << 3,
2000 PInfo_DeclaringType = 1 << 4,
2005 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2007 MonoDomain *domain = mono_object_domain (property);
2009 MONO_ARCH_SAVE_REGS;
2011 if ((req_info & PInfo_ReflectedType) != 0)
2012 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2013 if ((req_info & PInfo_DeclaringType) != 0)
2014 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2016 if ((req_info & PInfo_Name) != 0)
2017 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2019 if ((req_info & PInfo_Attributes) != 0)
2020 info->attrs = property->property->attrs;
2022 if ((req_info & PInfo_GetMethod) != 0)
2023 MONO_STRUCT_SETREF (info, get, property->property->get ?
2024 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2026 if ((req_info & PInfo_SetMethod) != 0)
2027 MONO_STRUCT_SETREF (info, set, property->property->set ?
2028 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2030 * There may be other methods defined for properties, though, it seems they are not exposed
2031 * in the reflection API
2036 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2038 MonoDomain *domain = mono_object_domain (event);
2040 MONO_ARCH_SAVE_REGS;
2042 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2043 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2045 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2046 info->attrs = event->event->attrs;
2047 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2048 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2049 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2051 #ifndef MONO_SMALL_CONFIG
2052 if (event->event->other) {
2054 while (event->event->other [n])
2056 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2058 for (i = 0; i < n; i++)
2059 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2065 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2070 mono_class_setup_interfaces (klass, error);
2071 if (!mono_error_ok (error))
2074 for (i = 0; i < klass->interface_count; i++) {
2075 ic = klass->interfaces [i];
2076 g_hash_table_insert (ifaces, ic, ic);
2078 collect_interfaces (ic, ifaces, error);
2079 if (!mono_error_ok (error))
2085 MonoArray *iface_array;
2086 MonoGenericContext *context;
2090 } FillIfaceArrayData;
2093 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2095 FillIfaceArrayData *data = user_data;
2096 MonoClass *ic = key;
2097 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2099 if (!mono_error_ok (data->error))
2102 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2103 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2104 if (!mono_error_ok (data->error))
2108 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2111 mono_metadata_free_type (inflated);
2115 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2118 MonoClass *class = mono_class_from_mono_type (type->type);
2120 FillIfaceArrayData data = { 0 };
2123 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2125 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2126 data.context = mono_class_get_context (class);
2127 class = class->generic_class->container_class;
2130 for (parent = class; parent; parent = parent->parent) {
2131 mono_class_setup_interfaces (parent, &error);
2132 if (!mono_error_ok (&error))
2134 collect_interfaces (parent, iface_hash, &error);
2135 if (!mono_error_ok (&error))
2139 data.error = &error;
2140 data.domain = mono_object_domain (type);
2142 len = g_hash_table_size (iface_hash);
2144 g_hash_table_destroy (iface_hash);
2145 if (!data.domain->empty_types)
2146 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2147 return data.domain->empty_types;
2150 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2151 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2152 if (!mono_error_ok (&error))
2155 g_hash_table_destroy (iface_hash);
2156 return data.iface_array;
2159 g_hash_table_destroy (iface_hash);
2160 mono_error_raise_exception (&error);
2165 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2167 gboolean variance_used;
2168 MonoClass *class = mono_class_from_mono_type (type->type);
2169 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2170 MonoReflectionMethod *member;
2173 int i = 0, len, ioffset;
2176 MONO_ARCH_SAVE_REGS;
2177 mono_class_init_or_throw (class);
2178 mono_class_init_or_throw (iclass);
2180 mono_class_setup_vtable (class);
2182 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2186 len = mono_class_num_methods (iclass);
2187 domain = mono_object_domain (type);
2188 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2189 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2191 while ((method = mono_class_get_methods (iclass, &iter))) {
2192 member = mono_method_get_object (domain, method, iclass);
2193 mono_array_setref (*methods, i, member);
2194 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2195 mono_array_setref (*targets, i, member);
2202 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2204 MonoClass *klass = mono_class_from_mono_type (type->type);
2205 mono_class_init_or_throw (klass);
2207 if (klass->image->dynamic) {
2208 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2209 *packing = tb->packing_size;
2210 *size = tb->class_size;
2212 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2216 static MonoReflectionType*
2217 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2221 MONO_ARCH_SAVE_REGS;
2223 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2224 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2226 class = mono_class_from_mono_type (type->type);
2227 mono_class_init_or_throw (class);
2229 // GetElementType should only return a type for:
2230 // Array Pointer PassedByRef
2231 if (type->type->byref)
2232 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2233 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2234 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2235 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2236 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2241 static MonoReflectionType*
2242 ves_icall_get_type_parent (MonoReflectionType *type)
2244 MonoClass *class = mono_class_from_mono_type (type->type);
2245 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2249 ves_icall_type_ispointer (MonoReflectionType *type)
2251 MONO_ARCH_SAVE_REGS;
2253 return type->type->type == MONO_TYPE_PTR;
2257 ves_icall_type_isprimitive (MonoReflectionType *type)
2259 MONO_ARCH_SAVE_REGS;
2261 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)));
2265 ves_icall_type_isbyref (MonoReflectionType *type)
2267 MONO_ARCH_SAVE_REGS;
2269 return type->type->byref;
2273 ves_icall_type_iscomobject (MonoReflectionType *type)
2275 MonoClass *klass = mono_class_from_mono_type (type->type);
2276 mono_class_init_or_throw (klass);
2278 return (klass && klass->is_com_object);
2281 static MonoReflectionModule*
2282 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2284 MonoClass *class = mono_class_from_mono_type (type->type);
2285 return mono_module_get_object (mono_object_domain (type), class->image);
2288 static MonoReflectionAssembly*
2289 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2291 MonoDomain *domain = mono_domain_get ();
2292 MonoClass *class = mono_class_from_mono_type (type->type);
2293 return mono_assembly_get_object (domain, class->image->assembly);
2296 static MonoReflectionType*
2297 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2299 MonoDomain *domain = mono_domain_get ();
2302 MONO_ARCH_SAVE_REGS;
2304 if (type->type->byref)
2306 if (type->type->type == MONO_TYPE_VAR)
2307 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2308 else if (type->type->type == MONO_TYPE_MVAR)
2309 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2311 class = mono_class_from_mono_type (type->type)->nested_in;
2313 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2317 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2319 MonoDomain *domain = mono_domain_get ();
2320 MonoClass *class = mono_class_from_mono_type (type->type);
2322 if (type->type->byref) {
2323 char *n = g_strdup_printf ("%s&", class->name);
2324 MonoString *res = mono_string_new (domain, n);
2330 return mono_string_new (domain, class->name);
2335 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2337 MonoDomain *domain = mono_domain_get ();
2338 MonoClass *class = mono_class_from_mono_type (type->type);
2340 while (class->nested_in)
2341 class = class->nested_in;
2343 if (class->name_space [0] == '\0')
2346 return mono_string_new (domain, class->name_space);
2350 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2354 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2355 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2357 class = mono_class_from_mono_type (type->type);
2363 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2366 MonoClass *klass, *pklass;
2367 MonoDomain *domain = mono_object_domain (type);
2368 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2370 MONO_ARCH_SAVE_REGS;
2372 klass = mono_class_from_mono_type (type->type);
2374 if (klass->generic_container) {
2375 MonoGenericContainer *container = klass->generic_container;
2376 res = mono_array_new_specific (array_vtable, container->type_argc);
2377 for (i = 0; i < container->type_argc; ++i) {
2378 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2379 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2381 } else if (klass->generic_class) {
2382 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2383 res = mono_array_new_specific (array_vtable, inst->type_argc);
2384 for (i = 0; i < inst->type_argc; ++i)
2385 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2387 res = mono_array_new_specific (array_vtable, 0);
2393 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2396 MONO_ARCH_SAVE_REGS;
2398 if (!IS_MONOTYPE (type))
2401 if (type->type->byref)
2404 klass = mono_class_from_mono_type (type->type);
2405 return klass->generic_container != NULL;
2408 static MonoReflectionType*
2409 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2412 MONO_ARCH_SAVE_REGS;
2414 if (type->type->byref)
2417 klass = mono_class_from_mono_type (type->type);
2419 if (klass->generic_container) {
2420 return type; /* check this one */
2422 if (klass->generic_class) {
2423 MonoClass *generic_class = klass->generic_class->container_class;
2426 tb = mono_class_get_ref_info (generic_class);
2428 if (generic_class->wastypebuilder && tb)
2431 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2436 static MonoReflectionType*
2437 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2440 MonoType *geninst, **types;
2443 g_assert (IS_MONOTYPE (type));
2444 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2446 count = mono_array_length (type_array);
2447 types = g_new0 (MonoType *, count);
2449 for (i = 0; i < count; i++) {
2450 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2451 types [i] = t->type;
2454 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2459 class = mono_class_from_mono_type (geninst);
2461 /*we might inflate to the GTD*/
2462 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2463 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2465 return mono_type_get_object (mono_object_domain (type), geninst);
2469 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2472 MONO_ARCH_SAVE_REGS;
2474 if (type->type->byref)
2477 klass = mono_class_from_mono_type (type->type);
2479 return klass->generic_class != NULL;
2483 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2486 MONO_ARCH_SAVE_REGS;
2488 if (!IS_MONOTYPE (type))
2491 if (type->type->byref)
2494 klass = mono_class_from_mono_type (type->type);
2495 return klass->generic_class != NULL || klass->generic_container != NULL;
2499 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2501 MONO_ARCH_SAVE_REGS;
2503 if (!IS_MONOTYPE (type))
2506 if (is_generic_parameter (type->type))
2507 return mono_type_get_generic_param_num (type->type);
2511 static GenericParameterAttributes
2512 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2514 MONO_ARCH_SAVE_REGS;
2516 g_assert (IS_MONOTYPE (type));
2517 g_assert (is_generic_parameter (type->type));
2518 return mono_generic_param_info (type->type->data.generic_param)->flags;
2522 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2524 MonoGenericParamInfo *param_info;
2530 MONO_ARCH_SAVE_REGS;
2532 g_assert (IS_MONOTYPE (type));
2534 domain = mono_object_domain (type);
2535 param_info = mono_generic_param_info (type->type->data.generic_param);
2536 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2539 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2540 for (i = 0; i < count; i++)
2541 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2548 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2550 MONO_ARCH_SAVE_REGS;
2551 return is_generic_parameter (type->type);
2555 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2557 MONO_ARCH_SAVE_REGS;
2558 return is_generic_parameter (tb->type.type);
2562 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2563 MonoReflectionType *t)
2565 enumtype->type = t->type;
2568 static MonoReflectionMethod*
2569 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2570 MonoReflectionMethod* generic)
2577 MONO_ARCH_SAVE_REGS;
2579 domain = ((MonoObject *)type)->vtable->domain;
2581 klass = mono_class_from_mono_type (type->type);
2582 mono_class_init_or_throw (klass);
2585 while ((method = mono_class_get_methods (klass, &iter))) {
2586 if (method->token == generic->method->token)
2587 return mono_method_get_object (domain, method, klass);
2595 static MonoReflectionMethod *
2596 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2599 MonoType *type = ref_type->type;
2601 MONO_ARCH_SAVE_REGS;
2603 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2604 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2605 if (type->type == MONO_TYPE_VAR)
2608 method = mono_type_get_generic_param_owner (type)->owner.method;
2610 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2613 static MonoReflectionDllImportAttribute*
2614 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2616 static MonoClass *DllImportAttributeClass = NULL;
2617 MonoDomain *domain = mono_domain_get ();
2618 MonoReflectionDllImportAttribute *attr;
2619 MonoImage *image = method->klass->image;
2620 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2621 MonoTableInfo *tables = image->tables;
2622 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2623 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2624 guint32 im_cols [MONO_IMPLMAP_SIZE];
2625 guint32 scope_token;
2626 const char *import = NULL;
2627 const char *scope = NULL;
2630 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2633 if (!DllImportAttributeClass) {
2634 DllImportAttributeClass =
2635 mono_class_from_name (mono_defaults.corlib,
2636 "System.Runtime.InteropServices", "DllImportAttribute");
2637 g_assert (DllImportAttributeClass);
2640 if (method->klass->image->dynamic) {
2641 MonoReflectionMethodAux *method_aux =
2642 g_hash_table_lookup (
2643 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2645 import = method_aux->dllentry;
2646 scope = method_aux->dll;
2649 if (!import || !scope) {
2650 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2655 if (piinfo->implmap_idx) {
2656 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2658 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2659 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2660 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2661 scope = mono_metadata_string_heap (image, scope_token);
2664 flags = piinfo->piflags;
2666 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2668 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2669 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2670 attr->call_conv = (flags & 0x700) >> 8;
2671 attr->charset = ((flags & 0x6) >> 1) + 1;
2672 if (attr->charset == 1)
2674 attr->exact_spelling = (flags & 0x1) != 0;
2675 attr->set_last_error = (flags & 0x40) != 0;
2676 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2677 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2678 attr->preserve_sig = FALSE;
2683 static MonoReflectionMethod *
2684 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2686 MonoMethodInflated *imethod;
2689 MONO_ARCH_SAVE_REGS;
2691 if (method->method->is_generic)
2694 if (!method->method->is_inflated)
2697 imethod = (MonoMethodInflated *) method->method;
2699 result = imethod->declaring;
2700 /* Not a generic method. */
2701 if (!result->is_generic)
2704 if (method->method->klass->image->dynamic) {
2705 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2706 MonoReflectionMethod *res;
2709 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2710 * the dynamic case as well ?
2712 mono_loader_lock ();
2713 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2714 mono_loader_unlock ();
2720 if (imethod->context.class_inst) {
2721 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2722 /*Generic methods gets the context of the GTD.*/
2723 if (mono_class_get_context (klass))
2724 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2727 return mono_method_get_object (mono_object_domain (method), result, NULL);
2731 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2733 MONO_ARCH_SAVE_REGS;
2735 return mono_method_signature (method->method)->generic_param_count != 0;
2739 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2741 MONO_ARCH_SAVE_REGS;
2743 return method->method->is_generic;
2747 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2752 MONO_ARCH_SAVE_REGS;
2754 domain = mono_object_domain (method);
2756 if (method->method->is_inflated) {
2757 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2760 count = inst->type_argc;
2761 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2763 for (i = 0; i < count; i++)
2764 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2770 count = mono_method_signature (method->method)->generic_param_count;
2771 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2773 for (i = 0; i < count; i++) {
2774 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2775 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2776 MonoClass *pklass = mono_class_from_generic_parameter (
2777 param, method->method->klass->image, TRUE);
2778 mono_array_setref (res, i,
2779 mono_type_get_object (domain, &pklass->byval_arg));
2786 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2789 * Invoke from reflection is supposed to always be a virtual call (the API
2790 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2791 * greater flexibility.
2793 MonoMethod *m = method->method;
2797 MONO_ARCH_SAVE_REGS;
2801 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2802 mono_security_core_clr_ensure_reflection_access_method (m);
2804 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2805 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2806 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2811 if (!mono_object_isinst (this, m->klass)) {
2812 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2813 char *target_name = mono_type_get_full_name (m->klass);
2814 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2815 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2817 g_free (target_name);
2821 m = mono_object_get_virtual_method (this, m);
2822 /* must pass the pointer to the value for valuetype methods */
2823 if (m->klass->valuetype)
2824 obj = mono_object_unbox (this);
2825 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2826 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2831 pcount = params? mono_array_length (params): 0;
2832 if (pcount != mono_method_signature (m)->param_count) {
2833 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2837 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2838 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."));
2842 if (m->klass->image->assembly->ref_only) {
2843 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."));
2847 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2850 intptr_t *lower_bounds;
2851 pcount = mono_array_length (params);
2852 lengths = alloca (sizeof (uintptr_t) * pcount);
2853 /* Note: the synthetized array .ctors have int32 as argument type */
2854 for (i = 0; i < pcount; ++i)
2855 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2857 if (m->klass->rank == pcount) {
2858 /* Only lengths provided. */
2859 lower_bounds = NULL;
2861 g_assert (pcount == (m->klass->rank * 2));
2862 /* lower bounds are first. */
2863 lower_bounds = (intptr_t*)lengths;
2864 lengths += m->klass->rank;
2867 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2869 return mono_runtime_invoke_array (m, obj, params, NULL);
2873 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2875 MonoDomain *domain = mono_object_domain (method);
2876 MonoMethod *m = method->method;
2877 MonoMethodSignature *sig = mono_method_signature (m);
2878 MonoArray *out_args;
2880 int i, j, outarg_count = 0;
2882 MONO_ARCH_SAVE_REGS;
2884 if (m->klass == mono_defaults.object_class) {
2886 if (!strcmp (m->name, "FieldGetter")) {
2887 MonoClass *k = this->vtable->klass;
2891 /* If this is a proxy, then it must be a CBO */
2892 if (k == mono_defaults.transparent_proxy_class) {
2893 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2894 this = tp->rp->unwrapped_server;
2896 k = this->vtable->klass;
2899 name = mono_array_get (params, MonoString *, 1);
2900 str = mono_string_to_utf8 (name);
2903 MonoClassField* field = mono_class_get_field_from_name (k, str);
2905 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2906 if (field_klass->valuetype)
2907 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2909 result = *((gpointer *)((char *)this + field->offset));
2911 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2912 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2913 mono_array_setref (out_args, 0, result);
2921 g_assert_not_reached ();
2923 } else if (!strcmp (m->name, "FieldSetter")) {
2924 MonoClass *k = this->vtable->klass;
2930 /* If this is a proxy, then it must be a CBO */
2931 if (k == mono_defaults.transparent_proxy_class) {
2932 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2933 this = tp->rp->unwrapped_server;
2935 k = this->vtable->klass;
2938 name = mono_array_get (params, MonoString *, 1);
2939 str = mono_string_to_utf8 (name);
2942 MonoClassField* field = mono_class_get_field_from_name (k, str);
2944 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2945 MonoObject *val = mono_array_get (params, gpointer, 2);
2947 if (field_klass->valuetype) {
2948 size = mono_type_size (field->type, &align);
2949 g_assert (size == mono_class_value_size (field_klass, NULL));
2950 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2952 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2955 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2956 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2966 g_assert_not_reached ();
2971 for (i = 0; i < mono_array_length (params); i++) {
2972 if (sig->params [i]->byref)
2976 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2978 /* handle constructors only for objects already allocated */
2979 if (!strcmp (method->method->name, ".ctor"))
2982 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2983 g_assert (!method->method->klass->valuetype);
2984 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2986 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2987 if (sig->params [i]->byref) {
2989 arg = mono_array_get (params, gpointer, i);
2990 mono_array_setref (out_args, j, arg);
2995 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3001 read_enum_value (char *mem, int type)
3005 return *(guint8*)mem;
3007 return *(gint8*)mem;
3009 return *(guint16*)mem;
3011 return *(gint16*)mem;
3013 return *(guint32*)mem;
3015 return *(gint32*)mem;
3017 return *(guint64*)mem;
3019 return *(gint64*)mem;
3021 g_assert_not_reached ();
3027 write_enum_value (char *mem, int type, guint64 value)
3031 case MONO_TYPE_I1: {
3032 guint8 *p = (guint8*)mem;
3037 case MONO_TYPE_I2: {
3038 guint16 *p = (void*)mem;
3043 case MONO_TYPE_I4: {
3044 guint32 *p = (void*)mem;
3049 case MONO_TYPE_I8: {
3050 guint64 *p = (void*)mem;
3055 g_assert_not_reached ();
3061 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3064 MonoClass *enumc, *objc;
3069 MONO_ARCH_SAVE_REGS;
3071 MONO_CHECK_ARG_NULL (enumType);
3072 MONO_CHECK_ARG_NULL (value);
3074 domain = mono_object_domain (enumType);
3075 enumc = mono_class_from_mono_type (enumType->type);
3077 mono_class_init_or_throw (enumc);
3079 objc = value->vtable->klass;
3081 if (!enumc->enumtype)
3082 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3083 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3084 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."));
3086 etype = mono_class_enum_basetype (enumc);
3088 /* MS throws this for typebuilders */
3089 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3091 res = mono_object_new (domain, enumc);
3092 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3093 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3099 ves_icall_System_Enum_get_value (MonoObject *this)
3107 MONO_ARCH_SAVE_REGS;
3112 g_assert (this->vtable->klass->enumtype);
3114 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3115 res = mono_object_new (mono_object_domain (this), enumc);
3116 dst = (char *)res + sizeof (MonoObject);
3117 src = (char *)this + sizeof (MonoObject);
3118 size = mono_class_value_size (enumc, NULL);
3120 memcpy (dst, src, size);
3125 static MonoReflectionType *
3126 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3131 MONO_ARCH_SAVE_REGS;
3133 klass = mono_class_from_mono_type (type->type);
3134 mono_class_init_or_throw (klass);
3136 etype = mono_class_enum_basetype (klass);
3138 /* MS throws this for typebuilders */
3139 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3141 return mono_type_get_object (mono_object_domain (type), etype);
3145 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3147 gpointer tdata = (char *)this + sizeof (MonoObject);
3148 gpointer odata = (char *)other + sizeof (MonoObject);
3149 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3150 g_assert (basetype);
3152 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3153 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3154 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3157 return me > other ? 1 : -1; \
3160 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3161 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3162 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3165 return me - other; \
3168 switch (basetype->type) {
3170 COMPARE_ENUM_VALUES (guint8);
3172 COMPARE_ENUM_VALUES (gint8);
3173 case MONO_TYPE_CHAR:
3175 COMPARE_ENUM_VALUES_RANGE (guint16);
3177 COMPARE_ENUM_VALUES (gint16);
3179 COMPARE_ENUM_VALUES (guint32);
3181 COMPARE_ENUM_VALUES (gint32);
3183 COMPARE_ENUM_VALUES (guint64);
3185 COMPARE_ENUM_VALUES (gint64);
3187 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3189 #undef COMPARE_ENUM_VALUES_RANGE
3190 #undef COMPARE_ENUM_VALUES
3195 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3197 gpointer data = (char *)this + sizeof (MonoObject);
3198 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3199 g_assert (basetype);
3201 switch (basetype->type) {
3203 return *((gint8*)data);
3205 return *((guint8*)data);
3206 case MONO_TYPE_CHAR:
3208 return *((guint16*)data);
3211 return *((gint16*)data);
3213 return *((guint32*)data);
3215 return *((gint32*)data);
3217 case MONO_TYPE_I8: {
3218 gint64 value = *((gint64*)data);
3219 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3222 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3228 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3230 MonoDomain *domain = mono_object_domain (type);
3231 MonoClass *enumc = mono_class_from_mono_type (type->type);
3232 guint j = 0, nvalues, crow;
3234 MonoClassField *field;
3236 MONO_ARCH_SAVE_REGS;
3238 mono_class_init_or_throw (enumc);
3240 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3241 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3242 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3243 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3247 while ((field = mono_class_get_fields (enumc, &iter))) {
3250 MonoTypeEnum def_type;
3252 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3254 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3256 if (mono_field_is_deleted (field))
3258 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3260 p = mono_class_get_field_default_value (field, &def_type);
3261 len = mono_metadata_decode_blob_size (p, &p);
3262 switch (mono_class_enum_basetype (enumc)->type) {
3265 mono_array_set (info->values, gchar, j, *p);
3267 case MONO_TYPE_CHAR:
3270 mono_array_set (info->values, gint16, j, read16 (p));
3274 mono_array_set (info->values, gint32, j, read32 (p));
3278 mono_array_set (info->values, gint64, j, read64 (p));
3281 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3288 BFLAGS_IgnoreCase = 1,
3289 BFLAGS_DeclaredOnly = 2,
3290 BFLAGS_Instance = 4,
3292 BFLAGS_Public = 0x10,
3293 BFLAGS_NonPublic = 0x20,
3294 BFLAGS_FlattenHierarchy = 0x40,
3295 BFLAGS_InvokeMethod = 0x100,
3296 BFLAGS_CreateInstance = 0x200,
3297 BFLAGS_GetField = 0x400,
3298 BFLAGS_SetField = 0x800,
3299 BFLAGS_GetProperty = 0x1000,
3300 BFLAGS_SetProperty = 0x2000,
3301 BFLAGS_ExactBinding = 0x10000,
3302 BFLAGS_SuppressChangeType = 0x20000,
3303 BFLAGS_OptionalParamBinding = 0x40000
3306 static MonoReflectionField *
3307 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3310 MonoClass *startklass, *klass;
3312 MonoClassField *field;
3315 int (*compare_func) (const char *s1, const char *s2) = NULL;
3316 domain = ((MonoObject *)type)->vtable->domain;
3317 klass = startklass = mono_class_from_mono_type (type->type);
3320 mono_raise_exception (mono_get_exception_argument_null ("name"));
3321 if (type->type->byref)
3324 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3327 if (klass->exception_type != MONO_EXCEPTION_NONE)
3328 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3331 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3332 guint32 flags = mono_field_get_flags (field);
3335 if (mono_field_is_deleted_with_flags (field, flags))
3337 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3338 if (bflags & BFLAGS_Public)
3340 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3341 if (bflags & BFLAGS_NonPublic) {
3348 if (flags & FIELD_ATTRIBUTE_STATIC) {
3349 if (bflags & BFLAGS_Static)
3350 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3353 if (bflags & BFLAGS_Instance)
3360 utf8_name = mono_string_to_utf8 (name);
3362 if (compare_func (mono_field_get_name (field), utf8_name)) {
3368 return mono_field_get_object (domain, klass, field);
3370 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3377 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3380 MonoClass *startklass, *klass, *refklass;
3385 MonoClassField *field;
3386 MonoPtrArray tmp_array;
3388 MONO_ARCH_SAVE_REGS;
3390 domain = ((MonoObject *)type)->vtable->domain;
3391 if (type->type->byref)
3392 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3393 klass = startklass = mono_class_from_mono_type (type->type);
3394 refklass = mono_class_from_mono_type (reftype->type);
3396 mono_ptr_array_init (tmp_array, 2);
3399 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3400 mono_ptr_array_destroy (tmp_array);
3401 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3405 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3406 guint32 flags = mono_field_get_flags (field);
3408 if (mono_field_is_deleted_with_flags (field, flags))
3410 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3411 if (bflags & BFLAGS_Public)
3413 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3414 if (bflags & BFLAGS_NonPublic) {
3421 if (flags & FIELD_ATTRIBUTE_STATIC) {
3422 if (bflags & BFLAGS_Static)
3423 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3426 if (bflags & BFLAGS_Instance)
3432 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3433 mono_ptr_array_append (tmp_array, member);
3435 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3438 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3440 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3441 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3443 mono_ptr_array_destroy (tmp_array);
3449 method_nonpublic (MonoMethod* method, gboolean start_klass)
3451 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3452 case METHOD_ATTRIBUTE_ASSEM:
3453 return (start_klass || mono_defaults.generic_ilist_class);
3454 case METHOD_ATTRIBUTE_PRIVATE:
3456 case METHOD_ATTRIBUTE_PUBLIC:
3464 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, MonoException **ex)
3467 MonoClass *startklass;
3470 int len, match, nslots;
3471 /*FIXME, use MonoBitSet*/
3472 guint32 method_slots_default [8];
3473 guint32 *method_slots = NULL;
3474 int (*compare_func) (const char *s1, const char *s2) = NULL;
3476 array = g_ptr_array_new ();
3482 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3484 /* An optimization for calls made from Delegate:CreateDelegate () */
3485 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3486 method = mono_get_delegate_invoke (klass);
3487 if (mono_loader_get_last_error ())
3490 g_ptr_array_add (array, method);
3494 mono_class_setup_vtable (klass);
3495 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3498 if (is_generic_parameter (&klass->byval_arg))
3499 nslots = mono_class_get_vtable_size (klass->parent);
3501 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3502 if (nslots >= sizeof (method_slots_default) * 8) {
3503 method_slots = g_new0 (guint32, nslots / 32 + 1);
3505 method_slots = method_slots_default;
3506 memset (method_slots, 0, sizeof (method_slots_default));
3509 mono_class_setup_vtable (klass);
3510 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3514 while ((method = mono_class_get_methods (klass, &iter))) {
3516 if (method->slot != -1) {
3517 g_assert (method->slot < nslots);
3518 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3520 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3521 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3524 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3526 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3527 if (bflags & BFLAGS_Public)
3529 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3535 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3536 if (bflags & BFLAGS_Static)
3537 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3540 if (bflags & BFLAGS_Instance)
3548 if (compare_func (name, method->name))
3553 g_ptr_array_add (array, method);
3555 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3557 if (method_slots != method_slots_default)
3558 g_free (method_slots);
3563 if (method_slots != method_slots_default)
3564 g_free (method_slots);
3565 g_ptr_array_free (array, TRUE);
3567 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3568 *ex = mono_class_get_exception_for_failure (klass);
3570 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3571 mono_loader_clear_error ();
3577 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3579 static MonoClass *MethodInfo_array;
3582 MonoVTable *array_vtable;
3583 MonoException *ex = NULL;
3584 const char *mname = NULL;
3585 GPtrArray *method_array;
3586 MonoClass *klass, *refklass;
3589 if (!MethodInfo_array) {
3590 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3591 mono_memory_barrier ();
3592 MethodInfo_array = klass;
3595 klass = mono_class_from_mono_type (type->type);
3596 refklass = mono_class_from_mono_type (reftype->type);
3597 domain = ((MonoObject *)type)->vtable->domain;
3598 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3599 if (type->type->byref)
3600 return mono_array_new_specific (array_vtable, 0);
3603 mname = mono_string_to_utf8 (name);
3605 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, &ex);
3606 g_free ((char*)mname);
3608 mono_raise_exception (ex);
3610 res = mono_array_new_specific (array_vtable, method_array->len);
3613 for (i = 0; i < method_array->len; ++i) {
3614 MonoMethod *method = g_ptr_array_index (method_array, i);
3615 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3618 g_ptr_array_free (method_array, TRUE);
3623 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3626 static MonoClass *System_Reflection_ConstructorInfo;
3627 MonoClass *startklass, *klass, *refklass;
3632 gpointer iter = NULL;
3633 MonoPtrArray tmp_array;
3635 MONO_ARCH_SAVE_REGS;
3637 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3639 domain = ((MonoObject *)type)->vtable->domain;
3640 if (type->type->byref)
3641 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3642 klass = startklass = mono_class_from_mono_type (type->type);
3643 refklass = mono_class_from_mono_type (reftype->type);
3645 if (!System_Reflection_ConstructorInfo)
3646 System_Reflection_ConstructorInfo = mono_class_from_name (
3647 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3650 while ((method = mono_class_get_methods (klass, &iter))) {
3652 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3654 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3655 if (bflags & BFLAGS_Public)
3658 if (bflags & BFLAGS_NonPublic)
3664 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3665 if (bflags & BFLAGS_Static)
3666 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3669 if (bflags & BFLAGS_Instance)
3675 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3677 mono_ptr_array_append (tmp_array, member);
3680 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3682 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3683 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3685 mono_ptr_array_destroy (tmp_array);
3691 property_hash (gconstpointer data)
3693 MonoProperty *prop = (MonoProperty*)data;
3695 return g_str_hash (prop->name);
3699 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3701 // Properties are hide-by-name-and-signature
3702 if (!g_str_equal (prop1->name, prop2->name))
3705 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3707 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3713 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3718 return method_nonpublic (accessor, start_klass);
3722 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3726 static MonoClass *System_Reflection_PropertyInfo;
3727 MonoClass *startklass, *klass;
3733 gchar *propname = NULL;
3734 int (*compare_func) (const char *s1, const char *s2) = NULL;
3736 GHashTable *properties = NULL;
3737 MonoPtrArray tmp_array;
3739 MONO_ARCH_SAVE_REGS;
3741 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3743 if (!System_Reflection_PropertyInfo)
3744 System_Reflection_PropertyInfo = mono_class_from_name (
3745 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3747 domain = ((MonoObject *)type)->vtable->domain;
3748 if (type->type->byref)
3749 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3750 klass = startklass = mono_class_from_mono_type (type->type);
3753 propname = mono_string_to_utf8 (name);
3754 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3757 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3759 mono_class_setup_vtable (klass);
3760 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3764 while ((prop = mono_class_get_properties (klass, &iter))) {
3770 flags = method->flags;
3773 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3774 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3775 if (bflags & BFLAGS_Public)
3777 } else if (bflags & BFLAGS_NonPublic) {
3778 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3779 property_accessor_nonpublic(prop->set, startklass == klass)) {
3786 if (flags & METHOD_ATTRIBUTE_STATIC) {
3787 if (bflags & BFLAGS_Static)
3788 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3791 if (bflags & BFLAGS_Instance)
3800 if (compare_func (propname, prop->name))
3804 if (g_hash_table_lookup (properties, prop))
3807 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3809 g_hash_table_insert (properties, prop, prop);
3811 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3814 g_hash_table_destroy (properties);
3817 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3818 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3819 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3821 mono_ptr_array_destroy (tmp_array);
3827 g_hash_table_destroy (properties);
3830 mono_ptr_array_destroy (tmp_array);
3832 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3833 ex = mono_class_get_exception_for_failure (klass);
3835 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3836 mono_loader_clear_error ();
3838 mono_raise_exception (ex);
3842 static MonoReflectionEvent *
3843 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3846 MonoClass *klass, *startklass;
3851 int (*compare_func) (const char *s1, const char *s2);
3853 MONO_ARCH_SAVE_REGS;
3855 event_name = mono_string_to_utf8 (name);
3856 if (type->type->byref)
3858 klass = startklass = mono_class_from_mono_type (type->type);
3859 domain = mono_object_domain (type);
3861 mono_class_init_or_throw (klass);
3863 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3865 if (klass->exception_type != MONO_EXCEPTION_NONE)
3866 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3869 while ((event = mono_class_get_events (klass, &iter))) {
3870 if (compare_func (event->name, event_name))
3873 method = event->add;
3875 method = event->remove;
3877 method = event->raise;
3879 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3880 if (!(bflags & BFLAGS_Public))
3883 if (!(bflags & BFLAGS_NonPublic))
3885 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3889 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3890 if (!(bflags & BFLAGS_Static))
3892 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3895 if (!(bflags & BFLAGS_Instance))
3899 if (!(bflags & BFLAGS_NonPublic))
3902 g_free (event_name);
3903 return mono_event_get_object (domain, startklass, event);
3906 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3909 g_free (event_name);
3914 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3918 static MonoClass *System_Reflection_EventInfo;
3919 MonoClass *startklass, *klass;
3926 MonoPtrArray tmp_array;
3928 MONO_ARCH_SAVE_REGS;
3930 mono_ptr_array_init (tmp_array, 4);
3932 if (!System_Reflection_EventInfo)
3933 System_Reflection_EventInfo = mono_class_from_name (
3934 mono_defaults.corlib, "System.Reflection", "EventInfo");
3936 domain = mono_object_domain (type);
3937 if (type->type->byref)
3938 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3939 klass = startklass = mono_class_from_mono_type (type->type);
3942 mono_class_setup_vtable (klass);
3943 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3947 while ((event = mono_class_get_events (klass, &iter))) {
3949 method = event->add;
3951 method = event->remove;
3953 method = event->raise;
3955 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3956 if (bflags & BFLAGS_Public)
3958 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3959 if (bflags & BFLAGS_NonPublic)
3964 if (bflags & BFLAGS_NonPublic)
3970 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3971 if (bflags & BFLAGS_Static)
3972 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3975 if (bflags & BFLAGS_Instance)
3980 if (bflags & BFLAGS_Instance)
3984 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3986 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3989 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3991 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3992 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3994 mono_ptr_array_destroy (tmp_array);
3999 mono_ptr_array_destroy (tmp_array);
4000 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4001 ex = mono_class_get_exception_for_failure (klass);
4003 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4004 mono_loader_clear_error ();
4006 mono_raise_exception (ex);
4010 static MonoReflectionType *
4011 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4019 MONO_ARCH_SAVE_REGS;
4022 mono_raise_exception (mono_get_exception_argument_null ("name"));
4024 domain = ((MonoObject *)type)->vtable->domain;
4025 if (type->type->byref)
4027 klass = mono_class_from_mono_type (type->type);
4029 str = mono_string_to_utf8 (name);
4032 if (klass->exception_type != MONO_EXCEPTION_NONE)
4033 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4036 * If a nested type is generic, return its generic type definition.
4037 * Note that this means that the return value is essentially a
4038 * nested type of the generic type definition of @klass.
4040 * A note in MSDN claims that a generic type definition can have
4041 * nested types that aren't generic. In any case, the container of that
4042 * nested type would be the generic type definition.
4044 if (klass->generic_class)
4045 klass = klass->generic_class->container_class;
4048 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4050 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4051 if (bflags & BFLAGS_Public)
4054 if (bflags & BFLAGS_NonPublic)
4059 if (strcmp (nested->name, str) == 0){
4061 return mono_type_get_object (domain, &nested->byval_arg);
4064 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4071 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4080 MonoPtrArray tmp_array;
4082 MONO_ARCH_SAVE_REGS;
4084 domain = ((MonoObject *)type)->vtable->domain;
4085 if (type->type->byref)
4086 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4087 klass = mono_class_from_mono_type (type->type);
4090 * If a nested type is generic, return its generic type definition.
4091 * Note that this means that the return value is essentially the set
4092 * of nested types of the generic type definition of @klass.
4094 * A note in MSDN claims that a generic type definition can have
4095 * nested types that aren't generic. In any case, the container of that
4096 * nested type would be the generic type definition.
4098 if (klass->generic_class)
4099 klass = klass->generic_class->container_class;
4101 mono_ptr_array_init (tmp_array, 1);
4103 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4105 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4106 if (bflags & BFLAGS_Public)
4109 if (bflags & BFLAGS_NonPublic)
4114 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4115 mono_ptr_array_append (tmp_array, member);
4118 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4120 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4121 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4123 mono_ptr_array_destroy (tmp_array);
4128 static MonoReflectionType*
4129 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4132 MonoType *type = NULL;
4133 MonoTypeNameParse info;
4134 gboolean type_resolve;
4136 MONO_ARCH_SAVE_REGS;
4138 /* On MS.NET, this does not fire a TypeResolve event */
4139 type_resolve = TRUE;
4140 str = mono_string_to_utf8 (name);
4141 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4142 if (!mono_reflection_parse_type (str, &info)) {
4144 mono_reflection_free_type_info (&info);
4145 if (throwOnError) /* uhm: this is a parse error, though... */
4146 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4147 /*g_print ("failed parse\n");*/
4151 if (info.assembly.name) {
4153 mono_reflection_free_type_info (&info);
4155 /* 1.0 and 2.0 throw different exceptions */
4156 if (mono_defaults.generic_ilist_class)
4157 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4159 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4164 if (module != NULL) {
4166 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4171 if (assembly->assembly->dynamic) {
4172 /* Enumerate all modules */
4173 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4177 if (abuilder->modules) {
4178 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4179 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4180 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4186 if (!type && abuilder->loaded_modules) {
4187 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4188 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4189 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4196 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4198 mono_reflection_free_type_info (&info);
4200 MonoException *e = NULL;
4203 e = mono_get_exception_type_load (name, NULL);
4205 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4206 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4208 mono_loader_clear_error ();
4211 mono_raise_exception (e);
4214 } else if (mono_loader_get_last_error ()) {
4216 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4217 mono_loader_clear_error ();
4220 if (type->type == MONO_TYPE_CLASS) {
4221 MonoClass *klass = mono_type_get_class (type);
4223 if (mono_is_security_manager_active () && !klass->exception_type)
4224 /* Some security problems are detected during generic vtable construction */
4225 mono_class_setup_vtable (klass);
4226 /* need to report exceptions ? */
4227 if (throwOnError && klass->exception_type) {
4228 /* report SecurityException (or others) that occured when loading the assembly */
4229 MonoException *exc = mono_class_get_exception_for_failure (klass);
4230 mono_loader_clear_error ();
4231 mono_raise_exception (exc);
4232 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4237 /* g_print ("got it\n"); */
4238 return mono_type_get_object (mono_object_domain (assembly), type);
4242 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4245 gchar *shadow_ini_file;
4248 /* Check for shadow-copied assembly */
4249 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4250 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4252 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4253 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4259 g_free (shadow_ini_file);
4260 if (content != NULL) {
4263 *filename = content;
4271 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4273 MonoDomain *domain = mono_object_domain (assembly);
4274 MonoAssembly *mass = assembly->assembly;
4275 MonoString *res = NULL;
4280 MONO_ARCH_SAVE_REGS;
4282 if (g_path_is_absolute (mass->image->name)) {
4283 absolute = g_strdup (mass->image->name);
4284 dirname = g_path_get_dirname (absolute);
4286 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4287 dirname = g_strdup (mass->basedir);
4290 replace_shadow_path (domain, dirname, &absolute);
4295 for (i = strlen (absolute) - 1; i >= 0; i--)
4296 if (absolute [i] == '\\')
4301 uri = g_filename_to_uri (absolute, NULL, NULL);
4303 const char *prepend = "file://";
4305 if (*absolute == '/' && *(absolute + 1) == '/') {
4308 prepend = "file:///";
4311 uri = g_strconcat (prepend, absolute, NULL);
4315 res = mono_string_new (domain, uri);
4323 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4325 MonoAssembly *mass = assembly->assembly;
4327 MONO_ARCH_SAVE_REGS;
4329 return mass->in_gac;
4332 static MonoReflectionAssembly*
4333 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4337 MonoImageOpenStatus status;
4339 MONO_ARCH_SAVE_REGS;
4341 name = mono_string_to_utf8 (mname);
4342 res = mono_assembly_load_with_partial_name (name, &status);
4348 return mono_assembly_get_object (mono_domain_get (), res);
4352 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4354 MonoDomain *domain = mono_object_domain (assembly);
4357 MONO_ARCH_SAVE_REGS;
4359 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4365 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4367 MONO_ARCH_SAVE_REGS;
4369 return assembly->assembly->ref_only;
4373 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4375 MonoDomain *domain = mono_object_domain (assembly);
4377 MONO_ARCH_SAVE_REGS;
4379 return mono_string_new (domain, assembly->assembly->image->version);
4382 static MonoReflectionMethod*
4383 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4385 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4387 MONO_ARCH_SAVE_REGS;
4391 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4394 static MonoReflectionModule*
4395 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4397 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4401 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4403 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4404 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4408 MONO_ARCH_SAVE_REGS;
4410 for (i = 0; i < table->rows; ++i) {
4411 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4412 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4418 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4420 static MonoClass *System_Version = NULL;
4421 static MonoMethod *create_version = NULL;
4425 if (!System_Version) {
4426 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4427 g_assert (System_Version);
4430 if (!create_version) {
4431 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4432 create_version = mono_method_desc_search_in_class (desc, System_Version);
4433 g_assert (create_version);
4434 mono_method_desc_free (desc);
4440 args [3] = &revision;
4441 result = mono_object_new (domain, System_Version);
4442 mono_runtime_invoke (create_version, result, args, NULL);
4448 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4450 static MonoClass *System_Reflection_AssemblyName;
4452 MonoDomain *domain = mono_object_domain (assembly);
4454 static MonoMethod *create_culture = NULL;
4455 MonoImage *image = assembly->assembly->image;
4458 MONO_ARCH_SAVE_REGS;
4460 if (!System_Reflection_AssemblyName)
4461 System_Reflection_AssemblyName = mono_class_from_name (
4462 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4464 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4467 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4469 if (count > 0 && !create_culture) {
4470 MonoMethodDesc *desc = mono_method_desc_new (
4471 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4472 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4473 g_assert (create_culture);
4474 mono_method_desc_free (desc);
4477 for (i = 0; i < count; i++) {
4478 MonoReflectionAssemblyName *aname;
4479 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4481 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4483 aname = (MonoReflectionAssemblyName *) mono_object_new (
4484 domain, System_Reflection_AssemblyName);
4486 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4488 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4489 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4490 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4491 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4492 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4493 aname->versioncompat = 1; /* SameMachine (default) */
4494 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4495 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4497 if (create_culture) {
4499 MonoBoolean assembly_ref = 1;
4500 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4501 args [1] = &assembly_ref;
4502 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4505 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4506 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4507 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4509 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4510 /* public key token isn't copied - the class library will
4511 automatically generate it from the public key if required */
4512 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4513 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4515 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4516 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4519 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4522 /* note: this function doesn't return the codebase on purpose (i.e. it can
4523 be used under partial trust as path information isn't present). */
4525 mono_array_setref (result, i, aname);
4536 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4538 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4540 mono_array_setref (info->res, info->idx, name);
4545 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4547 MonoImage *img = assembly->assembly->image;
4552 MONO_ARCH_SAVE_REGS;
4554 mono_image_lock (img);
4555 mono_image_init_name_cache (img);
4558 len = g_hash_table_size (img->name_cache);
4559 mono_image_unlock (img);
4561 /*we can't create objects holding the image lock */
4562 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4564 mono_image_lock (img);
4565 /*len might have changed, create a new array*/
4566 if (len != g_hash_table_size (img->name_cache))
4571 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4572 mono_image_unlock (img);
4577 /* move this in some file in mono/util/ */
4579 g_concat_dir_and_file (const char *dir, const char *file)
4581 g_return_val_if_fail (dir != NULL, NULL);
4582 g_return_val_if_fail (file != NULL, NULL);
4585 * If the directory name doesn't have a / on the end, we need
4586 * to add one so we get a proper path to the file
4588 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4589 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4591 return g_strconcat (dir, file, NULL);
4595 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4597 char *n = mono_string_to_utf8 (name);
4598 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4600 guint32 cols [MONO_MANIFEST_SIZE];
4601 guint32 impl, file_idx;
4605 MONO_ARCH_SAVE_REGS;
4607 for (i = 0; i < table->rows; ++i) {
4608 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4609 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4610 if (strcmp (val, n) == 0)
4614 if (i == table->rows)
4617 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4620 * this code should only be called after obtaining the
4621 * ResourceInfo and handling the other cases.
4623 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4624 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4626 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4631 module = assembly->assembly->image;
4633 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4635 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4639 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4641 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4643 guint32 cols [MONO_MANIFEST_SIZE];
4644 guint32 file_cols [MONO_FILE_SIZE];
4648 MONO_ARCH_SAVE_REGS;
4650 n = mono_string_to_utf8 (name);
4651 for (i = 0; i < table->rows; ++i) {
4652 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4653 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4654 if (strcmp (val, n) == 0)
4658 if (i == table->rows)
4661 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4662 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4665 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4666 case MONO_IMPLEMENTATION_FILE:
4667 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4668 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4669 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4670 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4671 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4672 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4675 info->location = RESOURCE_LOCATION_EMBEDDED;
4678 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4679 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4680 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4681 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4682 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4683 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4685 mono_raise_exception (ex);
4687 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4689 /* Obtain info recursively */
4690 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4691 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4694 case MONO_IMPLEMENTATION_EXP_TYPE:
4695 g_assert_not_reached ();
4704 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4706 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4707 MonoArray *result = NULL;
4712 MONO_ARCH_SAVE_REGS;
4714 /* check hash if needed */
4716 n = mono_string_to_utf8 (name);
4717 for (i = 0; i < table->rows; ++i) {
4718 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4719 if (strcmp (val, n) == 0) {
4722 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4723 fn = mono_string_new (mono_object_domain (assembly), n);
4725 return (MonoObject*)fn;
4733 for (i = 0; i < table->rows; ++i) {
4734 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4738 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4741 for (i = 0; i < table->rows; ++i) {
4742 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4743 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4744 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4745 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4750 return (MonoObject*)result;
4754 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4756 MonoDomain *domain = mono_domain_get();
4759 int i, j, file_count = 0;
4760 MonoImage **modules;
4761 guint32 module_count, real_module_count;
4762 MonoTableInfo *table;
4763 guint32 cols [MONO_FILE_SIZE];
4764 MonoImage *image = assembly->assembly->image;
4766 g_assert (image != NULL);
4767 g_assert (!assembly->assembly->dynamic);
4769 table = &image->tables [MONO_TABLE_FILE];
4770 file_count = table->rows;
4772 modules = image->modules;
4773 module_count = image->module_count;
4775 real_module_count = 0;
4776 for (i = 0; i < module_count; ++i)
4778 real_module_count ++;
4780 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4781 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4783 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4785 for (i = 0; i < module_count; ++i)
4787 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4791 for (i = 0; i < file_count; ++i, ++j) {
4792 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4793 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4794 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4796 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4798 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4799 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4801 mono_array_setref (res, j, mono_module_get_object (domain, m));
4808 static MonoReflectionMethod*
4809 ves_icall_GetCurrentMethod (void)
4811 MonoMethod *m = mono_method_get_last_managed ();
4813 while (m->is_inflated)
4814 m = ((MonoMethodInflated*)m)->declaring;
4816 return mono_method_get_object (mono_domain_get (), m, NULL);
4821 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4824 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4825 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4826 //method is inflated, we should inflate it on the other class
4827 MonoGenericContext ctx;
4828 ctx.method_inst = inflated->context.method_inst;
4829 ctx.class_inst = inflated->context.class_inst;
4830 if (klass->generic_class)
4831 ctx.class_inst = klass->generic_class->context.class_inst;
4832 else if (klass->generic_container)
4833 ctx.class_inst = klass->generic_container->context.class_inst;
4834 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4837 mono_class_setup_methods (method->klass);
4838 if (method->klass->exception_type)
4840 for (i = 0; i < method->klass->method.count; ++i) {
4841 if (method->klass->methods [i] == method) {
4846 mono_class_setup_methods (klass);
4847 if (klass->exception_type)
4849 g_assert (offset >= 0 && offset < klass->method.count);
4850 return klass->methods [offset];
4853 static MonoReflectionMethod*
4854 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4858 klass = mono_class_from_mono_type (type);
4859 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4861 if (method->klass != klass) {
4862 method = mono_method_get_equivalent_method (method, klass);
4867 klass = method->klass;
4868 return mono_method_get_object (mono_domain_get (), method, klass);
4871 static MonoReflectionMethod*
4872 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4874 return mono_method_get_object (mono_domain_get (), method, NULL);
4877 static MonoReflectionMethodBody*
4878 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4880 return mono_method_body_get_object (mono_domain_get (), method);
4883 static MonoReflectionAssembly*
4884 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4886 MonoMethod *dest = NULL;
4888 MONO_ARCH_SAVE_REGS;
4890 mono_stack_walk_no_il (get_executing, &dest);
4891 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4895 static MonoReflectionAssembly*
4896 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4898 MonoDomain* domain = mono_domain_get ();
4900 MONO_ARCH_SAVE_REGS;
4902 if (!domain->entry_assembly)
4905 return mono_assembly_get_object (domain, domain->entry_assembly);
4908 static MonoReflectionAssembly*
4909 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4914 MONO_ARCH_SAVE_REGS;
4917 mono_stack_walk_no_il (get_executing, &dest);
4919 mono_stack_walk_no_il (get_caller, &dest);
4922 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4926 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4927 gboolean assembly_qualified)
4929 MonoDomain *domain = mono_object_domain (object);
4930 MonoTypeNameFormat format;
4935 format = assembly_qualified ?
4936 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4937 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4939 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4941 name = mono_type_get_name_full (object->type, format);
4945 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4950 res = mono_string_new (domain, name);
4957 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4959 MonoClass *klass = mono_class_from_mono_type (this->type);
4960 mono_class_init_or_throw (klass);
4961 return mono_security_core_clr_class_level (klass);
4965 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4967 static MonoMethod *create_culture = NULL;
4970 const char *pkey_ptr;
4972 MonoBoolean assembly_ref = 0;
4974 MONO_ARCH_SAVE_REGS;
4976 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4977 aname->major = name->major;
4978 aname->minor = name->minor;
4979 aname->build = name->build;
4980 aname->flags = name->flags;
4981 aname->revision = name->revision;
4982 aname->hashalg = name->hash_alg;
4983 aname->versioncompat = 1; /* SameMachine (default) */
4984 aname->processor_architecture = name->arch;
4986 if (by_default_version)
4987 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4990 if (absolute != NULL && *absolute != '\0') {
4991 const gchar *prepend = "file://";
4994 codebase = g_strdup (absolute);
4999 for (i = strlen (codebase) - 1; i >= 0; i--)
5000 if (codebase [i] == '\\')
5003 if (*codebase == '/' && *(codebase + 1) == '/') {
5006 prepend = "file:///";
5010 result = g_strconcat (prepend, codebase, NULL);
5016 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5020 if (!create_culture) {
5021 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5022 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5023 g_assert (create_culture);
5024 mono_method_desc_free (desc);
5027 if (name->culture) {
5028 args [0] = mono_string_new (domain, name->culture);
5029 args [1] = &assembly_ref;
5030 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5033 if (name->public_key) {
5034 pkey_ptr = (char*)name->public_key;
5035 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5037 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5038 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5039 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5040 } else if (default_publickey) {
5041 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5042 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5045 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5046 if (name->public_key_token [0]) {
5050 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5051 p = mono_array_addr (aname->keyToken, char, 0);
5053 for (i = 0, j = 0; i < 8; i++) {
5054 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5055 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5058 } else if (default_token) {
5059 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5064 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5066 MonoDomain *domain = mono_object_domain (assembly);
5067 MonoAssembly *mass = assembly->assembly;
5071 name = mono_stringify_assembly_name (&mass->aname);
5072 res = mono_string_new (domain, name);
5079 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5082 MonoAssembly *mass = assembly->assembly;
5084 MONO_ARCH_SAVE_REGS;
5086 if (g_path_is_absolute (mass->image->name)) {
5087 fill_reflection_assembly_name (mono_object_domain (assembly),
5088 aname, &mass->aname, mass->image->name, TRUE,
5092 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5094 fill_reflection_assembly_name (mono_object_domain (assembly),
5095 aname, &mass->aname, absolute, TRUE, TRUE,
5102 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5105 MonoImageOpenStatus status = MONO_IMAGE_OK;
5108 MonoAssemblyName name;
5111 MONO_ARCH_SAVE_REGS;
5113 filename = mono_string_to_utf8 (fname);
5115 dirname = g_path_get_dirname (filename);
5116 replace_shadow_path (mono_domain_get (), dirname, &filename);
5119 image = mono_image_open (filename, &status);
5125 if (status == MONO_IMAGE_IMAGE_INVALID)
5126 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5128 exc = mono_get_exception_file_not_found2 (NULL, fname);
5129 mono_raise_exception (exc);
5132 res = mono_assembly_fill_assembly_name (image, &name);
5134 mono_image_close (image);
5136 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5139 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5143 mono_image_close (image);
5147 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5148 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5150 MonoBoolean result = FALSE;
5151 MonoDeclSecurityEntry entry;
5153 /* SecurityAction.RequestMinimum */
5154 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5155 *minimum = entry.blob;
5156 *minLength = entry.size;
5159 /* SecurityAction.RequestOptional */
5160 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5161 *optional = entry.blob;
5162 *optLength = entry.size;
5165 /* SecurityAction.RequestRefuse */
5166 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5167 *refused = entry.blob;
5168 *refLength = entry.size;
5176 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5180 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5182 guint32 attrs, visibility;
5184 /* we start the count from 1 because we skip the special type <Module> */
5187 for (i = 1; i < tdef->rows; ++i) {
5188 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5189 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5190 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5194 count = tdef->rows - 1;
5196 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5197 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5199 for (i = 1; i < tdef->rows; ++i) {
5200 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5201 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5202 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5203 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5205 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5207 MonoLoaderError *error;
5210 error = mono_loader_get_last_error ();
5211 g_assert (error != NULL);
5213 ex = mono_loader_error_prepare_exception (error);
5214 mono_array_setref (*exceptions, count, ex);
5216 if (mono_loader_get_last_error ())
5217 mono_loader_clear_error ();
5226 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5228 MonoArray *res = NULL;
5229 MonoArray *exceptions = NULL;
5230 MonoImage *image = NULL;
5231 MonoTableInfo *table = NULL;
5234 int i, len, ex_count;
5236 MONO_ARCH_SAVE_REGS;
5238 domain = mono_object_domain (assembly);
5240 g_assert (!assembly->assembly->dynamic);
5241 image = assembly->assembly->image;
5242 table = &image->tables [MONO_TABLE_FILE];
5243 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5245 /* Append data from all modules in the assembly */
5246 for (i = 0; i < table->rows; ++i) {
5247 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5248 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5251 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5252 /* Append the new types to the end of the array */
5253 if (mono_array_length (res2) > 0) {
5255 MonoArray *res3, *ex3;
5257 len1 = mono_array_length (res);
5258 len2 = mono_array_length (res2);
5260 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5261 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5262 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5265 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5266 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5267 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5274 /* the ReflectionTypeLoadException must have all the types (Types property),
5275 * NULL replacing types which throws an exception. The LoaderException must
5276 * contain all exceptions for NULL items.
5279 len = mono_array_length (res);
5282 for (i = 0; i < len; i++) {
5283 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5287 klass = mono_type_get_class (t->type);
5288 if ((klass != NULL) && klass->exception_type) {
5289 /* keep the class in the list */
5290 list = g_list_append (list, klass);
5291 /* and replace Type with NULL */
5292 mono_array_setref (res, i, NULL);
5299 if (list || ex_count) {
5301 MonoException *exc = NULL;
5302 MonoArray *exl = NULL;
5303 int j, length = g_list_length (list) + ex_count;
5305 mono_loader_clear_error ();
5307 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5308 /* Types for which mono_class_get () succeeded */
5309 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5310 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5311 mono_array_setref (exl, i, exc);
5313 /* Types for which it don't */
5314 for (j = 0; j < mono_array_length (exceptions); ++j) {
5315 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5317 g_assert (i < length);
5318 mono_array_setref (exl, i, exc);
5325 exc = mono_get_exception_reflection_type_load (res, exl);
5326 mono_loader_clear_error ();
5327 mono_raise_exception (exc);
5334 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5336 MonoAssemblyName aname;
5337 MonoDomain *domain = mono_object_domain (name);
5339 gboolean is_version_defined;
5340 gboolean is_token_defined;
5342 aname.public_key = NULL;
5343 val = mono_string_to_utf8 (assname);
5344 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5345 g_free ((guint8*) aname.public_key);
5350 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5351 FALSE, is_token_defined);
5353 mono_assembly_name_free (&aname);
5354 g_free ((guint8*) aname.public_key);
5360 static MonoReflectionType*
5361 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5363 MonoDomain *domain = mono_object_domain (module);
5366 MONO_ARCH_SAVE_REGS;
5368 g_assert (module->image);
5370 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5371 /* These images do not have a global type */
5374 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5375 return mono_type_get_object (domain, &klass->byval_arg);
5379 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5381 /*if (module->image)
5382 mono_image_close (module->image);*/
5386 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5388 MonoDomain *domain = mono_object_domain (module);
5390 MONO_ARCH_SAVE_REGS;
5392 g_assert (module->image);
5393 return mono_string_new (domain, module->image->guid);
5397 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5400 if (module->image && module->image->is_module_handle)
5401 return module->image->raw_data;
5404 return (gpointer) (-1);
5408 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5410 if (image->dynamic) {
5411 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5412 *pe_kind = dyn->pe_kind;
5413 *machine = dyn->machine;
5416 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5417 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5422 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5424 return (image->md_version_major << 16) | (image->md_version_minor);
5428 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5430 MonoArray *exceptions;
5433 MONO_ARCH_SAVE_REGS;
5436 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5438 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5439 for (i = 0; i < mono_array_length (exceptions); ++i) {
5440 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5442 mono_raise_exception (ex);
5449 mono_memberref_is_method (MonoImage *image, guint32 token)
5451 if (!image->dynamic) {
5452 guint32 cols [MONO_MEMBERREF_SIZE];
5454 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5455 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5456 mono_metadata_decode_blob_size (sig, &sig);
5457 return (*sig != 0x6);
5459 MonoClass *handle_class;
5461 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5464 return mono_defaults.methodhandle_class == handle_class;
5469 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5472 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5473 mono_array_addr (type_args, MonoType*, 0));
5475 context->class_inst = NULL;
5477 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5478 mono_array_addr (method_args, MonoType*, 0));
5480 context->method_inst = NULL;
5484 ves_icall_System_Reflection_Module_ResolveTypeToken (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;
5491 *error = ResolveTokenError_Other;
5493 /* Validate token */
5494 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5495 (table != MONO_TABLE_TYPESPEC)) {
5496 *error = ResolveTokenError_BadTable;
5500 if (image->dynamic) {
5501 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5502 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5503 return klass ? &klass->byval_arg : NULL;
5506 init_generic_context_from_args (&context, type_args, method_args);
5507 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5508 return klass ? &klass->byval_arg : NULL;
5511 if ((index <= 0) || (index > image->tables [table].rows)) {
5512 *error = ResolveTokenError_OutOfRange;
5516 init_generic_context_from_args (&context, type_args, method_args);
5517 klass = mono_class_get_full (image, token, &context);
5519 if (mono_loader_get_last_error ())
5520 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5523 return &klass->byval_arg;
5529 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5531 int table = mono_metadata_token_table (token);
5532 int index = mono_metadata_token_index (token);
5533 MonoGenericContext context;
5536 *error = ResolveTokenError_Other;
5538 /* Validate token */
5539 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5540 (table != MONO_TABLE_MEMBERREF)) {
5541 *error = ResolveTokenError_BadTable;
5545 if (image->dynamic) {
5546 if (table == MONO_TABLE_METHOD)
5547 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5549 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5550 *error = ResolveTokenError_BadTable;
5554 init_generic_context_from_args (&context, type_args, method_args);
5555 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5558 if ((index <= 0) || (index > image->tables [table].rows)) {
5559 *error = ResolveTokenError_OutOfRange;
5562 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5563 *error = ResolveTokenError_BadTable;
5567 init_generic_context_from_args (&context, type_args, method_args);
5568 method = mono_get_method_full (image, token, NULL, &context);
5570 if (mono_loader_get_last_error ())
5571 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5577 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5579 int index = mono_metadata_token_index (token);
5581 *error = ResolveTokenError_Other;
5583 /* Validate token */
5584 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5585 *error = ResolveTokenError_BadTable;
5590 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5592 if ((index <= 0) || (index >= image->heap_us.size)) {
5593 *error = ResolveTokenError_OutOfRange;
5597 /* FIXME: What to do if the index points into the middle of a string ? */
5599 return mono_ldstr (mono_domain_get (), image, index);
5602 static MonoClassField*
5603 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5606 int table = mono_metadata_token_table (token);
5607 int index = mono_metadata_token_index (token);
5608 MonoGenericContext context;
5609 MonoClassField *field;
5611 *error = ResolveTokenError_Other;
5613 /* Validate token */
5614 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5615 *error = ResolveTokenError_BadTable;
5619 if (image->dynamic) {
5620 if (table == MONO_TABLE_FIELD)
5621 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5623 if (mono_memberref_is_method (image, token)) {
5624 *error = ResolveTokenError_BadTable;
5628 init_generic_context_from_args (&context, type_args, method_args);
5629 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5632 if ((index <= 0) || (index > image->tables [table].rows)) {
5633 *error = ResolveTokenError_OutOfRange;
5636 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5637 *error = ResolveTokenError_BadTable;
5641 init_generic_context_from_args (&context, type_args, method_args);
5642 field = mono_field_from_token (image, token, &klass, &context);
5644 if (mono_loader_get_last_error ())
5645 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5652 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5654 int table = mono_metadata_token_table (token);
5656 *error = ResolveTokenError_Other;
5659 case MONO_TABLE_TYPEDEF:
5660 case MONO_TABLE_TYPEREF:
5661 case MONO_TABLE_TYPESPEC: {
5662 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5664 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5668 case MONO_TABLE_METHOD:
5669 case MONO_TABLE_METHODSPEC: {
5670 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5672 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5676 case MONO_TABLE_FIELD: {
5677 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5679 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5683 case MONO_TABLE_MEMBERREF:
5684 if (mono_memberref_is_method (image, token)) {
5685 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5687 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5692 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5694 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5701 *error = ResolveTokenError_BadTable;
5708 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5710 int table = mono_metadata_token_table (token);
5711 int idx = mono_metadata_token_index (token);
5712 MonoTableInfo *tables = image->tables;
5717 *error = ResolveTokenError_OutOfRange;
5719 /* FIXME: Support other tables ? */
5720 if (table != MONO_TABLE_STANDALONESIG)
5726 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5729 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5731 ptr = mono_metadata_blob_heap (image, sig);
5732 len = mono_metadata_decode_blob_size (ptr, &ptr);
5734 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5735 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5739 static MonoReflectionType*
5740 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5743 int isbyref = 0, rank;
5744 char *str = mono_string_to_utf8 (smodifiers);
5747 MONO_ARCH_SAVE_REGS;
5749 klass = mono_class_from_mono_type (tb->type.type);
5751 /* logic taken from mono_reflection_parse_type(): keep in sync */
5755 if (isbyref) { /* only one level allowed by the spec */
5762 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5765 klass = mono_ptr_class_get (&klass->byval_arg);
5766 mono_class_init (klass);
5777 else if (*p != '*') { /* '*' means unknown lower bound */
5788 klass = mono_array_class_get (klass, rank);
5789 mono_class_init (klass);
5796 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5800 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5805 MONO_ARCH_SAVE_REGS;
5808 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5814 check_for_invalid_type (MonoClass *klass)
5818 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5821 name = mono_type_get_full_name (klass);
5822 str = mono_string_new (mono_domain_get (), name);
5824 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5827 static MonoReflectionType *
5828 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5830 MonoClass *klass, *aklass;
5832 MONO_ARCH_SAVE_REGS;
5834 klass = mono_class_from_mono_type (type->type);
5835 check_for_invalid_type (klass);
5837 if (rank == 0) //single dimentional array
5838 aklass = mono_array_class_get (klass, 1);
5840 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5842 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5845 static MonoReflectionType *
5846 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5850 MONO_ARCH_SAVE_REGS;
5852 klass = mono_class_from_mono_type (type->type);
5853 mono_class_init_or_throw (klass);
5854 check_for_invalid_type (klass);
5856 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5859 static MonoReflectionType *
5860 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5862 MonoClass *klass, *pklass;
5864 klass = mono_class_from_mono_type (type->type);
5865 mono_class_init_or_throw (klass);
5866 check_for_invalid_type (klass);
5868 pklass = mono_ptr_class_get (type->type);
5870 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5874 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5875 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5877 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5878 MonoObject *delegate;
5880 MonoMethod *method = info->method;
5882 MONO_ARCH_SAVE_REGS;
5884 mono_class_init_or_throw (delegate_class);
5886 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5888 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5889 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5893 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5895 if (method->dynamic) {
5896 /* Creating a trampoline would leak memory */
5897 func = mono_compile_method (method);
5899 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5900 method = mono_object_get_virtual_method (target, method);
5901 func = mono_create_ftnptr (mono_domain_get (),
5902 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5905 mono_delegate_ctor_with_method (delegate, target, func, method);
5911 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5913 /* Reset the invoke impl to the default one */
5914 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5918 * Magic number to convert a time which is relative to
5919 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5921 #define EPOCH_ADJUST ((guint64)62135596800LL)
5924 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5926 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5929 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5931 convert_to_absolute_date(SYSTEMTIME *date)
5933 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5934 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5935 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5936 /* from the calendar FAQ */
5937 int a = (14 - date->wMonth) / 12;
5938 int y = date->wYear - a;
5939 int m = date->wMonth + 12 * a - 2;
5940 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5942 /* d is now the day of the week for the first of the month (0 == Sunday) */
5944 int day_of_week = date->wDayOfWeek;
5946 /* set day_in_month to the first day in the month which falls on day_of_week */
5947 int day_in_month = 1 + (day_of_week - d);
5948 if (day_in_month <= 0)
5951 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5952 date->wDay = day_in_month + (date->wDay - 1) * 7;
5953 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5960 * Return's the offset from GMT of a local time.
5962 * tm is a local time
5963 * t is the same local time as seconds.
5966 gmt_offset(struct tm *tm, time_t t)
5968 #if defined (HAVE_TM_GMTOFF)
5969 return tm->tm_gmtoff;
5974 g.tm_isdst = tm->tm_isdst;
5976 return (int)difftime(t, t2);
5981 * This is heavily based on zdump.c from glibc 2.2.
5983 * * data[0]: start of daylight saving time (in DateTime ticks).
5984 * * data[1]: end of daylight saving time (in DateTime ticks).
5985 * * data[2]: utcoffset (in TimeSpan ticks).
5986 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5987 * * name[0]: name of this timezone when not daylight saving.
5988 * * name[1]: name of this timezone when daylight saving.
5990 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5991 * the class library allows years between 1 and 9999.
5993 * Returns true on success and zero on failure.
5996 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5999 MonoDomain *domain = mono_domain_get ();
6000 struct tm start, tt;
6004 int is_daylight = 0, day;
6007 MONO_ARCH_SAVE_REGS;
6009 MONO_CHECK_ARG_NULL (data);
6010 MONO_CHECK_ARG_NULL (names);
6012 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
6013 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
6016 * no info is better than crashing: we'll need our own tz data
6017 * to make this work properly, anyway. The range is probably
6018 * reduced to 1970 .. 2037 because that is what mktime is
6019 * guaranteed to support (we get into an infinite loop
6023 memset (&start, 0, sizeof (start));
6026 start.tm_year = year-1900;
6028 t = mktime (&start);
6030 if ((year < 1970) || (year > 2037) || (t == -1)) {
6032 tt = *localtime (&t);
6033 strftime (tzone, sizeof (tzone), "%Z", &tt);
6034 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6035 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6039 gmtoff = gmt_offset (&start, t);
6041 /* For each day of the year, calculate the tm_gmtoff. */
6042 for (day = 0; day < 365; day++) {
6045 tt = *localtime (&t);
6047 /* Daylight saving starts or ends here. */
6048 if (gmt_offset (&tt, t) != gmtoff) {
6052 /* Try to find the exact hour when daylight saving starts/ends. */
6056 tt1 = *localtime (&t1);
6057 } while (gmt_offset (&tt1, t1) != gmtoff);
6059 /* Try to find the exact minute when daylight saving starts/ends. */
6062 tt1 = *localtime (&t1);
6063 } while (gmt_offset (&tt1, t1) == gmtoff);
6065 strftime (tzone, sizeof (tzone), "%Z", &tt);
6067 /* Write data, if we're already in daylight saving, we're done. */
6069 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6070 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6073 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6074 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6078 /* This is only set once when we enter daylight saving. */
6079 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6080 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6082 gmtoff = gmt_offset (&tt, t);
6087 strftime (tzone, sizeof (tzone), "%Z", &tt);
6088 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6089 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6090 mono_array_set ((*data), gint64, 0, 0);
6091 mono_array_set ((*data), gint64, 1, 0);
6092 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6093 mono_array_set ((*data), gint64, 3, 0);
6098 MonoDomain *domain = mono_domain_get ();
6099 TIME_ZONE_INFORMATION tz_info;
6104 tz_id = GetTimeZoneInformation (&tz_info);
6105 if (tz_id == TIME_ZONE_ID_INVALID)
6108 MONO_CHECK_ARG_NULL (data);
6109 MONO_CHECK_ARG_NULL (names);
6111 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6112 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6114 for (i = 0; i < 32; ++i)
6115 if (!tz_info.DaylightName [i])
6117 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6118 for (i = 0; i < 32; ++i)
6119 if (!tz_info.StandardName [i])
6121 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6123 if ((year <= 1601) || (year > 30827)) {
6125 * According to MSDN, the MS time functions can't handle dates outside
6131 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6132 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6133 tz_info.StandardDate.wYear = year;
6134 convert_to_absolute_date(&tz_info.StandardDate);
6135 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6140 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6141 tz_info.DaylightDate.wYear = year;
6142 convert_to_absolute_date(&tz_info.DaylightDate);
6143 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6148 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6150 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6151 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6158 ves_icall_System_Object_obj_address (MonoObject *this)
6160 MONO_ARCH_SAVE_REGS;
6167 static inline gint32
6168 mono_array_get_byte_length (MonoArray *array)
6174 klass = array->obj.vtable->klass;
6176 if (array->bounds == NULL)
6177 length = array->max_length;
6180 for (i = 0; i < klass->rank; ++ i)
6181 length *= array->bounds [i].length;
6184 switch (klass->element_class->byval_arg.type) {
6187 case MONO_TYPE_BOOLEAN:
6191 case MONO_TYPE_CHAR:
6199 return length * sizeof (gpointer);
6210 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6212 MONO_ARCH_SAVE_REGS;
6214 return mono_array_get_byte_length (array);
6218 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6220 MONO_ARCH_SAVE_REGS;
6222 return mono_array_get (array, gint8, idx);
6226 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6228 MONO_ARCH_SAVE_REGS;
6230 mono_array_set (array, gint8, idx, value);
6234 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6236 guint8 *src_buf, *dest_buf;
6238 MONO_ARCH_SAVE_REGS;
6240 /* watch out for integer overflow */
6241 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6244 src_buf = (guint8 *)src->vector + src_offset;
6245 dest_buf = (guint8 *)dest->vector + dest_offset;
6248 memcpy (dest_buf, src_buf, count);
6250 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6256 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6258 MonoDomain *domain = mono_object_domain (this);
6260 MonoRealProxy *rp = ((MonoRealProxy *)this);
6261 MonoTransparentProxy *tp;
6265 MONO_ARCH_SAVE_REGS;
6267 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6268 tp = (MonoTransparentProxy*) res;
6270 MONO_OBJECT_SETREF (tp, rp, rp);
6271 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6272 klass = mono_class_from_mono_type (type);
6274 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6275 tp->remote_class = mono_remote_class (domain, class_name, klass);
6277 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6281 static MonoReflectionType *
6282 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6284 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6287 /* System.Environment */
6290 ves_icall_System_Environment_get_UserName (void)
6292 MONO_ARCH_SAVE_REGS;
6294 /* using glib is more portable */
6295 return mono_string_new (mono_domain_get (), g_get_user_name ());
6300 ves_icall_System_Environment_get_MachineName (void)
6302 #if defined (HOST_WIN32)
6307 len = MAX_COMPUTERNAME_LENGTH + 1;
6308 buf = g_new (gunichar2, len);
6311 if (GetComputerName (buf, (PDWORD) &len))
6312 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6316 #elif !defined(DISABLE_SOCKETS)
6320 if (gethostname (buf, sizeof (buf)) == 0)
6321 result = mono_string_new (mono_domain_get (), buf);
6327 return mono_string_new (mono_domain_get (), "mono");
6332 ves_icall_System_Environment_get_Platform (void)
6334 #if defined (TARGET_WIN32)
6337 #elif defined(__MACH__)
6340 // Notice that the value is hidden from user code, and only exposed
6341 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6342 // define and making assumptions based on Unix/128/4 values before there
6343 // was a MacOS define. Lots of code would assume that not-Unix meant
6344 // Windows, but in this case, it would be OSX.
6354 ves_icall_System_Environment_get_NewLine (void)
6356 MONO_ARCH_SAVE_REGS;
6358 #if defined (HOST_WIN32)
6359 return mono_string_new (mono_domain_get (), "\r\n");
6361 return mono_string_new (mono_domain_get (), "\n");
6366 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6371 MONO_ARCH_SAVE_REGS;
6376 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6377 value = g_getenv (utf8_name);
6384 return mono_string_new (mono_domain_get (), value);
6388 * There is no standard way to get at environ.
6391 #ifndef __MINGW32_VERSION
6392 #if defined(__APPLE__) && !defined (__arm__)
6393 /* Apple defines this in crt_externs.h but doesn't provide that header for
6394 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6395 * in fact exist on all implementations (so far)
6397 gchar ***_NSGetEnviron(void);
6398 #define environ (*_NSGetEnviron())
6407 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6418 env_strings = GetEnvironmentStrings();
6421 env_string = env_strings;
6422 while (*env_string != '\0') {
6423 /* weird case that MS seems to skip */
6424 if (*env_string != '=')
6426 while (*env_string != '\0')
6432 domain = mono_domain_get ();
6433 names = mono_array_new (domain, mono_defaults.string_class, n);
6437 env_string = env_strings;
6438 while (*env_string != '\0') {
6439 /* weird case that MS seems to skip */
6440 if (*env_string != '=') {
6441 equal_str = wcschr(env_string, '=');
6442 g_assert(equal_str);
6443 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6444 mono_array_setref (names, n, str);
6447 while (*env_string != '\0')
6452 FreeEnvironmentStrings (env_strings);
6464 MONO_ARCH_SAVE_REGS;
6467 for (e = environ; *e != 0; ++ e)
6470 domain = mono_domain_get ();
6471 names = mono_array_new (domain, mono_defaults.string_class, n);
6474 for (e = environ; *e != 0; ++ e) {
6475 parts = g_strsplit (*e, "=", 2);
6477 str = mono_string_new (domain, *parts);
6478 mono_array_setref (names, n, str);
6491 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6493 #if !GLIB_CHECK_VERSION(2,4,0)
6494 #define g_setenv(a,b,c) setenv(a,b,c)
6495 #define g_unsetenv(a) unsetenv(a)
6499 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6504 gunichar2 *utf16_name, *utf16_value;
6506 gchar *utf8_name, *utf8_value;
6509 MONO_ARCH_SAVE_REGS;
6512 utf16_name = mono_string_to_utf16 (name);
6513 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6514 SetEnvironmentVariable (utf16_name, NULL);
6515 g_free (utf16_name);
6519 utf16_value = mono_string_to_utf16 (value);
6521 SetEnvironmentVariable (utf16_name, utf16_value);
6523 g_free (utf16_name);
6524 g_free (utf16_value);
6526 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6528 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6529 g_unsetenv (utf8_name);
6534 utf8_value = mono_string_to_utf8_checked (value, &error);
6535 if (!mono_error_ok (&error)) {
6537 mono_error_raise_exception (&error);
6539 g_setenv (utf8_name, utf8_value, TRUE);
6542 g_free (utf8_value);
6547 ves_icall_System_Environment_Exit (int result)
6549 MONO_ARCH_SAVE_REGS;
6551 mono_threads_set_shutting_down ();
6553 mono_runtime_set_shutting_down ();
6555 /* This will kill the tp threads which cannot be suspended */
6556 mono_thread_pool_cleanup ();
6558 /* Suspend all managed threads since the runtime is going away */
6559 mono_thread_suspend_all_other_threads ();
6561 mono_runtime_quit ();
6563 /* we may need to do some cleanup here... */
6568 ves_icall_System_Environment_GetGacPath (void)
6570 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6574 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6576 #if defined (HOST_WIN32)
6577 #ifndef CSIDL_FLAG_CREATE
6578 #define CSIDL_FLAG_CREATE 0x8000
6581 WCHAR path [MAX_PATH];
6582 /* Create directory if no existing */
6583 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6587 return mono_string_new_utf16 (mono_domain_get (), path, len);
6590 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6592 return mono_string_new (mono_domain_get (), "");
6596 ves_icall_System_Environment_GetLogicalDrives (void)
6598 gunichar2 buf [256], *ptr, *dname;
6600 guint initial_size = 127, size = 128;
6603 MonoString *drivestr;
6604 MonoDomain *domain = mono_domain_get ();
6607 MONO_ARCH_SAVE_REGS;
6612 while (size > initial_size) {
6613 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6614 if (size > initial_size) {
6617 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6618 initial_size = size;
6632 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6637 while (*u16) { u16++; len ++; }
6638 drivestr = mono_string_new_utf16 (domain, dname, len);
6639 mono_array_setref (result, ndrives++, drivestr);
6650 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6652 gunichar2 volume_name [MAX_PATH + 1];
6654 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6656 return mono_string_from_utf16 (volume_name);
6660 ves_icall_System_Environment_InternalGetHome (void)
6662 MONO_ARCH_SAVE_REGS;
6664 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6667 static const char *encodings [] = {
6669 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6670 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6671 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6673 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6674 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6675 "x_unicode_2_0_utf_7",
6677 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6678 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6680 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6683 "unicodefffe", "utf_16be",
6690 * Returns the internal codepage, if the value of "int_code_page" is
6691 * 1 at entry, and we can not compute a suitable code page number,
6692 * returns the code page as a string
6695 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6700 char *codepage = NULL;
6702 int want_name = *int_code_page;
6705 *int_code_page = -1;
6706 MONO_ARCH_SAVE_REGS;
6708 g_get_charset (&cset);
6709 c = codepage = strdup (cset);
6710 for (c = codepage; *c; c++){
6711 if (isascii (*c) && isalpha (*c))
6716 /* g_print ("charset: %s\n", cset); */
6718 /* handle some common aliases */
6721 for (i = 0; p != 0; ){
6722 if ((gssize) p < 7){
6724 p = encodings [++i];
6727 if (strcmp (p, codepage) == 0){
6728 *int_code_page = code;
6731 p = encodings [++i];
6734 if (strstr (codepage, "utf_8") != NULL)
6735 *int_code_page |= 0x10000000;
6738 if (want_name && *int_code_page == -1)
6739 return mono_string_new (mono_domain_get (), cset);
6745 ves_icall_System_Environment_get_HasShutdownStarted (void)
6747 if (mono_runtime_is_shutting_down ())
6750 if (mono_domain_is_unloading (mono_domain_get ()))
6757 ves_icall_System_Environment_BroadcastSettingChange (void)
6760 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6765 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6766 MonoReflectionMethod *method,
6767 MonoArray *out_args)
6769 MONO_ARCH_SAVE_REGS;
6771 mono_message_init (mono_object_domain (this), this, method, out_args);
6775 ves_icall_IsTransparentProxy (MonoObject *proxy)
6777 MONO_ARCH_SAVE_REGS;
6782 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6788 static MonoReflectionMethod *
6789 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6790 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6794 MonoMethod **vtable;
6795 MonoMethod *res = NULL;
6797 MONO_CHECK_ARG_NULL (rtype);
6798 MONO_CHECK_ARG_NULL (rmethod);
6800 method = rmethod->method;
6801 klass = mono_class_from_mono_type (rtype->type);
6802 mono_class_init_or_throw (klass);
6804 if (MONO_CLASS_IS_INTERFACE (klass))
6807 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6810 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6811 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6817 mono_class_setup_vtable (klass);
6818 vtable = klass->vtable;
6820 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6821 gboolean variance_used = FALSE;
6822 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6823 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6825 res = vtable [offs + method->slot];
6827 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6830 if (method->slot != -1)
6831 res = vtable [method->slot];
6837 return mono_method_get_object (mono_domain_get (), res, NULL);
6841 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6846 MONO_ARCH_SAVE_REGS;
6848 klass = mono_class_from_mono_type (type->type);
6849 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6851 if (enable) vtable->remote = 1;
6852 else vtable->remote = 0;
6856 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6861 MONO_ARCH_SAVE_REGS;
6863 domain = mono_object_domain (type);
6864 klass = mono_class_from_mono_type (type->type);
6865 mono_class_init_or_throw (klass);
6867 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6868 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6870 if (klass->rank >= 1) {
6871 g_assert (klass->rank == 1);
6872 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6874 /* Bypass remoting object creation check */
6875 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6880 ves_icall_System_IO_get_temp_path (void)
6882 MONO_ARCH_SAVE_REGS;
6884 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6887 #ifndef PLATFORM_NO_DRIVEINFO
6889 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6890 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6894 ULARGE_INTEGER wapi_free_bytes_avail;
6895 ULARGE_INTEGER wapi_total_number_of_bytes;
6896 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6898 MONO_ARCH_SAVE_REGS;
6900 *error = ERROR_SUCCESS;
6901 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6902 &wapi_total_number_of_free_bytes);
6905 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6906 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6907 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6909 *free_bytes_avail = 0;
6910 *total_number_of_bytes = 0;
6911 *total_number_of_free_bytes = 0;
6912 *error = GetLastError ();
6919 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6921 MONO_ARCH_SAVE_REGS;
6923 return GetDriveType (mono_string_chars (root_path_name));
6928 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6930 MONO_ARCH_SAVE_REGS;
6932 return mono_compile_method (method);
6936 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6941 MONO_ARCH_SAVE_REGS;
6943 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6945 #if defined (HOST_WIN32)
6946 /* Avoid mixing '/' and '\\' */
6949 for (i = strlen (path) - 1; i >= 0; i--)
6950 if (path [i] == '/')
6954 mcpath = mono_string_new (mono_domain_get (), path);
6961 get_bundled_app_config (void)
6963 const gchar *app_config;
6966 gchar *config_file_name, *config_file_path;
6970 MONO_ARCH_SAVE_REGS;
6972 domain = mono_domain_get ();
6973 file = domain->setup->configuration_file;
6977 // Retrieve config file and remove the extension
6978 config_file_name = mono_string_to_utf8 (file);
6979 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6980 if (!config_file_path)
6981 config_file_path = config_file_name;
6982 len = strlen (config_file_path) - strlen (".config");
6983 module = g_malloc0 (len + 1);
6984 memcpy (module, config_file_path, len);
6985 // Get the config file from the module name
6986 app_config = mono_config_string_for_assembly_file (module);
6989 if (config_file_name != config_file_path)
6990 g_free (config_file_name);
6991 g_free (config_file_path);
6996 return mono_string_new (mono_domain_get (), app_config);
7000 get_bundled_machine_config (void)
7002 const gchar *machine_config;
7004 MONO_ARCH_SAVE_REGS;
7006 machine_config = mono_get_machine_config ();
7008 if (!machine_config)
7011 return mono_string_new (mono_domain_get (), machine_config);
7015 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7020 MONO_ARCH_SAVE_REGS;
7022 path = g_path_get_dirname (mono_get_config_dir ());
7024 #if defined (HOST_WIN32)
7025 /* Avoid mixing '/' and '\\' */
7028 for (i = strlen (path) - 1; i >= 0; i--)
7029 if (path [i] == '/')
7033 ipath = mono_string_new (mono_domain_get (), path);
7040 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7042 MonoPEResourceDataEntry *entry;
7045 MONO_ARCH_SAVE_REGS;
7047 if (!assembly || !result || !size)
7052 image = assembly->assembly->image;
7053 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7057 *result = mono_image_rva_map (image, entry->rde_data_offset);
7062 *size = entry->rde_size;
7068 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7070 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7074 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7076 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7077 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7083 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7085 if (mono_get_runtime_callbacks ()->debug_log)
7086 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7090 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7092 #if defined (HOST_WIN32)
7093 OutputDebugString (mono_string_chars (message));
7095 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7099 /* Only used for value types */
7101 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7106 MONO_ARCH_SAVE_REGS;
7108 domain = mono_object_domain (type);
7109 klass = mono_class_from_mono_type (type->type);
7110 mono_class_init_or_throw (klass);
7112 if (mono_class_is_nullable (klass))
7113 /* No arguments -> null */
7116 return mono_object_new (domain, klass);
7119 static MonoReflectionMethod *
7120 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7122 MonoClass *klass, *parent;
7123 MonoMethod *method = m->method;
7124 MonoMethod *result = NULL;
7127 MONO_ARCH_SAVE_REGS;
7129 if (method->klass == NULL)
7132 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7133 MONO_CLASS_IS_INTERFACE (method->klass) ||
7134 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7137 slot = mono_method_get_vtable_slot (method);
7141 klass = method->klass;
7142 if (klass->generic_class)
7143 klass = klass->generic_class->container_class;
7146 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7147 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7148 mono_class_setup_vtable (parent);
7149 if (parent->vtable_size <= slot)
7154 klass = klass->parent;
7159 if (klass == method->klass)
7162 /*This is possible if definition == FALSE.
7163 * Do it here to be really sure we don't read invalid memory.
7165 if (slot >= klass->vtable_size)
7168 mono_class_setup_vtable (klass);
7170 result = klass->vtable [slot];
7171 if (result == NULL) {
7172 /* It is an abstract method */
7173 gpointer iter = NULL;
7174 while ((result = mono_class_get_methods (klass, &iter)))
7175 if (result->slot == slot)
7182 return mono_method_get_object (mono_domain_get (), result, NULL);
7186 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7188 MonoMethod *method = m->method;
7190 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7195 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7197 MONO_ARCH_SAVE_REGS;
7199 iter->sig = *(MonoMethodSignature**)argsp;
7201 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7202 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7205 /* FIXME: it's not documented what start is exactly... */
7209 iter->args = argsp + sizeof (gpointer);
7211 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7213 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7217 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7219 guint32 i, arg_size;
7222 MONO_ARCH_SAVE_REGS;
7224 i = iter->sig->sentinelpos + iter->next_arg;
7226 g_assert (i < iter->sig->param_count);
7228 res.type = iter->sig->params [i];
7229 res.klass = mono_class_from_mono_type (res.type);
7230 arg_size = mono_type_stack_size (res.type, &align);
7231 #if defined(__arm__)
7232 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7234 res.value = iter->args;
7235 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7236 if (arg_size <= sizeof (gpointer)) {
7238 int padding = arg_size - mono_type_size (res.type, &dummy);
7239 res.value = (guint8*)res.value + padding;
7242 iter->args = (char*)iter->args + arg_size;
7245 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7251 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7253 guint32 i, arg_size;
7256 MONO_ARCH_SAVE_REGS;
7258 i = iter->sig->sentinelpos + iter->next_arg;
7260 g_assert (i < iter->sig->param_count);
7262 while (i < iter->sig->param_count) {
7263 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7265 res.type = iter->sig->params [i];
7266 res.klass = mono_class_from_mono_type (res.type);
7267 /* FIXME: endianess issue... */
7268 arg_size = mono_type_stack_size (res.type, &align);
7269 #if defined(__arm__)
7270 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7272 res.value = iter->args;
7273 iter->args = (char*)iter->args + arg_size;
7275 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7278 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7287 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7290 MONO_ARCH_SAVE_REGS;
7292 i = iter->sig->sentinelpos + iter->next_arg;
7294 g_assert (i < iter->sig->param_count);
7296 return iter->sig->params [i];
7300 mono_TypedReference_ToObject (MonoTypedRef tref)
7302 MONO_ARCH_SAVE_REGS;
7304 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7305 MonoObject** objp = tref.value;
7309 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7313 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7315 MONO_ARCH_SAVE_REGS;
7317 if (MONO_TYPE_IS_REFERENCE (type)) {
7318 MonoObject** objp = value;
7322 return mono_value_box (mono_domain_get (), klass, value);
7326 prelink_method (MonoMethod *method)
7328 const char *exc_class, *exc_arg;
7329 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7331 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7333 mono_raise_exception(
7334 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7336 /* create the wrapper, too? */
7340 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7342 MONO_ARCH_SAVE_REGS;
7343 prelink_method (method->method);
7347 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7349 MonoClass *klass = mono_class_from_mono_type (type->type);
7351 gpointer iter = NULL;
7352 MONO_ARCH_SAVE_REGS;
7354 mono_class_init_or_throw (klass);
7356 while ((m = mono_class_get_methods (klass, &iter)))
7360 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7362 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7363 gint32 const **exponents,
7364 gunichar2 const **digitLowerTable,
7365 gunichar2 const **digitUpperTable,
7366 gint64 const **tenPowersList,
7367 gint32 const **decHexDigits)
7369 *mantissas = Formatter_MantissaBitsTable;
7370 *exponents = Formatter_TensExponentTable;
7371 *digitLowerTable = Formatter_DigitLowerTable;
7372 *digitUpperTable = Formatter_DigitUpperTable;
7373 *tenPowersList = Formatter_TenPowersList;
7374 *decHexDigits = Formatter_DecHexDigits;
7378 get_category_data (int version,
7379 guint8 const **category_data,
7380 guint16 const **category_astral_index)
7382 *category_astral_index = NULL;
7384 #ifndef DISABLE_NET_4_0
7386 *category_data = CategoryData_v4;
7387 #ifndef DISABLE_ASTRAL
7388 *category_astral_index = CategoryData_v4_astral_index;
7394 *category_data = CategoryData_v2;
7395 #ifndef DISABLE_ASTRAL
7396 *category_astral_index = CategoryData_v2_astral_index;
7400 /* These parameters are "readonly" in corlib/System/Char.cs */
7402 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7403 guint8 const **category_data,
7404 guint16 const **category_astral_index,
7405 guint8 const **numeric_data,
7406 gdouble const **numeric_data_values,
7407 guint16 const **to_lower_data_low,
7408 guint16 const **to_lower_data_high,
7409 guint16 const **to_upper_data_low,
7410 guint16 const **to_upper_data_high)
7412 get_category_data (category_data_version, category_data, category_astral_index);
7413 *numeric_data = NumericData;
7414 *numeric_data_values = NumericDataValues;
7415 *to_lower_data_low = ToLowerDataLow;
7416 *to_lower_data_high = ToLowerDataHigh;
7417 *to_upper_data_low = ToUpperDataLow;
7418 *to_upper_data_high = ToUpperDataHigh;
7422 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7424 return method->method->token;
7428 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7429 * and avoid useless allocations.
7432 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7436 for (i = 0; i < type->num_mods; ++i) {
7437 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7442 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7444 for (i = 0; i < type->num_mods; ++i) {
7445 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7446 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7447 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7455 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7457 MonoType *type = param->ClassImpl->type;
7458 MonoClass *member_class = mono_object_class (param->MemberImpl);
7459 MonoMethod *method = NULL;
7462 MonoMethodSignature *sig;
7464 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7465 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7466 method = rmethod->method;
7467 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7468 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7469 if (!(method = prop->property->get))
7470 method = prop->property->set;
7473 char *type_name = mono_type_get_full_name (member_class);
7474 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7475 MonoException *ex = mono_get_exception_not_supported (msg);
7478 mono_raise_exception (ex);
7481 image = method->klass->image;
7482 pos = param->PositionImpl;
7483 sig = mono_method_signature (method);
7487 type = sig->params [pos];
7489 return type_array_from_modifiers (image, type, optional);
7493 get_property_type (MonoProperty *prop)
7495 MonoMethodSignature *sig;
7497 sig = mono_method_signature (prop->get);
7499 } else if (prop->set) {
7500 sig = mono_method_signature (prop->set);
7501 return sig->params [sig->param_count - 1];
7507 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7509 MonoType *type = get_property_type (property->property);
7510 MonoImage *image = property->klass->image;
7514 return type_array_from_modifiers (image, type, optional);
7518 *Construct a MonoType suited to be used to decode a constant blob object.
7520 * @type is the target type which will be constructed
7521 * @blob_type is the blob type, for example, that comes from the constant table
7522 * @real_type is the expected constructed type.
7525 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7527 type->type = blob_type;
7528 type->data.klass = NULL;
7529 if (blob_type == MONO_TYPE_CLASS)
7530 type->data.klass = mono_defaults.object_class;
7531 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7532 /* For enums, we need to use the base type */
7533 type->type = MONO_TYPE_VALUETYPE;
7534 type->data.klass = mono_class_from_mono_type (real_type);
7536 type->data.klass = mono_class_from_mono_type (real_type);
7540 property_info_get_default_value (MonoReflectionProperty *property)
7543 MonoProperty *prop = property->property;
7544 MonoType *type = get_property_type (prop);
7545 MonoDomain *domain = mono_object_domain (property);
7546 MonoTypeEnum def_type;
7547 const char *def_value;
7550 mono_class_init (prop->parent);
7552 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7553 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7555 def_value = mono_class_get_property_default_value (prop, &def_type);
7557 mono_type_from_blob_type (&blob_type, def_type, type);
7558 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7564 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7566 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7567 MonoCustomAttrInfo *cinfo;
7570 mono_class_init_or_throw (attr_class);
7572 cinfo = mono_reflection_get_custom_attrs_info (obj);
7575 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7577 mono_custom_attrs_free (cinfo);
7582 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7584 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7589 mono_class_init_or_throw (attr_class);
7591 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7592 if (!mono_error_ok (&error))
7593 mono_error_raise_exception (&error);
7594 if (mono_loader_get_last_error ()) {
7595 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7596 g_assert_not_reached ();
7605 ves_icall_Mono_Runtime_GetDisplayName (void)
7608 MonoString *display_name;
7610 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7611 display_name = mono_string_new (mono_domain_get (), info);
7613 return display_name;
7617 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7619 MonoString *message;
7623 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7624 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7627 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7629 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7637 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7638 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7639 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7640 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7641 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7642 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7643 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7644 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7648 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7653 gunichar2 last, prev_last, prev2_last;
7661 last = prev_last = 0, prev2_last = 0;
7662 for (i = 0; i < ilength; i++) {
7664 if (c >= sizeof (dbase64)) {
7665 exc = mono_exception_from_name_msg (mono_get_corlib (),
7666 "System", "FormatException",
7667 "Invalid character found.");
7668 mono_raise_exception (exc);
7669 } else if (isspace (c)) {
7672 prev2_last = prev_last;
7678 olength = ilength - ignored;
7680 if (allowWhitespaceOnly && olength == 0) {
7681 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7684 if ((olength & 3) != 0 || olength <= 0) {
7685 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7686 "FormatException", "Invalid length.");
7687 mono_raise_exception (exc);
7690 if (prev2_last == '=') {
7691 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7692 mono_raise_exception (exc);
7695 olength = (olength * 3) / 4;
7699 if (prev_last == '=')
7702 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7703 res_ptr = mono_array_addr (result, guchar, 0);
7704 for (i = 0; i < ilength; ) {
7707 for (k = 0; k < 4 && i < ilength;) {
7713 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7714 exc = mono_exception_from_name_msg (mono_get_corlib (),
7715 "System", "FormatException",
7716 "Invalid character found.");
7717 mono_raise_exception (exc);
7722 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7724 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7726 *res_ptr++ = (b [2] << 6) | b [3];
7728 while (i < ilength && isspace (start [i]))
7736 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7738 MONO_ARCH_SAVE_REGS;
7740 return base64_to_byte_array (mono_string_chars (str),
7741 mono_string_length (str), allowWhitespaceOnly);
7745 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7747 MONO_ARCH_SAVE_REGS;
7749 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7753 #define ICALL_TYPE(id,name,first)
7754 #define ICALL(id,name,func) Icall_ ## id,
7757 #include "metadata/icall-def.h"
7763 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7764 #define ICALL(id,name,func)
7766 #include "metadata/icall-def.h"
7772 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7773 #define ICALL(id,name,func)
7775 guint16 first_icall;
7778 static const IcallTypeDesc
7779 icall_type_descs [] = {
7780 #include "metadata/icall-def.h"
7784 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7787 #define ICALL_TYPE(id,name,first)
7790 #ifdef HAVE_ARRAY_ELEM_INIT
7791 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7792 #define MSGSTRFIELD1(line) str##line
7794 static const struct msgstrtn_t {
7795 #define ICALL(id,name,func)
7797 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7798 #include "metadata/icall-def.h"
7800 } icall_type_names_str = {
7801 #define ICALL_TYPE(id,name,first) (name),
7802 #include "metadata/icall-def.h"
7805 static const guint16 icall_type_names_idx [] = {
7806 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7807 #include "metadata/icall-def.h"
7810 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7812 static const struct msgstr_t {
7814 #define ICALL_TYPE(id,name,first)
7815 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7816 #include "metadata/icall-def.h"
7818 } icall_names_str = {
7819 #define ICALL(id,name,func) (name),
7820 #include "metadata/icall-def.h"
7823 static const guint16 icall_names_idx [] = {
7824 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7825 #include "metadata/icall-def.h"
7828 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7834 #define ICALL_TYPE(id,name,first) name,
7835 #define ICALL(id,name,func)
7836 static const char* const
7837 icall_type_names [] = {
7838 #include "metadata/icall-def.h"
7842 #define icall_type_name_get(id) (icall_type_names [(id)])
7846 #define ICALL_TYPE(id,name,first)
7847 #define ICALL(id,name,func) name,
7848 static const char* const
7850 #include "metadata/icall-def.h"
7853 #define icall_name_get(id) icall_names [(id)]
7855 #endif /* !HAVE_ARRAY_ELEM_INIT */
7859 #define ICALL_TYPE(id,name,first)
7860 #define ICALL(id,name,func) func,
7861 static const gconstpointer
7862 icall_functions [] = {
7863 #include "metadata/icall-def.h"
7867 static GHashTable *icall_hash = NULL;
7868 static GHashTable *jit_icall_hash_name = NULL;
7869 static GHashTable *jit_icall_hash_addr = NULL;
7872 mono_icall_init (void)
7876 /* check that tables are sorted: disable in release */
7879 const char *prev_class = NULL;
7880 const char *prev_method;
7882 for (i = 0; i < Icall_type_num; ++i) {
7883 const IcallTypeDesc *desc;
7886 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7887 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7888 prev_class = icall_type_name_get (i);
7889 desc = &icall_type_descs [i];
7890 num_icalls = icall_desc_num_icalls (desc);
7891 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7892 for (j = 0; j < num_icalls; ++j) {
7893 const char *methodn = icall_name_get (desc->first_icall + j);
7894 if (prev_method && strcmp (prev_method, methodn) >= 0)
7895 g_print ("method %s should come before method %s\n", methodn, prev_method);
7896 prev_method = methodn;
7901 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7905 mono_icall_cleanup (void)
7907 g_hash_table_destroy (icall_hash);
7908 g_hash_table_destroy (jit_icall_hash_name);
7909 g_hash_table_destroy (jit_icall_hash_addr);
7913 mono_add_internal_call (const char *name, gconstpointer method)
7915 mono_loader_lock ();
7917 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7919 mono_loader_unlock ();
7922 #ifdef HAVE_ARRAY_ELEM_INIT
7924 compare_method_imap (const void *key, const void *elem)
7926 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7927 return strcmp (key, method_name);
7931 find_method_icall (const IcallTypeDesc *imap, const char *name)
7933 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7936 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7940 compare_class_imap (const void *key, const void *elem)
7942 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7943 return strcmp (key, class_name);
7946 static const IcallTypeDesc*
7947 find_class_icalls (const char *name)
7949 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7952 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7957 compare_method_imap (const void *key, const void *elem)
7959 const char** method_name = (const char**)elem;
7960 return strcmp (key, *method_name);
7964 find_method_icall (const IcallTypeDesc *imap, const char *name)
7966 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7969 return (gpointer)icall_functions [(nameslot - icall_names)];
7973 compare_class_imap (const void *key, const void *elem)
7975 const char** class_name = (const char**)elem;
7976 return strcmp (key, *class_name);
7979 static const IcallTypeDesc*
7980 find_class_icalls (const char *name)
7982 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7985 return &icall_type_descs [nameslot - icall_type_names];
7991 * we should probably export this as an helper (handle nested types).
7992 * Returns the number of chars written in buf.
7995 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7997 int nspacelen, cnamelen;
7998 nspacelen = strlen (klass->name_space);
7999 cnamelen = strlen (klass->name);
8000 if (nspacelen + cnamelen + 2 > bufsize)
8003 memcpy (buf, klass->name_space, nspacelen);
8004 buf [nspacelen ++] = '.';
8006 memcpy (buf + nspacelen, klass->name, cnamelen);
8007 buf [nspacelen + cnamelen] = 0;
8008 return nspacelen + cnamelen;
8012 mono_lookup_internal_call (MonoMethod *method)
8017 int typelen = 0, mlen, siglen;
8019 const IcallTypeDesc *imap;
8021 g_assert (method != NULL);
8023 if (method->is_inflated)
8024 method = ((MonoMethodInflated *) method)->declaring;
8026 if (method->klass->nested_in) {
8027 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8031 mname [pos++] = '/';
8034 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8040 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8045 imap = find_class_icalls (mname);
8047 mname [typelen] = ':';
8048 mname [typelen + 1] = ':';
8050 mlen = strlen (method->name);
8051 memcpy (mname + typelen + 2, method->name, mlen);
8052 sigstart = mname + typelen + 2 + mlen;
8055 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8056 siglen = strlen (tmpsig);
8057 if (typelen + mlen + siglen + 6 > sizeof (mname))
8060 memcpy (sigstart + 1, tmpsig, siglen);
8061 sigstart [siglen + 1] = ')';
8062 sigstart [siglen + 2] = 0;
8065 mono_loader_lock ();
8067 res = g_hash_table_lookup (icall_hash, mname);
8069 mono_loader_unlock ();
8072 /* try without signature */
8074 res = g_hash_table_lookup (icall_hash, mname);
8076 mono_loader_unlock ();
8080 /* it wasn't found in the static call tables */
8082 mono_loader_unlock ();
8085 res = find_method_icall (imap, sigstart - mlen);
8087 mono_loader_unlock ();
8090 /* try _with_ signature */
8092 res = find_method_icall (imap, sigstart - mlen);
8094 mono_loader_unlock ();
8098 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8099 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8100 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8101 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8102 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");
8103 g_print ("If you see other errors or faults after this message they are probably related\n");
8104 g_print ("and you need to fix your mono install first.\n");
8106 mono_loader_unlock ();
8112 type_from_typename (char *typename)
8114 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8116 if (!strcmp (typename, "int"))
8117 klass = mono_defaults.int_class;
8118 else if (!strcmp (typename, "ptr"))
8119 klass = mono_defaults.int_class;
8120 else if (!strcmp (typename, "void"))
8121 klass = mono_defaults.void_class;
8122 else if (!strcmp (typename, "int32"))
8123 klass = mono_defaults.int32_class;
8124 else if (!strcmp (typename, "uint32"))
8125 klass = mono_defaults.uint32_class;
8126 else if (!strcmp (typename, "int8"))
8127 klass = mono_defaults.sbyte_class;
8128 else if (!strcmp (typename, "uint8"))
8129 klass = mono_defaults.byte_class;
8130 else if (!strcmp (typename, "int16"))
8131 klass = mono_defaults.int16_class;
8132 else if (!strcmp (typename, "uint16"))
8133 klass = mono_defaults.uint16_class;
8134 else if (!strcmp (typename, "long"))
8135 klass = mono_defaults.int64_class;
8136 else if (!strcmp (typename, "ulong"))
8137 klass = mono_defaults.uint64_class;
8138 else if (!strcmp (typename, "float"))
8139 klass = mono_defaults.single_class;
8140 else if (!strcmp (typename, "double"))
8141 klass = mono_defaults.double_class;
8142 else if (!strcmp (typename, "object"))
8143 klass = mono_defaults.object_class;
8144 else if (!strcmp (typename, "obj"))
8145 klass = mono_defaults.object_class;
8146 else if (!strcmp (typename, "string"))
8147 klass = mono_defaults.string_class;
8148 else if (!strcmp (typename, "bool"))
8149 klass = mono_defaults.boolean_class;
8150 else if (!strcmp (typename, "boolean"))
8151 klass = mono_defaults.boolean_class;
8153 g_error ("%s", typename);
8154 g_assert_not_reached ();
8156 return &klass->byval_arg;
8159 MonoMethodSignature*
8160 mono_create_icall_signature (const char *sigstr)
8165 MonoMethodSignature *res;
8167 mono_loader_lock ();
8168 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8170 mono_loader_unlock ();
8174 parts = g_strsplit (sigstr, " ", 256);
8183 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8188 * Under windows, the default pinvoke calling convention is STDCALL but
8191 res->call_convention = MONO_CALL_C;
8194 res->ret = type_from_typename (parts [0]);
8195 for (i = 1; i < len; ++i) {
8196 res->params [i - 1] = type_from_typename (parts [i]);
8201 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8203 mono_loader_unlock ();
8209 mono_find_jit_icall_by_name (const char *name)
8211 MonoJitICallInfo *info;
8212 g_assert (jit_icall_hash_name);
8214 mono_loader_lock ();
8215 info = g_hash_table_lookup (jit_icall_hash_name, name);
8216 mono_loader_unlock ();
8221 mono_find_jit_icall_by_addr (gconstpointer addr)
8223 MonoJitICallInfo *info;
8224 g_assert (jit_icall_hash_addr);
8226 mono_loader_lock ();
8227 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8228 mono_loader_unlock ();
8234 * mono_get_jit_icall_info:
8236 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8237 * caller should access it while holding the loader lock.
8240 mono_get_jit_icall_info (void)
8242 return jit_icall_hash_name;
8246 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8248 mono_loader_lock ();
8249 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8250 mono_loader_unlock ();
8254 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8256 MonoJitICallInfo *info;
8261 mono_loader_lock ();
8263 if (!jit_icall_hash_name) {
8264 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8265 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8268 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8269 g_warning ("jit icall already defined \"%s\"\n", name);
8270 g_assert_not_reached ();
8273 info = g_new0 (MonoJitICallInfo, 1);
8280 info->wrapper = func;
8282 info->wrapper = NULL;
8285 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8286 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8288 mono_loader_unlock ();