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)
21 #ifdef HAVE_SYS_TIME_H
27 #if defined (HOST_WIN32)
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/metadata/mono-ptr-array.h>
71 #include <mono/metadata/verify-internals.h>
72 #include <mono/io-layer/io-layer.h>
73 #include <mono/utils/strtod.h>
74 #include <mono/utils/monobitset.h>
75 #include <mono/utils/mono-time.h>
76 #include <mono/utils/mono-proclib.h>
77 #include <mono/utils/mono-string.h>
78 #include <mono/utils/mono-error-internals.h>
79 #include <mono/utils/mono-mmap.h>
80 #include <mono/utils/mono-io-portability.h>
82 #if defined (HOST_WIN32)
88 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
90 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
93 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
95 static inline MonoBoolean
96 is_generic_parameter (MonoType *type)
98 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
102 mono_class_init_or_throw (MonoClass *klass)
104 if (!mono_class_init (klass))
105 mono_raise_exception (mono_class_get_exception_for_failure (klass));
109 * We expect a pointer to a char, not a string
112 mono_double_ParseImpl (char *ptr, double *result)
114 gchar *endptr = NULL;
121 *result = strtod (ptr, &endptr);
124 /* mono_strtod () is not thread-safe */
125 EnterCriticalSection (&mono_strtod_mutex);
126 *result = mono_strtod (ptr, &endptr);
127 LeaveCriticalSection (&mono_strtod_mutex);
131 if (!*ptr || (endptr && *endptr))
138 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
147 ao = (MonoArray *)this;
148 ac = (MonoClass *)ao->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)ao->vector + (pos * esize));
153 if (ac->element_class->valuetype)
154 return mono_value_box (this->vtable->domain, ac->element_class, ea);
160 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
168 MONO_CHECK_ARG_NULL (idxs);
170 io = (MonoArray *)idxs;
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ao = (MonoArray *)this;
174 ac = (MonoClass *)ao->obj.vtable->klass;
176 g_assert (ic->rank == 1);
177 if (io->bounds != NULL || io->max_length != ac->rank)
178 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
180 ind = (gint32 *)io->vector;
182 if (ao->bounds == NULL) {
183 if (*ind < 0 || *ind >= ao->max_length)
184 mono_raise_exception (mono_get_exception_index_out_of_range ());
186 return ves_icall_System_Array_GetValueImpl (this, *ind);
189 for (i = 0; i < ac->rank; i++)
190 if ((ind [i] < ao->bounds [i].lower_bound) ||
191 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
192 mono_raise_exception (mono_get_exception_index_out_of_range ());
194 pos = ind [0] - ao->bounds [0].lower_bound;
195 for (i = 1; i < ac->rank; i++)
196 pos = pos*ao->bounds [i].length + ind [i] -
197 ao->bounds [i].lower_bound;
199 return ves_icall_System_Array_GetValueImpl (this, pos);
203 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
205 MonoClass *ac, *vc, *ec;
217 vc = value->vtable->klass;
221 ac = this->obj.vtable->klass;
222 ec = ac->element_class;
224 esize = mono_array_element_size (ac);
225 ea = (gpointer*)((char*)this->vector + (pos * esize));
226 va = (gpointer*)((char*)value + sizeof (MonoObject));
228 if (mono_class_is_nullable (ec)) {
229 mono_nullable_init ((guint8*)ea, value, ec);
234 memset (ea, 0, esize);
238 #define NO_WIDENING_CONVERSION G_STMT_START{\
239 mono_raise_exception (mono_get_exception_argument ( \
240 "value", "not a widening conversion")); \
243 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
244 if (esize < vsize + (extra)) \
245 mono_raise_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
249 #define INVALID_CAST G_STMT_START{ \
250 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
251 mono_raise_exception (mono_get_exception_invalid_cast ()); \
254 /* Check element (destination) type. */
255 switch (ec->byval_arg.type) {
256 case MONO_TYPE_STRING:
257 switch (vc->byval_arg.type) {
258 case MONO_TYPE_STRING:
264 case MONO_TYPE_BOOLEAN:
265 switch (vc->byval_arg.type) {
266 case MONO_TYPE_BOOLEAN:
279 NO_WIDENING_CONVERSION;
286 if (!ec->valuetype) {
287 if (!mono_object_isinst (value, ec))
289 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
293 if (mono_object_isinst (value, ec)) {
294 if (ec->has_references)
295 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
297 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
304 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
306 et = ec->byval_arg.type;
307 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
308 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
310 vt = vc->byval_arg.type;
311 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
312 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
314 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
320 case MONO_TYPE_CHAR: \
321 CHECK_WIDENING_CONVERSION(0); \
322 *(etype *) ea = (etype) u64; \
324 /* You can't assign a signed value to an unsigned array. */ \
329 /* You can't assign a floating point number to an integer array. */ \
332 NO_WIDENING_CONVERSION; \
336 #define ASSIGN_SIGNED(etype) G_STMT_START{\
342 CHECK_WIDENING_CONVERSION(0); \
343 *(etype *) ea = (etype) i64; \
345 /* You can assign an unsigned value to a signed array if the array's */ \
346 /* element size is larger than the value size. */ \
351 case MONO_TYPE_CHAR: \
352 CHECK_WIDENING_CONVERSION(1); \
353 *(etype *) ea = (etype) u64; \
355 /* You can't assign a floating point number to an integer array. */ \
358 NO_WIDENING_CONVERSION; \
362 #define ASSIGN_REAL(etype) G_STMT_START{\
366 CHECK_WIDENING_CONVERSION(0); \
367 *(etype *) ea = (etype) r64; \
369 /* All integer values fit into a floating point array, so we don't */ \
370 /* need to CHECK_WIDENING_CONVERSION here. */ \
375 *(etype *) ea = (etype) i64; \
381 case MONO_TYPE_CHAR: \
382 *(etype *) ea = (etype) u64; \
389 u64 = *(guint8 *) va;
392 u64 = *(guint16 *) va;
395 u64 = *(guint32 *) va;
398 u64 = *(guint64 *) va;
404 i64 = *(gint16 *) va;
407 i64 = *(gint32 *) va;
410 i64 = *(gint64 *) va;
413 r64 = *(gfloat *) va;
416 r64 = *(gdouble *) va;
419 u64 = *(guint16 *) va;
421 case MONO_TYPE_BOOLEAN:
422 /* Boolean is only compatible with itself. */
435 NO_WIDENING_CONVERSION;
442 /* If we can't do a direct copy, let's try a widening conversion. */
445 ASSIGN_UNSIGNED (guint16);
447 ASSIGN_UNSIGNED (guint8);
449 ASSIGN_UNSIGNED (guint16);
451 ASSIGN_UNSIGNED (guint32);
453 ASSIGN_UNSIGNED (guint64);
455 ASSIGN_SIGNED (gint8);
457 ASSIGN_SIGNED (gint16);
459 ASSIGN_SIGNED (gint32);
461 ASSIGN_SIGNED (gint64);
463 ASSIGN_REAL (gfloat);
465 ASSIGN_REAL (gdouble);
469 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
473 #undef NO_WIDENING_CONVERSION
474 #undef CHECK_WIDENING_CONVERSION
475 #undef ASSIGN_UNSIGNED
481 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
489 MONO_CHECK_ARG_NULL (idxs);
491 ic = idxs->obj.vtable->klass;
492 ac = this->obj.vtable->klass;
494 g_assert (ic->rank == 1);
495 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
496 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
498 ind = (gint32 *)idxs->vector;
500 if (this->bounds == NULL) {
501 if (*ind < 0 || *ind >= this->max_length)
502 mono_raise_exception (mono_get_exception_index_out_of_range ());
504 ves_icall_System_Array_SetValueImpl (this, value, *ind);
508 for (i = 0; i < ac->rank; i++)
509 if ((ind [i] < this->bounds [i].lower_bound) ||
510 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
511 mono_raise_exception (mono_get_exception_index_out_of_range ());
513 pos = ind [0] - this->bounds [0].lower_bound;
514 for (i = 1; i < ac->rank; i++)
515 pos = pos * this->bounds [i].length + ind [i] -
516 this->bounds [i].lower_bound;
518 ves_icall_System_Array_SetValueImpl (this, value, pos);
522 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
524 MonoClass *aklass, *klass;
527 gboolean bounded = FALSE;
531 MONO_CHECK_ARG_NULL (type);
532 MONO_CHECK_ARG_NULL (lengths);
534 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
536 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
538 for (i = 0; i < mono_array_length (lengths); i++)
539 if (mono_array_get (lengths, gint32, i) < 0)
540 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
542 klass = mono_class_from_mono_type (type->type);
543 mono_class_init_or_throw (klass);
545 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
546 /* vectors are not the same as one dimensional arrays with no-zero bounds */
551 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
553 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
554 for (i = 0; i < aklass->rank; ++i) {
555 sizes [i] = mono_array_get (lengths, guint32, i);
557 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
559 sizes [i + aklass->rank] = 0;
562 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
568 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
570 MonoClass *aklass, *klass;
573 gboolean bounded = FALSE;
577 MONO_CHECK_ARG_NULL (type);
578 MONO_CHECK_ARG_NULL (lengths);
580 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
582 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
584 for (i = 0; i < mono_array_length (lengths); i++)
585 if ((mono_array_get (lengths, gint64, i) < 0) ||
586 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
587 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
589 klass = mono_class_from_mono_type (type->type);
590 mono_class_init_or_throw (klass);
592 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
593 /* vectors are not the same as one dimensional arrays with no-zero bounds */
598 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
600 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
601 for (i = 0; i < aklass->rank; ++i) {
602 sizes [i] = mono_array_get (lengths, guint64, i);
604 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
606 sizes [i + aklass->rank] = 0;
609 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
615 ves_icall_System_Array_GetRank (MonoObject *this)
619 return this->vtable->klass->rank;
623 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
625 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
630 if ((dimension < 0) || (dimension >= rank))
631 mono_raise_exception (mono_get_exception_index_out_of_range ());
633 if (this->bounds == NULL)
634 length = this->max_length;
636 length = this->bounds [dimension].length;
638 #ifdef MONO_BIG_ARRAYS
639 if (length > G_MAXINT32)
640 mono_raise_exception (mono_get_exception_overflow ());
646 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
648 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
652 if ((dimension < 0) || (dimension >= rank))
653 mono_raise_exception (mono_get_exception_index_out_of_range ());
655 if (this->bounds == NULL)
656 return this->max_length;
658 return this->bounds [dimension].length;
662 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
664 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
668 if ((dimension < 0) || (dimension >= rank))
669 mono_raise_exception (mono_get_exception_index_out_of_range ());
671 if (this->bounds == NULL)
674 return this->bounds [dimension].lower_bound;
678 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
680 int sz = mono_array_element_size (mono_object_class (arr));
681 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
685 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
690 MonoClass *src_class;
691 MonoClass *dest_class;
695 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
698 if (source->bounds || dest->bounds)
701 /* there's no integer overflow since mono_array_length returns an unsigned integer */
702 if ((dest_idx + length > mono_array_length (dest)) ||
703 (source_idx + length > mono_array_length (source)))
706 src_class = source->obj.vtable->klass->element_class;
707 dest_class = dest->obj.vtable->klass->element_class;
710 * Handle common cases.
713 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
714 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
715 // FIXME: This is racy
719 int has_refs = dest_class->has_references;
720 for (i = source_idx; i < source_idx + length; ++i) {
721 MonoObject *elem = mono_array_get (source, MonoObject*, i);
722 if (elem && !mono_object_isinst (elem, dest_class))
726 element_size = mono_array_element_size (dest->obj.vtable->klass);
727 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
728 for (i = 0; i < length; ++i) {
729 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
730 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
734 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
736 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
742 /* Check if we're copying a char[] <==> (u)short[] */
743 if (src_class != dest_class) {
744 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
747 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
749 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
750 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
751 // FIXME: This is racy
755 for (i = source_idx; i < source_idx + length; ++i) {
756 MonoObject *elem = mono_array_get (source, MonoObject*, i);
757 if (elem && !mono_object_isinst (elem, dest_class))
765 if (dest_class->valuetype) {
766 element_size = mono_array_element_size (source->obj.vtable->klass);
767 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
768 if (dest_class->has_references) {
769 mono_value_copy_array (dest, dest_idx, source_addr, length);
771 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
772 memmove (dest_addr, source_addr, element_size * length);
775 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
782 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
791 ao = (MonoArray *)this;
792 ac = (MonoClass *)ao->obj.vtable->klass;
794 esize = mono_array_element_size (ac);
795 ea = (gpointer*)((char*)ao->vector + (pos * esize));
797 memcpy (value, ea, esize);
801 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
810 ao = (MonoArray *)this;
811 ac = (MonoClass *)ao->obj.vtable->klass;
812 ec = ac->element_class;
814 esize = mono_array_element_size (ac);
815 ea = (gpointer*)((char*)ao->vector + (pos * esize));
817 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818 g_assert (esize == sizeof (gpointer));
819 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
821 g_assert (ec->inited);
822 g_assert (esize == mono_class_value_size (ec, NULL));
823 if (ec->has_references)
824 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
826 memcpy (ea, value, esize);
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
833 MonoClass *klass = array->obj.vtable->klass;
834 guint32 size = mono_array_element_size (klass);
835 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
837 const char *field_data;
839 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_raise_exception (exc);
845 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
846 MonoException *exc = mono_get_exception_argument("field_handle",
847 "Field doesn't have an RVA");
848 mono_raise_exception (exc);
851 size *= array->max_length;
852 field_data = mono_field_get_data (field_handle);
854 if (size > mono_type_size (field_handle->type, &align)) {
855 MonoException *exc = mono_get_exception_argument("field_handle",
856 "Field not large enough to fill array");
857 mono_raise_exception (exc);
860 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
862 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
863 guint ## n *src = (guint ## n *) field_data; \
864 guint ## n *end = (guint ## n *)((char*)src + size); \
866 for (; src < end; data++, src++) { \
867 *data = read ## n (src); \
871 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
873 switch (type->type) {
890 memcpy (mono_array_addr (array, char, 0), field_data, size);
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
896 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
899 double *data = (double*)mono_array_addr (array, double, 0);
901 for (i = 0; i < size; i++, data++) {
911 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
915 return offsetof (MonoString, chars);
919 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
923 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
926 return mono_object_clone (obj);
930 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
935 MONO_CHECK_ARG_NULL (handle);
937 klass = mono_class_from_mono_type (handle);
938 MONO_CHECK_ARG (handle, klass);
940 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
942 /* This will call the type constructor */
943 mono_runtime_class_init (vtable);
947 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
951 mono_image_check_for_module_cctor (image);
952 if (image->has_module_cctor) {
953 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
954 /*It's fine to raise the exception here*/
955 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
960 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
965 /* later make this configurable and per-arch */
966 int min_size = 4096 * 4 * sizeof (void*);
967 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
968 /* if we have no info we are optimistic and assume there is enough room */
971 current = (guint8 *)&stack_addr;
972 if (current > stack_addr) {
973 if ((current - stack_addr) < min_size)
976 if (current - (stack_addr - stack_size) < min_size)
983 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
987 return mono_object_clone (this);
991 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
994 MonoObject **values = NULL;
998 MonoClassField* field;
1001 MONO_ARCH_SAVE_REGS;
1003 klass = mono_object_class (this);
1005 if (mono_class_num_fields (klass) == 0)
1006 return mono_object_hash (this);
1009 * Compute the starting value of the hashcode for fields of primitive
1010 * types, and return the remaining fields in an array to the managed side.
1011 * This way, we can avoid costly reflection operations in managed code.
1014 while ((field = mono_class_get_fields (klass, &iter))) {
1015 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1017 if (mono_field_is_deleted (field))
1019 /* FIXME: Add more types */
1020 switch (field->type->type) {
1022 result ^= *(gint32*)((guint8*)this + field->offset);
1024 case MONO_TYPE_STRING: {
1026 s = *(MonoString**)((guint8*)this + field->offset);
1028 result ^= mono_string_hash (s);
1033 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1034 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1035 values [count++] = o;
1041 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1042 for (i = 0; i < count; ++i)
1043 mono_array_setref (*fields, i, values [i]);
1051 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1054 MonoObject **values = NULL;
1056 MonoClassField* field;
1060 MONO_ARCH_SAVE_REGS;
1062 MONO_CHECK_ARG_NULL (that);
1064 if (this->vtable != that->vtable)
1067 klass = mono_object_class (this);
1069 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1070 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1073 * Do the comparison for fields of primitive type and return a result if
1074 * possible. Otherwise, return the remaining fields in an array to the
1075 * managed side. This way, we can avoid costly reflection operations in
1080 while ((field = mono_class_get_fields (klass, &iter))) {
1081 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1083 if (mono_field_is_deleted (field))
1085 /* FIXME: Add more types */
1086 switch (field->type->type) {
1089 case MONO_TYPE_BOOLEAN:
1090 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1095 case MONO_TYPE_CHAR:
1096 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1101 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1106 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1110 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1114 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1119 case MONO_TYPE_STRING: {
1120 MonoString *s1, *s2;
1121 guint32 s1len, s2len;
1122 s1 = *(MonoString**)((guint8*)this + field->offset);
1123 s2 = *(MonoString**)((guint8*)that + field->offset);
1126 if ((s1 == NULL) || (s2 == NULL))
1128 s1len = mono_string_length (s1);
1129 s2len = mono_string_length (s2);
1133 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1139 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1140 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1141 values [count++] = o;
1142 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1143 values [count++] = o;
1146 if (klass->enumtype)
1147 /* enums only have one non-static field */
1153 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1154 for (i = 0; i < count; ++i)
1155 mono_array_setref (*fields, i, values [i]);
1162 static MonoReflectionType *
1163 ves_icall_System_Object_GetType (MonoObject *obj)
1165 MONO_ARCH_SAVE_REGS;
1167 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1168 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1170 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1174 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1176 MONO_ARCH_SAVE_REGS;
1178 mtype->type = &obj->vtable->klass->byval_arg;
1179 g_assert (mtype->type->type);
1183 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1185 MONO_ARCH_SAVE_REGS;
1187 MONO_CHECK_ARG_NULL (obj);
1189 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1193 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1194 MonoReflectionMethod *method,
1195 MonoArray *opt_param_types)
1197 MONO_ARCH_SAVE_REGS;
1199 MONO_CHECK_ARG_NULL (method);
1201 return mono_image_create_method_token (
1202 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1206 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1208 MONO_ARCH_SAVE_REGS;
1210 mono_image_create_pefile (mb, file);
1214 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1216 MONO_ARCH_SAVE_REGS;
1218 mono_image_build_metadata (mb);
1222 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1224 MONO_ARCH_SAVE_REGS;
1226 mono_image_register_token (mb->dynamic_image, token, obj);
1230 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1232 MonoMethod **dest = data;
1234 /* skip unmanaged frames */
1250 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1252 MonoMethod **dest = data;
1254 /* skip unmanaged frames */
1259 if (!strcmp (m->klass->name_space, "System.Reflection"))
1268 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1270 MonoMethod **dest = data;
1272 /* skip unmanaged frames */
1276 if (m->wrapper_type != MONO_WRAPPER_NONE)
1279 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1293 static MonoReflectionType *
1294 type_from_name (const char *str, MonoBoolean ignoreCase)
1296 MonoType *type = NULL;
1297 MonoAssembly *assembly = NULL;
1298 MonoTypeNameParse info;
1299 char *temp_str = g_strdup (str);
1300 gboolean type_resolve = FALSE;
1302 MONO_ARCH_SAVE_REGS;
1304 /* mono_reflection_parse_type() mangles the string */
1305 if (!mono_reflection_parse_type (temp_str, &info)) {
1306 mono_reflection_free_type_info (&info);
1311 if (info.assembly.name) {
1312 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1314 MonoMethod *m = mono_method_get_last_managed ();
1315 MonoMethod *dest = m;
1317 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1322 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1323 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1324 * to crash. This only seems to happen in some strange remoting
1325 * scenarios and I was unable to figure out what's happening there.
1326 * Dec 10, 2005 - Martin.
1330 assembly = dest->klass->image->assembly;
1331 type_resolve = TRUE;
1333 g_warning (G_STRLOC);
1338 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1339 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1342 if (!info.assembly.name && !type) /* try mscorlib */
1343 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1345 if (assembly && !type && type_resolve) {
1346 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1347 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1350 mono_reflection_free_type_info (&info);
1356 return mono_type_get_object (mono_domain_get (), type);
1360 MonoReflectionType *
1361 mono_type_get (const char *str)
1363 char *copy = g_strdup (str);
1364 MonoReflectionType *type = type_from_name (copy, FALSE);
1371 static MonoReflectionType*
1372 ves_icall_type_from_name (MonoString *name,
1373 MonoBoolean throwOnError,
1374 MonoBoolean ignoreCase)
1376 char *str = mono_string_to_utf8 (name);
1377 MonoReflectionType *type;
1379 type = type_from_name (str, ignoreCase);
1382 MonoException *e = NULL;
1385 e = mono_get_exception_type_load (name, NULL);
1387 mono_loader_clear_error ();
1389 mono_raise_exception (e);
1396 static MonoReflectionType*
1397 ves_icall_type_from_handle (MonoType *handle)
1399 MonoDomain *domain = mono_domain_get ();
1401 MONO_ARCH_SAVE_REGS;
1403 return mono_type_get_object (domain, handle);
1407 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1409 MONO_ARCH_SAVE_REGS;
1411 if (c && type->type && c->type)
1412 return mono_metadata_type_equal (type->type, c->type);
1414 return (type == c) ? TRUE : FALSE;
1417 /* System.TypeCode */
1436 TYPECODE_STRING = 18
1440 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1442 int t = type->type->type;
1444 MONO_ARCH_SAVE_REGS;
1446 if (type->type->byref)
1447 return TYPECODE_OBJECT;
1451 case MONO_TYPE_VOID:
1452 return TYPECODE_OBJECT;
1453 case MONO_TYPE_BOOLEAN:
1454 return TYPECODE_BOOLEAN;
1456 return TYPECODE_BYTE;
1458 return TYPECODE_SBYTE;
1460 return TYPECODE_UINT16;
1462 return TYPECODE_INT16;
1463 case MONO_TYPE_CHAR:
1464 return TYPECODE_CHAR;
1468 return TYPECODE_OBJECT;
1470 return TYPECODE_UINT32;
1472 return TYPECODE_INT32;
1474 return TYPECODE_UINT64;
1476 return TYPECODE_INT64;
1478 return TYPECODE_SINGLE;
1480 return TYPECODE_DOUBLE;
1481 case MONO_TYPE_VALUETYPE: {
1482 MonoClass *klass = type->type->data.klass;
1484 if (klass->enumtype) {
1485 t = mono_class_enum_basetype (klass)->type;
1487 } else if (mono_is_corlib_image (klass->image)) {
1488 if (strcmp (klass->name_space, "System") == 0) {
1489 if (strcmp (klass->name, "Decimal") == 0)
1490 return TYPECODE_DECIMAL;
1491 else if (strcmp (klass->name, "DateTime") == 0)
1492 return TYPECODE_DATETIME;
1495 return TYPECODE_OBJECT;
1497 case MONO_TYPE_STRING:
1498 return TYPECODE_STRING;
1499 case MONO_TYPE_SZARRAY:
1500 case MONO_TYPE_ARRAY:
1501 case MONO_TYPE_OBJECT:
1503 case MONO_TYPE_MVAR:
1504 case MONO_TYPE_TYPEDBYREF:
1505 return TYPECODE_OBJECT;
1506 case MONO_TYPE_CLASS:
1508 MonoClass *klass = type->type->data.klass;
1509 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1510 if (strcmp (klass->name, "DBNull") == 0)
1511 return TYPECODE_DBNULL;
1514 return TYPECODE_OBJECT;
1515 case MONO_TYPE_GENERICINST:
1516 return TYPECODE_OBJECT;
1518 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1524 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1530 MONO_ARCH_SAVE_REGS;
1532 g_assert (type != NULL);
1534 domain = ((MonoObject *)type)->vtable->domain;
1536 if (!c) /* FIXME: dont know what do do here */
1539 klass = mono_class_from_mono_type (type->type);
1540 klassc = mono_class_from_mono_type (c->type);
1542 /* Interface check requires a more complex setup so we
1543 * only do for them. Otherwise we simply avoid mono_class_init.
1545 if (check_interfaces) {
1546 mono_class_init_or_throw (klass);
1547 mono_class_init_or_throw (klassc);
1548 } else if (!klass->supertypes || !klassc->supertypes) {
1549 mono_loader_lock ();
1550 mono_class_setup_supertypes (klass);
1551 mono_class_setup_supertypes (klassc);
1552 mono_loader_unlock ();
1555 if (type->type->byref)
1556 return klassc == mono_defaults.object_class;
1558 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1562 mono_type_is_primitive (MonoType *type)
1564 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1565 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1569 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1571 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1572 return mono_class_enum_basetype (type->data.klass);
1573 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1574 return mono_class_enum_basetype (type->data.generic_class->container_class);
1579 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1585 MONO_ARCH_SAVE_REGS;
1587 g_assert (type != NULL);
1589 domain = ((MonoObject *)type)->vtable->domain;
1591 klass = mono_class_from_mono_type (type->type);
1592 klassc = mono_class_from_mono_type (c->type);
1594 mono_class_init_or_throw (klass);
1595 mono_class_init_or_throw (klassc);
1597 if (type->type->byref ^ c->type->byref)
1600 if (type->type->byref) {
1601 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1602 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1604 klass = mono_class_from_mono_type (t);
1605 klassc = mono_class_from_mono_type (ot);
1607 if (mono_type_is_primitive (t)) {
1608 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1609 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1610 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1611 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1612 return t->type == ot->type;
1614 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1617 if (klass->valuetype)
1618 return klass == klassc;
1619 return klass->valuetype == klassc->valuetype;
1622 return mono_class_is_assignable_from (klass, klassc);
1626 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1628 MonoClass *klass = mono_class_from_mono_type (type->type);
1629 mono_class_init_or_throw (klass);
1630 return mono_object_isinst (obj, klass) != NULL;
1634 ves_icall_get_attributes (MonoReflectionType *type)
1636 MonoClass *klass = mono_class_from_mono_type (type->type);
1637 return klass->flags;
1640 static MonoReflectionMarshal*
1641 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1643 MonoClass *klass = field->field->parent;
1644 MonoMarshalType *info;
1647 if (klass->generic_container ||
1648 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1651 info = mono_marshal_load_type_info (klass);
1653 for (i = 0; i < info->num_fields; ++i) {
1654 if (info->fields [i].field == field->field) {
1655 if (!info->fields [i].mspec)
1658 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1665 static MonoReflectionField*
1666 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1668 gboolean found = FALSE;
1675 klass = handle->parent;
1677 klass = mono_class_from_mono_type (type);
1679 /* Check that the field belongs to the class */
1680 for (k = klass; k; k = k->parent) {
1681 if (k == handle->parent) {
1688 /* The managed code will throw the exception */
1692 return mono_field_get_object (mono_domain_get (), klass, handle);
1696 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1699 MonoType *type = mono_field_get_type_checked (field->field, &error);
1700 if (!mono_error_ok (&error))
1701 mono_error_raise_exception (&error);
1703 return type_array_from_modifiers (field->field->parent->image, type, optional);
1707 vell_icall_get_method_attributes (MonoMethod *method)
1709 return method->flags;
1713 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1716 MonoDomain *domain = mono_domain_get ();
1717 MonoMethodSignature* sig;
1718 MONO_ARCH_SAVE_REGS;
1720 sig = mono_method_signature_checked (method, &error);
1721 if (!mono_error_ok (&error))
1722 mono_error_raise_exception (&error);
1725 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1726 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1727 info->attrs = method->flags;
1728 info->implattrs = method->iflags;
1729 if (sig->call_convention == MONO_CALL_DEFAULT)
1730 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1732 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1737 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1741 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1743 MonoDomain *domain = mono_domain_get ();
1745 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1748 static MonoReflectionMarshal*
1749 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1751 MonoDomain *domain = mono_domain_get ();
1752 MonoReflectionMarshal* res = NULL;
1753 MonoMarshalSpec **mspecs;
1756 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1757 mono_method_get_marshal_info (method, mspecs);
1760 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1762 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1764 mono_metadata_free_marshal_spec (mspecs [i]);
1771 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1773 MonoClass *parent = field->field->parent;
1774 if (!parent->size_inited)
1775 mono_class_init (parent);
1777 return field->field->offset - sizeof (MonoObject);
1780 static MonoReflectionType*
1781 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1784 MONO_ARCH_SAVE_REGS;
1786 parent = declaring? field->field->parent: field->klass;
1788 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1792 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1794 MonoClass *fklass = field->klass;
1795 MonoClassField *cf = field->field;
1796 MonoDomain *domain = mono_object_domain (field);
1798 if (fklass->image->assembly->ref_only)
1799 mono_raise_exception (mono_get_exception_invalid_operation (
1800 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1802 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1803 mono_security_core_clr_ensure_reflection_access_field (cf);
1805 return mono_field_get_value_object (domain, cf, obj);
1809 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1812 MonoClassField *cf = field->field;
1816 MONO_ARCH_SAVE_REGS;
1818 if (field->klass->image->assembly->ref_only)
1819 mono_raise_exception (mono_get_exception_invalid_operation (
1820 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1822 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1823 mono_security_core_clr_ensure_reflection_access_field (cf);
1825 type = mono_field_get_type_checked (cf, &error);
1826 if (!mono_error_ok (&error))
1827 mono_error_raise_exception (&error);
1829 v = (gchar *) value;
1831 switch (type->type) {
1834 case MONO_TYPE_BOOLEAN:
1837 case MONO_TYPE_CHAR:
1846 case MONO_TYPE_VALUETYPE:
1849 v += sizeof (MonoObject);
1851 case MONO_TYPE_STRING:
1852 case MONO_TYPE_OBJECT:
1853 case MONO_TYPE_CLASS:
1854 case MONO_TYPE_ARRAY:
1855 case MONO_TYPE_SZARRAY:
1858 case MONO_TYPE_GENERICINST: {
1859 MonoGenericClass *gclass = type->data.generic_class;
1860 g_assert (!gclass->context.class_inst->is_open);
1862 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1863 MonoClass *nklass = mono_class_from_mono_type (type);
1864 MonoObject *nullable;
1867 * Convert the boxed vtype into a Nullable structure.
1868 * This is complicated by the fact that Nullables have
1869 * a variable structure.
1871 nullable = mono_object_new (mono_domain_get (), nklass);
1873 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1875 v = mono_object_unbox (nullable);
1878 if (gclass->container_class->valuetype && (v != NULL))
1879 v += sizeof (MonoObject);
1883 g_error ("type 0x%x not handled in "
1884 "ves_icall_FieldInfo_SetValueInternal", type->type);
1889 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1890 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1891 if (!vtable->initialized)
1892 mono_runtime_class_init (vtable);
1893 mono_field_static_set_value (vtable, cf, v);
1895 mono_field_set_value (obj, cf, v);
1900 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1902 MonoObject *o = NULL;
1903 MonoClassField *field = this->field;
1905 MonoDomain *domain = mono_object_domain (this);
1907 MonoTypeEnum def_type;
1908 const char *def_value;
1910 MONO_ARCH_SAVE_REGS;
1912 mono_class_init (field->parent);
1914 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1915 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1917 if (field->parent->image->dynamic) {
1919 g_assert_not_reached ();
1922 def_value = mono_class_get_field_default_value (field, &def_type);
1924 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1928 case MONO_TYPE_BOOLEAN:
1931 case MONO_TYPE_CHAR:
1939 case MONO_TYPE_R8: {
1942 /* boxed value type */
1943 t = g_new0 (MonoType, 1);
1945 klass = mono_class_from_mono_type (t);
1947 o = mono_object_new (domain, klass);
1948 v = ((gchar *) o) + sizeof (MonoObject);
1949 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1952 case MONO_TYPE_STRING:
1953 case MONO_TYPE_CLASS:
1954 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1957 g_assert_not_reached ();
1963 static MonoReflectionType*
1964 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1967 MonoClassField *field = ref_field->field;
1968 MonoType *type = mono_field_get_type_checked (field, &error);
1969 if (!mono_error_ok (&error))
1970 mono_error_raise_exception (&error);
1971 return mono_type_get_object (mono_object_domain (ref_field), type);
1974 static MonoReflectionType*
1975 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1977 MonoMethod *method = rmethod->method.method;
1979 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1982 /* From MonoProperty.cs */
1984 PInfo_Attributes = 1,
1985 PInfo_GetMethod = 1 << 1,
1986 PInfo_SetMethod = 1 << 2,
1987 PInfo_ReflectedType = 1 << 3,
1988 PInfo_DeclaringType = 1 << 4,
1993 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1995 MonoDomain *domain = mono_object_domain (property);
1997 MONO_ARCH_SAVE_REGS;
1999 if ((req_info & PInfo_ReflectedType) != 0)
2000 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2001 if ((req_info & PInfo_DeclaringType) != 0)
2002 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2004 if ((req_info & PInfo_Name) != 0)
2005 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2007 if ((req_info & PInfo_Attributes) != 0)
2008 info->attrs = property->property->attrs;
2010 if ((req_info & PInfo_GetMethod) != 0)
2011 MONO_STRUCT_SETREF (info, get, property->property->get ?
2012 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2014 if ((req_info & PInfo_SetMethod) != 0)
2015 MONO_STRUCT_SETREF (info, set, property->property->set ?
2016 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2018 * There may be other methods defined for properties, though, it seems they are not exposed
2019 * in the reflection API
2024 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2026 MonoDomain *domain = mono_object_domain (event);
2028 MONO_ARCH_SAVE_REGS;
2030 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2031 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2033 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2034 info->attrs = event->event->attrs;
2035 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2036 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2037 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2039 #ifndef MONO_SMALL_CONFIG
2040 if (event->event->other) {
2042 while (event->event->other [n])
2044 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2046 for (i = 0; i < n; i++)
2047 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2053 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2058 mono_class_setup_interfaces (klass, error);
2059 if (!mono_error_ok (error))
2062 for (i = 0; i < klass->interface_count; i++) {
2063 ic = klass->interfaces [i];
2064 g_hash_table_insert (ifaces, ic, ic);
2066 collect_interfaces (ic, ifaces, error);
2067 if (!mono_error_ok (error))
2073 MonoArray *iface_array;
2074 MonoGenericContext *context;
2078 } FillIfaceArrayData;
2081 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2083 FillIfaceArrayData *data = user_data;
2084 MonoClass *ic = key;
2085 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2087 if (!mono_error_ok (data->error))
2090 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2091 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2092 if (!mono_error_ok (data->error))
2096 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2099 mono_metadata_free_type (inflated);
2103 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2106 MonoClass *class = mono_class_from_mono_type (type->type);
2108 FillIfaceArrayData data = { 0 };
2111 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2113 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2114 data.context = mono_class_get_context (class);
2115 class = class->generic_class->container_class;
2118 for (parent = class; parent; parent = parent->parent) {
2119 mono_class_setup_interfaces (parent, &error);
2120 if (!mono_error_ok (&error))
2122 collect_interfaces (parent, iface_hash, &error);
2123 if (!mono_error_ok (&error))
2127 data.error = &error;
2128 data.domain = mono_object_domain (type);
2130 len = g_hash_table_size (iface_hash);
2132 g_hash_table_destroy (iface_hash);
2133 if (!data.domain->empty_types)
2134 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2135 return data.domain->empty_types;
2138 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2139 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2140 if (!mono_error_ok (&error))
2143 g_hash_table_destroy (iface_hash);
2144 return data.iface_array;
2147 g_hash_table_destroy (iface_hash);
2148 mono_error_raise_exception (&error);
2153 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2155 gboolean variance_used;
2156 MonoClass *class = mono_class_from_mono_type (type->type);
2157 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2158 MonoReflectionMethod *member;
2161 int i = 0, len, ioffset;
2164 MONO_ARCH_SAVE_REGS;
2165 mono_class_init_or_throw (class);
2166 mono_class_init_or_throw (iclass);
2168 mono_class_setup_vtable (class);
2170 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2174 len = mono_class_num_methods (iclass);
2175 domain = mono_object_domain (type);
2176 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2177 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2179 while ((method = mono_class_get_methods (iclass, &iter))) {
2180 member = mono_method_get_object (domain, method, iclass);
2181 mono_array_setref (*methods, i, member);
2182 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2183 mono_array_setref (*targets, i, member);
2190 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2192 MonoClass *klass = mono_class_from_mono_type (type->type);
2193 mono_class_init_or_throw (klass);
2195 if (klass->image->dynamic) {
2196 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2197 *packing = tb->packing_size;
2198 *size = tb->class_size;
2200 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2204 static MonoReflectionType*
2205 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2209 MONO_ARCH_SAVE_REGS;
2211 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2212 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2214 class = mono_class_from_mono_type (type->type);
2215 mono_class_init_or_throw (class);
2217 // GetElementType should only return a type for:
2218 // Array Pointer PassedByRef
2219 if (type->type->byref)
2220 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2221 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2222 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2223 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2224 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2229 static MonoReflectionType*
2230 ves_icall_get_type_parent (MonoReflectionType *type)
2232 MonoClass *class = mono_class_from_mono_type (type->type);
2233 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2237 ves_icall_type_ispointer (MonoReflectionType *type)
2239 MONO_ARCH_SAVE_REGS;
2241 return type->type->type == MONO_TYPE_PTR;
2245 ves_icall_type_isprimitive (MonoReflectionType *type)
2247 MONO_ARCH_SAVE_REGS;
2249 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)));
2253 ves_icall_type_isbyref (MonoReflectionType *type)
2255 MONO_ARCH_SAVE_REGS;
2257 return type->type->byref;
2261 ves_icall_type_iscomobject (MonoReflectionType *type)
2263 MonoClass *klass = mono_class_from_mono_type (type->type);
2264 mono_class_init_or_throw (klass);
2266 return (klass && klass->is_com_object);
2269 static MonoReflectionModule*
2270 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2272 MonoClass *class = mono_class_from_mono_type (type->type);
2273 return mono_module_get_object (mono_object_domain (type), class->image);
2276 static MonoReflectionAssembly*
2277 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2279 MonoDomain *domain = mono_domain_get ();
2280 MonoClass *class = mono_class_from_mono_type (type->type);
2281 return mono_assembly_get_object (domain, class->image->assembly);
2284 static MonoReflectionType*
2285 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2287 MonoDomain *domain = mono_domain_get ();
2290 MONO_ARCH_SAVE_REGS;
2292 if (type->type->byref)
2294 if (type->type->type == MONO_TYPE_VAR)
2295 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2296 else if (type->type->type == MONO_TYPE_MVAR)
2297 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2299 class = mono_class_from_mono_type (type->type)->nested_in;
2301 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2305 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2307 MonoDomain *domain = mono_domain_get ();
2308 MonoClass *class = mono_class_from_mono_type (type->type);
2310 if (type->type->byref) {
2311 char *n = g_strdup_printf ("%s&", class->name);
2312 MonoString *res = mono_string_new (domain, n);
2318 return mono_string_new (domain, class->name);
2323 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2325 MonoDomain *domain = mono_domain_get ();
2326 MonoClass *class = mono_class_from_mono_type (type->type);
2328 while (class->nested_in)
2329 class = class->nested_in;
2331 if (class->name_space [0] == '\0')
2334 return mono_string_new (domain, class->name_space);
2338 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2342 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2343 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2345 class = mono_class_from_mono_type (type->type);
2351 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2354 MonoClass *klass, *pklass;
2355 MonoDomain *domain = mono_object_domain (type);
2356 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2358 MONO_ARCH_SAVE_REGS;
2360 klass = mono_class_from_mono_type (type->type);
2362 if (klass->generic_container) {
2363 MonoGenericContainer *container = klass->generic_container;
2364 res = mono_array_new_specific (array_vtable, container->type_argc);
2365 for (i = 0; i < container->type_argc; ++i) {
2366 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2367 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2369 } else if (klass->generic_class) {
2370 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2371 res = mono_array_new_specific (array_vtable, inst->type_argc);
2372 for (i = 0; i < inst->type_argc; ++i)
2373 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2375 res = mono_array_new_specific (array_vtable, 0);
2381 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2384 MONO_ARCH_SAVE_REGS;
2386 if (!IS_MONOTYPE (type))
2389 if (type->type->byref)
2392 klass = mono_class_from_mono_type (type->type);
2393 return klass->generic_container != NULL;
2396 static MonoReflectionType*
2397 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2400 MONO_ARCH_SAVE_REGS;
2402 if (type->type->byref)
2405 klass = mono_class_from_mono_type (type->type);
2407 if (klass->generic_container) {
2408 return type; /* check this one */
2410 if (klass->generic_class) {
2411 MonoClass *generic_class = klass->generic_class->container_class;
2414 tb = mono_class_get_ref_info (generic_class);
2416 if (generic_class->wastypebuilder && tb)
2419 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2424 static MonoReflectionType*
2425 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2428 MonoType *geninst, **types;
2431 g_assert (IS_MONOTYPE (type));
2432 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2434 count = mono_array_length (type_array);
2435 types = g_new0 (MonoType *, count);
2437 for (i = 0; i < count; i++) {
2438 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2439 types [i] = t->type;
2442 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2447 class = mono_class_from_mono_type (geninst);
2449 /*we might inflate to the GTD*/
2450 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2451 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2453 return mono_type_get_object (mono_object_domain (type), geninst);
2457 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2460 MONO_ARCH_SAVE_REGS;
2462 if (type->type->byref)
2465 klass = mono_class_from_mono_type (type->type);
2467 return klass->generic_class != NULL;
2471 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2474 MONO_ARCH_SAVE_REGS;
2476 if (!IS_MONOTYPE (type))
2479 if (type->type->byref)
2482 klass = mono_class_from_mono_type (type->type);
2483 return klass->generic_class != NULL || klass->generic_container != NULL;
2487 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2489 MONO_ARCH_SAVE_REGS;
2491 if (!IS_MONOTYPE (type))
2494 if (is_generic_parameter (type->type))
2495 return mono_type_get_generic_param_num (type->type);
2499 static GenericParameterAttributes
2500 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2502 MONO_ARCH_SAVE_REGS;
2504 g_assert (IS_MONOTYPE (type));
2505 g_assert (is_generic_parameter (type->type));
2506 return mono_generic_param_info (type->type->data.generic_param)->flags;
2510 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2512 MonoGenericParamInfo *param_info;
2518 MONO_ARCH_SAVE_REGS;
2520 g_assert (IS_MONOTYPE (type));
2522 domain = mono_object_domain (type);
2523 param_info = mono_generic_param_info (type->type->data.generic_param);
2524 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2527 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2528 for (i = 0; i < count; i++)
2529 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2536 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2538 MONO_ARCH_SAVE_REGS;
2539 return is_generic_parameter (type->type);
2543 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2545 MONO_ARCH_SAVE_REGS;
2546 return is_generic_parameter (tb->type.type);
2550 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2551 MonoReflectionType *t)
2553 enumtype->type = t->type;
2556 static MonoReflectionMethod*
2557 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2558 MonoReflectionMethod* generic)
2565 MONO_ARCH_SAVE_REGS;
2567 domain = ((MonoObject *)type)->vtable->domain;
2569 klass = mono_class_from_mono_type (type->type);
2570 mono_class_init_or_throw (klass);
2573 while ((method = mono_class_get_methods (klass, &iter))) {
2574 if (method->token == generic->method->token)
2575 return mono_method_get_object (domain, method, klass);
2583 static MonoReflectionMethod *
2584 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2587 MonoType *type = ref_type->type;
2589 MONO_ARCH_SAVE_REGS;
2591 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2592 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2593 if (type->type == MONO_TYPE_VAR)
2596 method = mono_type_get_generic_param_owner (type)->owner.method;
2598 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2601 static MonoReflectionDllImportAttribute*
2602 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2604 static MonoClass *DllImportAttributeClass = NULL;
2605 MonoDomain *domain = mono_domain_get ();
2606 MonoReflectionDllImportAttribute *attr;
2607 MonoImage *image = method->klass->image;
2608 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2609 MonoTableInfo *tables = image->tables;
2610 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2611 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2612 guint32 im_cols [MONO_IMPLMAP_SIZE];
2613 guint32 scope_token;
2614 const char *import = NULL;
2615 const char *scope = NULL;
2618 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2621 if (!DllImportAttributeClass) {
2622 DllImportAttributeClass =
2623 mono_class_from_name (mono_defaults.corlib,
2624 "System.Runtime.InteropServices", "DllImportAttribute");
2625 g_assert (DllImportAttributeClass);
2628 if (method->klass->image->dynamic) {
2629 MonoReflectionMethodAux *method_aux =
2630 g_hash_table_lookup (
2631 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2633 import = method_aux->dllentry;
2634 scope = method_aux->dll;
2637 if (!import || !scope) {
2638 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2643 if (piinfo->implmap_idx) {
2644 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2646 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2647 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2648 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2649 scope = mono_metadata_string_heap (image, scope_token);
2652 flags = piinfo->piflags;
2654 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2656 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2657 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2658 attr->call_conv = (flags & 0x700) >> 8;
2659 attr->charset = ((flags & 0x6) >> 1) + 1;
2660 if (attr->charset == 1)
2662 attr->exact_spelling = (flags & 0x1) != 0;
2663 attr->set_last_error = (flags & 0x40) != 0;
2664 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2665 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2666 attr->preserve_sig = FALSE;
2671 static MonoReflectionMethod *
2672 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2674 MonoMethodInflated *imethod;
2677 MONO_ARCH_SAVE_REGS;
2679 if (method->method->is_generic)
2682 if (!method->method->is_inflated)
2685 imethod = (MonoMethodInflated *) method->method;
2687 result = imethod->declaring;
2688 /* Not a generic method. */
2689 if (!result->is_generic)
2692 if (method->method->klass->image->dynamic) {
2693 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2694 MonoReflectionMethod *res;
2697 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2698 * the dynamic case as well ?
2700 mono_loader_lock ();
2701 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2702 mono_loader_unlock ();
2708 if (imethod->context.class_inst) {
2709 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2710 /*Generic methods gets the context of the GTD.*/
2711 if (mono_class_get_context (klass))
2712 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2715 return mono_method_get_object (mono_object_domain (method), result, NULL);
2719 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2721 MONO_ARCH_SAVE_REGS;
2723 return mono_method_signature (method->method)->generic_param_count != 0;
2727 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2729 MONO_ARCH_SAVE_REGS;
2731 return method->method->is_generic;
2735 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2740 MONO_ARCH_SAVE_REGS;
2742 domain = mono_object_domain (method);
2744 if (method->method->is_inflated) {
2745 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2748 count = inst->type_argc;
2749 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2751 for (i = 0; i < count; i++)
2752 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2758 count = mono_method_signature (method->method)->generic_param_count;
2759 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2761 for (i = 0; i < count; i++) {
2762 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2763 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2764 MonoClass *pklass = mono_class_from_generic_parameter (
2765 param, method->method->klass->image, TRUE);
2766 mono_array_setref (res, i,
2767 mono_type_get_object (domain, &pklass->byval_arg));
2774 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2777 * Invoke from reflection is supposed to always be a virtual call (the API
2778 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2779 * greater flexibility.
2781 MonoMethod *m = method->method;
2785 MONO_ARCH_SAVE_REGS;
2789 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2790 mono_security_core_clr_ensure_reflection_access_method (m);
2792 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2793 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2794 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2799 if (!mono_object_isinst (this, m->klass)) {
2800 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2803 m = mono_object_get_virtual_method (this, m);
2804 /* must pass the pointer to the value for valuetype methods */
2805 if (m->klass->valuetype)
2806 obj = mono_object_unbox (this);
2807 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2808 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2813 pcount = params? mono_array_length (params): 0;
2814 if (pcount != mono_method_signature (m)->param_count) {
2815 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2819 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2820 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2824 if (m->klass->image->assembly->ref_only) {
2825 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."));
2829 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2832 intptr_t *lower_bounds;
2833 pcount = mono_array_length (params);
2834 lengths = alloca (sizeof (uintptr_t) * pcount);
2835 /* Note: the synthetized array .ctors have int32 as argument type */
2836 for (i = 0; i < pcount; ++i)
2837 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2839 if (m->klass->rank == pcount) {
2840 /* Only lengths provided. */
2841 lower_bounds = NULL;
2843 g_assert (pcount == (m->klass->rank * 2));
2844 /* lower bounds are first. */
2845 lower_bounds = (intptr_t*)lengths;
2846 lengths += m->klass->rank;
2849 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2851 return mono_runtime_invoke_array (m, obj, params, NULL);
2855 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2857 MonoDomain *domain = mono_object_domain (method);
2858 MonoMethod *m = method->method;
2859 MonoMethodSignature *sig = mono_method_signature (m);
2860 MonoArray *out_args;
2862 int i, j, outarg_count = 0;
2864 MONO_ARCH_SAVE_REGS;
2866 if (m->klass == mono_defaults.object_class) {
2868 if (!strcmp (m->name, "FieldGetter")) {
2869 MonoClass *k = this->vtable->klass;
2873 /* If this is a proxy, then it must be a CBO */
2874 if (k == mono_defaults.transparent_proxy_class) {
2875 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2876 this = tp->rp->unwrapped_server;
2878 k = this->vtable->klass;
2881 name = mono_array_get (params, MonoString *, 1);
2882 str = mono_string_to_utf8 (name);
2885 MonoClassField* field = mono_class_get_field_from_name (k, str);
2887 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2888 if (field_klass->valuetype)
2889 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2891 result = *((gpointer *)((char *)this + field->offset));
2893 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2894 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2895 mono_array_setref (out_args, 0, result);
2903 g_assert_not_reached ();
2905 } else if (!strcmp (m->name, "FieldSetter")) {
2906 MonoClass *k = this->vtable->klass;
2912 /* If this is a proxy, then it must be a CBO */
2913 if (k == mono_defaults.transparent_proxy_class) {
2914 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2915 this = tp->rp->unwrapped_server;
2917 k = this->vtable->klass;
2920 name = mono_array_get (params, MonoString *, 1);
2921 str = mono_string_to_utf8 (name);
2924 MonoClassField* field = mono_class_get_field_from_name (k, str);
2926 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2927 MonoObject *val = mono_array_get (params, gpointer, 2);
2929 if (field_klass->valuetype) {
2930 size = mono_type_size (field->type, &align);
2931 g_assert (size == mono_class_value_size (field_klass, NULL));
2932 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2934 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2937 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2938 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2948 g_assert_not_reached ();
2953 for (i = 0; i < mono_array_length (params); i++) {
2954 if (sig->params [i]->byref)
2958 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2960 /* handle constructors only for objects already allocated */
2961 if (!strcmp (method->method->name, ".ctor"))
2964 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2965 g_assert (!method->method->klass->valuetype);
2966 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2968 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2969 if (sig->params [i]->byref) {
2971 arg = mono_array_get (params, gpointer, i);
2972 mono_array_setref (out_args, j, arg);
2977 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2983 read_enum_value (char *mem, int type)
2987 return *(guint8*)mem;
2989 return *(gint8*)mem;
2991 return *(guint16*)mem;
2993 return *(gint16*)mem;
2995 return *(guint32*)mem;
2997 return *(gint32*)mem;
2999 return *(guint64*)mem;
3001 return *(gint64*)mem;
3003 g_assert_not_reached ();
3009 write_enum_value (char *mem, int type, guint64 value)
3013 case MONO_TYPE_I1: {
3014 guint8 *p = (guint8*)mem;
3019 case MONO_TYPE_I2: {
3020 guint16 *p = (void*)mem;
3025 case MONO_TYPE_I4: {
3026 guint32 *p = (void*)mem;
3031 case MONO_TYPE_I8: {
3032 guint64 *p = (void*)mem;
3037 g_assert_not_reached ();
3043 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3046 MonoClass *enumc, *objc;
3051 MONO_ARCH_SAVE_REGS;
3053 MONO_CHECK_ARG_NULL (enumType);
3054 MONO_CHECK_ARG_NULL (value);
3056 domain = mono_object_domain (enumType);
3057 enumc = mono_class_from_mono_type (enumType->type);
3059 mono_class_init_or_throw (enumc);
3061 objc = value->vtable->klass;
3063 if (!enumc->enumtype)
3064 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3065 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3066 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."));
3068 etype = mono_class_enum_basetype (enumc);
3070 /* MS throws this for typebuilders */
3071 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3073 res = mono_object_new (domain, enumc);
3074 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3075 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3081 ves_icall_System_Enum_get_value (MonoObject *this)
3089 MONO_ARCH_SAVE_REGS;
3094 g_assert (this->vtable->klass->enumtype);
3096 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3097 res = mono_object_new (mono_object_domain (this), enumc);
3098 dst = (char *)res + sizeof (MonoObject);
3099 src = (char *)this + sizeof (MonoObject);
3100 size = mono_class_value_size (enumc, NULL);
3102 memcpy (dst, src, size);
3107 static MonoReflectionType *
3108 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3113 MONO_ARCH_SAVE_REGS;
3115 klass = mono_class_from_mono_type (type->type);
3116 mono_class_init_or_throw (klass);
3118 etype = mono_class_enum_basetype (klass);
3120 /* MS throws this for typebuilders */
3121 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3123 return mono_type_get_object (mono_object_domain (type), etype);
3127 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3129 gpointer tdata = (char *)this + sizeof (MonoObject);
3130 gpointer odata = (char *)other + sizeof (MonoObject);
3131 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3132 g_assert (basetype);
3134 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3135 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3136 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3139 return me > other ? 1 : -1; \
3142 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3143 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3144 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3147 return me - other; \
3150 switch (basetype->type) {
3152 COMPARE_ENUM_VALUES (guint8);
3154 COMPARE_ENUM_VALUES (gint8);
3155 case MONO_TYPE_CHAR:
3157 COMPARE_ENUM_VALUES_RANGE (guint16);
3159 COMPARE_ENUM_VALUES (gint16);
3161 COMPARE_ENUM_VALUES (guint32);
3163 COMPARE_ENUM_VALUES (gint32);
3165 COMPARE_ENUM_VALUES (guint64);
3167 COMPARE_ENUM_VALUES (gint64);
3169 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3171 #undef COMPARE_ENUM_VALUES_RANGE
3172 #undef COMPARE_ENUM_VALUES
3177 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3179 gpointer data = (char *)this + sizeof (MonoObject);
3180 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3181 g_assert (basetype);
3183 switch (basetype->type) {
3185 return *((gint8*)data);
3187 return *((guint8*)data);
3188 case MONO_TYPE_CHAR:
3190 return *((guint16*)data);
3193 return *((gint16*)data);
3195 return *((guint32*)data);
3197 return *((gint32*)data);
3199 case MONO_TYPE_I8: {
3200 gint64 value = *((gint64*)data);
3201 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3204 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3210 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3212 MonoDomain *domain = mono_object_domain (type);
3213 MonoClass *enumc = mono_class_from_mono_type (type->type);
3214 guint j = 0, nvalues, crow;
3216 MonoClassField *field;
3218 MONO_ARCH_SAVE_REGS;
3220 mono_class_init_or_throw (enumc);
3222 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3223 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3224 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3225 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3229 while ((field = mono_class_get_fields (enumc, &iter))) {
3232 MonoTypeEnum def_type;
3234 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3236 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3238 if (mono_field_is_deleted (field))
3240 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3242 p = mono_class_get_field_default_value (field, &def_type);
3243 len = mono_metadata_decode_blob_size (p, &p);
3244 switch (mono_class_enum_basetype (enumc)->type) {
3247 mono_array_set (info->values, gchar, j, *p);
3249 case MONO_TYPE_CHAR:
3252 mono_array_set (info->values, gint16, j, read16 (p));
3256 mono_array_set (info->values, gint32, j, read32 (p));
3260 mono_array_set (info->values, gint64, j, read64 (p));
3263 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3270 BFLAGS_IgnoreCase = 1,
3271 BFLAGS_DeclaredOnly = 2,
3272 BFLAGS_Instance = 4,
3274 BFLAGS_Public = 0x10,
3275 BFLAGS_NonPublic = 0x20,
3276 BFLAGS_FlattenHierarchy = 0x40,
3277 BFLAGS_InvokeMethod = 0x100,
3278 BFLAGS_CreateInstance = 0x200,
3279 BFLAGS_GetField = 0x400,
3280 BFLAGS_SetField = 0x800,
3281 BFLAGS_GetProperty = 0x1000,
3282 BFLAGS_SetProperty = 0x2000,
3283 BFLAGS_ExactBinding = 0x10000,
3284 BFLAGS_SuppressChangeType = 0x20000,
3285 BFLAGS_OptionalParamBinding = 0x40000
3288 static MonoReflectionField *
3289 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3292 MonoClass *startklass, *klass;
3294 MonoClassField *field;
3297 int (*compare_func) (const char *s1, const char *s2) = NULL;
3298 domain = ((MonoObject *)type)->vtable->domain;
3299 klass = startklass = mono_class_from_mono_type (type->type);
3302 mono_raise_exception (mono_get_exception_argument_null ("name"));
3303 if (type->type->byref)
3306 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3309 if (klass->exception_type != MONO_EXCEPTION_NONE)
3310 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3313 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3314 guint32 flags = mono_field_get_flags (field);
3317 if (mono_field_is_deleted_with_flags (field, flags))
3319 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3320 if (bflags & BFLAGS_Public)
3322 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3323 if (bflags & BFLAGS_NonPublic) {
3330 if (flags & FIELD_ATTRIBUTE_STATIC) {
3331 if (bflags & BFLAGS_Static)
3332 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3335 if (bflags & BFLAGS_Instance)
3342 utf8_name = mono_string_to_utf8 (name);
3344 if (compare_func (mono_field_get_name (field), utf8_name)) {
3350 return mono_field_get_object (domain, klass, field);
3352 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3359 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3362 MonoClass *startklass, *klass, *refklass;
3367 MonoClassField *field;
3368 MonoPtrArray tmp_array;
3370 MONO_ARCH_SAVE_REGS;
3372 domain = ((MonoObject *)type)->vtable->domain;
3373 if (type->type->byref)
3374 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3375 klass = startklass = mono_class_from_mono_type (type->type);
3376 refklass = mono_class_from_mono_type (reftype->type);
3378 mono_ptr_array_init (tmp_array, 2);
3381 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3382 mono_ptr_array_destroy (tmp_array);
3383 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3387 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3388 guint32 flags = mono_field_get_flags (field);
3390 if (mono_field_is_deleted_with_flags (field, flags))
3392 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3393 if (bflags & BFLAGS_Public)
3395 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3396 if (bflags & BFLAGS_NonPublic) {
3403 if (flags & FIELD_ATTRIBUTE_STATIC) {
3404 if (bflags & BFLAGS_Static)
3405 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3408 if (bflags & BFLAGS_Instance)
3414 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3415 mono_ptr_array_append (tmp_array, member);
3417 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3420 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3422 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3423 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3425 mono_ptr_array_destroy (tmp_array);
3431 method_nonpublic (MonoMethod* method, gboolean start_klass)
3433 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3434 case METHOD_ATTRIBUTE_ASSEM:
3435 return (start_klass || mono_defaults.generic_ilist_class);
3436 case METHOD_ATTRIBUTE_PRIVATE:
3438 case METHOD_ATTRIBUTE_PUBLIC:
3446 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3448 static MonoClass *MethodInfo_array;
3450 MonoClass *startklass, *klass, *refklass;
3455 int i, len, match, nslots;
3456 /*FIXME, use MonoBitSet*/
3457 guint32 method_slots_default [8];
3458 guint32 *method_slots = NULL;
3459 gchar *mname = NULL;
3460 int (*compare_func) (const char *s1, const char *s2) = NULL;
3461 MonoVTable *array_vtable;
3463 MonoPtrArray tmp_array;
3465 mono_ptr_array_init (tmp_array, 4);
3467 if (!MethodInfo_array) {
3468 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3469 mono_memory_barrier ();
3470 MethodInfo_array = klass;
3473 domain = ((MonoObject *)type)->vtable->domain;
3474 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3475 if (type->type->byref)
3476 return mono_array_new_specific (array_vtable, 0);
3477 klass = startklass = mono_class_from_mono_type (type->type);
3478 refklass = mono_class_from_mono_type (reftype->type);
3482 mname = mono_string_to_utf8 (name);
3483 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3486 /* An optimization for calls made from Delegate:CreateDelegate () */
3487 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3488 method = mono_get_delegate_invoke (klass);
3489 if (mono_loader_get_last_error ())
3492 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3494 res = mono_array_new_specific (array_vtable, 1);
3495 mono_array_setref (res, 0, member);
3500 mono_class_setup_vtable (klass);
3501 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3504 if (is_generic_parameter (type->type))
3505 nslots = mono_class_get_vtable_size (klass->parent);
3507 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3508 if (nslots >= sizeof (method_slots_default) * 8) {
3509 method_slots = g_new0 (guint32, nslots / 32 + 1);
3511 method_slots = method_slots_default;
3512 memset (method_slots, 0, sizeof (method_slots_default));
3515 mono_class_setup_vtable (klass);
3516 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3520 while ((method = mono_class_get_methods (klass, &iter))) {
3522 if (method->slot != -1) {
3523 g_assert (method->slot < nslots);
3524 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3526 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3527 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3530 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3532 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3533 if (bflags & BFLAGS_Public)
3535 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3541 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3542 if (bflags & BFLAGS_Static)
3543 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3546 if (bflags & BFLAGS_Instance)
3554 if (compare_func (mname, method->name))
3560 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3562 mono_ptr_array_append (tmp_array, member);
3564 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3568 if (method_slots != method_slots_default)
3569 g_free (method_slots);
3571 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3573 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3574 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3576 mono_ptr_array_destroy (tmp_array);
3581 if (method_slots != method_slots_default)
3582 g_free (method_slots);
3583 mono_ptr_array_destroy (tmp_array);
3584 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3585 ex = mono_class_get_exception_for_failure (klass);
3587 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3588 mono_loader_clear_error ();
3590 mono_raise_exception (ex);
3595 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3598 static MonoClass *System_Reflection_ConstructorInfo;
3599 MonoClass *startklass, *klass, *refklass;
3604 gpointer iter = NULL;
3605 MonoPtrArray tmp_array;
3607 MONO_ARCH_SAVE_REGS;
3609 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3611 domain = ((MonoObject *)type)->vtable->domain;
3612 if (type->type->byref)
3613 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3614 klass = startklass = mono_class_from_mono_type (type->type);
3615 refklass = mono_class_from_mono_type (reftype->type);
3617 if (!System_Reflection_ConstructorInfo)
3618 System_Reflection_ConstructorInfo = mono_class_from_name (
3619 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3622 while ((method = mono_class_get_methods (klass, &iter))) {
3624 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3626 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3627 if (bflags & BFLAGS_Public)
3630 if (bflags & BFLAGS_NonPublic)
3636 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3637 if (bflags & BFLAGS_Static)
3638 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3641 if (bflags & BFLAGS_Instance)
3647 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3649 mono_ptr_array_append (tmp_array, member);
3652 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3654 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3655 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3657 mono_ptr_array_destroy (tmp_array);
3663 property_hash (gconstpointer data)
3665 MonoProperty *prop = (MonoProperty*)data;
3667 return g_str_hash (prop->name);
3671 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3673 // Properties are hide-by-name-and-signature
3674 if (!g_str_equal (prop1->name, prop2->name))
3677 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3679 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3685 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3690 return method_nonpublic (accessor, start_klass);
3694 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3698 static MonoClass *System_Reflection_PropertyInfo;
3699 MonoClass *startklass, *klass;
3705 gchar *propname = NULL;
3706 int (*compare_func) (const char *s1, const char *s2) = NULL;
3708 GHashTable *properties = NULL;
3709 MonoPtrArray tmp_array;
3711 MONO_ARCH_SAVE_REGS;
3713 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3715 if (!System_Reflection_PropertyInfo)
3716 System_Reflection_PropertyInfo = mono_class_from_name (
3717 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3719 domain = ((MonoObject *)type)->vtable->domain;
3720 if (type->type->byref)
3721 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3722 klass = startklass = mono_class_from_mono_type (type->type);
3725 propname = mono_string_to_utf8 (name);
3726 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3729 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3731 mono_class_setup_vtable (klass);
3732 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3736 while ((prop = mono_class_get_properties (klass, &iter))) {
3742 flags = method->flags;
3745 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3746 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3747 if (bflags & BFLAGS_Public)
3749 } else if (bflags & BFLAGS_NonPublic) {
3750 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3751 property_accessor_nonpublic(prop->set, startklass == klass)) {
3758 if (flags & METHOD_ATTRIBUTE_STATIC) {
3759 if (bflags & BFLAGS_Static)
3760 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3763 if (bflags & BFLAGS_Instance)
3772 if (compare_func (propname, prop->name))
3776 if (g_hash_table_lookup (properties, prop))
3779 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3781 g_hash_table_insert (properties, prop, prop);
3783 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3786 g_hash_table_destroy (properties);
3789 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3790 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3791 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3793 mono_ptr_array_destroy (tmp_array);
3799 g_hash_table_destroy (properties);
3802 mono_ptr_array_destroy (tmp_array);
3804 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3805 ex = mono_class_get_exception_for_failure (klass);
3807 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3808 mono_loader_clear_error ();
3810 mono_raise_exception (ex);
3814 static MonoReflectionEvent *
3815 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3818 MonoClass *klass, *startklass;
3823 int (*compare_func) (const char *s1, const char *s2);
3825 MONO_ARCH_SAVE_REGS;
3827 event_name = mono_string_to_utf8 (name);
3828 if (type->type->byref)
3830 klass = startklass = mono_class_from_mono_type (type->type);
3831 domain = mono_object_domain (type);
3833 mono_class_init_or_throw (klass);
3835 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3837 if (klass->exception_type != MONO_EXCEPTION_NONE)
3838 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3841 while ((event = mono_class_get_events (klass, &iter))) {
3842 if (compare_func (event->name, event_name))
3845 method = event->add;
3847 method = event->remove;
3849 method = event->raise;
3851 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3852 if (!(bflags & BFLAGS_Public))
3855 if (!(bflags & BFLAGS_NonPublic))
3857 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3861 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3862 if (!(bflags & BFLAGS_Static))
3864 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3867 if (!(bflags & BFLAGS_Instance))
3871 if (!(bflags & BFLAGS_NonPublic))
3874 g_free (event_name);
3875 return mono_event_get_object (domain, startklass, event);
3878 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3881 g_free (event_name);
3886 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3890 static MonoClass *System_Reflection_EventInfo;
3891 MonoClass *startklass, *klass;
3898 MonoPtrArray tmp_array;
3900 MONO_ARCH_SAVE_REGS;
3902 mono_ptr_array_init (tmp_array, 4);
3904 if (!System_Reflection_EventInfo)
3905 System_Reflection_EventInfo = mono_class_from_name (
3906 mono_defaults.corlib, "System.Reflection", "EventInfo");
3908 domain = mono_object_domain (type);
3909 if (type->type->byref)
3910 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3911 klass = startklass = mono_class_from_mono_type (type->type);
3914 mono_class_setup_vtable (klass);
3915 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3919 while ((event = mono_class_get_events (klass, &iter))) {
3921 method = event->add;
3923 method = event->remove;
3925 method = event->raise;
3927 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3928 if (bflags & BFLAGS_Public)
3930 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3931 if (bflags & BFLAGS_NonPublic)
3936 if (bflags & BFLAGS_NonPublic)
3942 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3943 if (bflags & BFLAGS_Static)
3944 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3947 if (bflags & BFLAGS_Instance)
3952 if (bflags & BFLAGS_Instance)
3956 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3958 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3961 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3963 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3964 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3966 mono_ptr_array_destroy (tmp_array);
3971 mono_ptr_array_destroy (tmp_array);
3972 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3973 ex = mono_class_get_exception_for_failure (klass);
3975 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3976 mono_loader_clear_error ();
3978 mono_raise_exception (ex);
3982 static MonoReflectionType *
3983 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3991 MONO_ARCH_SAVE_REGS;
3994 mono_raise_exception (mono_get_exception_argument_null ("name"));
3996 domain = ((MonoObject *)type)->vtable->domain;
3997 if (type->type->byref)
3999 klass = mono_class_from_mono_type (type->type);
4001 str = mono_string_to_utf8 (name);
4004 if (klass->exception_type != MONO_EXCEPTION_NONE)
4005 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4008 * If a nested type is generic, return its generic type definition.
4009 * Note that this means that the return value is essentially a
4010 * nested type of the generic type definition of @klass.
4012 * A note in MSDN claims that a generic type definition can have
4013 * nested types that aren't generic. In any case, the container of that
4014 * nested type would be the generic type definition.
4016 if (klass->generic_class)
4017 klass = klass->generic_class->container_class;
4020 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4022 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4023 if (bflags & BFLAGS_Public)
4026 if (bflags & BFLAGS_NonPublic)
4031 if (strcmp (nested->name, str) == 0){
4033 return mono_type_get_object (domain, &nested->byval_arg);
4036 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4043 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4052 MonoPtrArray tmp_array;
4054 MONO_ARCH_SAVE_REGS;
4056 domain = ((MonoObject *)type)->vtable->domain;
4057 if (type->type->byref)
4058 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4059 klass = mono_class_from_mono_type (type->type);
4062 * If a nested type is generic, return its generic type definition.
4063 * Note that this means that the return value is essentially the set
4064 * of nested types of the generic type definition of @klass.
4066 * A note in MSDN claims that a generic type definition can have
4067 * nested types that aren't generic. In any case, the container of that
4068 * nested type would be the generic type definition.
4070 if (klass->generic_class)
4071 klass = klass->generic_class->container_class;
4073 mono_ptr_array_init (tmp_array, 1);
4075 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4077 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4078 if (bflags & BFLAGS_Public)
4081 if (bflags & BFLAGS_NonPublic)
4086 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4087 mono_ptr_array_append (tmp_array, member);
4090 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4092 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4093 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4095 mono_ptr_array_destroy (tmp_array);
4100 static MonoReflectionType*
4101 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4104 MonoType *type = NULL;
4105 MonoTypeNameParse info;
4106 gboolean type_resolve;
4108 MONO_ARCH_SAVE_REGS;
4110 /* On MS.NET, this does not fire a TypeResolve event */
4111 type_resolve = TRUE;
4112 str = mono_string_to_utf8 (name);
4113 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4114 if (!mono_reflection_parse_type (str, &info)) {
4116 mono_reflection_free_type_info (&info);
4117 if (throwOnError) /* uhm: this is a parse error, though... */
4118 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4119 /*g_print ("failed parse\n");*/
4123 if (info.assembly.name) {
4125 mono_reflection_free_type_info (&info);
4127 /* 1.0 and 2.0 throw different exceptions */
4128 if (mono_defaults.generic_ilist_class)
4129 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4131 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4136 if (module != NULL) {
4138 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4143 if (assembly->assembly->dynamic) {
4144 /* Enumerate all modules */
4145 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4149 if (abuilder->modules) {
4150 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4151 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4152 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4158 if (!type && abuilder->loaded_modules) {
4159 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4160 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4161 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4168 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4170 mono_reflection_free_type_info (&info);
4172 MonoException *e = NULL;
4175 e = mono_get_exception_type_load (name, NULL);
4177 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4178 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4180 mono_loader_clear_error ();
4183 mono_raise_exception (e);
4186 } else if (mono_loader_get_last_error ()) {
4188 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4189 mono_loader_clear_error ();
4192 if (type->type == MONO_TYPE_CLASS) {
4193 MonoClass *klass = mono_type_get_class (type);
4195 if (mono_is_security_manager_active () && !klass->exception_type)
4196 /* Some security problems are detected during generic vtable construction */
4197 mono_class_setup_vtable (klass);
4198 /* need to report exceptions ? */
4199 if (throwOnError && klass->exception_type) {
4200 /* report SecurityException (or others) that occured when loading the assembly */
4201 MonoException *exc = mono_class_get_exception_for_failure (klass);
4202 mono_loader_clear_error ();
4203 mono_raise_exception (exc);
4204 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4209 /* g_print ("got it\n"); */
4210 return mono_type_get_object (mono_object_domain (assembly), type);
4214 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4217 gchar *shadow_ini_file;
4220 /* Check for shadow-copied assembly */
4221 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4222 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4224 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4225 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4231 g_free (shadow_ini_file);
4232 if (content != NULL) {
4235 *filename = content;
4243 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4245 MonoDomain *domain = mono_object_domain (assembly);
4246 MonoAssembly *mass = assembly->assembly;
4247 MonoString *res = NULL;
4252 MONO_ARCH_SAVE_REGS;
4254 if (g_path_is_absolute (mass->image->name)) {
4255 absolute = g_strdup (mass->image->name);
4256 dirname = g_path_get_dirname (absolute);
4258 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4259 dirname = g_strdup (mass->basedir);
4262 replace_shadow_path (domain, dirname, &absolute);
4267 for (i = strlen (absolute) - 1; i >= 0; i--)
4268 if (absolute [i] == '\\')
4273 uri = g_filename_to_uri (absolute, NULL, NULL);
4275 const char *prepend = "file://";
4277 if (*absolute == '/' && *(absolute + 1) == '/') {
4280 prepend = "file:///";
4283 uri = g_strconcat (prepend, absolute, NULL);
4287 res = mono_string_new (domain, uri);
4295 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4297 MonoAssembly *mass = assembly->assembly;
4299 MONO_ARCH_SAVE_REGS;
4301 return mass->in_gac;
4304 static MonoReflectionAssembly*
4305 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4309 MonoImageOpenStatus status;
4311 MONO_ARCH_SAVE_REGS;
4313 name = mono_string_to_utf8 (mname);
4314 res = mono_assembly_load_with_partial_name (name, &status);
4320 return mono_assembly_get_object (mono_domain_get (), res);
4324 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4326 MonoDomain *domain = mono_object_domain (assembly);
4329 MONO_ARCH_SAVE_REGS;
4331 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4337 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4339 MONO_ARCH_SAVE_REGS;
4341 return assembly->assembly->ref_only;
4345 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4347 MonoDomain *domain = mono_object_domain (assembly);
4349 MONO_ARCH_SAVE_REGS;
4351 return mono_string_new (domain, assembly->assembly->image->version);
4354 static MonoReflectionMethod*
4355 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4357 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4359 MONO_ARCH_SAVE_REGS;
4363 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4366 static MonoReflectionModule*
4367 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4369 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4373 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4375 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4376 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4380 MONO_ARCH_SAVE_REGS;
4382 for (i = 0; i < table->rows; ++i) {
4383 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4384 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4390 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4392 static MonoClass *System_Version = NULL;
4393 static MonoMethod *create_version = NULL;
4397 if (!System_Version) {
4398 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4399 g_assert (System_Version);
4402 if (!create_version) {
4403 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4404 create_version = mono_method_desc_search_in_class (desc, System_Version);
4405 g_assert (create_version);
4406 mono_method_desc_free (desc);
4412 args [3] = &revision;
4413 result = mono_object_new (domain, System_Version);
4414 mono_runtime_invoke (create_version, result, args, NULL);
4420 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4422 static MonoClass *System_Reflection_AssemblyName;
4424 MonoDomain *domain = mono_object_domain (assembly);
4426 static MonoMethod *create_culture = NULL;
4427 MonoImage *image = assembly->assembly->image;
4430 MONO_ARCH_SAVE_REGS;
4432 if (!System_Reflection_AssemblyName)
4433 System_Reflection_AssemblyName = mono_class_from_name (
4434 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4436 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4439 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4441 if (count > 0 && !create_culture) {
4442 MonoMethodDesc *desc = mono_method_desc_new (
4443 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4444 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4445 g_assert (create_culture);
4446 mono_method_desc_free (desc);
4449 for (i = 0; i < count; i++) {
4450 MonoReflectionAssemblyName *aname;
4451 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4453 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4455 aname = (MonoReflectionAssemblyName *) mono_object_new (
4456 domain, System_Reflection_AssemblyName);
4458 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4460 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4461 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4462 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4463 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4464 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4465 aname->versioncompat = 1; /* SameMachine (default) */
4466 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4467 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4469 if (create_culture) {
4471 MonoBoolean assembly_ref = 1;
4472 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4473 args [1] = &assembly_ref;
4474 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4477 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4478 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4479 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4481 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4482 /* public key token isn't copied - the class library will
4483 automatically generate it from the public key if required */
4484 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4485 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4487 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4488 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4491 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4494 /* note: this function doesn't return the codebase on purpose (i.e. it can
4495 be used under partial trust as path information isn't present). */
4497 mono_array_setref (result, i, aname);
4508 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4510 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4512 mono_array_setref (info->res, info->idx, name);
4517 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4519 MonoImage *img = assembly->assembly->image;
4524 MONO_ARCH_SAVE_REGS;
4526 mono_image_lock (img);
4527 mono_image_init_name_cache (img);
4530 len = g_hash_table_size (img->name_cache);
4531 mono_image_unlock (img);
4533 /*we can't create objects holding the image lock */
4534 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4536 mono_image_lock (img);
4537 /*len might have changed, create a new array*/
4538 if (len != g_hash_table_size (img->name_cache))
4543 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4544 mono_image_unlock (img);
4549 /* move this in some file in mono/util/ */
4551 g_concat_dir_and_file (const char *dir, const char *file)
4553 g_return_val_if_fail (dir != NULL, NULL);
4554 g_return_val_if_fail (file != NULL, NULL);
4557 * If the directory name doesn't have a / on the end, we need
4558 * to add one so we get a proper path to the file
4560 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4561 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4563 return g_strconcat (dir, file, NULL);
4567 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4569 char *n = mono_string_to_utf8 (name);
4570 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4572 guint32 cols [MONO_MANIFEST_SIZE];
4573 guint32 impl, file_idx;
4577 MONO_ARCH_SAVE_REGS;
4579 for (i = 0; i < table->rows; ++i) {
4580 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4581 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4582 if (strcmp (val, n) == 0)
4586 if (i == table->rows)
4589 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4592 * this code should only be called after obtaining the
4593 * ResourceInfo and handling the other cases.
4595 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4596 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4598 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4603 module = assembly->assembly->image;
4605 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4607 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4611 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4613 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4615 guint32 cols [MONO_MANIFEST_SIZE];
4616 guint32 file_cols [MONO_FILE_SIZE];
4620 MONO_ARCH_SAVE_REGS;
4622 n = mono_string_to_utf8 (name);
4623 for (i = 0; i < table->rows; ++i) {
4624 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4625 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4626 if (strcmp (val, n) == 0)
4630 if (i == table->rows)
4633 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4634 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4637 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4638 case MONO_IMPLEMENTATION_FILE:
4639 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4640 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4641 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4642 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4643 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4644 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4647 info->location = RESOURCE_LOCATION_EMBEDDED;
4650 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4651 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4652 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4653 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4654 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4655 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4657 mono_raise_exception (ex);
4659 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4661 /* Obtain info recursively */
4662 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4663 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4666 case MONO_IMPLEMENTATION_EXP_TYPE:
4667 g_assert_not_reached ();
4676 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4678 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4679 MonoArray *result = NULL;
4684 MONO_ARCH_SAVE_REGS;
4686 /* check hash if needed */
4688 n = mono_string_to_utf8 (name);
4689 for (i = 0; i < table->rows; ++i) {
4690 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4691 if (strcmp (val, n) == 0) {
4694 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4695 fn = mono_string_new (mono_object_domain (assembly), n);
4697 return (MonoObject*)fn;
4705 for (i = 0; i < table->rows; ++i) {
4706 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4710 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4713 for (i = 0; i < table->rows; ++i) {
4714 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4715 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4716 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4717 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4722 return (MonoObject*)result;
4726 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4728 MonoDomain *domain = mono_domain_get();
4731 int i, j, file_count = 0;
4732 MonoImage **modules;
4733 guint32 module_count, real_module_count;
4734 MonoTableInfo *table;
4735 guint32 cols [MONO_FILE_SIZE];
4736 MonoImage *image = assembly->assembly->image;
4738 g_assert (image != NULL);
4739 g_assert (!assembly->assembly->dynamic);
4741 table = &image->tables [MONO_TABLE_FILE];
4742 file_count = table->rows;
4744 modules = image->modules;
4745 module_count = image->module_count;
4747 real_module_count = 0;
4748 for (i = 0; i < module_count; ++i)
4750 real_module_count ++;
4752 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4753 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4755 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4757 for (i = 0; i < module_count; ++i)
4759 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4763 for (i = 0; i < file_count; ++i, ++j) {
4764 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4765 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4766 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4768 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4770 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4771 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4773 mono_array_setref (res, j, mono_module_get_object (domain, m));
4780 static MonoReflectionMethod*
4781 ves_icall_GetCurrentMethod (void)
4783 MonoMethod *m = mono_method_get_last_managed ();
4785 while (m->is_inflated)
4786 m = ((MonoMethodInflated*)m)->declaring;
4788 return mono_method_get_object (mono_domain_get (), m, NULL);
4793 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4796 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4797 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4798 //method is inflated, we should inflate it on the other class
4799 MonoGenericContext ctx;
4800 ctx.method_inst = inflated->context.method_inst;
4801 ctx.class_inst = inflated->context.class_inst;
4802 if (klass->generic_class)
4803 ctx.class_inst = klass->generic_class->context.class_inst;
4804 else if (klass->generic_container)
4805 ctx.class_inst = klass->generic_container->context.class_inst;
4806 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4809 mono_class_setup_methods (method->klass);
4810 if (method->klass->exception_type)
4812 for (i = 0; i < method->klass->method.count; ++i) {
4813 if (method->klass->methods [i] == method) {
4818 mono_class_setup_methods (klass);
4819 if (klass->exception_type)
4821 g_assert (offset >= 0 && offset < klass->method.count);
4822 return klass->methods [offset];
4825 static MonoReflectionMethod*
4826 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4830 klass = mono_class_from_mono_type (type);
4831 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4833 if (method->klass != klass) {
4834 method = mono_method_get_equivalent_method (method, klass);
4839 klass = method->klass;
4840 return mono_method_get_object (mono_domain_get (), method, klass);
4843 static MonoReflectionMethod*
4844 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4846 return mono_method_get_object (mono_domain_get (), method, NULL);
4849 static MonoReflectionMethodBody*
4850 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4852 return mono_method_body_get_object (mono_domain_get (), method);
4855 static MonoReflectionAssembly*
4856 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4858 MonoMethod *dest = NULL;
4860 MONO_ARCH_SAVE_REGS;
4862 mono_stack_walk_no_il (get_executing, &dest);
4863 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4867 static MonoReflectionAssembly*
4868 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4870 MonoDomain* domain = mono_domain_get ();
4872 MONO_ARCH_SAVE_REGS;
4874 if (!domain->entry_assembly)
4877 return mono_assembly_get_object (domain, domain->entry_assembly);
4880 static MonoReflectionAssembly*
4881 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4886 MONO_ARCH_SAVE_REGS;
4889 mono_stack_walk_no_il (get_executing, &dest);
4891 mono_stack_walk_no_il (get_caller, &dest);
4894 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4898 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4899 gboolean assembly_qualified)
4901 MonoDomain *domain = mono_object_domain (object);
4902 MonoTypeNameFormat format;
4907 format = assembly_qualified ?
4908 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4909 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4911 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4913 name = mono_type_get_name_full (object->type, format);
4917 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4922 res = mono_string_new (domain, name);
4929 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4931 MonoClass *klass = mono_class_from_mono_type (this->type);
4932 mono_class_init_or_throw (klass);
4933 return mono_security_core_clr_class_level (klass);
4937 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4939 static MonoMethod *create_culture = NULL;
4942 const char *pkey_ptr;
4944 MonoBoolean assembly_ref = 0;
4946 MONO_ARCH_SAVE_REGS;
4948 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4949 aname->major = name->major;
4950 aname->minor = name->minor;
4951 aname->build = name->build;
4952 aname->flags = name->flags;
4953 aname->revision = name->revision;
4954 aname->hashalg = name->hash_alg;
4955 aname->versioncompat = 1; /* SameMachine (default) */
4956 aname->processor_architecture = name->arch;
4958 if (by_default_version)
4959 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4962 if (absolute != NULL && *absolute != '\0') {
4963 const gchar *prepend = "file://";
4966 codebase = g_strdup (absolute);
4971 for (i = strlen (codebase) - 1; i >= 0; i--)
4972 if (codebase [i] == '\\')
4975 if (*codebase == '/' && *(codebase + 1) == '/') {
4978 prepend = "file:///";
4982 result = g_strconcat (prepend, codebase, NULL);
4988 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4992 if (!create_culture) {
4993 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4994 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4995 g_assert (create_culture);
4996 mono_method_desc_free (desc);
4999 if (name->culture) {
5000 args [0] = mono_string_new (domain, name->culture);
5001 args [1] = &assembly_ref;
5002 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5005 if (name->public_key) {
5006 pkey_ptr = (char*)name->public_key;
5007 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5009 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5010 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5011 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5012 } else if (default_publickey) {
5013 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5014 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5017 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5018 if (name->public_key_token [0]) {
5022 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5023 p = mono_array_addr (aname->keyToken, char, 0);
5025 for (i = 0, j = 0; i < 8; i++) {
5026 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5027 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5030 } else if (default_token) {
5031 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5036 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5038 MonoDomain *domain = mono_object_domain (assembly);
5039 MonoAssembly *mass = assembly->assembly;
5043 name = mono_stringify_assembly_name (&mass->aname);
5044 res = mono_string_new (domain, name);
5051 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5054 MonoAssembly *mass = assembly->assembly;
5056 MONO_ARCH_SAVE_REGS;
5058 if (g_path_is_absolute (mass->image->name)) {
5059 fill_reflection_assembly_name (mono_object_domain (assembly),
5060 aname, &mass->aname, mass->image->name, TRUE,
5064 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5066 fill_reflection_assembly_name (mono_object_domain (assembly),
5067 aname, &mass->aname, absolute, TRUE, TRUE,
5074 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5077 MonoImageOpenStatus status = MONO_IMAGE_OK;
5080 MonoAssemblyName name;
5083 MONO_ARCH_SAVE_REGS;
5085 filename = mono_string_to_utf8 (fname);
5087 dirname = g_path_get_dirname (filename);
5088 replace_shadow_path (mono_domain_get (), dirname, &filename);
5091 image = mono_image_open (filename, &status);
5097 if (status == MONO_IMAGE_IMAGE_INVALID)
5098 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5100 exc = mono_get_exception_file_not_found2 (NULL, fname);
5101 mono_raise_exception (exc);
5104 res = mono_assembly_fill_assembly_name (image, &name);
5106 mono_image_close (image);
5108 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5111 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5115 mono_image_close (image);
5119 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5120 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5122 MonoBoolean result = FALSE;
5123 MonoDeclSecurityEntry entry;
5125 /* SecurityAction.RequestMinimum */
5126 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5127 *minimum = entry.blob;
5128 *minLength = entry.size;
5131 /* SecurityAction.RequestOptional */
5132 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5133 *optional = entry.blob;
5134 *optLength = entry.size;
5137 /* SecurityAction.RequestRefuse */
5138 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5139 *refused = entry.blob;
5140 *refLength = entry.size;
5148 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5152 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5154 guint32 attrs, visibility;
5156 /* we start the count from 1 because we skip the special type <Module> */
5159 for (i = 1; i < tdef->rows; ++i) {
5160 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5161 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5162 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5166 count = tdef->rows - 1;
5168 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5169 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5171 for (i = 1; i < tdef->rows; ++i) {
5172 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5173 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5174 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5175 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5177 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5179 MonoLoaderError *error;
5182 error = mono_loader_get_last_error ();
5183 g_assert (error != NULL);
5185 ex = mono_loader_error_prepare_exception (error);
5186 mono_array_setref (*exceptions, count, ex);
5188 if (mono_loader_get_last_error ())
5189 mono_loader_clear_error ();
5198 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5200 MonoArray *res = NULL;
5201 MonoArray *exceptions = NULL;
5202 MonoImage *image = NULL;
5203 MonoTableInfo *table = NULL;
5206 int i, len, ex_count;
5208 MONO_ARCH_SAVE_REGS;
5210 domain = mono_object_domain (assembly);
5212 g_assert (!assembly->assembly->dynamic);
5213 image = assembly->assembly->image;
5214 table = &image->tables [MONO_TABLE_FILE];
5215 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5217 /* Append data from all modules in the assembly */
5218 for (i = 0; i < table->rows; ++i) {
5219 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5220 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5223 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5224 /* Append the new types to the end of the array */
5225 if (mono_array_length (res2) > 0) {
5227 MonoArray *res3, *ex3;
5229 len1 = mono_array_length (res);
5230 len2 = mono_array_length (res2);
5232 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5233 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5234 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5237 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5238 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5239 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5246 /* the ReflectionTypeLoadException must have all the types (Types property),
5247 * NULL replacing types which throws an exception. The LoaderException must
5248 * contain all exceptions for NULL items.
5251 len = mono_array_length (res);
5254 for (i = 0; i < len; i++) {
5255 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5259 klass = mono_type_get_class (t->type);
5260 if ((klass != NULL) && klass->exception_type) {
5261 /* keep the class in the list */
5262 list = g_list_append (list, klass);
5263 /* and replace Type with NULL */
5264 mono_array_setref (res, i, NULL);
5271 if (list || ex_count) {
5273 MonoException *exc = NULL;
5274 MonoArray *exl = NULL;
5275 int j, length = g_list_length (list) + ex_count;
5277 mono_loader_clear_error ();
5279 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5280 /* Types for which mono_class_get () succeeded */
5281 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5282 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5283 mono_array_setref (exl, i, exc);
5285 /* Types for which it don't */
5286 for (j = 0; j < mono_array_length (exceptions); ++j) {
5287 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5289 g_assert (i < length);
5290 mono_array_setref (exl, i, exc);
5297 exc = mono_get_exception_reflection_type_load (res, exl);
5298 mono_loader_clear_error ();
5299 mono_raise_exception (exc);
5306 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5308 MonoAssemblyName aname;
5309 MonoDomain *domain = mono_object_domain (name);
5311 gboolean is_version_defined;
5312 gboolean is_token_defined;
5314 aname.public_key = NULL;
5315 val = mono_string_to_utf8 (assname);
5316 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5317 g_free ((guint8*) aname.public_key);
5322 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5323 FALSE, is_token_defined);
5325 mono_assembly_name_free (&aname);
5326 g_free ((guint8*) aname.public_key);
5332 static MonoReflectionType*
5333 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5335 MonoDomain *domain = mono_object_domain (module);
5338 MONO_ARCH_SAVE_REGS;
5340 g_assert (module->image);
5342 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5343 /* These images do not have a global type */
5346 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5347 return mono_type_get_object (domain, &klass->byval_arg);
5351 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5353 /*if (module->image)
5354 mono_image_close (module->image);*/
5358 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5360 MonoDomain *domain = mono_object_domain (module);
5362 MONO_ARCH_SAVE_REGS;
5364 g_assert (module->image);
5365 return mono_string_new (domain, module->image->guid);
5369 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5372 if (module->image && module->image->is_module_handle)
5373 return module->image->raw_data;
5376 return (gpointer) (-1);
5380 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5382 if (image->dynamic) {
5383 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5384 *pe_kind = dyn->pe_kind;
5385 *machine = dyn->machine;
5388 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5389 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5394 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5396 return (image->md_version_major << 16) | (image->md_version_minor);
5400 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5402 MonoArray *exceptions;
5405 MONO_ARCH_SAVE_REGS;
5408 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5410 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5411 for (i = 0; i < mono_array_length (exceptions); ++i) {
5412 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5414 mono_raise_exception (ex);
5421 mono_memberref_is_method (MonoImage *image, guint32 token)
5423 if (!image->dynamic) {
5424 guint32 cols [MONO_MEMBERREF_SIZE];
5426 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5427 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5428 mono_metadata_decode_blob_size (sig, &sig);
5429 return (*sig != 0x6);
5431 MonoClass *handle_class;
5433 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5436 return mono_defaults.methodhandle_class == handle_class;
5441 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5444 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5445 mono_array_addr (type_args, MonoType*, 0));
5447 context->class_inst = NULL;
5449 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5450 mono_array_addr (method_args, MonoType*, 0));
5452 context->method_inst = NULL;
5456 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5459 int table = mono_metadata_token_table (token);
5460 int index = mono_metadata_token_index (token);
5461 MonoGenericContext context;
5463 *error = ResolveTokenError_Other;
5465 /* Validate token */
5466 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5467 (table != MONO_TABLE_TYPESPEC)) {
5468 *error = ResolveTokenError_BadTable;
5472 if (image->dynamic) {
5473 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5474 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5475 return klass ? &klass->byval_arg : NULL;
5478 init_generic_context_from_args (&context, type_args, method_args);
5479 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5480 return klass ? &klass->byval_arg : NULL;
5483 if ((index <= 0) || (index > image->tables [table].rows)) {
5484 *error = ResolveTokenError_OutOfRange;
5488 init_generic_context_from_args (&context, type_args, method_args);
5489 klass = mono_class_get_full (image, token, &context);
5491 if (mono_loader_get_last_error ())
5492 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5495 return &klass->byval_arg;
5501 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5503 int table = mono_metadata_token_table (token);
5504 int index = mono_metadata_token_index (token);
5505 MonoGenericContext context;
5508 *error = ResolveTokenError_Other;
5510 /* Validate token */
5511 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5512 (table != MONO_TABLE_MEMBERREF)) {
5513 *error = ResolveTokenError_BadTable;
5517 if (image->dynamic) {
5518 if (table == MONO_TABLE_METHOD)
5519 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5521 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5522 *error = ResolveTokenError_BadTable;
5526 init_generic_context_from_args (&context, type_args, method_args);
5527 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5530 if ((index <= 0) || (index > image->tables [table].rows)) {
5531 *error = ResolveTokenError_OutOfRange;
5534 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5535 *error = ResolveTokenError_BadTable;
5539 init_generic_context_from_args (&context, type_args, method_args);
5540 method = mono_get_method_full (image, token, NULL, &context);
5542 if (mono_loader_get_last_error ())
5543 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5549 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5551 int index = mono_metadata_token_index (token);
5553 *error = ResolveTokenError_Other;
5555 /* Validate token */
5556 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5557 *error = ResolveTokenError_BadTable;
5562 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5564 if ((index <= 0) || (index >= image->heap_us.size)) {
5565 *error = ResolveTokenError_OutOfRange;
5569 /* FIXME: What to do if the index points into the middle of a string ? */
5571 return mono_ldstr (mono_domain_get (), image, index);
5574 static MonoClassField*
5575 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5578 int table = mono_metadata_token_table (token);
5579 int index = mono_metadata_token_index (token);
5580 MonoGenericContext context;
5581 MonoClassField *field;
5583 *error = ResolveTokenError_Other;
5585 /* Validate token */
5586 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5587 *error = ResolveTokenError_BadTable;
5591 if (image->dynamic) {
5592 if (table == MONO_TABLE_FIELD)
5593 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5595 if (mono_memberref_is_method (image, token)) {
5596 *error = ResolveTokenError_BadTable;
5600 init_generic_context_from_args (&context, type_args, method_args);
5601 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5604 if ((index <= 0) || (index > image->tables [table].rows)) {
5605 *error = ResolveTokenError_OutOfRange;
5608 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5609 *error = ResolveTokenError_BadTable;
5613 init_generic_context_from_args (&context, type_args, method_args);
5614 field = mono_field_from_token (image, token, &klass, &context);
5616 if (mono_loader_get_last_error ())
5617 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5624 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5626 int table = mono_metadata_token_table (token);
5628 *error = ResolveTokenError_Other;
5631 case MONO_TABLE_TYPEDEF:
5632 case MONO_TABLE_TYPEREF:
5633 case MONO_TABLE_TYPESPEC: {
5634 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5636 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5640 case MONO_TABLE_METHOD:
5641 case MONO_TABLE_METHODSPEC: {
5642 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5644 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5648 case MONO_TABLE_FIELD: {
5649 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5651 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5655 case MONO_TABLE_MEMBERREF:
5656 if (mono_memberref_is_method (image, token)) {
5657 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5659 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5664 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5666 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5673 *error = ResolveTokenError_BadTable;
5680 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5682 int table = mono_metadata_token_table (token);
5683 int idx = mono_metadata_token_index (token);
5684 MonoTableInfo *tables = image->tables;
5689 *error = ResolveTokenError_OutOfRange;
5691 /* FIXME: Support other tables ? */
5692 if (table != MONO_TABLE_STANDALONESIG)
5698 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5701 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5703 ptr = mono_metadata_blob_heap (image, sig);
5704 len = mono_metadata_decode_blob_size (ptr, &ptr);
5706 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5707 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5711 static MonoReflectionType*
5712 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5715 int isbyref = 0, rank;
5716 char *str = mono_string_to_utf8 (smodifiers);
5719 MONO_ARCH_SAVE_REGS;
5721 klass = mono_class_from_mono_type (tb->type.type);
5723 /* logic taken from mono_reflection_parse_type(): keep in sync */
5727 if (isbyref) { /* only one level allowed by the spec */
5734 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5737 klass = mono_ptr_class_get (&klass->byval_arg);
5738 mono_class_init (klass);
5749 else if (*p != '*') { /* '*' means unknown lower bound */
5760 klass = mono_array_class_get (klass, rank);
5761 mono_class_init (klass);
5768 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5772 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5777 MONO_ARCH_SAVE_REGS;
5780 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5786 check_for_invalid_type (MonoClass *klass)
5790 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5793 name = mono_type_get_full_name (klass);
5794 str = mono_string_new (mono_domain_get (), name);
5796 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5799 static MonoReflectionType *
5800 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5802 MonoClass *klass, *aklass;
5804 MONO_ARCH_SAVE_REGS;
5806 klass = mono_class_from_mono_type (type->type);
5807 check_for_invalid_type (klass);
5809 if (rank == 0) //single dimentional array
5810 aklass = mono_array_class_get (klass, 1);
5812 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5814 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5817 static MonoReflectionType *
5818 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5822 MONO_ARCH_SAVE_REGS;
5824 klass = mono_class_from_mono_type (type->type);
5825 mono_class_init_or_throw (klass);
5826 check_for_invalid_type (klass);
5828 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5831 static MonoReflectionType *
5832 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5834 MonoClass *klass, *pklass;
5836 klass = mono_class_from_mono_type (type->type);
5837 mono_class_init_or_throw (klass);
5838 check_for_invalid_type (klass);
5840 pklass = mono_ptr_class_get (type->type);
5842 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5846 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5847 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5849 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5850 MonoObject *delegate;
5852 MonoMethod *method = info->method;
5854 MONO_ARCH_SAVE_REGS;
5856 mono_class_init_or_throw (delegate_class);
5858 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5860 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5861 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5865 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5867 if (method->dynamic) {
5868 /* Creating a trampoline would leak memory */
5869 func = mono_compile_method (method);
5871 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5872 method = mono_object_get_virtual_method (target, method);
5873 func = mono_create_ftnptr (mono_domain_get (),
5874 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5877 mono_delegate_ctor_with_method (delegate, target, func, method);
5883 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5885 /* Reset the invoke impl to the default one */
5886 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5890 * Magic number to convert a time which is relative to
5891 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5893 #define EPOCH_ADJUST ((guint64)62135596800LL)
5896 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5898 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5901 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5903 convert_to_absolute_date(SYSTEMTIME *date)
5905 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5906 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5907 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5908 /* from the calendar FAQ */
5909 int a = (14 - date->wMonth) / 12;
5910 int y = date->wYear - a;
5911 int m = date->wMonth + 12 * a - 2;
5912 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5914 /* d is now the day of the week for the first of the month (0 == Sunday) */
5916 int day_of_week = date->wDayOfWeek;
5918 /* set day_in_month to the first day in the month which falls on day_of_week */
5919 int day_in_month = 1 + (day_of_week - d);
5920 if (day_in_month <= 0)
5923 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5924 date->wDay = day_in_month + (date->wDay - 1) * 7;
5925 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5932 * Return's the offset from GMT of a local time.
5934 * tm is a local time
5935 * t is the same local time as seconds.
5938 gmt_offset(struct tm *tm, time_t t)
5940 #if defined (HAVE_TM_GMTOFF)
5941 return tm->tm_gmtoff;
5946 g.tm_isdst = tm->tm_isdst;
5948 return (int)difftime(t, t2);
5953 * This is heavily based on zdump.c from glibc 2.2.
5955 * * data[0]: start of daylight saving time (in DateTime ticks).
5956 * * data[1]: end of daylight saving time (in DateTime ticks).
5957 * * data[2]: utcoffset (in TimeSpan ticks).
5958 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5959 * * name[0]: name of this timezone when not daylight saving.
5960 * * name[1]: name of this timezone when daylight saving.
5962 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5963 * the class library allows years between 1 and 9999.
5965 * Returns true on success and zero on failure.
5968 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5971 MonoDomain *domain = mono_domain_get ();
5972 struct tm start, tt;
5976 int is_daylight = 0, day;
5979 MONO_ARCH_SAVE_REGS;
5981 MONO_CHECK_ARG_NULL (data);
5982 MONO_CHECK_ARG_NULL (names);
5984 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5985 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5988 * no info is better than crashing: we'll need our own tz data
5989 * to make this work properly, anyway. The range is probably
5990 * reduced to 1970 .. 2037 because that is what mktime is
5991 * guaranteed to support (we get into an infinite loop
5995 memset (&start, 0, sizeof (start));
5998 start.tm_year = year-1900;
6000 t = mktime (&start);
6002 if ((year < 1970) || (year > 2037) || (t == -1)) {
6004 tt = *localtime (&t);
6005 strftime (tzone, sizeof (tzone), "%Z", &tt);
6006 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6007 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6011 gmtoff = gmt_offset (&start, t);
6013 /* For each day of the year, calculate the tm_gmtoff. */
6014 for (day = 0; day < 365; day++) {
6017 tt = *localtime (&t);
6019 /* Daylight saving starts or ends here. */
6020 if (gmt_offset (&tt, t) != gmtoff) {
6024 /* Try to find the exact hour when daylight saving starts/ends. */
6028 tt1 = *localtime (&t1);
6029 } while (gmt_offset (&tt1, t1) != gmtoff);
6031 /* Try to find the exact minute when daylight saving starts/ends. */
6034 tt1 = *localtime (&t1);
6035 } while (gmt_offset (&tt1, t1) == gmtoff);
6037 strftime (tzone, sizeof (tzone), "%Z", &tt);
6039 /* Write data, if we're already in daylight saving, we're done. */
6041 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6042 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6045 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6046 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6050 /* This is only set once when we enter daylight saving. */
6051 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6052 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6054 gmtoff = gmt_offset (&tt, t);
6059 strftime (tzone, sizeof (tzone), "%Z", &tt);
6060 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6061 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6062 mono_array_set ((*data), gint64, 0, 0);
6063 mono_array_set ((*data), gint64, 1, 0);
6064 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6065 mono_array_set ((*data), gint64, 3, 0);
6070 MonoDomain *domain = mono_domain_get ();
6071 TIME_ZONE_INFORMATION tz_info;
6076 tz_id = GetTimeZoneInformation (&tz_info);
6077 if (tz_id == TIME_ZONE_ID_INVALID)
6080 MONO_CHECK_ARG_NULL (data);
6081 MONO_CHECK_ARG_NULL (names);
6083 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6084 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6086 for (i = 0; i < 32; ++i)
6087 if (!tz_info.DaylightName [i])
6089 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6090 for (i = 0; i < 32; ++i)
6091 if (!tz_info.StandardName [i])
6093 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6095 if ((year <= 1601) || (year > 30827)) {
6097 * According to MSDN, the MS time functions can't handle dates outside
6103 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6104 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6105 tz_info.StandardDate.wYear = year;
6106 convert_to_absolute_date(&tz_info.StandardDate);
6107 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6112 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6113 tz_info.DaylightDate.wYear = year;
6114 convert_to_absolute_date(&tz_info.DaylightDate);
6115 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6120 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6122 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6123 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6130 ves_icall_System_Object_obj_address (MonoObject *this)
6132 MONO_ARCH_SAVE_REGS;
6139 static inline gint32
6140 mono_array_get_byte_length (MonoArray *array)
6146 klass = array->obj.vtable->klass;
6148 if (array->bounds == NULL)
6149 length = array->max_length;
6152 for (i = 0; i < klass->rank; ++ i)
6153 length *= array->bounds [i].length;
6156 switch (klass->element_class->byval_arg.type) {
6159 case MONO_TYPE_BOOLEAN:
6163 case MONO_TYPE_CHAR:
6171 return length * sizeof (gpointer);
6182 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6184 MONO_ARCH_SAVE_REGS;
6186 return mono_array_get_byte_length (array);
6190 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6192 MONO_ARCH_SAVE_REGS;
6194 return mono_array_get (array, gint8, idx);
6198 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6200 MONO_ARCH_SAVE_REGS;
6202 mono_array_set (array, gint8, idx, value);
6206 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6208 guint8 *src_buf, *dest_buf;
6210 MONO_ARCH_SAVE_REGS;
6212 /* watch out for integer overflow */
6213 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6216 src_buf = (guint8 *)src->vector + src_offset;
6217 dest_buf = (guint8 *)dest->vector + dest_offset;
6220 memcpy (dest_buf, src_buf, count);
6222 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6228 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6230 MonoDomain *domain = mono_object_domain (this);
6232 MonoRealProxy *rp = ((MonoRealProxy *)this);
6233 MonoTransparentProxy *tp;
6237 MONO_ARCH_SAVE_REGS;
6239 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6240 tp = (MonoTransparentProxy*) res;
6242 MONO_OBJECT_SETREF (tp, rp, rp);
6243 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6244 klass = mono_class_from_mono_type (type);
6246 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6247 tp->remote_class = mono_remote_class (domain, class_name, klass);
6249 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6253 static MonoReflectionType *
6254 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6256 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6259 /* System.Environment */
6262 ves_icall_System_Environment_get_UserName (void)
6264 MONO_ARCH_SAVE_REGS;
6266 /* using glib is more portable */
6267 return mono_string_new (mono_domain_get (), g_get_user_name ());
6272 ves_icall_System_Environment_get_MachineName (void)
6274 #if defined (HOST_WIN32)
6279 len = MAX_COMPUTERNAME_LENGTH + 1;
6280 buf = g_new (gunichar2, len);
6283 if (GetComputerName (buf, (PDWORD) &len))
6284 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6288 #elif !defined(DISABLE_SOCKETS)
6292 if (gethostname (buf, sizeof (buf)) == 0)
6293 result = mono_string_new (mono_domain_get (), buf);
6299 return mono_string_new (mono_domain_get (), "mono");
6304 ves_icall_System_Environment_get_Platform (void)
6306 #if defined (TARGET_WIN32)
6309 #elif defined(__MACH__)
6312 // Notice that the value is hidden from user code, and only exposed
6313 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6314 // define and making assumptions based on Unix/128/4 values before there
6315 // was a MacOS define. Lots of code would assume that not-Unix meant
6316 // Windows, but in this case, it would be OSX.
6326 ves_icall_System_Environment_get_NewLine (void)
6328 MONO_ARCH_SAVE_REGS;
6330 #if defined (HOST_WIN32)
6331 return mono_string_new (mono_domain_get (), "\r\n");
6333 return mono_string_new (mono_domain_get (), "\n");
6338 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6343 MONO_ARCH_SAVE_REGS;
6348 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6349 value = g_getenv (utf8_name);
6356 return mono_string_new (mono_domain_get (), value);
6360 * There is no standard way to get at environ.
6363 #ifndef __MINGW32_VERSION
6364 #if defined(__APPLE__) && !defined (__arm__)
6365 /* Apple defines this in crt_externs.h but doesn't provide that header for
6366 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6367 * in fact exist on all implementations (so far)
6369 gchar ***_NSGetEnviron(void);
6370 #define environ (*_NSGetEnviron())
6379 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6390 env_strings = GetEnvironmentStrings();
6393 env_string = env_strings;
6394 while (*env_string != '\0') {
6395 /* weird case that MS seems to skip */
6396 if (*env_string != '=')
6398 while (*env_string != '\0')
6404 domain = mono_domain_get ();
6405 names = mono_array_new (domain, mono_defaults.string_class, n);
6409 env_string = env_strings;
6410 while (*env_string != '\0') {
6411 /* weird case that MS seems to skip */
6412 if (*env_string != '=') {
6413 equal_str = wcschr(env_string, '=');
6414 g_assert(equal_str);
6415 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6416 mono_array_setref (names, n, str);
6419 while (*env_string != '\0')
6424 FreeEnvironmentStrings (env_strings);
6436 MONO_ARCH_SAVE_REGS;
6439 for (e = environ; *e != 0; ++ e)
6442 domain = mono_domain_get ();
6443 names = mono_array_new (domain, mono_defaults.string_class, n);
6446 for (e = environ; *e != 0; ++ e) {
6447 parts = g_strsplit (*e, "=", 2);
6449 str = mono_string_new (domain, *parts);
6450 mono_array_setref (names, n, str);
6463 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6465 #if !GLIB_CHECK_VERSION(2,4,0)
6466 #define g_setenv(a,b,c) setenv(a,b,c)
6467 #define g_unsetenv(a) unsetenv(a)
6471 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6476 gunichar2 *utf16_name, *utf16_value;
6478 gchar *utf8_name, *utf8_value;
6481 MONO_ARCH_SAVE_REGS;
6484 utf16_name = mono_string_to_utf16 (name);
6485 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6486 SetEnvironmentVariable (utf16_name, NULL);
6487 g_free (utf16_name);
6491 utf16_value = mono_string_to_utf16 (value);
6493 SetEnvironmentVariable (utf16_name, utf16_value);
6495 g_free (utf16_name);
6496 g_free (utf16_value);
6498 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6500 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6501 g_unsetenv (utf8_name);
6506 utf8_value = mono_string_to_utf8_checked (value, &error);
6507 if (!mono_error_ok (&error)) {
6509 mono_error_raise_exception (&error);
6511 g_setenv (utf8_name, utf8_value, TRUE);
6514 g_free (utf8_value);
6519 ves_icall_System_Environment_Exit (int result)
6521 MONO_ARCH_SAVE_REGS;
6523 mono_threads_set_shutting_down ();
6525 mono_runtime_set_shutting_down ();
6527 /* This will kill the tp threads which cannot be suspended */
6528 mono_thread_pool_cleanup ();
6530 /* Suspend all managed threads since the runtime is going away */
6531 mono_thread_suspend_all_other_threads ();
6533 mono_runtime_quit ();
6535 /* we may need to do some cleanup here... */
6540 ves_icall_System_Environment_GetGacPath (void)
6542 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6546 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6548 #if defined (HOST_WIN32)
6549 #ifndef CSIDL_FLAG_CREATE
6550 #define CSIDL_FLAG_CREATE 0x8000
6553 WCHAR path [MAX_PATH];
6554 /* Create directory if no existing */
6555 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6559 return mono_string_new_utf16 (mono_domain_get (), path, len);
6562 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6564 return mono_string_new (mono_domain_get (), "");
6568 ves_icall_System_Environment_GetLogicalDrives (void)
6570 gunichar2 buf [256], *ptr, *dname;
6572 guint initial_size = 127, size = 128;
6575 MonoString *drivestr;
6576 MonoDomain *domain = mono_domain_get ();
6579 MONO_ARCH_SAVE_REGS;
6584 while (size > initial_size) {
6585 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6586 if (size > initial_size) {
6589 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6590 initial_size = size;
6604 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6609 while (*u16) { u16++; len ++; }
6610 drivestr = mono_string_new_utf16 (domain, dname, len);
6611 mono_array_setref (result, ndrives++, drivestr);
6622 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6624 gunichar2 volume_name [MAX_PATH];
6626 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, &volume_name, MAX_PATH) == 0)
6628 return mono_string_new_utf16 (mono_domain_get (), volume_name, wcslen (volume_name));
6632 ves_icall_System_Environment_InternalGetHome (void)
6634 MONO_ARCH_SAVE_REGS;
6636 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6639 static const char *encodings [] = {
6641 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6642 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6643 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6645 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6646 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6647 "x_unicode_2_0_utf_7",
6649 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6650 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6652 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6655 "unicodefffe", "utf_16be",
6662 * Returns the internal codepage, if the value of "int_code_page" is
6663 * 1 at entry, and we can not compute a suitable code page number,
6664 * returns the code page as a string
6667 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6672 char *codepage = NULL;
6674 int want_name = *int_code_page;
6677 *int_code_page = -1;
6678 MONO_ARCH_SAVE_REGS;
6680 g_get_charset (&cset);
6681 c = codepage = strdup (cset);
6682 for (c = codepage; *c; c++){
6683 if (isascii (*c) && isalpha (*c))
6688 /* g_print ("charset: %s\n", cset); */
6690 /* handle some common aliases */
6693 for (i = 0; p != 0; ){
6694 if ((gssize) p < 7){
6696 p = encodings [++i];
6699 if (strcmp (p, codepage) == 0){
6700 *int_code_page = code;
6703 p = encodings [++i];
6706 if (strstr (codepage, "utf_8") != NULL)
6707 *int_code_page |= 0x10000000;
6710 if (want_name && *int_code_page == -1)
6711 return mono_string_new (mono_domain_get (), cset);
6717 ves_icall_System_Environment_get_HasShutdownStarted (void)
6719 if (mono_runtime_is_shutting_down ())
6722 if (mono_domain_is_unloading (mono_domain_get ()))
6729 ves_icall_System_Environment_BroadcastSettingChange (void)
6732 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6737 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6738 MonoReflectionMethod *method,
6739 MonoArray *out_args)
6741 MONO_ARCH_SAVE_REGS;
6743 mono_message_init (mono_object_domain (this), this, method, out_args);
6747 ves_icall_IsTransparentProxy (MonoObject *proxy)
6749 MONO_ARCH_SAVE_REGS;
6754 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6760 static MonoReflectionMethod *
6761 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6762 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6766 MonoMethod **vtable;
6767 MonoMethod *res = NULL;
6769 MONO_CHECK_ARG_NULL (rtype);
6770 MONO_CHECK_ARG_NULL (rmethod);
6772 method = rmethod->method;
6773 klass = mono_class_from_mono_type (rtype->type);
6774 mono_class_init_or_throw (klass);
6776 if (MONO_CLASS_IS_INTERFACE (klass))
6779 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6782 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6783 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6789 mono_class_setup_vtable (klass);
6790 vtable = klass->vtable;
6792 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6793 gboolean variance_used = FALSE;
6794 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6795 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6797 res = vtable [offs + method->slot];
6799 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6802 if (method->slot != -1)
6803 res = vtable [method->slot];
6809 return mono_method_get_object (mono_domain_get (), res, NULL);
6813 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6818 MONO_ARCH_SAVE_REGS;
6820 klass = mono_class_from_mono_type (type->type);
6821 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6823 if (enable) vtable->remote = 1;
6824 else vtable->remote = 0;
6828 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6833 MONO_ARCH_SAVE_REGS;
6835 domain = mono_object_domain (type);
6836 klass = mono_class_from_mono_type (type->type);
6837 mono_class_init_or_throw (klass);
6839 if (klass->rank >= 1) {
6840 g_assert (klass->rank == 1);
6841 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6843 /* Bypass remoting object creation check */
6844 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6849 ves_icall_System_IO_get_temp_path (void)
6851 MONO_ARCH_SAVE_REGS;
6853 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6856 #ifndef PLATFORM_NO_DRIVEINFO
6858 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6859 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6863 ULARGE_INTEGER wapi_free_bytes_avail;
6864 ULARGE_INTEGER wapi_total_number_of_bytes;
6865 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6867 MONO_ARCH_SAVE_REGS;
6869 *error = ERROR_SUCCESS;
6870 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6871 &wapi_total_number_of_free_bytes);
6874 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6875 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6876 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6878 *free_bytes_avail = 0;
6879 *total_number_of_bytes = 0;
6880 *total_number_of_free_bytes = 0;
6881 *error = GetLastError ();
6888 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6890 MONO_ARCH_SAVE_REGS;
6892 return GetDriveType (mono_string_chars (root_path_name));
6897 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6899 MONO_ARCH_SAVE_REGS;
6901 return mono_compile_method (method);
6905 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6910 MONO_ARCH_SAVE_REGS;
6912 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6914 #if defined (HOST_WIN32)
6915 /* Avoid mixing '/' and '\\' */
6918 for (i = strlen (path) - 1; i >= 0; i--)
6919 if (path [i] == '/')
6923 mcpath = mono_string_new (mono_domain_get (), path);
6930 get_bundled_app_config (void)
6932 const gchar *app_config;
6935 gchar *config_file_name, *config_file_path;
6939 MONO_ARCH_SAVE_REGS;
6941 domain = mono_domain_get ();
6942 file = domain->setup->configuration_file;
6946 // Retrieve config file and remove the extension
6947 config_file_name = mono_string_to_utf8 (file);
6948 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6949 if (!config_file_path)
6950 config_file_path = config_file_name;
6951 len = strlen (config_file_path) - strlen (".config");
6952 module = g_malloc0 (len + 1);
6953 memcpy (module, config_file_path, len);
6954 // Get the config file from the module name
6955 app_config = mono_config_string_for_assembly_file (module);
6958 if (config_file_name != config_file_path)
6959 g_free (config_file_name);
6960 g_free (config_file_path);
6965 return mono_string_new (mono_domain_get (), app_config);
6969 get_bundled_machine_config (void)
6971 const gchar *machine_config;
6973 MONO_ARCH_SAVE_REGS;
6975 machine_config = mono_get_machine_config ();
6977 if (!machine_config)
6980 return mono_string_new (mono_domain_get (), machine_config);
6984 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6989 MONO_ARCH_SAVE_REGS;
6991 path = g_path_get_dirname (mono_get_config_dir ());
6993 #if defined (HOST_WIN32)
6994 /* Avoid mixing '/' and '\\' */
6997 for (i = strlen (path) - 1; i >= 0; i--)
6998 if (path [i] == '/')
7002 ipath = mono_string_new (mono_domain_get (), path);
7009 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7011 MonoPEResourceDataEntry *entry;
7014 MONO_ARCH_SAVE_REGS;
7016 if (!assembly || !result || !size)
7021 image = assembly->assembly->image;
7022 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7026 *result = mono_image_rva_map (image, entry->rde_data_offset);
7031 *size = entry->rde_size;
7037 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7039 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7043 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7045 #if defined (HOST_WIN32)
7046 OutputDebugString (mono_string_chars (message));
7048 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7052 /* Only used for value types */
7054 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7059 MONO_ARCH_SAVE_REGS;
7061 domain = mono_object_domain (type);
7062 klass = mono_class_from_mono_type (type->type);
7063 mono_class_init_or_throw (klass);
7065 if (mono_class_is_nullable (klass))
7066 /* No arguments -> null */
7069 return mono_object_new (domain, klass);
7072 static MonoReflectionMethod *
7073 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7075 MonoClass *klass, *parent;
7076 MonoMethod *method = m->method;
7077 MonoMethod *result = NULL;
7080 MONO_ARCH_SAVE_REGS;
7082 if (method->klass == NULL)
7085 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7086 MONO_CLASS_IS_INTERFACE (method->klass) ||
7087 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7090 slot = mono_method_get_vtable_slot (method);
7094 klass = method->klass;
7095 if (klass->generic_class)
7096 klass = klass->generic_class->container_class;
7099 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7100 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7101 mono_class_setup_vtable (parent);
7102 if (parent->vtable_size <= slot)
7107 klass = klass->parent;
7112 if (klass == method->klass)
7115 /*This is possible if definition == FALSE.
7116 * Do it here to be really sure we don't read invalid memory.
7118 if (slot >= klass->vtable_size)
7121 mono_class_setup_vtable (klass);
7123 result = klass->vtable [slot];
7124 if (result == NULL) {
7125 /* It is an abstract method */
7126 gpointer iter = NULL;
7127 while ((result = mono_class_get_methods (klass, &iter)))
7128 if (result->slot == slot)
7135 return mono_method_get_object (mono_domain_get (), result, NULL);
7139 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7141 MonoMethod *method = m->method;
7143 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7148 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7150 MONO_ARCH_SAVE_REGS;
7152 iter->sig = *(MonoMethodSignature**)argsp;
7154 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7155 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7158 /* FIXME: it's not documented what start is exactly... */
7162 iter->args = argsp + sizeof (gpointer);
7164 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7166 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7170 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7172 guint32 i, arg_size;
7175 MONO_ARCH_SAVE_REGS;
7177 i = iter->sig->sentinelpos + iter->next_arg;
7179 g_assert (i < iter->sig->param_count);
7181 res.type = iter->sig->params [i];
7182 res.klass = mono_class_from_mono_type (res.type);
7183 res.value = iter->args;
7184 arg_size = mono_type_stack_size (res.type, &align);
7185 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7186 if (arg_size <= sizeof (gpointer)) {
7188 int padding = arg_size - mono_type_size (res.type, &dummy);
7189 res.value = (guint8*)res.value + padding;
7192 iter->args = (char*)iter->args + arg_size;
7195 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7201 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7203 guint32 i, arg_size;
7206 MONO_ARCH_SAVE_REGS;
7208 i = iter->sig->sentinelpos + iter->next_arg;
7210 g_assert (i < iter->sig->param_count);
7212 while (i < iter->sig->param_count) {
7213 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7215 res.type = iter->sig->params [i];
7216 res.klass = mono_class_from_mono_type (res.type);
7217 /* FIXME: endianess issue... */
7218 res.value = iter->args;
7219 arg_size = mono_type_stack_size (res.type, &align);
7220 iter->args = (char*)iter->args + arg_size;
7222 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7225 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7234 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7237 MONO_ARCH_SAVE_REGS;
7239 i = iter->sig->sentinelpos + iter->next_arg;
7241 g_assert (i < iter->sig->param_count);
7243 return iter->sig->params [i];
7247 mono_TypedReference_ToObject (MonoTypedRef tref)
7249 MONO_ARCH_SAVE_REGS;
7251 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7252 MonoObject** objp = tref.value;
7256 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7260 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7262 MONO_ARCH_SAVE_REGS;
7264 if (MONO_TYPE_IS_REFERENCE (type)) {
7265 MonoObject** objp = value;
7269 return mono_value_box (mono_domain_get (), klass, value);
7273 prelink_method (MonoMethod *method)
7275 const char *exc_class, *exc_arg;
7276 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7278 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7280 mono_raise_exception(
7281 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7283 /* create the wrapper, too? */
7287 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7289 MONO_ARCH_SAVE_REGS;
7290 prelink_method (method->method);
7294 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7296 MonoClass *klass = mono_class_from_mono_type (type->type);
7298 gpointer iter = NULL;
7299 MONO_ARCH_SAVE_REGS;
7301 mono_class_init_or_throw (klass);
7303 while ((m = mono_class_get_methods (klass, &iter)))
7307 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7309 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7310 gint32 const **exponents,
7311 gunichar2 const **digitLowerTable,
7312 gunichar2 const **digitUpperTable,
7313 gint64 const **tenPowersList,
7314 gint32 const **decHexDigits)
7316 *mantissas = Formatter_MantissaBitsTable;
7317 *exponents = Formatter_TensExponentTable;
7318 *digitLowerTable = Formatter_DigitLowerTable;
7319 *digitUpperTable = Formatter_DigitUpperTable;
7320 *tenPowersList = Formatter_TenPowersList;
7321 *decHexDigits = Formatter_DecHexDigits;
7324 /* These parameters are "readonly" in corlib/System/Char.cs */
7326 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7327 guint8 const **numeric_data,
7328 gdouble const **numeric_data_values,
7329 guint16 const **to_lower_data_low,
7330 guint16 const **to_lower_data_high,
7331 guint16 const **to_upper_data_low,
7332 guint16 const **to_upper_data_high)
7334 *category_data = CategoryData;
7335 *numeric_data = NumericData;
7336 *numeric_data_values = NumericDataValues;
7337 *to_lower_data_low = ToLowerDataLow;
7338 *to_lower_data_high = ToLowerDataHigh;
7339 *to_upper_data_low = ToUpperDataLow;
7340 *to_upper_data_high = ToUpperDataHigh;
7344 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7346 return method->method->token;
7350 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7351 * and avoid useless allocations.
7354 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7358 for (i = 0; i < type->num_mods; ++i) {
7359 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7364 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7366 for (i = 0; i < type->num_mods; ++i) {
7367 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7368 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7369 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7377 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7379 MonoType *type = param->ClassImpl->type;
7380 MonoClass *member_class = mono_object_class (param->MemberImpl);
7381 MonoMethod *method = NULL;
7384 MonoMethodSignature *sig;
7386 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7387 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7388 method = rmethod->method;
7389 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7390 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7391 if (!(method = prop->property->get))
7392 method = prop->property->set;
7395 char *type_name = mono_type_get_full_name (member_class);
7396 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7397 MonoException *ex = mono_get_exception_not_supported (msg);
7400 mono_raise_exception (ex);
7403 image = method->klass->image;
7404 pos = param->PositionImpl;
7405 sig = mono_method_signature (method);
7409 type = sig->params [pos];
7411 return type_array_from_modifiers (image, type, optional);
7415 get_property_type (MonoProperty *prop)
7417 MonoMethodSignature *sig;
7419 sig = mono_method_signature (prop->get);
7421 } else if (prop->set) {
7422 sig = mono_method_signature (prop->set);
7423 return sig->params [sig->param_count - 1];
7429 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7431 MonoType *type = get_property_type (property->property);
7432 MonoImage *image = property->klass->image;
7436 return type_array_from_modifiers (image, type, optional);
7440 *Construct a MonoType suited to be used to decode a constant blob object.
7442 * @type is the target type which will be constructed
7443 * @blob_type is the blob type, for example, that comes from the constant table
7444 * @real_type is the expected constructed type.
7447 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7449 type->type = blob_type;
7450 type->data.klass = NULL;
7451 if (blob_type == MONO_TYPE_CLASS)
7452 type->data.klass = mono_defaults.object_class;
7453 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7454 /* For enums, we need to use the base type */
7455 type->type = MONO_TYPE_VALUETYPE;
7456 type->data.klass = mono_class_from_mono_type (real_type);
7458 type->data.klass = mono_class_from_mono_type (real_type);
7462 property_info_get_default_value (MonoReflectionProperty *property)
7465 MonoProperty *prop = property->property;
7466 MonoType *type = get_property_type (prop);
7467 MonoDomain *domain = mono_object_domain (property);
7468 MonoTypeEnum def_type;
7469 const char *def_value;
7472 mono_class_init (prop->parent);
7474 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7475 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7477 def_value = mono_class_get_property_default_value (prop, &def_type);
7479 mono_type_from_blob_type (&blob_type, def_type, type);
7480 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7486 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7488 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7489 MonoCustomAttrInfo *cinfo;
7492 mono_class_init_or_throw (attr_class);
7494 cinfo = mono_reflection_get_custom_attrs_info (obj);
7497 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7499 mono_custom_attrs_free (cinfo);
7504 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7506 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7511 mono_class_init_or_throw (attr_class);
7513 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7514 if (!mono_error_ok (&error))
7515 mono_error_raise_exception (&error);
7516 if (mono_loader_get_last_error ()) {
7517 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7518 g_assert_not_reached ();
7527 ves_icall_Mono_Runtime_GetDisplayName (void)
7530 MonoString *display_name;
7532 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7533 display_name = mono_string_new (mono_domain_get (), info);
7535 return display_name;
7539 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7541 MonoString *message;
7545 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7546 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7549 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7551 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7559 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7560 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7561 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7562 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7563 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7564 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7565 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7566 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7570 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7575 gunichar2 last, prev_last, prev2_last;
7583 last = prev_last = 0, prev2_last = 0;
7584 for (i = 0; i < ilength; i++) {
7586 if (c >= sizeof (dbase64)) {
7587 exc = mono_exception_from_name_msg (mono_get_corlib (),
7588 "System", "FormatException",
7589 "Invalid character found.");
7590 mono_raise_exception (exc);
7591 } else if (isspace (c)) {
7594 prev2_last = prev_last;
7600 olength = ilength - ignored;
7602 if (allowWhitespaceOnly && olength == 0) {
7603 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7606 if ((olength & 3) != 0 || olength <= 0) {
7607 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7608 "FormatException", "Invalid length.");
7609 mono_raise_exception (exc);
7612 if (prev2_last == '=') {
7613 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7614 mono_raise_exception (exc);
7617 olength = (olength * 3) / 4;
7621 if (prev_last == '=')
7624 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7625 res_ptr = mono_array_addr (result, guchar, 0);
7626 for (i = 0; i < ilength; ) {
7629 for (k = 0; k < 4 && i < ilength;) {
7635 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7636 exc = mono_exception_from_name_msg (mono_get_corlib (),
7637 "System", "FormatException",
7638 "Invalid character found.");
7639 mono_raise_exception (exc);
7644 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7646 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7648 *res_ptr++ = (b [2] << 6) | b [3];
7650 while (i < ilength && isspace (start [i]))
7658 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7660 MONO_ARCH_SAVE_REGS;
7662 return base64_to_byte_array (mono_string_chars (str),
7663 mono_string_length (str), allowWhitespaceOnly);
7667 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7669 MONO_ARCH_SAVE_REGS;
7671 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7675 #define ICALL_TYPE(id,name,first)
7676 #define ICALL(id,name,func) Icall_ ## id,
7679 #include "metadata/icall-def.h"
7685 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7686 #define ICALL(id,name,func)
7688 #include "metadata/icall-def.h"
7694 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7695 #define ICALL(id,name,func)
7697 guint16 first_icall;
7700 static const IcallTypeDesc
7701 icall_type_descs [] = {
7702 #include "metadata/icall-def.h"
7706 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7709 #define ICALL_TYPE(id,name,first)
7712 #ifdef HAVE_ARRAY_ELEM_INIT
7713 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7714 #define MSGSTRFIELD1(line) str##line
7716 static const struct msgstrtn_t {
7717 #define ICALL(id,name,func)
7719 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7720 #include "metadata/icall-def.h"
7722 } icall_type_names_str = {
7723 #define ICALL_TYPE(id,name,first) (name),
7724 #include "metadata/icall-def.h"
7727 static const guint16 icall_type_names_idx [] = {
7728 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7729 #include "metadata/icall-def.h"
7732 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7734 static const struct msgstr_t {
7736 #define ICALL_TYPE(id,name,first)
7737 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7738 #include "metadata/icall-def.h"
7740 } icall_names_str = {
7741 #define ICALL(id,name,func) (name),
7742 #include "metadata/icall-def.h"
7745 static const guint16 icall_names_idx [] = {
7746 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7747 #include "metadata/icall-def.h"
7750 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7756 #define ICALL_TYPE(id,name,first) name,
7757 #define ICALL(id,name,func)
7758 static const char* const
7759 icall_type_names [] = {
7760 #include "metadata/icall-def.h"
7764 #define icall_type_name_get(id) (icall_type_names [(id)])
7768 #define ICALL_TYPE(id,name,first)
7769 #define ICALL(id,name,func) name,
7770 static const char* const
7772 #include "metadata/icall-def.h"
7775 #define icall_name_get(id) icall_names [(id)]
7777 #endif /* !HAVE_ARRAY_ELEM_INIT */
7781 #define ICALL_TYPE(id,name,first)
7782 #define ICALL(id,name,func) func,
7783 static const gconstpointer
7784 icall_functions [] = {
7785 #include "metadata/icall-def.h"
7789 static GHashTable *icall_hash = NULL;
7790 static GHashTable *jit_icall_hash_name = NULL;
7791 static GHashTable *jit_icall_hash_addr = NULL;
7794 mono_icall_init (void)
7798 /* check that tables are sorted: disable in release */
7801 const char *prev_class = NULL;
7802 const char *prev_method;
7804 for (i = 0; i < Icall_type_num; ++i) {
7805 const IcallTypeDesc *desc;
7808 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7809 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7810 prev_class = icall_type_name_get (i);
7811 desc = &icall_type_descs [i];
7812 num_icalls = icall_desc_num_icalls (desc);
7813 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7814 for (j = 0; j < num_icalls; ++j) {
7815 const char *methodn = icall_name_get (desc->first_icall + j);
7816 if (prev_method && strcmp (prev_method, methodn) >= 0)
7817 g_print ("method %s should come before method %s\n", methodn, prev_method);
7818 prev_method = methodn;
7823 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7827 mono_icall_cleanup (void)
7829 g_hash_table_destroy (icall_hash);
7830 g_hash_table_destroy (jit_icall_hash_name);
7831 g_hash_table_destroy (jit_icall_hash_addr);
7835 mono_add_internal_call (const char *name, gconstpointer method)
7837 mono_loader_lock ();
7839 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7841 mono_loader_unlock ();
7844 #ifdef HAVE_ARRAY_ELEM_INIT
7846 compare_method_imap (const void *key, const void *elem)
7848 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7849 return strcmp (key, method_name);
7853 find_method_icall (const IcallTypeDesc *imap, const char *name)
7855 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7858 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7862 compare_class_imap (const void *key, const void *elem)
7864 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7865 return strcmp (key, class_name);
7868 static const IcallTypeDesc*
7869 find_class_icalls (const char *name)
7871 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7874 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7879 compare_method_imap (const void *key, const void *elem)
7881 const char** method_name = (const char**)elem;
7882 return strcmp (key, *method_name);
7886 find_method_icall (const IcallTypeDesc *imap, const char *name)
7888 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7891 return (gpointer)icall_functions [(nameslot - icall_names)];
7895 compare_class_imap (const void *key, const void *elem)
7897 const char** class_name = (const char**)elem;
7898 return strcmp (key, *class_name);
7901 static const IcallTypeDesc*
7902 find_class_icalls (const char *name)
7904 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7907 return &icall_type_descs [nameslot - icall_type_names];
7913 * we should probably export this as an helper (handle nested types).
7914 * Returns the number of chars written in buf.
7917 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7919 int nspacelen, cnamelen;
7920 nspacelen = strlen (klass->name_space);
7921 cnamelen = strlen (klass->name);
7922 if (nspacelen + cnamelen + 2 > bufsize)
7925 memcpy (buf, klass->name_space, nspacelen);
7926 buf [nspacelen ++] = '.';
7928 memcpy (buf + nspacelen, klass->name, cnamelen);
7929 buf [nspacelen + cnamelen] = 0;
7930 return nspacelen + cnamelen;
7934 mono_lookup_internal_call (MonoMethod *method)
7939 int typelen = 0, mlen, siglen;
7941 const IcallTypeDesc *imap;
7943 g_assert (method != NULL);
7945 if (method->is_inflated)
7946 method = ((MonoMethodInflated *) method)->declaring;
7948 if (method->klass->nested_in) {
7949 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7953 mname [pos++] = '/';
7956 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7962 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7967 imap = find_class_icalls (mname);
7969 mname [typelen] = ':';
7970 mname [typelen + 1] = ':';
7972 mlen = strlen (method->name);
7973 memcpy (mname + typelen + 2, method->name, mlen);
7974 sigstart = mname + typelen + 2 + mlen;
7977 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7978 siglen = strlen (tmpsig);
7979 if (typelen + mlen + siglen + 6 > sizeof (mname))
7982 memcpy (sigstart + 1, tmpsig, siglen);
7983 sigstart [siglen + 1] = ')';
7984 sigstart [siglen + 2] = 0;
7987 mono_loader_lock ();
7989 res = g_hash_table_lookup (icall_hash, mname);
7991 mono_loader_unlock ();
7994 /* try without signature */
7996 res = g_hash_table_lookup (icall_hash, mname);
7998 mono_loader_unlock ();
8002 /* it wasn't found in the static call tables */
8004 mono_loader_unlock ();
8007 res = find_method_icall (imap, sigstart - mlen);
8009 mono_loader_unlock ();
8012 /* try _with_ signature */
8014 res = find_method_icall (imap, sigstart - mlen);
8016 mono_loader_unlock ();
8020 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8021 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8022 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8023 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8024 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");
8025 g_print ("If you see other errors or faults after this message they are probably related\n");
8026 g_print ("and you need to fix your mono install first.\n");
8028 mono_loader_unlock ();
8034 type_from_typename (char *typename)
8036 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8038 if (!strcmp (typename, "int"))
8039 klass = mono_defaults.int_class;
8040 else if (!strcmp (typename, "ptr"))
8041 klass = mono_defaults.int_class;
8042 else if (!strcmp (typename, "void"))
8043 klass = mono_defaults.void_class;
8044 else if (!strcmp (typename, "int32"))
8045 klass = mono_defaults.int32_class;
8046 else if (!strcmp (typename, "uint32"))
8047 klass = mono_defaults.uint32_class;
8048 else if (!strcmp (typename, "int8"))
8049 klass = mono_defaults.sbyte_class;
8050 else if (!strcmp (typename, "uint8"))
8051 klass = mono_defaults.byte_class;
8052 else if (!strcmp (typename, "int16"))
8053 klass = mono_defaults.int16_class;
8054 else if (!strcmp (typename, "uint16"))
8055 klass = mono_defaults.uint16_class;
8056 else if (!strcmp (typename, "long"))
8057 klass = mono_defaults.int64_class;
8058 else if (!strcmp (typename, "ulong"))
8059 klass = mono_defaults.uint64_class;
8060 else if (!strcmp (typename, "float"))
8061 klass = mono_defaults.single_class;
8062 else if (!strcmp (typename, "double"))
8063 klass = mono_defaults.double_class;
8064 else if (!strcmp (typename, "object"))
8065 klass = mono_defaults.object_class;
8066 else if (!strcmp (typename, "obj"))
8067 klass = mono_defaults.object_class;
8068 else if (!strcmp (typename, "string"))
8069 klass = mono_defaults.string_class;
8070 else if (!strcmp (typename, "bool"))
8071 klass = mono_defaults.boolean_class;
8072 else if (!strcmp (typename, "boolean"))
8073 klass = mono_defaults.boolean_class;
8075 g_error ("%s", typename);
8076 g_assert_not_reached ();
8078 return &klass->byval_arg;
8081 MonoMethodSignature*
8082 mono_create_icall_signature (const char *sigstr)
8087 MonoMethodSignature *res;
8089 mono_loader_lock ();
8090 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8092 mono_loader_unlock ();
8096 parts = g_strsplit (sigstr, " ", 256);
8105 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8110 * Under windows, the default pinvoke calling convention is STDCALL but
8113 res->call_convention = MONO_CALL_C;
8116 res->ret = type_from_typename (parts [0]);
8117 for (i = 1; i < len; ++i) {
8118 res->params [i - 1] = type_from_typename (parts [i]);
8123 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8125 mono_loader_unlock ();
8131 mono_find_jit_icall_by_name (const char *name)
8133 MonoJitICallInfo *info;
8134 g_assert (jit_icall_hash_name);
8136 mono_loader_lock ();
8137 info = g_hash_table_lookup (jit_icall_hash_name, name);
8138 mono_loader_unlock ();
8143 mono_find_jit_icall_by_addr (gconstpointer addr)
8145 MonoJitICallInfo *info;
8146 g_assert (jit_icall_hash_addr);
8148 mono_loader_lock ();
8149 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8150 mono_loader_unlock ();
8156 * mono_get_jit_icall_info:
8158 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8159 * caller should access it while holding the loader lock.
8162 mono_get_jit_icall_info (void)
8164 return jit_icall_hash_name;
8168 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8170 mono_loader_lock ();
8171 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8172 mono_loader_unlock ();
8176 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8178 MonoJitICallInfo *info;
8183 mono_loader_lock ();
8185 if (!jit_icall_hash_name) {
8186 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8187 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8190 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8191 g_warning ("jit icall already defined \"%s\"\n", name);
8192 g_assert_not_reached ();
8195 info = g_new0 (MonoJitICallInfo, 1);
8202 info->wrapper = func;
8204 info->wrapper = NULL;
8207 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8208 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8210 mono_loader_unlock ();