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>
81 #if defined (HOST_WIN32)
87 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
89 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
92 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
94 static inline MonoBoolean
95 is_generic_parameter (MonoType *type)
97 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
101 mono_class_init_or_throw (MonoClass *klass)
103 if (!mono_class_init (klass))
104 mono_raise_exception (mono_class_get_exception_for_failure (klass));
108 * We expect a pointer to a char, not a string
111 mono_double_ParseImpl (char *ptr, double *result)
113 gchar *endptr = NULL;
120 *result = strtod (ptr, &endptr);
123 /* mono_strtod () is not thread-safe */
124 EnterCriticalSection (&mono_strtod_mutex);
125 *result = mono_strtod (ptr, &endptr);
126 LeaveCriticalSection (&mono_strtod_mutex);
130 if (!*ptr || (endptr && *endptr))
137 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
146 ao = (MonoArray *)this;
147 ac = (MonoClass *)ao->obj.vtable->klass;
149 esize = mono_array_element_size (ac);
150 ea = (gpointer*)((char*)ao->vector + (pos * esize));
152 if (ac->element_class->valuetype)
153 return mono_value_box (this->vtable->domain, ac->element_class, ea);
159 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
167 MONO_CHECK_ARG_NULL (idxs);
169 io = (MonoArray *)idxs;
170 ic = (MonoClass *)io->obj.vtable->klass;
172 ao = (MonoArray *)this;
173 ac = (MonoClass *)ao->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank)
177 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
179 ind = (gint32 *)io->vector;
181 if (ao->bounds == NULL) {
182 if (*ind < 0 || *ind >= ao->max_length)
183 mono_raise_exception (mono_get_exception_index_out_of_range ());
185 return ves_icall_System_Array_GetValueImpl (this, *ind);
188 for (i = 0; i < ac->rank; i++)
189 if ((ind [i] < ao->bounds [i].lower_bound) ||
190 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
191 mono_raise_exception (mono_get_exception_index_out_of_range ());
193 pos = ind [0] - ao->bounds [0].lower_bound;
194 for (i = 1; i < ac->rank; i++)
195 pos = pos*ao->bounds [i].length + ind [i] -
196 ao->bounds [i].lower_bound;
198 return ves_icall_System_Array_GetValueImpl (this, pos);
202 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
204 MonoClass *ac, *vc, *ec;
216 vc = value->vtable->klass;
220 ac = this->obj.vtable->klass;
221 ec = ac->element_class;
223 esize = mono_array_element_size (ac);
224 ea = (gpointer*)((char*)this->vector + (pos * esize));
225 va = (gpointer*)((char*)value + sizeof (MonoObject));
227 if (mono_class_is_nullable (ec)) {
228 mono_nullable_init ((guint8*)ea, value, ec);
233 memset (ea, 0, esize);
237 #define NO_WIDENING_CONVERSION G_STMT_START{\
238 mono_raise_exception (mono_get_exception_argument ( \
239 "value", "not a widening conversion")); \
242 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
243 if (esize < vsize + (extra)) \
244 mono_raise_exception (mono_get_exception_argument ( \
245 "value", "not a widening conversion")); \
248 #define INVALID_CAST G_STMT_START{\
249 mono_raise_exception (mono_get_exception_invalid_cast ()); \
252 /* Check element (destination) type. */
253 switch (ec->byval_arg.type) {
254 case MONO_TYPE_STRING:
255 switch (vc->byval_arg.type) {
256 case MONO_TYPE_STRING:
262 case MONO_TYPE_BOOLEAN:
263 switch (vc->byval_arg.type) {
264 case MONO_TYPE_BOOLEAN:
277 NO_WIDENING_CONVERSION;
284 if (!ec->valuetype) {
285 if (!mono_object_isinst (value, ec))
287 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
291 if (mono_object_isinst (value, ec)) {
292 if (ec->has_references)
293 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
295 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
302 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
304 et = ec->byval_arg.type;
305 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
306 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
308 vt = vc->byval_arg.type;
309 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
310 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
312 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
318 case MONO_TYPE_CHAR: \
319 CHECK_WIDENING_CONVERSION(0); \
320 *(etype *) ea = (etype) u64; \
322 /* You can't assign a signed value to an unsigned array. */ \
327 /* You can't assign a floating point number to an integer array. */ \
330 NO_WIDENING_CONVERSION; \
334 #define ASSIGN_SIGNED(etype) G_STMT_START{\
340 CHECK_WIDENING_CONVERSION(0); \
341 *(etype *) ea = (etype) i64; \
343 /* You can assign an unsigned value to a signed array if the array's */ \
344 /* element size is larger than the value size. */ \
349 case MONO_TYPE_CHAR: \
350 CHECK_WIDENING_CONVERSION(1); \
351 *(etype *) ea = (etype) u64; \
353 /* You can't assign a floating point number to an integer array. */ \
356 NO_WIDENING_CONVERSION; \
360 #define ASSIGN_REAL(etype) G_STMT_START{\
364 CHECK_WIDENING_CONVERSION(0); \
365 *(etype *) ea = (etype) r64; \
367 /* All integer values fit into a floating point array, so we don't */ \
368 /* need to CHECK_WIDENING_CONVERSION here. */ \
373 *(etype *) ea = (etype) i64; \
379 case MONO_TYPE_CHAR: \
380 *(etype *) ea = (etype) u64; \
387 u64 = *(guint8 *) va;
390 u64 = *(guint16 *) va;
393 u64 = *(guint32 *) va;
396 u64 = *(guint64 *) va;
402 i64 = *(gint16 *) va;
405 i64 = *(gint32 *) va;
408 i64 = *(gint64 *) va;
411 r64 = *(gfloat *) va;
414 r64 = *(gdouble *) va;
417 u64 = *(guint16 *) va;
419 case MONO_TYPE_BOOLEAN:
420 /* Boolean is only compatible with itself. */
433 NO_WIDENING_CONVERSION;
440 /* If we can't do a direct copy, let's try a widening conversion. */
443 ASSIGN_UNSIGNED (guint16);
445 ASSIGN_UNSIGNED (guint8);
447 ASSIGN_UNSIGNED (guint16);
449 ASSIGN_UNSIGNED (guint32);
451 ASSIGN_UNSIGNED (guint64);
453 ASSIGN_SIGNED (gint8);
455 ASSIGN_SIGNED (gint16);
457 ASSIGN_SIGNED (gint32);
459 ASSIGN_SIGNED (gint64);
461 ASSIGN_REAL (gfloat);
463 ASSIGN_REAL (gdouble);
467 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
471 #undef NO_WIDENING_CONVERSION
472 #undef CHECK_WIDENING_CONVERSION
473 #undef ASSIGN_UNSIGNED
479 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
487 MONO_CHECK_ARG_NULL (idxs);
489 ic = idxs->obj.vtable->klass;
490 ac = this->obj.vtable->klass;
492 g_assert (ic->rank == 1);
493 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
494 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
496 ind = (gint32 *)idxs->vector;
498 if (this->bounds == NULL) {
499 if (*ind < 0 || *ind >= this->max_length)
500 mono_raise_exception (mono_get_exception_index_out_of_range ());
502 ves_icall_System_Array_SetValueImpl (this, value, *ind);
506 for (i = 0; i < ac->rank; i++)
507 if ((ind [i] < this->bounds [i].lower_bound) ||
508 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
509 mono_raise_exception (mono_get_exception_index_out_of_range ());
511 pos = ind [0] - this->bounds [0].lower_bound;
512 for (i = 1; i < ac->rank; i++)
513 pos = pos * this->bounds [i].length + ind [i] -
514 this->bounds [i].lower_bound;
516 ves_icall_System_Array_SetValueImpl (this, value, pos);
520 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
522 MonoClass *aklass, *klass;
525 gboolean bounded = FALSE;
529 MONO_CHECK_ARG_NULL (type);
530 MONO_CHECK_ARG_NULL (lengths);
532 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
534 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
536 for (i = 0; i < mono_array_length (lengths); i++)
537 if (mono_array_get (lengths, gint32, i) < 0)
538 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
540 klass = mono_class_from_mono_type (type->type);
541 mono_class_init_or_throw (klass);
543 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
544 /* vectors are not the same as one dimensional arrays with no-zero bounds */
549 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
551 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
552 for (i = 0; i < aklass->rank; ++i) {
553 sizes [i] = mono_array_get (lengths, guint32, i);
555 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
557 sizes [i + aklass->rank] = 0;
560 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
566 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
568 MonoClass *aklass, *klass;
571 gboolean bounded = FALSE;
575 MONO_CHECK_ARG_NULL (type);
576 MONO_CHECK_ARG_NULL (lengths);
578 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
580 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
582 for (i = 0; i < mono_array_length (lengths); i++)
583 if ((mono_array_get (lengths, gint64, i) < 0) ||
584 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
585 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
587 klass = mono_class_from_mono_type (type->type);
588 mono_class_init_or_throw (klass);
590 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
591 /* vectors are not the same as one dimensional arrays with no-zero bounds */
596 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
598 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
599 for (i = 0; i < aklass->rank; ++i) {
600 sizes [i] = mono_array_get (lengths, guint64, i);
602 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
604 sizes [i + aklass->rank] = 0;
607 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
613 ves_icall_System_Array_GetRank (MonoObject *this)
617 return this->vtable->klass->rank;
621 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
623 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
628 if ((dimension < 0) || (dimension >= rank))
629 mono_raise_exception (mono_get_exception_index_out_of_range ());
631 if (this->bounds == NULL)
632 length = this->max_length;
634 length = this->bounds [dimension].length;
636 #ifdef MONO_BIG_ARRAYS
637 if (length > G_MAXINT32)
638 mono_raise_exception (mono_get_exception_overflow ());
644 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
646 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
650 if ((dimension < 0) || (dimension >= rank))
651 mono_raise_exception (mono_get_exception_index_out_of_range ());
653 if (this->bounds == NULL)
654 return this->max_length;
656 return this->bounds [dimension].length;
660 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
662 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
666 if ((dimension < 0) || (dimension >= rank))
667 mono_raise_exception (mono_get_exception_index_out_of_range ());
669 if (this->bounds == NULL)
672 return this->bounds [dimension].lower_bound;
676 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
678 int sz = mono_array_element_size (mono_object_class (arr));
679 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
683 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
688 MonoClass *src_class;
689 MonoClass *dest_class;
694 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
697 if (source->bounds || dest->bounds)
700 /* there's no integer overflow since mono_array_length returns an unsigned integer */
701 if ((dest_idx + length > mono_array_length (dest)) ||
702 (source_idx + length > mono_array_length (source)))
705 src_class = source->obj.vtable->klass->element_class;
706 dest_class = dest->obj.vtable->klass->element_class;
709 * Handle common cases.
712 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
713 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
714 int has_refs = dest_class->has_references;
715 for (i = source_idx; i < source_idx + length; ++i) {
716 MonoObject *elem = mono_array_get (source, MonoObject*, i);
717 if (elem && !mono_object_isinst (elem, dest_class))
721 element_size = mono_array_element_size (dest->obj.vtable->klass);
722 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
723 for (i = 0; i < length; ++i) {
724 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
725 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
729 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
731 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
736 /* Check if we're copying a char[] <==> (u)short[] */
737 if (src_class != dest_class) {
738 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
741 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
743 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
744 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
745 for (i = source_idx; i < source_idx + length; ++i) {
746 MonoObject *elem = mono_array_get (source, MonoObject*, i);
747 if (elem && !mono_object_isinst (elem, dest_class))
754 if (dest_class->valuetype) {
755 element_size = mono_array_element_size (source->obj.vtable->klass);
756 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
757 if (dest_class->has_references) {
758 mono_value_copy_array (dest, dest_idx, source_addr, length);
760 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
761 memmove (dest_addr, source_addr, element_size * length);
764 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
771 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
780 ao = (MonoArray *)this;
781 ac = (MonoClass *)ao->obj.vtable->klass;
783 esize = mono_array_element_size (ac);
784 ea = (gpointer*)((char*)ao->vector + (pos * esize));
786 memcpy (value, ea, esize);
790 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
799 ao = (MonoArray *)this;
800 ac = (MonoClass *)ao->obj.vtable->klass;
801 ec = ac->element_class;
803 esize = mono_array_element_size (ac);
804 ea = (gpointer*)((char*)ao->vector + (pos * esize));
806 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
807 g_assert (esize == sizeof (gpointer));
808 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
810 g_assert (ec->inited);
811 g_assert (esize == mono_class_value_size (ec, NULL));
812 if (ec->has_references)
813 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
815 memcpy (ea, value, esize);
820 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
822 MonoClass *klass = array->obj.vtable->klass;
823 guint32 size = mono_array_element_size (klass);
824 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
826 const char *field_data;
828 if (MONO_TYPE_IS_REFERENCE (type) ||
829 (type->type == MONO_TYPE_VALUETYPE &&
830 (!mono_type_get_class (type) ||
831 mono_type_get_class (type)->has_references))) {
832 MonoException *exc = mono_get_exception_argument("array",
833 "Cannot initialize array containing references");
834 mono_raise_exception (exc);
837 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
838 MonoException *exc = mono_get_exception_argument("field_handle",
839 "Field doesn't have an RVA");
840 mono_raise_exception (exc);
843 size *= array->max_length;
844 field_data = mono_field_get_data (field_handle);
846 if (size > mono_type_size (field_handle->type, &align)) {
847 MonoException *exc = mono_get_exception_argument("field_handle",
848 "Field not large enough to fill array");
849 mono_raise_exception (exc);
852 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
854 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
855 guint ## n *src = (guint ## n *) field_data; \
856 guint ## n *end = (guint ## n *)((char*)src + size); \
858 for (; src < end; data++, src++) { \
859 *data = read ## n (src); \
863 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
865 switch (type->type) {
882 memcpy (mono_array_addr (array, char, 0), field_data, size);
886 memcpy (mono_array_addr (array, char, 0), field_data, size);
888 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
891 double *data = (double*)mono_array_addr (array, double, 0);
893 for (i = 0; i < size; i++, data++) {
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
907 return offsetof (MonoString, chars);
911 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
915 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
918 return mono_object_clone (obj);
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
927 MONO_CHECK_ARG_NULL (handle);
929 klass = mono_class_from_mono_type (handle);
930 MONO_CHECK_ARG (handle, klass);
932 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
934 /* This will call the type constructor */
935 mono_runtime_class_init (vtable);
939 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
943 mono_image_check_for_module_cctor (image);
944 if (image->has_module_cctor) {
945 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
946 /*It's fine to raise the exception here*/
947 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
952 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
957 /* later make this configurable and per-arch */
958 int min_size = 4096 * 4 * sizeof (void*);
959 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
960 /* if we have no info we are optimistic and assume there is enough room */
963 current = (guint8 *)&stack_addr;
964 if (current > stack_addr) {
965 if ((current - stack_addr) < min_size)
968 if (current - (stack_addr - stack_size) < min_size)
975 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
979 return mono_object_clone (this);
983 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
986 MonoObject **values = NULL;
990 MonoClassField* field;
995 klass = mono_object_class (this);
997 if (mono_class_num_fields (klass) == 0)
998 return mono_object_hash (this);
1001 * Compute the starting value of the hashcode for fields of primitive
1002 * types, and return the remaining fields in an array to the managed side.
1003 * This way, we can avoid costly reflection operations in managed code.
1006 while ((field = mono_class_get_fields (klass, &iter))) {
1007 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1009 if (mono_field_is_deleted (field))
1011 /* FIXME: Add more types */
1012 switch (field->type->type) {
1014 result ^= *(gint32*)((guint8*)this + field->offset);
1016 case MONO_TYPE_STRING: {
1018 s = *(MonoString**)((guint8*)this + field->offset);
1020 result ^= mono_string_hash (s);
1025 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1026 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1027 values [count++] = o;
1033 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1034 for (i = 0; i < count; ++i)
1035 mono_array_setref (*fields, i, values [i]);
1043 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1046 MonoObject **values = NULL;
1048 MonoClassField* field;
1052 MONO_ARCH_SAVE_REGS;
1054 MONO_CHECK_ARG_NULL (that);
1056 if (this->vtable != that->vtable)
1059 klass = mono_object_class (this);
1061 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1062 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1065 * Do the comparison for fields of primitive type and return a result if
1066 * possible. Otherwise, return the remaining fields in an array to the
1067 * managed side. This way, we can avoid costly reflection operations in
1072 while ((field = mono_class_get_fields (klass, &iter))) {
1073 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1075 if (mono_field_is_deleted (field))
1077 /* FIXME: Add more types */
1078 switch (field->type->type) {
1081 case MONO_TYPE_BOOLEAN:
1082 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1087 case MONO_TYPE_CHAR:
1088 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1093 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1098 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1102 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1106 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1111 case MONO_TYPE_STRING: {
1112 MonoString *s1, *s2;
1113 guint32 s1len, s2len;
1114 s1 = *(MonoString**)((guint8*)this + field->offset);
1115 s2 = *(MonoString**)((guint8*)that + field->offset);
1118 if ((s1 == NULL) || (s2 == NULL))
1120 s1len = mono_string_length (s1);
1121 s2len = mono_string_length (s2);
1125 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1131 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1132 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1133 values [count++] = o;
1134 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1135 values [count++] = o;
1138 if (klass->enumtype)
1139 /* enums only have one non-static field */
1145 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1146 for (i = 0; i < count; ++i)
1147 mono_array_setref (*fields, i, values [i]);
1154 static MonoReflectionType *
1155 ves_icall_System_Object_GetType (MonoObject *obj)
1157 MONO_ARCH_SAVE_REGS;
1159 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1160 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1162 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1166 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1168 MONO_ARCH_SAVE_REGS;
1170 mtype->type = &obj->vtable->klass->byval_arg;
1171 g_assert (mtype->type->type);
1175 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1177 MONO_ARCH_SAVE_REGS;
1179 MONO_CHECK_ARG_NULL (obj);
1181 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1185 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1186 MonoReflectionMethod *method,
1187 MonoArray *opt_param_types)
1189 MONO_ARCH_SAVE_REGS;
1191 MONO_CHECK_ARG_NULL (method);
1193 return mono_image_create_method_token (
1194 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1198 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1200 MONO_ARCH_SAVE_REGS;
1202 mono_image_create_pefile (mb, file);
1206 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1208 MONO_ARCH_SAVE_REGS;
1210 mono_image_build_metadata (mb);
1214 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1216 MONO_ARCH_SAVE_REGS;
1218 mono_image_register_token (mb->dynamic_image, token, obj);
1222 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1224 MonoMethod **dest = data;
1226 /* skip unmanaged frames */
1242 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1244 MonoMethod **dest = data;
1246 /* skip unmanaged frames */
1251 if (!strcmp (m->klass->name_space, "System.Reflection"))
1260 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1262 MonoMethod **dest = data;
1264 /* skip unmanaged frames */
1268 if (m->wrapper_type != MONO_WRAPPER_NONE)
1271 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1285 static MonoReflectionType *
1286 type_from_name (const char *str, MonoBoolean ignoreCase)
1288 MonoType *type = NULL;
1289 MonoAssembly *assembly = NULL;
1290 MonoTypeNameParse info;
1291 char *temp_str = g_strdup (str);
1292 gboolean type_resolve = FALSE;
1294 MONO_ARCH_SAVE_REGS;
1296 /* mono_reflection_parse_type() mangles the string */
1297 if (!mono_reflection_parse_type (temp_str, &info)) {
1298 mono_reflection_free_type_info (&info);
1303 if (info.assembly.name) {
1304 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1306 MonoMethod *m = mono_method_get_last_managed ();
1307 MonoMethod *dest = m;
1309 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1314 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1315 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1316 * to crash. This only seems to happen in some strange remoting
1317 * scenarios and I was unable to figure out what's happening there.
1318 * Dec 10, 2005 - Martin.
1322 assembly = dest->klass->image->assembly;
1323 type_resolve = TRUE;
1325 g_warning (G_STRLOC);
1330 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1331 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1334 if (!info.assembly.name && !type) /* try mscorlib */
1335 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1337 if (assembly && !type && type_resolve) {
1338 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1339 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1342 mono_reflection_free_type_info (&info);
1348 return mono_type_get_object (mono_domain_get (), type);
1352 MonoReflectionType *
1353 mono_type_get (const char *str)
1355 char *copy = g_strdup (str);
1356 MonoReflectionType *type = type_from_name (copy, FALSE);
1363 static MonoReflectionType*
1364 ves_icall_type_from_name (MonoString *name,
1365 MonoBoolean throwOnError,
1366 MonoBoolean ignoreCase)
1368 char *str = mono_string_to_utf8 (name);
1369 MonoReflectionType *type;
1371 type = type_from_name (str, ignoreCase);
1374 MonoException *e = NULL;
1377 e = mono_get_exception_type_load (name, NULL);
1379 mono_loader_clear_error ();
1381 mono_raise_exception (e);
1388 static MonoReflectionType*
1389 ves_icall_type_from_handle (MonoType *handle)
1391 MonoDomain *domain = mono_domain_get ();
1393 MONO_ARCH_SAVE_REGS;
1395 return mono_type_get_object (domain, handle);
1399 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1401 MONO_ARCH_SAVE_REGS;
1403 if (c && type->type && c->type)
1404 return mono_metadata_type_equal (type->type, c->type);
1406 return (type == c) ? TRUE : FALSE;
1409 /* System.TypeCode */
1428 TYPECODE_STRING = 18
1432 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1434 int t = type->type->type;
1436 MONO_ARCH_SAVE_REGS;
1438 if (type->type->byref)
1439 return TYPECODE_OBJECT;
1443 case MONO_TYPE_VOID:
1444 return TYPECODE_OBJECT;
1445 case MONO_TYPE_BOOLEAN:
1446 return TYPECODE_BOOLEAN;
1448 return TYPECODE_BYTE;
1450 return TYPECODE_SBYTE;
1452 return TYPECODE_UINT16;
1454 return TYPECODE_INT16;
1455 case MONO_TYPE_CHAR:
1456 return TYPECODE_CHAR;
1460 return TYPECODE_OBJECT;
1462 return TYPECODE_UINT32;
1464 return TYPECODE_INT32;
1466 return TYPECODE_UINT64;
1468 return TYPECODE_INT64;
1470 return TYPECODE_SINGLE;
1472 return TYPECODE_DOUBLE;
1473 case MONO_TYPE_VALUETYPE: {
1474 MonoClass *klass = type->type->data.klass;
1476 if (klass->enumtype) {
1477 t = mono_class_enum_basetype (klass)->type;
1479 } else if (mono_is_corlib_image (klass->image)) {
1480 if (strcmp (klass->name_space, "System") == 0) {
1481 if (strcmp (klass->name, "Decimal") == 0)
1482 return TYPECODE_DECIMAL;
1483 else if (strcmp (klass->name, "DateTime") == 0)
1484 return TYPECODE_DATETIME;
1487 return TYPECODE_OBJECT;
1489 case MONO_TYPE_STRING:
1490 return TYPECODE_STRING;
1491 case MONO_TYPE_SZARRAY:
1492 case MONO_TYPE_ARRAY:
1493 case MONO_TYPE_OBJECT:
1495 case MONO_TYPE_MVAR:
1496 case MONO_TYPE_TYPEDBYREF:
1497 return TYPECODE_OBJECT;
1498 case MONO_TYPE_CLASS:
1500 MonoClass *klass = type->type->data.klass;
1501 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1502 if (strcmp (klass->name, "DBNull") == 0)
1503 return TYPECODE_DBNULL;
1506 return TYPECODE_OBJECT;
1507 case MONO_TYPE_GENERICINST:
1508 return TYPECODE_OBJECT;
1510 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1516 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1522 MONO_ARCH_SAVE_REGS;
1524 g_assert (type != NULL);
1526 domain = ((MonoObject *)type)->vtable->domain;
1528 if (!c) /* FIXME: dont know what do do here */
1531 klass = mono_class_from_mono_type (type->type);
1532 klassc = mono_class_from_mono_type (c->type);
1534 /* Interface check requires a more complex setup so we
1535 * only do for them. Otherwise we simply avoid mono_class_init.
1537 if (check_interfaces) {
1538 mono_class_init_or_throw (klass);
1539 mono_class_init_or_throw (klassc);
1540 } else if (!klass->supertypes || !klassc->supertypes) {
1541 mono_loader_lock ();
1542 mono_class_setup_supertypes (klass);
1543 mono_class_setup_supertypes (klassc);
1544 mono_loader_unlock ();
1547 if (type->type->byref)
1548 return klassc == mono_defaults.object_class;
1550 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1554 mono_type_is_primitive (MonoType *type)
1556 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1557 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1561 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1563 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1564 return mono_class_enum_basetype (type->data.klass);
1565 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1566 return mono_class_enum_basetype (type->data.generic_class->container_class);
1571 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1577 MONO_ARCH_SAVE_REGS;
1579 g_assert (type != NULL);
1581 domain = ((MonoObject *)type)->vtable->domain;
1583 klass = mono_class_from_mono_type (type->type);
1584 klassc = mono_class_from_mono_type (c->type);
1586 mono_class_init_or_throw (klass);
1587 mono_class_init_or_throw (klassc);
1589 if (type->type->byref ^ c->type->byref)
1592 if (type->type->byref) {
1593 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1594 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1596 klass = mono_class_from_mono_type (t);
1597 klassc = mono_class_from_mono_type (ot);
1599 if (mono_type_is_primitive (t)) {
1600 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1601 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1602 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1603 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1604 return t->type == ot->type;
1606 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1609 if (klass->valuetype)
1610 return klass == klassc;
1611 return klass->valuetype == klassc->valuetype;
1614 return mono_class_is_assignable_from (klass, klassc);
1618 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1620 MonoClass *klass = mono_class_from_mono_type (type->type);
1621 mono_class_init_or_throw (klass);
1622 return mono_object_isinst (obj, klass) != NULL;
1626 ves_icall_get_attributes (MonoReflectionType *type)
1628 MonoClass *klass = mono_class_from_mono_type (type->type);
1629 return klass->flags;
1632 static MonoReflectionMarshal*
1633 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1635 MonoClass *klass = field->field->parent;
1636 MonoMarshalType *info;
1639 if (klass->generic_container ||
1640 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1643 info = mono_marshal_load_type_info (klass);
1645 for (i = 0; i < info->num_fields; ++i) {
1646 if (info->fields [i].field == field->field) {
1647 if (!info->fields [i].mspec)
1650 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1657 static MonoReflectionField*
1658 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1660 gboolean found = FALSE;
1667 klass = handle->parent;
1669 klass = mono_class_from_mono_type (type);
1671 /* Check that the field belongs to the class */
1672 for (k = klass; k; k = k->parent) {
1673 if (k == handle->parent) {
1680 /* The managed code will throw the exception */
1684 return mono_field_get_object (mono_domain_get (), klass, handle);
1688 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1691 MonoType *type = mono_field_get_type_checked (field->field, &error);
1692 if (!mono_error_ok (&error))
1693 mono_error_raise_exception (&error);
1695 return type_array_from_modifiers (field->field->parent->image, type, optional);
1699 vell_icall_get_method_attributes (MonoMethod *method)
1701 return method->flags;
1705 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1708 MonoDomain *domain = mono_domain_get ();
1709 MonoMethodSignature* sig;
1710 MONO_ARCH_SAVE_REGS;
1712 sig = mono_method_signature_checked (method, &error);
1713 if (!mono_error_ok (&error))
1714 mono_error_raise_exception (&error);
1717 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1718 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1719 info->attrs = method->flags;
1720 info->implattrs = method->iflags;
1721 if (sig->call_convention == MONO_CALL_DEFAULT)
1722 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1724 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1729 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1733 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1735 MonoDomain *domain = mono_domain_get ();
1737 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1740 static MonoReflectionMarshal*
1741 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1743 MonoDomain *domain = mono_domain_get ();
1744 MonoReflectionMarshal* res = NULL;
1745 MonoMarshalSpec **mspecs;
1748 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1749 mono_method_get_marshal_info (method, mspecs);
1752 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1754 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1756 mono_metadata_free_marshal_spec (mspecs [i]);
1763 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1765 MonoClass *parent = field->field->parent;
1766 if (!parent->size_inited)
1767 mono_class_init (parent);
1769 return field->field->offset - sizeof (MonoObject);
1772 static MonoReflectionType*
1773 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1776 MONO_ARCH_SAVE_REGS;
1778 parent = declaring? field->field->parent: field->klass;
1780 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1784 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1786 MonoClass *fklass = field->klass;
1787 MonoClassField *cf = field->field;
1788 MonoDomain *domain = mono_object_domain (field);
1790 if (fklass->image->assembly->ref_only)
1791 mono_raise_exception (mono_get_exception_invalid_operation (
1792 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1794 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1795 mono_security_core_clr_ensure_reflection_access_field (cf);
1797 return mono_field_get_value_object (domain, cf, obj);
1801 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1804 MonoClassField *cf = field->field;
1808 MONO_ARCH_SAVE_REGS;
1810 if (field->klass->image->assembly->ref_only)
1811 mono_raise_exception (mono_get_exception_invalid_operation (
1812 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1814 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1815 mono_security_core_clr_ensure_reflection_access_field (cf);
1817 type = mono_field_get_type_checked (cf, &error);
1818 if (!mono_error_ok (&error))
1819 mono_error_raise_exception (&error);
1821 v = (gchar *) value;
1823 switch (type->type) {
1826 case MONO_TYPE_BOOLEAN:
1829 case MONO_TYPE_CHAR:
1838 case MONO_TYPE_VALUETYPE:
1841 v += sizeof (MonoObject);
1843 case MONO_TYPE_STRING:
1844 case MONO_TYPE_OBJECT:
1845 case MONO_TYPE_CLASS:
1846 case MONO_TYPE_ARRAY:
1847 case MONO_TYPE_SZARRAY:
1850 case MONO_TYPE_GENERICINST: {
1851 MonoGenericClass *gclass = type->data.generic_class;
1852 g_assert (!gclass->context.class_inst->is_open);
1854 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1855 MonoClass *nklass = mono_class_from_mono_type (type);
1856 MonoObject *nullable;
1859 * Convert the boxed vtype into a Nullable structure.
1860 * This is complicated by the fact that Nullables have
1861 * a variable structure.
1863 nullable = mono_object_new (mono_domain_get (), nklass);
1865 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1867 v = mono_object_unbox (nullable);
1870 if (gclass->container_class->valuetype && (v != NULL))
1871 v += sizeof (MonoObject);
1875 g_error ("type 0x%x not handled in "
1876 "ves_icall_FieldInfo_SetValueInternal", type->type);
1881 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1882 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1883 if (!vtable->initialized)
1884 mono_runtime_class_init (vtable);
1885 mono_field_static_set_value (vtable, cf, v);
1887 mono_field_set_value (obj, cf, v);
1892 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1894 MonoObject *o = NULL;
1895 MonoClassField *field = this->field;
1897 MonoDomain *domain = mono_object_domain (this);
1899 MonoTypeEnum def_type;
1900 const char *def_value;
1902 MONO_ARCH_SAVE_REGS;
1904 mono_class_init (field->parent);
1906 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1907 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1909 if (field->parent->image->dynamic) {
1911 g_assert_not_reached ();
1914 def_value = mono_class_get_field_default_value (field, &def_type);
1916 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1920 case MONO_TYPE_BOOLEAN:
1923 case MONO_TYPE_CHAR:
1931 case MONO_TYPE_R8: {
1934 /* boxed value type */
1935 t = g_new0 (MonoType, 1);
1937 klass = mono_class_from_mono_type (t);
1939 o = mono_object_new (domain, klass);
1940 v = ((gchar *) o) + sizeof (MonoObject);
1941 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1944 case MONO_TYPE_STRING:
1945 case MONO_TYPE_CLASS:
1946 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1949 g_assert_not_reached ();
1955 static MonoReflectionType*
1956 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1959 MonoClassField *field = ref_field->field;
1960 MonoType *type = mono_field_get_type_checked (field, &error);
1961 if (!mono_error_ok (&error))
1962 mono_error_raise_exception (&error);
1963 return mono_type_get_object (mono_object_domain (ref_field), type);
1966 static MonoReflectionType*
1967 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1969 MonoMethod *method = rmethod->method.method;
1971 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1974 /* From MonoProperty.cs */
1976 PInfo_Attributes = 1,
1977 PInfo_GetMethod = 1 << 1,
1978 PInfo_SetMethod = 1 << 2,
1979 PInfo_ReflectedType = 1 << 3,
1980 PInfo_DeclaringType = 1 << 4,
1985 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1987 MonoDomain *domain = mono_object_domain (property);
1989 MONO_ARCH_SAVE_REGS;
1991 if ((req_info & PInfo_ReflectedType) != 0)
1992 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1993 if ((req_info & PInfo_DeclaringType) != 0)
1994 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1996 if ((req_info & PInfo_Name) != 0)
1997 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1999 if ((req_info & PInfo_Attributes) != 0)
2000 info->attrs = property->property->attrs;
2002 if ((req_info & PInfo_GetMethod) != 0)
2003 MONO_STRUCT_SETREF (info, get, property->property->get ?
2004 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2006 if ((req_info & PInfo_SetMethod) != 0)
2007 MONO_STRUCT_SETREF (info, set, property->property->set ?
2008 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2010 * There may be other methods defined for properties, though, it seems they are not exposed
2011 * in the reflection API
2016 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2018 MonoDomain *domain = mono_object_domain (event);
2020 MONO_ARCH_SAVE_REGS;
2022 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2023 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2025 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2026 info->attrs = event->event->attrs;
2027 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2028 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2029 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2031 #ifndef MONO_SMALL_CONFIG
2032 if (event->event->other) {
2034 while (event->event->other [n])
2036 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2038 for (i = 0; i < n; i++)
2039 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2045 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2050 mono_class_setup_interfaces (klass, error);
2051 if (!mono_error_ok (error))
2054 for (i = 0; i < klass->interface_count; i++) {
2055 ic = klass->interfaces [i];
2056 g_hash_table_insert (ifaces, ic, ic);
2058 collect_interfaces (ic, ifaces, error);
2059 if (!mono_error_ok (error))
2065 MonoArray *iface_array;
2066 MonoGenericContext *context;
2070 } FillIfaceArrayData;
2073 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2075 FillIfaceArrayData *data = user_data;
2076 MonoClass *ic = key;
2077 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2079 if (!mono_error_ok (data->error))
2082 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2083 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2084 if (!mono_error_ok (data->error))
2088 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2091 mono_metadata_free_type (inflated);
2095 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2098 MonoClass *class = mono_class_from_mono_type (type->type);
2100 FillIfaceArrayData data = { 0 };
2103 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2105 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2106 data.context = mono_class_get_context (class);
2107 class = class->generic_class->container_class;
2110 for (parent = class; parent; parent = parent->parent) {
2111 mono_class_setup_interfaces (parent, &error);
2112 if (!mono_error_ok (&error))
2114 collect_interfaces (parent, iface_hash, &error);
2115 if (!mono_error_ok (&error))
2119 data.error = &error;
2120 data.domain = mono_object_domain (type);
2122 len = g_hash_table_size (iface_hash);
2124 g_hash_table_destroy (iface_hash);
2125 if (!data.domain->empty_types)
2126 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2127 return data.domain->empty_types;
2130 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2131 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2132 if (!mono_error_ok (&error))
2135 g_hash_table_destroy (iface_hash);
2136 return data.iface_array;
2139 g_hash_table_destroy (iface_hash);
2140 mono_error_raise_exception (&error);
2145 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2147 gboolean variance_used;
2148 MonoClass *class = mono_class_from_mono_type (type->type);
2149 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2150 MonoReflectionMethod *member;
2153 int i = 0, len, ioffset;
2156 MONO_ARCH_SAVE_REGS;
2157 mono_class_init_or_throw (class);
2158 mono_class_init_or_throw (iclass);
2160 mono_class_setup_vtable (class);
2162 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2166 len = mono_class_num_methods (iclass);
2167 domain = mono_object_domain (type);
2168 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2169 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2171 while ((method = mono_class_get_methods (iclass, &iter))) {
2172 member = mono_method_get_object (domain, method, iclass);
2173 mono_array_setref (*methods, i, member);
2174 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2175 mono_array_setref (*targets, i, member);
2182 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2184 MonoClass *klass = mono_class_from_mono_type (type->type);
2185 mono_class_init_or_throw (klass);
2187 if (klass->image->dynamic) {
2188 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2189 *packing = tb->packing_size;
2190 *size = tb->class_size;
2192 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2196 static MonoReflectionType*
2197 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2201 MONO_ARCH_SAVE_REGS;
2203 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2204 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2206 class = mono_class_from_mono_type (type->type);
2207 mono_class_init_or_throw (class);
2209 // GetElementType should only return a type for:
2210 // Array Pointer PassedByRef
2211 if (type->type->byref)
2212 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2213 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2214 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2215 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2216 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2221 static MonoReflectionType*
2222 ves_icall_get_type_parent (MonoReflectionType *type)
2224 MonoClass *class = mono_class_from_mono_type (type->type);
2225 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2229 ves_icall_type_ispointer (MonoReflectionType *type)
2231 MONO_ARCH_SAVE_REGS;
2233 return type->type->type == MONO_TYPE_PTR;
2237 ves_icall_type_isprimitive (MonoReflectionType *type)
2239 MONO_ARCH_SAVE_REGS;
2241 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)));
2245 ves_icall_type_isbyref (MonoReflectionType *type)
2247 MONO_ARCH_SAVE_REGS;
2249 return type->type->byref;
2253 ves_icall_type_iscomobject (MonoReflectionType *type)
2255 MonoClass *klass = mono_class_from_mono_type (type->type);
2256 mono_class_init_or_throw (klass);
2258 return (klass && klass->is_com_object);
2261 static MonoReflectionModule*
2262 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2264 MonoClass *class = mono_class_from_mono_type (type->type);
2265 return mono_module_get_object (mono_object_domain (type), class->image);
2268 static MonoReflectionAssembly*
2269 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2271 MonoDomain *domain = mono_domain_get ();
2272 MonoClass *class = mono_class_from_mono_type (type->type);
2273 return mono_assembly_get_object (domain, class->image->assembly);
2276 static MonoReflectionType*
2277 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2279 MonoDomain *domain = mono_domain_get ();
2282 MONO_ARCH_SAVE_REGS;
2284 if (type->type->byref)
2286 if (type->type->type == MONO_TYPE_VAR)
2287 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2288 else if (type->type->type == MONO_TYPE_MVAR)
2289 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2291 class = mono_class_from_mono_type (type->type)->nested_in;
2293 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2297 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2299 MonoDomain *domain = mono_domain_get ();
2300 MonoClass *class = mono_class_from_mono_type (type->type);
2302 if (type->type->byref) {
2303 char *n = g_strdup_printf ("%s&", class->name);
2304 MonoString *res = mono_string_new (domain, n);
2310 return mono_string_new (domain, class->name);
2315 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2317 MonoDomain *domain = mono_domain_get ();
2318 MonoClass *class = mono_class_from_mono_type (type->type);
2320 while (class->nested_in)
2321 class = class->nested_in;
2323 if (class->name_space [0] == '\0')
2326 return mono_string_new (domain, class->name_space);
2330 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2334 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2335 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2337 class = mono_class_from_mono_type (type->type);
2343 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2346 MonoClass *klass, *pklass;
2347 MonoDomain *domain = mono_object_domain (type);
2348 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2350 MONO_ARCH_SAVE_REGS;
2352 klass = mono_class_from_mono_type (type->type);
2354 if (klass->generic_container) {
2355 MonoGenericContainer *container = klass->generic_container;
2356 res = mono_array_new_specific (array_vtable, container->type_argc);
2357 for (i = 0; i < container->type_argc; ++i) {
2358 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2359 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2361 } else if (klass->generic_class) {
2362 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2363 res = mono_array_new_specific (array_vtable, inst->type_argc);
2364 for (i = 0; i < inst->type_argc; ++i)
2365 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2367 res = mono_array_new_specific (array_vtable, 0);
2373 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2376 MONO_ARCH_SAVE_REGS;
2378 if (!IS_MONOTYPE (type))
2381 if (type->type->byref)
2384 klass = mono_class_from_mono_type (type->type);
2385 return klass->generic_container != NULL;
2388 static MonoReflectionType*
2389 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2392 MONO_ARCH_SAVE_REGS;
2394 if (type->type->byref)
2397 klass = mono_class_from_mono_type (type->type);
2399 if (klass->generic_container) {
2400 return type; /* check this one */
2402 if (klass->generic_class) {
2403 MonoClass *generic_class = klass->generic_class->container_class;
2406 tb = mono_class_get_ref_info (generic_class);
2408 if (generic_class->wastypebuilder && tb)
2411 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2416 static MonoReflectionType*
2417 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2420 MonoType *geninst, **types;
2423 g_assert (IS_MONOTYPE (type));
2424 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2426 count = mono_array_length (type_array);
2427 types = g_new0 (MonoType *, count);
2429 for (i = 0; i < count; i++) {
2430 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2431 types [i] = t->type;
2434 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2439 class = mono_class_from_mono_type (geninst);
2441 /*we might inflate to the GTD*/
2442 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2443 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2445 return mono_type_get_object (mono_object_domain (type), geninst);
2449 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2452 MONO_ARCH_SAVE_REGS;
2454 if (type->type->byref)
2457 klass = mono_class_from_mono_type (type->type);
2459 return klass->generic_class != NULL;
2463 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2466 MONO_ARCH_SAVE_REGS;
2468 if (!IS_MONOTYPE (type))
2471 if (type->type->byref)
2474 klass = mono_class_from_mono_type (type->type);
2475 return klass->generic_class != NULL || klass->generic_container != NULL;
2479 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2481 MONO_ARCH_SAVE_REGS;
2483 if (!IS_MONOTYPE (type))
2486 if (is_generic_parameter (type->type))
2487 return mono_type_get_generic_param_num (type->type);
2491 static GenericParameterAttributes
2492 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2494 MONO_ARCH_SAVE_REGS;
2496 g_assert (IS_MONOTYPE (type));
2497 g_assert (is_generic_parameter (type->type));
2498 return mono_generic_param_info (type->type->data.generic_param)->flags;
2502 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2504 MonoGenericParamInfo *param_info;
2510 MONO_ARCH_SAVE_REGS;
2512 g_assert (IS_MONOTYPE (type));
2514 domain = mono_object_domain (type);
2515 param_info = mono_generic_param_info (type->type->data.generic_param);
2516 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2519 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2520 for (i = 0; i < count; i++)
2521 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2528 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2530 MONO_ARCH_SAVE_REGS;
2531 return is_generic_parameter (type->type);
2535 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2537 MONO_ARCH_SAVE_REGS;
2538 return is_generic_parameter (tb->type.type);
2542 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2543 MonoReflectionType *t)
2545 enumtype->type = t->type;
2548 static MonoReflectionMethod*
2549 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2550 MonoReflectionMethod* generic)
2557 MONO_ARCH_SAVE_REGS;
2559 domain = ((MonoObject *)type)->vtable->domain;
2561 klass = mono_class_from_mono_type (type->type);
2562 mono_class_init_or_throw (klass);
2565 while ((method = mono_class_get_methods (klass, &iter))) {
2566 if (method->token == generic->method->token)
2567 return mono_method_get_object (domain, method, klass);
2575 static MonoReflectionMethod *
2576 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2579 MonoType *type = ref_type->type;
2581 MONO_ARCH_SAVE_REGS;
2583 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2584 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2585 if (type->type == MONO_TYPE_VAR)
2588 method = mono_type_get_generic_param_owner (type)->owner.method;
2590 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2593 static MonoReflectionDllImportAttribute*
2594 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2596 static MonoClass *DllImportAttributeClass = NULL;
2597 MonoDomain *domain = mono_domain_get ();
2598 MonoReflectionDllImportAttribute *attr;
2599 MonoImage *image = method->klass->image;
2600 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2601 MonoTableInfo *tables = image->tables;
2602 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2603 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2604 guint32 im_cols [MONO_IMPLMAP_SIZE];
2605 guint32 scope_token;
2606 const char *import = NULL;
2607 const char *scope = NULL;
2610 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2613 if (!DllImportAttributeClass) {
2614 DllImportAttributeClass =
2615 mono_class_from_name (mono_defaults.corlib,
2616 "System.Runtime.InteropServices", "DllImportAttribute");
2617 g_assert (DllImportAttributeClass);
2620 if (method->klass->image->dynamic) {
2621 MonoReflectionMethodAux *method_aux =
2622 g_hash_table_lookup (
2623 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2625 import = method_aux->dllentry;
2626 scope = method_aux->dll;
2629 if (!import || !scope) {
2630 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2635 if (piinfo->implmap_idx) {
2636 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2638 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2639 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2640 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2641 scope = mono_metadata_string_heap (image, scope_token);
2644 flags = piinfo->piflags;
2646 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2648 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2649 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2650 attr->call_conv = (flags & 0x700) >> 8;
2651 attr->charset = ((flags & 0x6) >> 1) + 1;
2652 if (attr->charset == 1)
2654 attr->exact_spelling = (flags & 0x1) != 0;
2655 attr->set_last_error = (flags & 0x40) != 0;
2656 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2657 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2658 attr->preserve_sig = FALSE;
2663 static MonoReflectionMethod *
2664 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2666 MonoMethodInflated *imethod;
2669 MONO_ARCH_SAVE_REGS;
2671 if (method->method->is_generic)
2674 if (!method->method->is_inflated)
2677 imethod = (MonoMethodInflated *) method->method;
2679 result = imethod->declaring;
2680 /* Not a generic method. */
2681 if (!result->is_generic)
2684 if (method->method->klass->image->dynamic) {
2685 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2686 MonoReflectionMethod *res;
2689 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2690 * the dynamic case as well ?
2692 mono_loader_lock ();
2693 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2694 mono_loader_unlock ();
2700 if (imethod->context.class_inst) {
2701 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2702 /*Generic methods gets the context of the GTD.*/
2703 if (mono_class_get_context (klass))
2704 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2707 return mono_method_get_object (mono_object_domain (method), result, NULL);
2711 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2713 MONO_ARCH_SAVE_REGS;
2715 return mono_method_signature (method->method)->generic_param_count != 0;
2719 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2721 MONO_ARCH_SAVE_REGS;
2723 return method->method->is_generic;
2727 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2732 MONO_ARCH_SAVE_REGS;
2734 domain = mono_object_domain (method);
2736 if (method->method->is_inflated) {
2737 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2740 count = inst->type_argc;
2741 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2743 for (i = 0; i < count; i++)
2744 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2750 count = mono_method_signature (method->method)->generic_param_count;
2751 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2753 for (i = 0; i < count; i++) {
2754 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2755 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2756 MonoClass *pklass = mono_class_from_generic_parameter (
2757 param, method->method->klass->image, TRUE);
2758 mono_array_setref (res, i,
2759 mono_type_get_object (domain, &pklass->byval_arg));
2766 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2769 * Invoke from reflection is supposed to always be a virtual call (the API
2770 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2771 * greater flexibility.
2773 MonoMethod *m = method->method;
2777 MONO_ARCH_SAVE_REGS;
2781 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2782 mono_security_core_clr_ensure_reflection_access_method (m);
2784 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2785 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2786 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2791 if (!mono_object_isinst (this, m->klass)) {
2792 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2795 m = mono_object_get_virtual_method (this, m);
2796 /* must pass the pointer to the value for valuetype methods */
2797 if (m->klass->valuetype)
2798 obj = mono_object_unbox (this);
2799 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2800 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2805 pcount = params? mono_array_length (params): 0;
2806 if (pcount != mono_method_signature (m)->param_count) {
2807 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2811 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2812 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."));
2816 if (m->klass->image->assembly->ref_only) {
2817 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."));
2821 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2824 intptr_t *lower_bounds;
2825 pcount = mono_array_length (params);
2826 lengths = alloca (sizeof (uintptr_t) * pcount);
2827 /* Note: the synthetized array .ctors have int32 as argument type */
2828 for (i = 0; i < pcount; ++i)
2829 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2831 if (m->klass->rank == pcount) {
2832 /* Only lengths provided. */
2833 lower_bounds = NULL;
2835 g_assert (pcount == (m->klass->rank * 2));
2836 /* lower bounds are first. */
2837 lower_bounds = (intptr_t*)lengths;
2838 lengths += m->klass->rank;
2841 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2843 return mono_runtime_invoke_array (m, obj, params, NULL);
2847 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2849 MonoDomain *domain = mono_object_domain (method);
2850 MonoMethod *m = method->method;
2851 MonoMethodSignature *sig = mono_method_signature (m);
2852 MonoArray *out_args;
2854 int i, j, outarg_count = 0;
2856 MONO_ARCH_SAVE_REGS;
2858 if (m->klass == mono_defaults.object_class) {
2860 if (!strcmp (m->name, "FieldGetter")) {
2861 MonoClass *k = this->vtable->klass;
2865 /* If this is a proxy, then it must be a CBO */
2866 if (k == mono_defaults.transparent_proxy_class) {
2867 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2868 this = tp->rp->unwrapped_server;
2870 k = this->vtable->klass;
2873 name = mono_array_get (params, MonoString *, 1);
2874 str = mono_string_to_utf8 (name);
2877 MonoClassField* field = mono_class_get_field_from_name (k, str);
2879 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2880 if (field_klass->valuetype)
2881 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2883 result = *((gpointer *)((char *)this + field->offset));
2885 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2886 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2887 mono_array_setref (out_args, 0, result);
2895 g_assert_not_reached ();
2897 } else if (!strcmp (m->name, "FieldSetter")) {
2898 MonoClass *k = this->vtable->klass;
2904 /* If this is a proxy, then it must be a CBO */
2905 if (k == mono_defaults.transparent_proxy_class) {
2906 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2907 this = tp->rp->unwrapped_server;
2909 k = this->vtable->klass;
2912 name = mono_array_get (params, MonoString *, 1);
2913 str = mono_string_to_utf8 (name);
2916 MonoClassField* field = mono_class_get_field_from_name (k, str);
2918 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2919 MonoObject *val = mono_array_get (params, gpointer, 2);
2921 if (field_klass->valuetype) {
2922 size = mono_type_size (field->type, &align);
2923 g_assert (size == mono_class_value_size (field_klass, NULL));
2924 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2926 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2929 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2930 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2940 g_assert_not_reached ();
2945 for (i = 0; i < mono_array_length (params); i++) {
2946 if (sig->params [i]->byref)
2950 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2952 /* handle constructors only for objects already allocated */
2953 if (!strcmp (method->method->name, ".ctor"))
2956 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2957 g_assert (!method->method->klass->valuetype);
2958 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2960 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2961 if (sig->params [i]->byref) {
2963 arg = mono_array_get (params, gpointer, i);
2964 mono_array_setref (out_args, j, arg);
2969 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2975 read_enum_value (char *mem, int type)
2979 return *(guint8*)mem;
2981 return *(gint8*)mem;
2983 return *(guint16*)mem;
2985 return *(gint16*)mem;
2987 return *(guint32*)mem;
2989 return *(gint32*)mem;
2991 return *(guint64*)mem;
2993 return *(gint64*)mem;
2995 g_assert_not_reached ();
3001 write_enum_value (char *mem, int type, guint64 value)
3005 case MONO_TYPE_I1: {
3006 guint8 *p = (guint8*)mem;
3011 case MONO_TYPE_I2: {
3012 guint16 *p = (void*)mem;
3017 case MONO_TYPE_I4: {
3018 guint32 *p = (void*)mem;
3023 case MONO_TYPE_I8: {
3024 guint64 *p = (void*)mem;
3029 g_assert_not_reached ();
3035 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3038 MonoClass *enumc, *objc;
3043 MONO_ARCH_SAVE_REGS;
3045 MONO_CHECK_ARG_NULL (enumType);
3046 MONO_CHECK_ARG_NULL (value);
3048 domain = mono_object_domain (enumType);
3049 enumc = mono_class_from_mono_type (enumType->type);
3051 mono_class_init_or_throw (enumc);
3053 objc = value->vtable->klass;
3055 if (!enumc->enumtype)
3056 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3057 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3058 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."));
3060 etype = mono_class_enum_basetype (enumc);
3062 /* MS throws this for typebuilders */
3063 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3065 res = mono_object_new (domain, enumc);
3066 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3067 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3073 ves_icall_System_Enum_get_value (MonoObject *this)
3081 MONO_ARCH_SAVE_REGS;
3086 g_assert (this->vtable->klass->enumtype);
3088 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3089 res = mono_object_new (mono_object_domain (this), enumc);
3090 dst = (char *)res + sizeof (MonoObject);
3091 src = (char *)this + sizeof (MonoObject);
3092 size = mono_class_value_size (enumc, NULL);
3094 memcpy (dst, src, size);
3099 static MonoReflectionType *
3100 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3105 MONO_ARCH_SAVE_REGS;
3107 klass = mono_class_from_mono_type (type->type);
3108 mono_class_init_or_throw (klass);
3110 etype = mono_class_enum_basetype (klass);
3112 /* MS throws this for typebuilders */
3113 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3115 return mono_type_get_object (mono_object_domain (type), etype);
3119 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3121 gpointer tdata = (char *)this + sizeof (MonoObject);
3122 gpointer odata = (char *)other + sizeof (MonoObject);
3123 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3124 g_assert (basetype);
3126 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3127 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3128 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3131 return me > other ? 1 : -1; \
3134 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3135 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3136 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3139 return me - other; \
3142 switch (basetype->type) {
3144 COMPARE_ENUM_VALUES (guint8);
3146 COMPARE_ENUM_VALUES (gint8);
3147 case MONO_TYPE_CHAR:
3149 COMPARE_ENUM_VALUES_RANGE (guint16);
3151 COMPARE_ENUM_VALUES (gint16);
3153 COMPARE_ENUM_VALUES (guint32);
3155 COMPARE_ENUM_VALUES (gint32);
3157 COMPARE_ENUM_VALUES (guint64);
3159 COMPARE_ENUM_VALUES (gint64);
3161 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3163 #undef COMPARE_ENUM_VALUES_RANGE
3164 #undef COMPARE_ENUM_VALUES
3169 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3171 gpointer data = (char *)this + sizeof (MonoObject);
3172 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3173 g_assert (basetype);
3175 switch (basetype->type) {
3177 return *((gint8*)data);
3179 return *((guint8*)data);
3180 case MONO_TYPE_CHAR:
3182 return *((guint16*)data);
3185 return *((gint16*)data);
3187 return *((guint32*)data);
3189 return *((gint32*)data);
3191 case MONO_TYPE_I8: {
3192 gint64 value = *((gint64*)data);
3193 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3196 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3202 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3204 MonoDomain *domain = mono_object_domain (type);
3205 MonoClass *enumc = mono_class_from_mono_type (type->type);
3206 guint j = 0, nvalues, crow;
3208 MonoClassField *field;
3210 MONO_ARCH_SAVE_REGS;
3212 mono_class_init_or_throw (enumc);
3214 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3215 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3216 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3217 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3221 while ((field = mono_class_get_fields (enumc, &iter))) {
3224 MonoTypeEnum def_type;
3226 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3228 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3230 if (mono_field_is_deleted (field))
3232 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3234 p = mono_class_get_field_default_value (field, &def_type);
3235 len = mono_metadata_decode_blob_size (p, &p);
3236 switch (mono_class_enum_basetype (enumc)->type) {
3239 mono_array_set (info->values, gchar, j, *p);
3241 case MONO_TYPE_CHAR:
3244 mono_array_set (info->values, gint16, j, read16 (p));
3248 mono_array_set (info->values, gint32, j, read32 (p));
3252 mono_array_set (info->values, gint64, j, read64 (p));
3255 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3262 BFLAGS_IgnoreCase = 1,
3263 BFLAGS_DeclaredOnly = 2,
3264 BFLAGS_Instance = 4,
3266 BFLAGS_Public = 0x10,
3267 BFLAGS_NonPublic = 0x20,
3268 BFLAGS_FlattenHierarchy = 0x40,
3269 BFLAGS_InvokeMethod = 0x100,
3270 BFLAGS_CreateInstance = 0x200,
3271 BFLAGS_GetField = 0x400,
3272 BFLAGS_SetField = 0x800,
3273 BFLAGS_GetProperty = 0x1000,
3274 BFLAGS_SetProperty = 0x2000,
3275 BFLAGS_ExactBinding = 0x10000,
3276 BFLAGS_SuppressChangeType = 0x20000,
3277 BFLAGS_OptionalParamBinding = 0x40000
3280 static MonoReflectionField *
3281 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3284 MonoClass *startklass, *klass;
3286 MonoClassField *field;
3289 int (*compare_func) (const char *s1, const char *s2) = NULL;
3290 domain = ((MonoObject *)type)->vtable->domain;
3291 klass = startklass = mono_class_from_mono_type (type->type);
3294 mono_raise_exception (mono_get_exception_argument_null ("name"));
3295 if (type->type->byref)
3298 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3301 if (klass->exception_type != MONO_EXCEPTION_NONE)
3302 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3305 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3306 guint32 flags = mono_field_get_flags (field);
3309 if (mono_field_is_deleted_with_flags (field, flags))
3311 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3312 if (bflags & BFLAGS_Public)
3314 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3315 if (bflags & BFLAGS_NonPublic) {
3322 if (flags & FIELD_ATTRIBUTE_STATIC) {
3323 if (bflags & BFLAGS_Static)
3324 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3327 if (bflags & BFLAGS_Instance)
3334 utf8_name = mono_string_to_utf8 (name);
3336 if (compare_func (mono_field_get_name (field), utf8_name)) {
3342 return mono_field_get_object (domain, klass, field);
3344 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3351 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3354 MonoClass *startklass, *klass, *refklass;
3359 MonoClassField *field;
3360 MonoPtrArray tmp_array;
3362 MONO_ARCH_SAVE_REGS;
3364 domain = ((MonoObject *)type)->vtable->domain;
3365 if (type->type->byref)
3366 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3367 klass = startklass = mono_class_from_mono_type (type->type);
3368 refklass = mono_class_from_mono_type (reftype->type);
3370 mono_ptr_array_init (tmp_array, 2);
3373 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3374 mono_ptr_array_destroy (tmp_array);
3375 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3379 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3380 guint32 flags = mono_field_get_flags (field);
3382 if (mono_field_is_deleted_with_flags (field, flags))
3384 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3385 if (bflags & BFLAGS_Public)
3387 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3388 if (bflags & BFLAGS_NonPublic) {
3395 if (flags & FIELD_ATTRIBUTE_STATIC) {
3396 if (bflags & BFLAGS_Static)
3397 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3400 if (bflags & BFLAGS_Instance)
3406 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3407 mono_ptr_array_append (tmp_array, member);
3409 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3412 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3414 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3415 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3417 mono_ptr_array_destroy (tmp_array);
3423 method_nonpublic (MonoMethod* method, gboolean start_klass)
3425 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3426 case METHOD_ATTRIBUTE_ASSEM:
3427 return (start_klass || mono_defaults.generic_ilist_class);
3428 case METHOD_ATTRIBUTE_PRIVATE:
3430 case METHOD_ATTRIBUTE_PUBLIC:
3438 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3440 static MonoClass *MethodInfo_array;
3442 MonoClass *startklass, *klass, *refklass;
3447 int i, len, match, nslots;
3448 /*FIXME, use MonoBitSet*/
3449 guint32 method_slots_default [8];
3450 guint32 *method_slots = NULL;
3451 gchar *mname = NULL;
3452 int (*compare_func) (const char *s1, const char *s2) = NULL;
3453 MonoVTable *array_vtable;
3455 MonoPtrArray tmp_array;
3457 mono_ptr_array_init (tmp_array, 4);
3459 if (!MethodInfo_array) {
3460 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3461 mono_memory_barrier ();
3462 MethodInfo_array = klass;
3465 domain = ((MonoObject *)type)->vtable->domain;
3466 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3467 if (type->type->byref)
3468 return mono_array_new_specific (array_vtable, 0);
3469 klass = startklass = mono_class_from_mono_type (type->type);
3470 refklass = mono_class_from_mono_type (reftype->type);
3474 mname = mono_string_to_utf8 (name);
3475 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3478 /* An optimization for calls made from Delegate:CreateDelegate () */
3479 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3480 method = mono_get_delegate_invoke (klass);
3481 if (mono_loader_get_last_error ())
3484 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3486 res = mono_array_new_specific (array_vtable, 1);
3487 mono_array_setref (res, 0, member);
3492 mono_class_setup_vtable (klass);
3493 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3496 if (is_generic_parameter (type->type))
3497 nslots = mono_class_get_vtable_size (klass->parent);
3499 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3500 if (nslots >= sizeof (method_slots_default) * 8) {
3501 method_slots = g_new0 (guint32, nslots / 32 + 1);
3503 method_slots = method_slots_default;
3504 memset (method_slots, 0, sizeof (method_slots_default));
3507 mono_class_setup_vtable (klass);
3508 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3512 while ((method = mono_class_get_methods (klass, &iter))) {
3514 if (method->slot != -1) {
3515 g_assert (method->slot < nslots);
3516 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3518 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3519 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3522 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3524 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3525 if (bflags & BFLAGS_Public)
3527 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3533 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3534 if (bflags & BFLAGS_Static)
3535 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3538 if (bflags & BFLAGS_Instance)
3546 if (compare_func (mname, method->name))
3552 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3554 mono_ptr_array_append (tmp_array, member);
3556 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3560 if (method_slots != method_slots_default)
3561 g_free (method_slots);
3563 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3565 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3566 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3568 mono_ptr_array_destroy (tmp_array);
3573 if (method_slots != method_slots_default)
3574 g_free (method_slots);
3575 mono_ptr_array_destroy (tmp_array);
3576 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3577 ex = mono_class_get_exception_for_failure (klass);
3579 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3580 mono_loader_clear_error ();
3582 mono_raise_exception (ex);
3587 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3590 static MonoClass *System_Reflection_ConstructorInfo;
3591 MonoClass *startklass, *klass, *refklass;
3596 gpointer iter = NULL;
3597 MonoPtrArray tmp_array;
3599 MONO_ARCH_SAVE_REGS;
3601 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3603 domain = ((MonoObject *)type)->vtable->domain;
3604 if (type->type->byref)
3605 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3606 klass = startklass = mono_class_from_mono_type (type->type);
3607 refklass = mono_class_from_mono_type (reftype->type);
3609 if (!System_Reflection_ConstructorInfo)
3610 System_Reflection_ConstructorInfo = mono_class_from_name (
3611 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3614 while ((method = mono_class_get_methods (klass, &iter))) {
3616 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3618 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3619 if (bflags & BFLAGS_Public)
3622 if (bflags & BFLAGS_NonPublic)
3628 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3629 if (bflags & BFLAGS_Static)
3630 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3633 if (bflags & BFLAGS_Instance)
3639 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3641 mono_ptr_array_append (tmp_array, member);
3644 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3646 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3647 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3649 mono_ptr_array_destroy (tmp_array);
3655 property_hash (gconstpointer data)
3657 MonoProperty *prop = (MonoProperty*)data;
3659 return g_str_hash (prop->name);
3663 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3665 // Properties are hide-by-name-and-signature
3666 if (!g_str_equal (prop1->name, prop2->name))
3669 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3671 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3677 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3682 return method_nonpublic (accessor, start_klass);
3686 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3690 static MonoClass *System_Reflection_PropertyInfo;
3691 MonoClass *startklass, *klass;
3697 gchar *propname = NULL;
3698 int (*compare_func) (const char *s1, const char *s2) = NULL;
3700 GHashTable *properties = NULL;
3701 MonoPtrArray tmp_array;
3703 MONO_ARCH_SAVE_REGS;
3705 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3707 if (!System_Reflection_PropertyInfo)
3708 System_Reflection_PropertyInfo = mono_class_from_name (
3709 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3711 domain = ((MonoObject *)type)->vtable->domain;
3712 if (type->type->byref)
3713 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3714 klass = startklass = mono_class_from_mono_type (type->type);
3717 propname = mono_string_to_utf8 (name);
3718 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3721 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3723 mono_class_setup_vtable (klass);
3724 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3728 while ((prop = mono_class_get_properties (klass, &iter))) {
3734 flags = method->flags;
3737 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3738 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3739 if (bflags & BFLAGS_Public)
3741 } else if (bflags & BFLAGS_NonPublic) {
3742 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3743 property_accessor_nonpublic(prop->set, startklass == klass)) {
3750 if (flags & METHOD_ATTRIBUTE_STATIC) {
3751 if (bflags & BFLAGS_Static)
3752 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3755 if (bflags & BFLAGS_Instance)
3764 if (compare_func (propname, prop->name))
3768 if (g_hash_table_lookup (properties, prop))
3771 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3773 g_hash_table_insert (properties, prop, prop);
3775 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3778 g_hash_table_destroy (properties);
3781 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3782 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3783 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3785 mono_ptr_array_destroy (tmp_array);
3791 g_hash_table_destroy (properties);
3794 mono_ptr_array_destroy (tmp_array);
3796 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3797 ex = mono_class_get_exception_for_failure (klass);
3799 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3800 mono_loader_clear_error ();
3802 mono_raise_exception (ex);
3806 static MonoReflectionEvent *
3807 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3810 MonoClass *klass, *startklass;
3815 int (*compare_func) (const char *s1, const char *s2);
3817 MONO_ARCH_SAVE_REGS;
3819 event_name = mono_string_to_utf8 (name);
3820 if (type->type->byref)
3822 klass = startklass = mono_class_from_mono_type (type->type);
3823 domain = mono_object_domain (type);
3825 mono_class_init_or_throw (klass);
3827 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3829 if (klass->exception_type != MONO_EXCEPTION_NONE)
3830 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3833 while ((event = mono_class_get_events (klass, &iter))) {
3834 if (compare_func (event->name, event_name))
3837 method = event->add;
3839 method = event->remove;
3841 method = event->raise;
3843 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3844 if (!(bflags & BFLAGS_Public))
3847 if (!(bflags & BFLAGS_NonPublic))
3849 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3853 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3854 if (!(bflags & BFLAGS_Static))
3856 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3859 if (!(bflags & BFLAGS_Instance))
3863 if (!(bflags & BFLAGS_NonPublic))
3866 g_free (event_name);
3867 return mono_event_get_object (domain, startklass, event);
3870 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3873 g_free (event_name);
3878 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3882 static MonoClass *System_Reflection_EventInfo;
3883 MonoClass *startklass, *klass;
3890 MonoPtrArray tmp_array;
3892 MONO_ARCH_SAVE_REGS;
3894 mono_ptr_array_init (tmp_array, 4);
3896 if (!System_Reflection_EventInfo)
3897 System_Reflection_EventInfo = mono_class_from_name (
3898 mono_defaults.corlib, "System.Reflection", "EventInfo");
3900 domain = mono_object_domain (type);
3901 if (type->type->byref)
3902 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3903 klass = startklass = mono_class_from_mono_type (type->type);
3906 mono_class_setup_vtable (klass);
3907 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3911 while ((event = mono_class_get_events (klass, &iter))) {
3913 method = event->add;
3915 method = event->remove;
3917 method = event->raise;
3919 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3920 if (bflags & BFLAGS_Public)
3922 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3923 if (bflags & BFLAGS_NonPublic)
3928 if (bflags & BFLAGS_NonPublic)
3934 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3935 if (bflags & BFLAGS_Static)
3936 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3939 if (bflags & BFLAGS_Instance)
3944 if (bflags & BFLAGS_Instance)
3948 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3950 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3953 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3955 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3956 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3958 mono_ptr_array_destroy (tmp_array);
3963 mono_ptr_array_destroy (tmp_array);
3964 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3965 ex = mono_class_get_exception_for_failure (klass);
3967 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3968 mono_loader_clear_error ();
3970 mono_raise_exception (ex);
3974 static MonoReflectionType *
3975 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3983 MONO_ARCH_SAVE_REGS;
3986 mono_raise_exception (mono_get_exception_argument_null ("name"));
3988 domain = ((MonoObject *)type)->vtable->domain;
3989 if (type->type->byref)
3991 klass = mono_class_from_mono_type (type->type);
3993 str = mono_string_to_utf8 (name);
3996 if (klass->exception_type != MONO_EXCEPTION_NONE)
3997 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4000 * If a nested type is generic, return its generic type definition.
4001 * Note that this means that the return value is essentially a
4002 * nested type of the generic type definition of @klass.
4004 * A note in MSDN claims that a generic type definition can have
4005 * nested types that aren't generic. In any case, the container of that
4006 * nested type would be the generic type definition.
4008 if (klass->generic_class)
4009 klass = klass->generic_class->container_class;
4012 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4014 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4015 if (bflags & BFLAGS_Public)
4018 if (bflags & BFLAGS_NonPublic)
4023 if (strcmp (nested->name, str) == 0){
4025 return mono_type_get_object (domain, &nested->byval_arg);
4028 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4035 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4044 MonoPtrArray tmp_array;
4046 MONO_ARCH_SAVE_REGS;
4048 domain = ((MonoObject *)type)->vtable->domain;
4049 if (type->type->byref)
4050 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4051 klass = mono_class_from_mono_type (type->type);
4054 * If a nested type is generic, return its generic type definition.
4055 * Note that this means that the return value is essentially the set
4056 * of nested types of the generic type definition of @klass.
4058 * A note in MSDN claims that a generic type definition can have
4059 * nested types that aren't generic. In any case, the container of that
4060 * nested type would be the generic type definition.
4062 if (klass->generic_class)
4063 klass = klass->generic_class->container_class;
4065 mono_ptr_array_init (tmp_array, 1);
4067 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4069 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4070 if (bflags & BFLAGS_Public)
4073 if (bflags & BFLAGS_NonPublic)
4078 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4079 mono_ptr_array_append (tmp_array, member);
4082 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4084 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4085 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4087 mono_ptr_array_destroy (tmp_array);
4092 static MonoReflectionType*
4093 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4096 MonoType *type = NULL;
4097 MonoTypeNameParse info;
4098 gboolean type_resolve;
4100 MONO_ARCH_SAVE_REGS;
4102 /* On MS.NET, this does not fire a TypeResolve event */
4103 type_resolve = TRUE;
4104 str = mono_string_to_utf8 (name);
4105 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4106 if (!mono_reflection_parse_type (str, &info)) {
4108 mono_reflection_free_type_info (&info);
4109 if (throwOnError) /* uhm: this is a parse error, though... */
4110 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4111 /*g_print ("failed parse\n");*/
4115 if (info.assembly.name) {
4117 mono_reflection_free_type_info (&info);
4119 /* 1.0 and 2.0 throw different exceptions */
4120 if (mono_defaults.generic_ilist_class)
4121 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4123 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4128 if (module != NULL) {
4130 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4135 if (assembly->assembly->dynamic) {
4136 /* Enumerate all modules */
4137 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4141 if (abuilder->modules) {
4142 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4143 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4144 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4150 if (!type && abuilder->loaded_modules) {
4151 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4152 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4153 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4160 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4162 mono_reflection_free_type_info (&info);
4164 MonoException *e = NULL;
4167 e = mono_get_exception_type_load (name, NULL);
4169 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4170 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4172 mono_loader_clear_error ();
4175 mono_raise_exception (e);
4178 } else if (mono_loader_get_last_error ()) {
4180 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4181 mono_loader_clear_error ();
4184 if (type->type == MONO_TYPE_CLASS) {
4185 MonoClass *klass = mono_type_get_class (type);
4187 if (mono_is_security_manager_active () && !klass->exception_type)
4188 /* Some security problems are detected during generic vtable construction */
4189 mono_class_setup_vtable (klass);
4190 /* need to report exceptions ? */
4191 if (throwOnError && klass->exception_type) {
4192 /* report SecurityException (or others) that occured when loading the assembly */
4193 MonoException *exc = mono_class_get_exception_for_failure (klass);
4194 mono_loader_clear_error ();
4195 mono_raise_exception (exc);
4196 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4201 /* g_print ("got it\n"); */
4202 return mono_type_get_object (mono_object_domain (assembly), type);
4206 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4209 gchar *shadow_ini_file;
4212 /* Check for shadow-copied assembly */
4213 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4214 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4216 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4217 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4223 g_free (shadow_ini_file);
4224 if (content != NULL) {
4227 *filename = content;
4235 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4237 MonoDomain *domain = mono_object_domain (assembly);
4238 MonoAssembly *mass = assembly->assembly;
4239 MonoString *res = NULL;
4244 MONO_ARCH_SAVE_REGS;
4246 if (g_path_is_absolute (mass->image->name)) {
4247 absolute = g_strdup (mass->image->name);
4248 dirname = g_path_get_dirname (absolute);
4250 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4251 dirname = g_strdup (mass->basedir);
4254 replace_shadow_path (domain, dirname, &absolute);
4259 for (i = strlen (absolute) - 1; i >= 0; i--)
4260 if (absolute [i] == '\\')
4265 uri = g_filename_to_uri (absolute, NULL, NULL);
4267 const char *prepend = "file://";
4269 if (*absolute == '/' && *(absolute + 1) == '/') {
4272 prepend = "file:///";
4275 uri = g_strconcat (prepend, absolute, NULL);
4279 res = mono_string_new (domain, uri);
4287 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4289 MonoAssembly *mass = assembly->assembly;
4291 MONO_ARCH_SAVE_REGS;
4293 return mass->in_gac;
4296 static MonoReflectionAssembly*
4297 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4301 MonoImageOpenStatus status;
4303 MONO_ARCH_SAVE_REGS;
4305 name = mono_string_to_utf8 (mname);
4306 res = mono_assembly_load_with_partial_name (name, &status);
4312 return mono_assembly_get_object (mono_domain_get (), res);
4316 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4318 MonoDomain *domain = mono_object_domain (assembly);
4321 MONO_ARCH_SAVE_REGS;
4323 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4329 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4331 MONO_ARCH_SAVE_REGS;
4333 return assembly->assembly->ref_only;
4337 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4339 MonoDomain *domain = mono_object_domain (assembly);
4341 MONO_ARCH_SAVE_REGS;
4343 return mono_string_new (domain, assembly->assembly->image->version);
4346 static MonoReflectionMethod*
4347 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4349 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4351 MONO_ARCH_SAVE_REGS;
4355 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4358 static MonoReflectionModule*
4359 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4361 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4365 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4367 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4368 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4372 MONO_ARCH_SAVE_REGS;
4374 for (i = 0; i < table->rows; ++i) {
4375 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4376 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4382 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4384 static MonoClass *System_Version = NULL;
4385 static MonoMethod *create_version = NULL;
4389 if (!System_Version) {
4390 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4391 g_assert (System_Version);
4394 if (!create_version) {
4395 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4396 create_version = mono_method_desc_search_in_class (desc, System_Version);
4397 g_assert (create_version);
4398 mono_method_desc_free (desc);
4404 args [3] = &revision;
4405 result = mono_object_new (domain, System_Version);
4406 mono_runtime_invoke (create_version, result, args, NULL);
4412 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4414 static MonoClass *System_Reflection_AssemblyName;
4416 MonoDomain *domain = mono_object_domain (assembly);
4418 static MonoMethod *create_culture = NULL;
4419 MonoImage *image = assembly->assembly->image;
4422 MONO_ARCH_SAVE_REGS;
4424 if (!System_Reflection_AssemblyName)
4425 System_Reflection_AssemblyName = mono_class_from_name (
4426 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4428 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4431 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4433 if (count > 0 && !create_culture) {
4434 MonoMethodDesc *desc = mono_method_desc_new (
4435 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4436 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4437 g_assert (create_culture);
4438 mono_method_desc_free (desc);
4441 for (i = 0; i < count; i++) {
4442 MonoReflectionAssemblyName *aname;
4443 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4445 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4447 aname = (MonoReflectionAssemblyName *) mono_object_new (
4448 domain, System_Reflection_AssemblyName);
4450 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4452 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4453 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4454 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4455 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4456 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4457 aname->versioncompat = 1; /* SameMachine (default) */
4458 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4459 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4461 if (create_culture) {
4463 MonoBoolean assembly_ref = 1;
4464 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4465 args [1] = &assembly_ref;
4466 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4469 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4470 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4471 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4473 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4474 /* public key token isn't copied - the class library will
4475 automatically generate it from the public key if required */
4476 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4477 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4479 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4480 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4483 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4486 /* note: this function doesn't return the codebase on purpose (i.e. it can
4487 be used under partial trust as path information isn't present). */
4489 mono_array_setref (result, i, aname);
4500 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4502 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4504 mono_array_setref (info->res, info->idx, name);
4509 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4511 MonoImage *img = assembly->assembly->image;
4516 MONO_ARCH_SAVE_REGS;
4518 mono_image_lock (img);
4519 mono_image_init_name_cache (img);
4522 len = g_hash_table_size (img->name_cache);
4523 mono_image_unlock (img);
4525 /*we can't create objects holding the image lock */
4526 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4528 mono_image_lock (img);
4529 /*len might have changed, create a new array*/
4530 if (len != g_hash_table_size (img->name_cache))
4535 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4536 mono_image_unlock (img);
4541 /* move this in some file in mono/util/ */
4543 g_concat_dir_and_file (const char *dir, const char *file)
4545 g_return_val_if_fail (dir != NULL, NULL);
4546 g_return_val_if_fail (file != NULL, NULL);
4549 * If the directory name doesn't have a / on the end, we need
4550 * to add one so we get a proper path to the file
4552 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4553 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4555 return g_strconcat (dir, file, NULL);
4559 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4561 char *n = mono_string_to_utf8 (name);
4562 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4564 guint32 cols [MONO_MANIFEST_SIZE];
4565 guint32 impl, file_idx;
4569 MONO_ARCH_SAVE_REGS;
4571 for (i = 0; i < table->rows; ++i) {
4572 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4573 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4574 if (strcmp (val, n) == 0)
4578 if (i == table->rows)
4581 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4584 * this code should only be called after obtaining the
4585 * ResourceInfo and handling the other cases.
4587 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4588 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4590 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4595 module = assembly->assembly->image;
4597 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4599 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4603 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4605 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4607 guint32 cols [MONO_MANIFEST_SIZE];
4608 guint32 file_cols [MONO_FILE_SIZE];
4612 MONO_ARCH_SAVE_REGS;
4614 n = mono_string_to_utf8 (name);
4615 for (i = 0; i < table->rows; ++i) {
4616 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4617 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4618 if (strcmp (val, n) == 0)
4622 if (i == table->rows)
4625 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4626 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4629 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4630 case MONO_IMPLEMENTATION_FILE:
4631 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4632 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4633 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4634 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4635 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4636 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4639 info->location = RESOURCE_LOCATION_EMBEDDED;
4642 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4643 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4644 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4645 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4646 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4647 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4649 mono_raise_exception (ex);
4651 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4653 /* Obtain info recursively */
4654 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4655 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4658 case MONO_IMPLEMENTATION_EXP_TYPE:
4659 g_assert_not_reached ();
4668 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4670 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4671 MonoArray *result = NULL;
4676 MONO_ARCH_SAVE_REGS;
4678 /* check hash if needed */
4680 n = mono_string_to_utf8 (name);
4681 for (i = 0; i < table->rows; ++i) {
4682 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4683 if (strcmp (val, n) == 0) {
4686 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4687 fn = mono_string_new (mono_object_domain (assembly), n);
4689 return (MonoObject*)fn;
4697 for (i = 0; i < table->rows; ++i) {
4698 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4702 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
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)) {
4707 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4708 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4709 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4714 return (MonoObject*)result;
4718 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4720 MonoDomain *domain = mono_domain_get();
4723 int i, j, file_count = 0;
4724 MonoImage **modules;
4725 guint32 module_count, real_module_count;
4726 MonoTableInfo *table;
4727 guint32 cols [MONO_FILE_SIZE];
4728 MonoImage *image = assembly->assembly->image;
4730 g_assert (image != NULL);
4731 g_assert (!assembly->assembly->dynamic);
4733 table = &image->tables [MONO_TABLE_FILE];
4734 file_count = table->rows;
4736 modules = image->modules;
4737 module_count = image->module_count;
4739 real_module_count = 0;
4740 for (i = 0; i < module_count; ++i)
4742 real_module_count ++;
4744 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4745 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4747 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4749 for (i = 0; i < module_count; ++i)
4751 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4755 for (i = 0; i < file_count; ++i, ++j) {
4756 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4757 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4758 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4760 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4762 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4763 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4765 mono_array_setref (res, j, mono_module_get_object (domain, m));
4772 static MonoReflectionMethod*
4773 ves_icall_GetCurrentMethod (void)
4775 MonoMethod *m = mono_method_get_last_managed ();
4777 while (m->is_inflated)
4778 m = ((MonoMethodInflated*)m)->declaring;
4780 return mono_method_get_object (mono_domain_get (), m, NULL);
4785 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4788 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4789 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4790 //method is inflated, we should inflate it on the other class
4791 MonoGenericContext ctx;
4792 ctx.method_inst = inflated->context.method_inst;
4793 ctx.class_inst = inflated->context.class_inst;
4794 if (klass->generic_class)
4795 ctx.class_inst = klass->generic_class->context.class_inst;
4796 else if (klass->generic_container)
4797 ctx.class_inst = klass->generic_container->context.class_inst;
4798 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4801 mono_class_setup_methods (method->klass);
4802 if (method->klass->exception_type)
4804 for (i = 0; i < method->klass->method.count; ++i) {
4805 if (method->klass->methods [i] == method) {
4810 mono_class_setup_methods (klass);
4811 if (klass->exception_type)
4813 g_assert (offset >= 0 && offset < klass->method.count);
4814 return klass->methods [offset];
4817 static MonoReflectionMethod*
4818 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4822 klass = mono_class_from_mono_type (type);
4823 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4825 if (method->klass != klass) {
4826 method = mono_method_get_equivalent_method (method, klass);
4831 klass = method->klass;
4832 return mono_method_get_object (mono_domain_get (), method, klass);
4835 static MonoReflectionMethod*
4836 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4838 return mono_method_get_object (mono_domain_get (), method, NULL);
4841 static MonoReflectionMethodBody*
4842 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4844 return mono_method_body_get_object (mono_domain_get (), method);
4847 static MonoReflectionAssembly*
4848 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4850 MonoMethod *dest = NULL;
4852 MONO_ARCH_SAVE_REGS;
4854 mono_stack_walk_no_il (get_executing, &dest);
4855 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4859 static MonoReflectionAssembly*
4860 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4862 MonoDomain* domain = mono_domain_get ();
4864 MONO_ARCH_SAVE_REGS;
4866 if (!domain->entry_assembly)
4869 return mono_assembly_get_object (domain, domain->entry_assembly);
4872 static MonoReflectionAssembly*
4873 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4878 MONO_ARCH_SAVE_REGS;
4881 mono_stack_walk_no_il (get_executing, &dest);
4883 mono_stack_walk_no_il (get_caller, &dest);
4886 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4890 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4891 gboolean assembly_qualified)
4893 MonoDomain *domain = mono_object_domain (object);
4894 MonoTypeNameFormat format;
4899 format = assembly_qualified ?
4900 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4901 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4903 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4905 name = mono_type_get_name_full (object->type, format);
4909 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4914 res = mono_string_new (domain, name);
4921 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4923 MonoClass *klass = mono_class_from_mono_type (this->type);
4924 mono_class_init_or_throw (klass);
4925 return mono_security_core_clr_class_level (klass);
4929 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4931 static MonoMethod *create_culture = NULL;
4934 const char *pkey_ptr;
4936 MonoBoolean assembly_ref = 0;
4938 MONO_ARCH_SAVE_REGS;
4940 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4941 aname->major = name->major;
4942 aname->minor = name->minor;
4943 aname->build = name->build;
4944 aname->flags = name->flags;
4945 aname->revision = name->revision;
4946 aname->hashalg = name->hash_alg;
4947 aname->versioncompat = 1; /* SameMachine (default) */
4948 aname->processor_architecture = name->arch;
4950 if (by_default_version)
4951 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4954 if (absolute != NULL && *absolute != '\0') {
4955 const gchar *prepend = "file://";
4958 codebase = g_strdup (absolute);
4963 for (i = strlen (codebase) - 1; i >= 0; i--)
4964 if (codebase [i] == '\\')
4967 if (*codebase == '/' && *(codebase + 1) == '/') {
4970 prepend = "file:///";
4974 result = g_strconcat (prepend, codebase, NULL);
4980 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4984 if (!create_culture) {
4985 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4986 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4987 g_assert (create_culture);
4988 mono_method_desc_free (desc);
4991 if (name->culture) {
4992 args [0] = mono_string_new (domain, name->culture);
4993 args [1] = &assembly_ref;
4994 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4997 if (name->public_key) {
4998 pkey_ptr = (char*)name->public_key;
4999 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5001 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5002 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5003 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5004 } else if (default_publickey) {
5005 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5006 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5009 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5010 if (name->public_key_token [0]) {
5014 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5015 p = mono_array_addr (aname->keyToken, char, 0);
5017 for (i = 0, j = 0; i < 8; i++) {
5018 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5019 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5022 } else if (default_token) {
5023 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5028 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5030 MonoDomain *domain = mono_object_domain (assembly);
5031 MonoAssembly *mass = assembly->assembly;
5035 name = mono_stringify_assembly_name (&mass->aname);
5036 res = mono_string_new (domain, name);
5043 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5046 MonoAssembly *mass = assembly->assembly;
5048 MONO_ARCH_SAVE_REGS;
5050 if (g_path_is_absolute (mass->image->name)) {
5051 fill_reflection_assembly_name (mono_object_domain (assembly),
5052 aname, &mass->aname, mass->image->name, TRUE,
5056 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5058 fill_reflection_assembly_name (mono_object_domain (assembly),
5059 aname, &mass->aname, absolute, TRUE, TRUE,
5066 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5069 MonoImageOpenStatus status = MONO_IMAGE_OK;
5072 MonoAssemblyName name;
5075 MONO_ARCH_SAVE_REGS;
5077 filename = mono_string_to_utf8 (fname);
5079 dirname = g_path_get_dirname (filename);
5080 replace_shadow_path (mono_domain_get (), dirname, &filename);
5083 image = mono_image_open (filename, &status);
5089 if (status == MONO_IMAGE_IMAGE_INVALID)
5090 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5092 exc = mono_get_exception_file_not_found2 (NULL, fname);
5093 mono_raise_exception (exc);
5096 res = mono_assembly_fill_assembly_name (image, &name);
5098 mono_image_close (image);
5100 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5103 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5107 mono_image_close (image);
5111 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5112 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5114 MonoBoolean result = FALSE;
5115 MonoDeclSecurityEntry entry;
5117 /* SecurityAction.RequestMinimum */
5118 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5119 *minimum = entry.blob;
5120 *minLength = entry.size;
5123 /* SecurityAction.RequestOptional */
5124 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5125 *optional = entry.blob;
5126 *optLength = entry.size;
5129 /* SecurityAction.RequestRefuse */
5130 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5131 *refused = entry.blob;
5132 *refLength = entry.size;
5140 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5144 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5146 guint32 attrs, visibility;
5148 /* we start the count from 1 because we skip the special type <Module> */
5151 for (i = 1; i < tdef->rows; ++i) {
5152 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5153 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5154 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5158 count = tdef->rows - 1;
5160 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5161 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5163 for (i = 1; i < tdef->rows; ++i) {
5164 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5165 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5166 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5167 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5169 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5171 MonoLoaderError *error;
5174 error = mono_loader_get_last_error ();
5175 g_assert (error != NULL);
5177 ex = mono_loader_error_prepare_exception (error);
5178 mono_array_setref (*exceptions, count, ex);
5180 if (mono_loader_get_last_error ())
5181 mono_loader_clear_error ();
5190 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5192 MonoArray *res = NULL;
5193 MonoArray *exceptions = NULL;
5194 MonoImage *image = NULL;
5195 MonoTableInfo *table = NULL;
5198 int i, len, ex_count;
5200 MONO_ARCH_SAVE_REGS;
5202 domain = mono_object_domain (assembly);
5204 g_assert (!assembly->assembly->dynamic);
5205 image = assembly->assembly->image;
5206 table = &image->tables [MONO_TABLE_FILE];
5207 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5209 /* Append data from all modules in the assembly */
5210 for (i = 0; i < table->rows; ++i) {
5211 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5212 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5215 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5216 /* Append the new types to the end of the array */
5217 if (mono_array_length (res2) > 0) {
5219 MonoArray *res3, *ex3;
5221 len1 = mono_array_length (res);
5222 len2 = mono_array_length (res2);
5224 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5225 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5226 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5229 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5230 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5231 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5238 /* the ReflectionTypeLoadException must have all the types (Types property),
5239 * NULL replacing types which throws an exception. The LoaderException must
5240 * contain all exceptions for NULL items.
5243 len = mono_array_length (res);
5246 for (i = 0; i < len; i++) {
5247 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5251 klass = mono_type_get_class (t->type);
5252 if ((klass != NULL) && klass->exception_type) {
5253 /* keep the class in the list */
5254 list = g_list_append (list, klass);
5255 /* and replace Type with NULL */
5256 mono_array_setref (res, i, NULL);
5263 if (list || ex_count) {
5265 MonoException *exc = NULL;
5266 MonoArray *exl = NULL;
5267 int j, length = g_list_length (list) + ex_count;
5269 mono_loader_clear_error ();
5271 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5272 /* Types for which mono_class_get () succeeded */
5273 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5274 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5275 mono_array_setref (exl, i, exc);
5277 /* Types for which it don't */
5278 for (j = 0; j < mono_array_length (exceptions); ++j) {
5279 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5281 g_assert (i < length);
5282 mono_array_setref (exl, i, exc);
5289 exc = mono_get_exception_reflection_type_load (res, exl);
5290 mono_loader_clear_error ();
5291 mono_raise_exception (exc);
5298 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5300 MonoAssemblyName aname;
5301 MonoDomain *domain = mono_object_domain (name);
5303 gboolean is_version_defined;
5304 gboolean is_token_defined;
5306 aname.public_key = NULL;
5307 val = mono_string_to_utf8 (assname);
5308 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5309 g_free ((guint8*) aname.public_key);
5314 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5315 FALSE, is_token_defined);
5317 mono_assembly_name_free (&aname);
5318 g_free ((guint8*) aname.public_key);
5324 static MonoReflectionType*
5325 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5327 MonoDomain *domain = mono_object_domain (module);
5330 MONO_ARCH_SAVE_REGS;
5332 g_assert (module->image);
5334 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5335 /* These images do not have a global type */
5338 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5339 return mono_type_get_object (domain, &klass->byval_arg);
5343 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5345 /*if (module->image)
5346 mono_image_close (module->image);*/
5350 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5352 MonoDomain *domain = mono_object_domain (module);
5354 MONO_ARCH_SAVE_REGS;
5356 g_assert (module->image);
5357 return mono_string_new (domain, module->image->guid);
5361 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5364 if (module->image && module->image->is_module_handle)
5365 return module->image->raw_data;
5368 return (gpointer) (-1);
5372 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5374 if (image->dynamic) {
5375 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5376 *pe_kind = dyn->pe_kind;
5377 *machine = dyn->machine;
5380 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5381 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5386 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5388 return (image->md_version_major << 16) | (image->md_version_minor);
5392 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5394 MonoArray *exceptions;
5397 MONO_ARCH_SAVE_REGS;
5400 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5402 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5403 for (i = 0; i < mono_array_length (exceptions); ++i) {
5404 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5406 mono_raise_exception (ex);
5413 mono_memberref_is_method (MonoImage *image, guint32 token)
5415 if (!image->dynamic) {
5416 guint32 cols [MONO_MEMBERREF_SIZE];
5418 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5419 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5420 mono_metadata_decode_blob_size (sig, &sig);
5421 return (*sig != 0x6);
5423 MonoClass *handle_class;
5425 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5428 return mono_defaults.methodhandle_class == handle_class;
5433 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5436 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5437 mono_array_addr (type_args, MonoType*, 0));
5439 context->class_inst = NULL;
5441 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5442 mono_array_addr (method_args, MonoType*, 0));
5444 context->method_inst = NULL;
5448 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5451 int table = mono_metadata_token_table (token);
5452 int index = mono_metadata_token_index (token);
5453 MonoGenericContext context;
5455 *error = ResolveTokenError_Other;
5457 /* Validate token */
5458 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5459 (table != MONO_TABLE_TYPESPEC)) {
5460 *error = ResolveTokenError_BadTable;
5464 if (image->dynamic) {
5465 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5466 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5467 return klass ? &klass->byval_arg : NULL;
5470 init_generic_context_from_args (&context, type_args, method_args);
5471 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5472 return klass ? &klass->byval_arg : NULL;
5475 if ((index <= 0) || (index > image->tables [table].rows)) {
5476 *error = ResolveTokenError_OutOfRange;
5480 init_generic_context_from_args (&context, type_args, method_args);
5481 klass = mono_class_get_full (image, token, &context);
5483 if (mono_loader_get_last_error ())
5484 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5487 return &klass->byval_arg;
5493 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5495 int table = mono_metadata_token_table (token);
5496 int index = mono_metadata_token_index (token);
5497 MonoGenericContext context;
5500 *error = ResolveTokenError_Other;
5502 /* Validate token */
5503 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5504 (table != MONO_TABLE_MEMBERREF)) {
5505 *error = ResolveTokenError_BadTable;
5509 if (image->dynamic) {
5510 if (table == MONO_TABLE_METHOD)
5511 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5513 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5514 *error = ResolveTokenError_BadTable;
5518 init_generic_context_from_args (&context, type_args, method_args);
5519 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5522 if ((index <= 0) || (index > image->tables [table].rows)) {
5523 *error = ResolveTokenError_OutOfRange;
5526 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5527 *error = ResolveTokenError_BadTable;
5531 init_generic_context_from_args (&context, type_args, method_args);
5532 method = mono_get_method_full (image, token, NULL, &context);
5534 if (mono_loader_get_last_error ())
5535 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5541 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5543 int index = mono_metadata_token_index (token);
5545 *error = ResolveTokenError_Other;
5547 /* Validate token */
5548 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5549 *error = ResolveTokenError_BadTable;
5554 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5556 if ((index <= 0) || (index >= image->heap_us.size)) {
5557 *error = ResolveTokenError_OutOfRange;
5561 /* FIXME: What to do if the index points into the middle of a string ? */
5563 return mono_ldstr (mono_domain_get (), image, index);
5566 static MonoClassField*
5567 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5570 int table = mono_metadata_token_table (token);
5571 int index = mono_metadata_token_index (token);
5572 MonoGenericContext context;
5573 MonoClassField *field;
5575 *error = ResolveTokenError_Other;
5577 /* Validate token */
5578 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5579 *error = ResolveTokenError_BadTable;
5583 if (image->dynamic) {
5584 if (table == MONO_TABLE_FIELD)
5585 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5587 if (mono_memberref_is_method (image, token)) {
5588 *error = ResolveTokenError_BadTable;
5592 init_generic_context_from_args (&context, type_args, method_args);
5593 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5596 if ((index <= 0) || (index > image->tables [table].rows)) {
5597 *error = ResolveTokenError_OutOfRange;
5600 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5601 *error = ResolveTokenError_BadTable;
5605 init_generic_context_from_args (&context, type_args, method_args);
5606 field = mono_field_from_token (image, token, &klass, &context);
5608 if (mono_loader_get_last_error ())
5609 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5616 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5618 int table = mono_metadata_token_table (token);
5620 *error = ResolveTokenError_Other;
5623 case MONO_TABLE_TYPEDEF:
5624 case MONO_TABLE_TYPEREF:
5625 case MONO_TABLE_TYPESPEC: {
5626 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5628 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5632 case MONO_TABLE_METHOD:
5633 case MONO_TABLE_METHODSPEC: {
5634 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5636 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5640 case MONO_TABLE_FIELD: {
5641 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5643 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5647 case MONO_TABLE_MEMBERREF:
5648 if (mono_memberref_is_method (image, token)) {
5649 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5651 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5656 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5658 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5665 *error = ResolveTokenError_BadTable;
5672 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5674 int table = mono_metadata_token_table (token);
5675 int idx = mono_metadata_token_index (token);
5676 MonoTableInfo *tables = image->tables;
5681 *error = ResolveTokenError_OutOfRange;
5683 /* FIXME: Support other tables ? */
5684 if (table != MONO_TABLE_STANDALONESIG)
5690 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5693 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5695 ptr = mono_metadata_blob_heap (image, sig);
5696 len = mono_metadata_decode_blob_size (ptr, &ptr);
5698 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5699 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5703 static MonoReflectionType*
5704 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5707 int isbyref = 0, rank;
5708 char *str = mono_string_to_utf8 (smodifiers);
5711 MONO_ARCH_SAVE_REGS;
5713 klass = mono_class_from_mono_type (tb->type.type);
5715 /* logic taken from mono_reflection_parse_type(): keep in sync */
5719 if (isbyref) { /* only one level allowed by the spec */
5726 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5729 klass = mono_ptr_class_get (&klass->byval_arg);
5730 mono_class_init (klass);
5741 else if (*p != '*') { /* '*' means unknown lower bound */
5752 klass = mono_array_class_get (klass, rank);
5753 mono_class_init (klass);
5760 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5764 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5769 MONO_ARCH_SAVE_REGS;
5772 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5778 check_for_invalid_type (MonoClass *klass)
5782 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5785 name = mono_type_get_full_name (klass);
5786 str = mono_string_new (mono_domain_get (), name);
5788 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5791 static MonoReflectionType *
5792 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5794 MonoClass *klass, *aklass;
5796 MONO_ARCH_SAVE_REGS;
5798 klass = mono_class_from_mono_type (type->type);
5799 check_for_invalid_type (klass);
5801 if (rank == 0) //single dimentional array
5802 aklass = mono_array_class_get (klass, 1);
5804 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5806 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5809 static MonoReflectionType *
5810 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5814 MONO_ARCH_SAVE_REGS;
5816 klass = mono_class_from_mono_type (type->type);
5817 mono_class_init_or_throw (klass);
5818 check_for_invalid_type (klass);
5820 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5823 static MonoReflectionType *
5824 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5826 MonoClass *klass, *pklass;
5828 klass = mono_class_from_mono_type (type->type);
5829 mono_class_init_or_throw (klass);
5830 check_for_invalid_type (klass);
5832 pklass = mono_ptr_class_get (type->type);
5834 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5838 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5839 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5841 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5842 MonoObject *delegate;
5844 MonoMethod *method = info->method;
5846 MONO_ARCH_SAVE_REGS;
5848 mono_class_init_or_throw (delegate_class);
5850 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5852 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5853 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5857 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5859 if (method->dynamic) {
5860 /* Creating a trampoline would leak memory */
5861 func = mono_compile_method (method);
5863 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5864 method = mono_object_get_virtual_method (target, method);
5865 func = mono_create_ftnptr (mono_domain_get (),
5866 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5869 mono_delegate_ctor_with_method (delegate, target, func, method);
5875 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5877 /* Reset the invoke impl to the default one */
5878 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5882 * Magic number to convert a time which is relative to
5883 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5885 #define EPOCH_ADJUST ((guint64)62135596800LL)
5888 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5890 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5893 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5895 convert_to_absolute_date(SYSTEMTIME *date)
5897 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5898 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5899 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5900 /* from the calendar FAQ */
5901 int a = (14 - date->wMonth) / 12;
5902 int y = date->wYear - a;
5903 int m = date->wMonth + 12 * a - 2;
5904 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5906 /* d is now the day of the week for the first of the month (0 == Sunday) */
5908 int day_of_week = date->wDayOfWeek;
5910 /* set day_in_month to the first day in the month which falls on day_of_week */
5911 int day_in_month = 1 + (day_of_week - d);
5912 if (day_in_month <= 0)
5915 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5916 date->wDay = day_in_month + (date->wDay - 1) * 7;
5917 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5924 * Return's the offset from GMT of a local time.
5926 * tm is a local time
5927 * t is the same local time as seconds.
5930 gmt_offset(struct tm *tm, time_t t)
5932 #if defined (HAVE_TM_GMTOFF)
5933 return tm->tm_gmtoff;
5938 g.tm_isdst = tm->tm_isdst;
5940 return (int)difftime(t, t2);
5945 * This is heavily based on zdump.c from glibc 2.2.
5947 * * data[0]: start of daylight saving time (in DateTime ticks).
5948 * * data[1]: end of daylight saving time (in DateTime ticks).
5949 * * data[2]: utcoffset (in TimeSpan ticks).
5950 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5951 * * name[0]: name of this timezone when not daylight saving.
5952 * * name[1]: name of this timezone when daylight saving.
5954 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5955 * the class library allows years between 1 and 9999.
5957 * Returns true on success and zero on failure.
5960 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5963 MonoDomain *domain = mono_domain_get ();
5964 struct tm start, tt;
5968 int is_daylight = 0, day;
5971 MONO_ARCH_SAVE_REGS;
5973 MONO_CHECK_ARG_NULL (data);
5974 MONO_CHECK_ARG_NULL (names);
5976 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5977 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5980 * no info is better than crashing: we'll need our own tz data
5981 * to make this work properly, anyway. The range is probably
5982 * reduced to 1970 .. 2037 because that is what mktime is
5983 * guaranteed to support (we get into an infinite loop
5987 memset (&start, 0, sizeof (start));
5990 start.tm_year = year-1900;
5992 t = mktime (&start);
5994 if ((year < 1970) || (year > 2037) || (t == -1)) {
5996 tt = *localtime (&t);
5997 strftime (tzone, sizeof (tzone), "%Z", &tt);
5998 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5999 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6003 gmtoff = gmt_offset (&start, t);
6005 /* For each day of the year, calculate the tm_gmtoff. */
6006 for (day = 0; day < 365; day++) {
6009 tt = *localtime (&t);
6011 /* Daylight saving starts or ends here. */
6012 if (gmt_offset (&tt, t) != gmtoff) {
6016 /* Try to find the exact hour when daylight saving starts/ends. */
6020 tt1 = *localtime (&t1);
6021 } while (gmt_offset (&tt1, t1) != gmtoff);
6023 /* Try to find the exact minute when daylight saving starts/ends. */
6026 tt1 = *localtime (&t1);
6027 } while (gmt_offset (&tt1, t1) == gmtoff);
6029 strftime (tzone, sizeof (tzone), "%Z", &tt);
6031 /* Write data, if we're already in daylight saving, we're done. */
6033 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6034 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6037 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6038 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6042 /* This is only set once when we enter daylight saving. */
6043 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6044 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6046 gmtoff = gmt_offset (&tt, t);
6051 strftime (tzone, sizeof (tzone), "%Z", &tt);
6052 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6053 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6054 mono_array_set ((*data), gint64, 0, 0);
6055 mono_array_set ((*data), gint64, 1, 0);
6056 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6057 mono_array_set ((*data), gint64, 3, 0);
6062 MonoDomain *domain = mono_domain_get ();
6063 TIME_ZONE_INFORMATION tz_info;
6068 tz_id = GetTimeZoneInformation (&tz_info);
6069 if (tz_id == TIME_ZONE_ID_INVALID)
6072 MONO_CHECK_ARG_NULL (data);
6073 MONO_CHECK_ARG_NULL (names);
6075 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6076 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6078 for (i = 0; i < 32; ++i)
6079 if (!tz_info.DaylightName [i])
6081 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6082 for (i = 0; i < 32; ++i)
6083 if (!tz_info.StandardName [i])
6085 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6087 if ((year <= 1601) || (year > 30827)) {
6089 * According to MSDN, the MS time functions can't handle dates outside
6095 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6096 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6097 tz_info.StandardDate.wYear = year;
6098 convert_to_absolute_date(&tz_info.StandardDate);
6099 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6104 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6105 tz_info.DaylightDate.wYear = year;
6106 convert_to_absolute_date(&tz_info.DaylightDate);
6107 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6112 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6114 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6115 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6122 ves_icall_System_Object_obj_address (MonoObject *this)
6124 MONO_ARCH_SAVE_REGS;
6131 static inline gint32
6132 mono_array_get_byte_length (MonoArray *array)
6138 klass = array->obj.vtable->klass;
6140 if (array->bounds == NULL)
6141 length = array->max_length;
6144 for (i = 0; i < klass->rank; ++ i)
6145 length *= array->bounds [i].length;
6148 switch (klass->element_class->byval_arg.type) {
6151 case MONO_TYPE_BOOLEAN:
6155 case MONO_TYPE_CHAR:
6163 return length * sizeof (gpointer);
6174 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6176 MONO_ARCH_SAVE_REGS;
6178 return mono_array_get_byte_length (array);
6182 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6184 MONO_ARCH_SAVE_REGS;
6186 return mono_array_get (array, gint8, idx);
6190 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6192 MONO_ARCH_SAVE_REGS;
6194 mono_array_set (array, gint8, idx, value);
6198 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6200 guint8 *src_buf, *dest_buf;
6202 MONO_ARCH_SAVE_REGS;
6204 /* watch out for integer overflow */
6205 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6208 src_buf = (guint8 *)src->vector + src_offset;
6209 dest_buf = (guint8 *)dest->vector + dest_offset;
6212 memcpy (dest_buf, src_buf, count);
6214 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6220 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6222 MonoDomain *domain = mono_object_domain (this);
6224 MonoRealProxy *rp = ((MonoRealProxy *)this);
6225 MonoTransparentProxy *tp;
6229 MONO_ARCH_SAVE_REGS;
6231 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6232 tp = (MonoTransparentProxy*) res;
6234 MONO_OBJECT_SETREF (tp, rp, rp);
6235 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6236 klass = mono_class_from_mono_type (type);
6238 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6239 tp->remote_class = mono_remote_class (domain, class_name, klass);
6241 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6245 static MonoReflectionType *
6246 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6248 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6251 /* System.Environment */
6254 ves_icall_System_Environment_get_UserName (void)
6256 MONO_ARCH_SAVE_REGS;
6258 /* using glib is more portable */
6259 return mono_string_new (mono_domain_get (), g_get_user_name ());
6264 ves_icall_System_Environment_get_MachineName (void)
6266 #if defined (HOST_WIN32)
6271 len = MAX_COMPUTERNAME_LENGTH + 1;
6272 buf = g_new (gunichar2, len);
6275 if (GetComputerName (buf, (PDWORD) &len))
6276 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6280 #elif !defined(DISABLE_SOCKETS)
6284 if (gethostname (buf, sizeof (buf)) == 0)
6285 result = mono_string_new (mono_domain_get (), buf);
6291 return mono_string_new (mono_domain_get (), "mono");
6296 ves_icall_System_Environment_get_Platform (void)
6298 #if defined (TARGET_WIN32)
6301 #elif defined(__MACH__)
6304 // For compatibility with our client code, this will be 4 for a while.
6305 // We will eventually move to 6 to match .NET, but it requires all client
6306 // code to be updated and the documentation everywhere to be updated
6317 ves_icall_System_Environment_get_NewLine (void)
6319 MONO_ARCH_SAVE_REGS;
6321 #if defined (HOST_WIN32)
6322 return mono_string_new (mono_domain_get (), "\r\n");
6324 return mono_string_new (mono_domain_get (), "\n");
6329 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6334 MONO_ARCH_SAVE_REGS;
6339 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6340 value = g_getenv (utf8_name);
6347 return mono_string_new (mono_domain_get (), value);
6351 * There is no standard way to get at environ.
6354 #ifndef __MINGW32_VERSION
6355 #if defined(__APPLE__) && !defined (__arm__)
6356 /* Apple defines this in crt_externs.h but doesn't provide that header for
6357 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6358 * in fact exist on all implementations (so far)
6360 gchar ***_NSGetEnviron(void);
6361 #define environ (*_NSGetEnviron())
6370 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6381 env_strings = GetEnvironmentStrings();
6384 env_string = env_strings;
6385 while (*env_string != '\0') {
6386 /* weird case that MS seems to skip */
6387 if (*env_string != '=')
6389 while (*env_string != '\0')
6395 domain = mono_domain_get ();
6396 names = mono_array_new (domain, mono_defaults.string_class, n);
6400 env_string = env_strings;
6401 while (*env_string != '\0') {
6402 /* weird case that MS seems to skip */
6403 if (*env_string != '=') {
6404 equal_str = wcschr(env_string, '=');
6405 g_assert(equal_str);
6406 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6407 mono_array_setref (names, n, str);
6410 while (*env_string != '\0')
6415 FreeEnvironmentStrings (env_strings);
6427 MONO_ARCH_SAVE_REGS;
6430 for (e = environ; *e != 0; ++ e)
6433 domain = mono_domain_get ();
6434 names = mono_array_new (domain, mono_defaults.string_class, n);
6437 for (e = environ; *e != 0; ++ e) {
6438 parts = g_strsplit (*e, "=", 2);
6440 str = mono_string_new (domain, *parts);
6441 mono_array_setref (names, n, str);
6454 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6456 #if !GLIB_CHECK_VERSION(2,4,0)
6457 #define g_setenv(a,b,c) setenv(a,b,c)
6458 #define g_unsetenv(a) unsetenv(a)
6462 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6467 gunichar2 *utf16_name, *utf16_value;
6469 gchar *utf8_name, *utf8_value;
6472 MONO_ARCH_SAVE_REGS;
6475 utf16_name = mono_string_to_utf16 (name);
6476 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6477 SetEnvironmentVariable (utf16_name, NULL);
6478 g_free (utf16_name);
6482 utf16_value = mono_string_to_utf16 (value);
6484 SetEnvironmentVariable (utf16_name, utf16_value);
6486 g_free (utf16_name);
6487 g_free (utf16_value);
6489 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6491 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6492 g_unsetenv (utf8_name);
6497 utf8_value = mono_string_to_utf8_checked (value, &error);
6498 if (!mono_error_ok (&error)) {
6500 mono_error_raise_exception (&error);
6502 g_setenv (utf8_name, utf8_value, TRUE);
6505 g_free (utf8_value);
6510 ves_icall_System_Environment_Exit (int result)
6512 MONO_ARCH_SAVE_REGS;
6514 mono_threads_set_shutting_down ();
6516 mono_runtime_set_shutting_down ();
6518 /* This will kill the tp threads which cannot be suspended */
6519 mono_thread_pool_cleanup ();
6521 /* Suspend all managed threads since the runtime is going away */
6522 mono_thread_suspend_all_other_threads ();
6524 mono_runtime_quit ();
6526 /* we may need to do some cleanup here... */
6531 ves_icall_System_Environment_GetGacPath (void)
6533 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6537 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6539 #if defined (HOST_WIN32)
6540 #ifndef CSIDL_FLAG_CREATE
6541 #define CSIDL_FLAG_CREATE 0x8000
6544 WCHAR path [MAX_PATH];
6545 /* Create directory if no existing */
6546 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6550 return mono_string_new_utf16 (mono_domain_get (), path, len);
6553 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6555 return mono_string_new (mono_domain_get (), "");
6559 ves_icall_System_Environment_GetLogicalDrives (void)
6561 gunichar2 buf [256], *ptr, *dname;
6563 guint initial_size = 127, size = 128;
6566 MonoString *drivestr;
6567 MonoDomain *domain = mono_domain_get ();
6570 MONO_ARCH_SAVE_REGS;
6575 while (size > initial_size) {
6576 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6577 if (size > initial_size) {
6580 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6581 initial_size = size;
6595 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6600 while (*u16) { u16++; len ++; }
6601 drivestr = mono_string_new_utf16 (domain, dname, len);
6602 mono_array_setref (result, ndrives++, drivestr);
6613 ves_icall_System_Environment_InternalGetHome (void)
6615 MONO_ARCH_SAVE_REGS;
6617 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6620 static const char *encodings [] = {
6622 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6623 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6624 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6626 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6627 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6628 "x_unicode_2_0_utf_7",
6630 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6631 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6633 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6636 "unicodefffe", "utf_16be",
6643 * Returns the internal codepage, if the value of "int_code_page" is
6644 * 1 at entry, and we can not compute a suitable code page number,
6645 * returns the code page as a string
6648 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6653 char *codepage = NULL;
6655 int want_name = *int_code_page;
6658 *int_code_page = -1;
6659 MONO_ARCH_SAVE_REGS;
6661 g_get_charset (&cset);
6662 c = codepage = strdup (cset);
6663 for (c = codepage; *c; c++){
6664 if (isascii (*c) && isalpha (*c))
6669 /* g_print ("charset: %s\n", cset); */
6671 /* handle some common aliases */
6674 for (i = 0; p != 0; ){
6675 if ((gssize) p < 7){
6677 p = encodings [++i];
6680 if (strcmp (p, codepage) == 0){
6681 *int_code_page = code;
6684 p = encodings [++i];
6687 if (strstr (codepage, "utf_8") != NULL)
6688 *int_code_page |= 0x10000000;
6691 if (want_name && *int_code_page == -1)
6692 return mono_string_new (mono_domain_get (), cset);
6698 ves_icall_System_Environment_get_HasShutdownStarted (void)
6700 if (mono_runtime_is_shutting_down ())
6703 if (mono_domain_is_unloading (mono_domain_get ()))
6710 ves_icall_System_Environment_BroadcastSettingChange (void)
6713 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6718 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6719 MonoReflectionMethod *method,
6720 MonoArray *out_args)
6722 MONO_ARCH_SAVE_REGS;
6724 mono_message_init (mono_object_domain (this), this, method, out_args);
6728 ves_icall_IsTransparentProxy (MonoObject *proxy)
6730 MONO_ARCH_SAVE_REGS;
6735 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6741 static MonoReflectionMethod *
6742 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6743 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6747 MonoMethod **vtable;
6748 MonoMethod *res = NULL;
6750 MONO_CHECK_ARG_NULL (rtype);
6751 MONO_CHECK_ARG_NULL (rmethod);
6753 method = rmethod->method;
6754 klass = mono_class_from_mono_type (rtype->type);
6755 mono_class_init_or_throw (klass);
6757 if (MONO_CLASS_IS_INTERFACE (klass))
6760 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6763 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6764 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6770 mono_class_setup_vtable (klass);
6771 vtable = klass->vtable;
6773 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6774 gboolean variance_used = FALSE;
6775 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6776 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6778 res = vtable [offs + method->slot];
6780 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6783 if (method->slot != -1)
6784 res = vtable [method->slot];
6790 return mono_method_get_object (mono_domain_get (), res, NULL);
6794 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6799 MONO_ARCH_SAVE_REGS;
6801 klass = mono_class_from_mono_type (type->type);
6802 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6804 if (enable) vtable->remote = 1;
6805 else vtable->remote = 0;
6809 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6814 MONO_ARCH_SAVE_REGS;
6816 domain = mono_object_domain (type);
6817 klass = mono_class_from_mono_type (type->type);
6818 mono_class_init_or_throw (klass);
6820 if (klass->rank >= 1) {
6821 g_assert (klass->rank == 1);
6822 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6824 /* Bypass remoting object creation check */
6825 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6830 ves_icall_System_IO_get_temp_path (void)
6832 MONO_ARCH_SAVE_REGS;
6834 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6837 #ifndef PLATFORM_NO_DRIVEINFO
6839 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6840 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6844 ULARGE_INTEGER wapi_free_bytes_avail;
6845 ULARGE_INTEGER wapi_total_number_of_bytes;
6846 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6848 MONO_ARCH_SAVE_REGS;
6850 *error = ERROR_SUCCESS;
6851 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6852 &wapi_total_number_of_free_bytes);
6855 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6856 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6857 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6859 *free_bytes_avail = 0;
6860 *total_number_of_bytes = 0;
6861 *total_number_of_free_bytes = 0;
6862 *error = GetLastError ();
6869 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6871 MONO_ARCH_SAVE_REGS;
6873 return GetDriveType (mono_string_chars (root_path_name));
6878 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6880 MONO_ARCH_SAVE_REGS;
6882 return mono_compile_method (method);
6886 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6891 MONO_ARCH_SAVE_REGS;
6893 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6895 #if defined (HOST_WIN32)
6896 /* Avoid mixing '/' and '\\' */
6899 for (i = strlen (path) - 1; i >= 0; i--)
6900 if (path [i] == '/')
6904 mcpath = mono_string_new (mono_domain_get (), path);
6911 get_bundled_app_config (void)
6913 const gchar *app_config;
6920 MONO_ARCH_SAVE_REGS;
6922 domain = mono_domain_get ();
6923 file = domain->setup->configuration_file;
6927 // Retrieve config file and remove the extension
6928 config_file = mono_string_to_utf8 (file);
6929 len = strlen (config_file) - strlen (".config");
6930 module = g_malloc0 (len + 1);
6931 memcpy (module, config_file, len);
6932 // Get the config file from the module name
6933 app_config = mono_config_string_for_assembly_file (module);
6936 g_free (config_file);
6941 return mono_string_new (mono_domain_get (), app_config);
6945 get_bundled_machine_config (void)
6947 const gchar *machine_config;
6949 MONO_ARCH_SAVE_REGS;
6951 machine_config = mono_get_machine_config ();
6953 if (!machine_config)
6956 return mono_string_new (mono_domain_get (), machine_config);
6960 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6965 MONO_ARCH_SAVE_REGS;
6967 path = g_path_get_dirname (mono_get_config_dir ());
6969 #if defined (HOST_WIN32)
6970 /* Avoid mixing '/' and '\\' */
6973 for (i = strlen (path) - 1; i >= 0; i--)
6974 if (path [i] == '/')
6978 ipath = mono_string_new (mono_domain_get (), path);
6985 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6987 MonoPEResourceDataEntry *entry;
6990 MONO_ARCH_SAVE_REGS;
6992 if (!assembly || !result || !size)
6997 image = assembly->assembly->image;
6998 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7002 *result = mono_image_rva_map (image, entry->rde_data_offset);
7007 *size = entry->rde_size;
7013 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7015 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7019 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7021 #if defined (HOST_WIN32)
7022 OutputDebugString (mono_string_chars (message));
7024 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7028 /* Only used for value types */
7030 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7035 MONO_ARCH_SAVE_REGS;
7037 domain = mono_object_domain (type);
7038 klass = mono_class_from_mono_type (type->type);
7039 mono_class_init_or_throw (klass);
7041 if (mono_class_is_nullable (klass))
7042 /* No arguments -> null */
7045 return mono_object_new (domain, klass);
7048 static MonoReflectionMethod *
7049 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7051 MonoClass *klass, *parent;
7052 MonoMethod *method = m->method;
7053 MonoMethod *result = NULL;
7055 MONO_ARCH_SAVE_REGS;
7057 if (method->klass == NULL)
7060 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7061 MONO_CLASS_IS_INTERFACE (method->klass) ||
7062 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7065 klass = method->klass;
7066 if (klass->generic_class)
7067 klass = klass->generic_class->container_class;
7070 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7071 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7072 mono_class_setup_vtable (parent);
7073 if (parent->vtable_size <= method->slot)
7078 klass = klass->parent;
7083 if (klass == method->klass)
7086 /*This is possible if definition == FALSE.
7087 * Do it here to be really sure we don't read invalid memory.
7089 if (method->slot >= klass->vtable_size)
7092 result = klass->vtable [method->slot];
7093 if (result == NULL) {
7094 /* It is an abstract method */
7095 gpointer iter = NULL;
7096 while ((result = mono_class_get_methods (klass, &iter)))
7097 if (result->slot == method->slot)
7104 return mono_method_get_object (mono_domain_get (), result, NULL);
7108 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7110 MonoMethod *method = m->method;
7112 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7117 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7119 MONO_ARCH_SAVE_REGS;
7121 iter->sig = *(MonoMethodSignature**)argsp;
7123 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7124 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7127 /* FIXME: it's not documented what start is exactly... */
7131 iter->args = argsp + sizeof (gpointer);
7133 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7135 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7139 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7141 guint32 i, arg_size;
7144 MONO_ARCH_SAVE_REGS;
7146 i = iter->sig->sentinelpos + iter->next_arg;
7148 g_assert (i < iter->sig->param_count);
7150 res.type = iter->sig->params [i];
7151 res.klass = mono_class_from_mono_type (res.type);
7152 res.value = iter->args;
7153 arg_size = mono_type_stack_size (res.type, &align);
7154 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7155 if (arg_size <= sizeof (gpointer)) {
7157 int padding = arg_size - mono_type_size (res.type, &dummy);
7158 res.value = (guint8*)res.value + padding;
7161 iter->args = (char*)iter->args + arg_size;
7164 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7170 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
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 while (i < iter->sig->param_count) {
7182 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7184 res.type = iter->sig->params [i];
7185 res.klass = mono_class_from_mono_type (res.type);
7186 /* FIXME: endianess issue... */
7187 res.value = iter->args;
7188 arg_size = mono_type_stack_size (res.type, &align);
7189 iter->args = (char*)iter->args + arg_size;
7191 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7194 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7203 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7206 MONO_ARCH_SAVE_REGS;
7208 i = iter->sig->sentinelpos + iter->next_arg;
7210 g_assert (i < iter->sig->param_count);
7212 return iter->sig->params [i];
7216 mono_TypedReference_ToObject (MonoTypedRef tref)
7218 MONO_ARCH_SAVE_REGS;
7220 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7221 MonoObject** objp = tref.value;
7225 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7229 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7231 MONO_ARCH_SAVE_REGS;
7233 if (MONO_TYPE_IS_REFERENCE (type)) {
7234 MonoObject** objp = value;
7238 return mono_value_box (mono_domain_get (), klass, value);
7242 prelink_method (MonoMethod *method)
7244 const char *exc_class, *exc_arg;
7245 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7247 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7249 mono_raise_exception(
7250 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7252 /* create the wrapper, too? */
7256 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7258 MONO_ARCH_SAVE_REGS;
7259 prelink_method (method->method);
7263 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7265 MonoClass *klass = mono_class_from_mono_type (type->type);
7267 gpointer iter = NULL;
7268 MONO_ARCH_SAVE_REGS;
7270 mono_class_init_or_throw (klass);
7272 while ((m = mono_class_get_methods (klass, &iter)))
7276 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7278 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7279 gint32 const **exponents,
7280 gunichar2 const **digitLowerTable,
7281 gunichar2 const **digitUpperTable,
7282 gint64 const **tenPowersList,
7283 gint32 const **decHexDigits)
7285 *mantissas = Formatter_MantissaBitsTable;
7286 *exponents = Formatter_TensExponentTable;
7287 *digitLowerTable = Formatter_DigitLowerTable;
7288 *digitUpperTable = Formatter_DigitUpperTable;
7289 *tenPowersList = Formatter_TenPowersList;
7290 *decHexDigits = Formatter_DecHexDigits;
7293 /* These parameters are "readonly" in corlib/System/Char.cs */
7295 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7296 guint8 const **numeric_data,
7297 gdouble const **numeric_data_values,
7298 guint16 const **to_lower_data_low,
7299 guint16 const **to_lower_data_high,
7300 guint16 const **to_upper_data_low,
7301 guint16 const **to_upper_data_high)
7303 *category_data = CategoryData;
7304 *numeric_data = NumericData;
7305 *numeric_data_values = NumericDataValues;
7306 *to_lower_data_low = ToLowerDataLow;
7307 *to_lower_data_high = ToLowerDataHigh;
7308 *to_upper_data_low = ToUpperDataLow;
7309 *to_upper_data_high = ToUpperDataHigh;
7313 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7315 return method->method->token;
7319 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7320 * and avoid useless allocations.
7323 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7327 for (i = 0; i < type->num_mods; ++i) {
7328 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7333 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7335 for (i = 0; i < type->num_mods; ++i) {
7336 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7337 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7338 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7346 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7348 MonoType *type = param->ClassImpl->type;
7349 MonoClass *member_class = mono_object_class (param->MemberImpl);
7350 MonoMethod *method = NULL;
7353 MonoMethodSignature *sig;
7355 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7356 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7357 method = rmethod->method;
7358 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7359 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7360 if (!(method = prop->property->get))
7361 method = prop->property->set;
7364 char *type_name = mono_type_get_full_name (member_class);
7365 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7366 MonoException *ex = mono_get_exception_not_supported (msg);
7369 mono_raise_exception (ex);
7372 image = method->klass->image;
7373 pos = param->PositionImpl;
7374 sig = mono_method_signature (method);
7378 type = sig->params [pos];
7380 return type_array_from_modifiers (image, type, optional);
7384 get_property_type (MonoProperty *prop)
7386 MonoMethodSignature *sig;
7388 sig = mono_method_signature (prop->get);
7390 } else if (prop->set) {
7391 sig = mono_method_signature (prop->set);
7392 return sig->params [sig->param_count - 1];
7398 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7400 MonoType *type = get_property_type (property->property);
7401 MonoImage *image = property->klass->image;
7405 return type_array_from_modifiers (image, type, optional);
7409 *Construct a MonoType suited to be used to decode a constant blob object.
7411 * @type is the target type which will be constructed
7412 * @blob_type is the blob type, for example, that comes from the constant table
7413 * @real_type is the expected constructed type.
7416 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7418 type->type = blob_type;
7419 type->data.klass = NULL;
7420 if (blob_type == MONO_TYPE_CLASS)
7421 type->data.klass = mono_defaults.object_class;
7422 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7423 /* For enums, we need to use the base type */
7424 type->type = MONO_TYPE_VALUETYPE;
7425 type->data.klass = mono_class_from_mono_type (real_type);
7427 type->data.klass = mono_class_from_mono_type (real_type);
7431 property_info_get_default_value (MonoReflectionProperty *property)
7434 MonoProperty *prop = property->property;
7435 MonoType *type = get_property_type (prop);
7436 MonoDomain *domain = mono_object_domain (property);
7437 MonoTypeEnum def_type;
7438 const char *def_value;
7441 mono_class_init (prop->parent);
7443 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7444 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7446 def_value = mono_class_get_property_default_value (prop, &def_type);
7448 mono_type_from_blob_type (&blob_type, def_type, type);
7449 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7455 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7457 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7458 MonoCustomAttrInfo *cinfo;
7461 mono_class_init_or_throw (attr_class);
7463 cinfo = mono_reflection_get_custom_attrs_info (obj);
7466 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7468 mono_custom_attrs_free (cinfo);
7473 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7475 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7480 mono_class_init_or_throw (attr_class);
7482 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7483 if (!mono_error_ok (&error))
7484 mono_error_raise_exception (&error);
7485 if (mono_loader_get_last_error ()) {
7486 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7487 g_assert_not_reached ();
7496 ves_icall_Mono_Runtime_GetDisplayName (void)
7499 MonoString *display_name;
7501 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7502 display_name = mono_string_new (mono_domain_get (), info);
7504 return display_name;
7508 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7510 MonoString *message;
7514 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7515 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7518 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7520 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7528 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7529 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7530 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7531 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7532 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7533 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7534 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7535 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7539 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7544 gunichar2 last, prev_last, prev2_last;
7552 last = prev_last = 0, prev2_last = 0;
7553 for (i = 0; i < ilength; i++) {
7555 if (c >= sizeof (dbase64)) {
7556 exc = mono_exception_from_name_msg (mono_get_corlib (),
7557 "System", "FormatException",
7558 "Invalid character found.");
7559 mono_raise_exception (exc);
7560 } else if (isspace (c)) {
7563 prev2_last = prev_last;
7569 olength = ilength - ignored;
7571 if (allowWhitespaceOnly && olength == 0) {
7572 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7575 if ((olength & 3) != 0 || olength <= 0) {
7576 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7577 "FormatException", "Invalid length.");
7578 mono_raise_exception (exc);
7581 if (prev2_last == '=') {
7582 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7583 mono_raise_exception (exc);
7586 olength = (olength * 3) / 4;
7590 if (prev_last == '=')
7593 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7594 res_ptr = mono_array_addr (result, guchar, 0);
7595 for (i = 0; i < ilength; ) {
7598 for (k = 0; k < 4 && i < ilength;) {
7604 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7605 exc = mono_exception_from_name_msg (mono_get_corlib (),
7606 "System", "FormatException",
7607 "Invalid character found.");
7608 mono_raise_exception (exc);
7613 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7615 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7617 *res_ptr++ = (b [2] << 6) | b [3];
7619 while (i < ilength && isspace (start [i]))
7627 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7629 MONO_ARCH_SAVE_REGS;
7631 return base64_to_byte_array (mono_string_chars (str),
7632 mono_string_length (str), allowWhitespaceOnly);
7636 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7638 MONO_ARCH_SAVE_REGS;
7640 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7644 #define ICALL_TYPE(id,name,first)
7645 #define ICALL(id,name,func) Icall_ ## id,
7648 #include "metadata/icall-def.h"
7654 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7655 #define ICALL(id,name,func)
7657 #include "metadata/icall-def.h"
7663 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7664 #define ICALL(id,name,func)
7666 guint16 first_icall;
7669 static const IcallTypeDesc
7670 icall_type_descs [] = {
7671 #include "metadata/icall-def.h"
7675 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7678 #define ICALL_TYPE(id,name,first)
7681 #ifdef HAVE_ARRAY_ELEM_INIT
7682 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7683 #define MSGSTRFIELD1(line) str##line
7685 static const struct msgstrtn_t {
7686 #define ICALL(id,name,func)
7688 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7689 #include "metadata/icall-def.h"
7691 } icall_type_names_str = {
7692 #define ICALL_TYPE(id,name,first) (name),
7693 #include "metadata/icall-def.h"
7696 static const guint16 icall_type_names_idx [] = {
7697 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7698 #include "metadata/icall-def.h"
7701 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7703 static const struct msgstr_t {
7705 #define ICALL_TYPE(id,name,first)
7706 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7707 #include "metadata/icall-def.h"
7709 } icall_names_str = {
7710 #define ICALL(id,name,func) (name),
7711 #include "metadata/icall-def.h"
7714 static const guint16 icall_names_idx [] = {
7715 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7716 #include "metadata/icall-def.h"
7719 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7725 #define ICALL_TYPE(id,name,first) name,
7726 #define ICALL(id,name,func)
7727 static const char* const
7728 icall_type_names [] = {
7729 #include "metadata/icall-def.h"
7733 #define icall_type_name_get(id) (icall_type_names [(id)])
7737 #define ICALL_TYPE(id,name,first)
7738 #define ICALL(id,name,func) name,
7739 static const char* const
7741 #include "metadata/icall-def.h"
7744 #define icall_name_get(id) icall_names [(id)]
7746 #endif /* !HAVE_ARRAY_ELEM_INIT */
7750 #define ICALL_TYPE(id,name,first)
7751 #define ICALL(id,name,func) func,
7752 static const gconstpointer
7753 icall_functions [] = {
7754 #include "metadata/icall-def.h"
7758 static GHashTable *icall_hash = NULL;
7759 static GHashTable *jit_icall_hash_name = NULL;
7760 static GHashTable *jit_icall_hash_addr = NULL;
7763 mono_icall_init (void)
7767 /* check that tables are sorted: disable in release */
7770 const char *prev_class = NULL;
7771 const char *prev_method;
7773 for (i = 0; i < Icall_type_num; ++i) {
7774 const IcallTypeDesc *desc;
7777 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7778 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7779 prev_class = icall_type_name_get (i);
7780 desc = &icall_type_descs [i];
7781 num_icalls = icall_desc_num_icalls (desc);
7782 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7783 for (j = 0; j < num_icalls; ++j) {
7784 const char *methodn = icall_name_get (desc->first_icall + j);
7785 if (prev_method && strcmp (prev_method, methodn) >= 0)
7786 g_print ("method %s should come before method %s\n", methodn, prev_method);
7787 prev_method = methodn;
7792 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7796 mono_icall_cleanup (void)
7798 g_hash_table_destroy (icall_hash);
7799 g_hash_table_destroy (jit_icall_hash_name);
7800 g_hash_table_destroy (jit_icall_hash_addr);
7804 mono_add_internal_call (const char *name, gconstpointer method)
7806 mono_loader_lock ();
7808 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7810 mono_loader_unlock ();
7813 #ifdef HAVE_ARRAY_ELEM_INIT
7815 compare_method_imap (const void *key, const void *elem)
7817 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7818 return strcmp (key, method_name);
7822 find_method_icall (const IcallTypeDesc *imap, const char *name)
7824 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7827 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7831 compare_class_imap (const void *key, const void *elem)
7833 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7834 return strcmp (key, class_name);
7837 static const IcallTypeDesc*
7838 find_class_icalls (const char *name)
7840 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7843 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7848 compare_method_imap (const void *key, const void *elem)
7850 const char** method_name = (const char**)elem;
7851 return strcmp (key, *method_name);
7855 find_method_icall (const IcallTypeDesc *imap, const char *name)
7857 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7860 return (gpointer)icall_functions [(nameslot - icall_names)];
7864 compare_class_imap (const void *key, const void *elem)
7866 const char** class_name = (const char**)elem;
7867 return strcmp (key, *class_name);
7870 static const IcallTypeDesc*
7871 find_class_icalls (const char *name)
7873 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7876 return &icall_type_descs [nameslot - icall_type_names];
7882 * we should probably export this as an helper (handle nested types).
7883 * Returns the number of chars written in buf.
7886 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7888 int nspacelen, cnamelen;
7889 nspacelen = strlen (klass->name_space);
7890 cnamelen = strlen (klass->name);
7891 if (nspacelen + cnamelen + 2 > bufsize)
7894 memcpy (buf, klass->name_space, nspacelen);
7895 buf [nspacelen ++] = '.';
7897 memcpy (buf + nspacelen, klass->name, cnamelen);
7898 buf [nspacelen + cnamelen] = 0;
7899 return nspacelen + cnamelen;
7903 mono_lookup_internal_call (MonoMethod *method)
7908 int typelen = 0, mlen, siglen;
7910 const IcallTypeDesc *imap;
7912 g_assert (method != NULL);
7914 if (method->is_inflated)
7915 method = ((MonoMethodInflated *) method)->declaring;
7917 if (method->klass->nested_in) {
7918 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7922 mname [pos++] = '/';
7925 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7931 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7936 imap = find_class_icalls (mname);
7938 mname [typelen] = ':';
7939 mname [typelen + 1] = ':';
7941 mlen = strlen (method->name);
7942 memcpy (mname + typelen + 2, method->name, mlen);
7943 sigstart = mname + typelen + 2 + mlen;
7946 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7947 siglen = strlen (tmpsig);
7948 if (typelen + mlen + siglen + 6 > sizeof (mname))
7951 memcpy (sigstart + 1, tmpsig, siglen);
7952 sigstart [siglen + 1] = ')';
7953 sigstart [siglen + 2] = 0;
7956 mono_loader_lock ();
7958 res = g_hash_table_lookup (icall_hash, mname);
7960 mono_loader_unlock ();
7963 /* try without signature */
7965 res = g_hash_table_lookup (icall_hash, mname);
7967 mono_loader_unlock ();
7971 /* it wasn't found in the static call tables */
7973 mono_loader_unlock ();
7976 res = find_method_icall (imap, sigstart - mlen);
7978 mono_loader_unlock ();
7981 /* try _with_ signature */
7983 res = find_method_icall (imap, sigstart - mlen);
7985 mono_loader_unlock ();
7989 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7990 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7991 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7992 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7993 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");
7994 g_print ("If you see other errors or faults after this message they are probably related\n");
7995 g_print ("and you need to fix your mono install first.\n");
7997 mono_loader_unlock ();
8003 type_from_typename (char *typename)
8005 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8007 if (!strcmp (typename, "int"))
8008 klass = mono_defaults.int_class;
8009 else if (!strcmp (typename, "ptr"))
8010 klass = mono_defaults.int_class;
8011 else if (!strcmp (typename, "void"))
8012 klass = mono_defaults.void_class;
8013 else if (!strcmp (typename, "int32"))
8014 klass = mono_defaults.int32_class;
8015 else if (!strcmp (typename, "uint32"))
8016 klass = mono_defaults.uint32_class;
8017 else if (!strcmp (typename, "int8"))
8018 klass = mono_defaults.sbyte_class;
8019 else if (!strcmp (typename, "uint8"))
8020 klass = mono_defaults.byte_class;
8021 else if (!strcmp (typename, "int16"))
8022 klass = mono_defaults.int16_class;
8023 else if (!strcmp (typename, "uint16"))
8024 klass = mono_defaults.uint16_class;
8025 else if (!strcmp (typename, "long"))
8026 klass = mono_defaults.int64_class;
8027 else if (!strcmp (typename, "ulong"))
8028 klass = mono_defaults.uint64_class;
8029 else if (!strcmp (typename, "float"))
8030 klass = mono_defaults.single_class;
8031 else if (!strcmp (typename, "double"))
8032 klass = mono_defaults.double_class;
8033 else if (!strcmp (typename, "object"))
8034 klass = mono_defaults.object_class;
8035 else if (!strcmp (typename, "obj"))
8036 klass = mono_defaults.object_class;
8037 else if (!strcmp (typename, "string"))
8038 klass = mono_defaults.string_class;
8039 else if (!strcmp (typename, "bool"))
8040 klass = mono_defaults.boolean_class;
8041 else if (!strcmp (typename, "boolean"))
8042 klass = mono_defaults.boolean_class;
8044 g_error ("%s", typename);
8045 g_assert_not_reached ();
8047 return &klass->byval_arg;
8050 MonoMethodSignature*
8051 mono_create_icall_signature (const char *sigstr)
8056 MonoMethodSignature *res;
8058 mono_loader_lock ();
8059 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8061 mono_loader_unlock ();
8065 parts = g_strsplit (sigstr, " ", 256);
8074 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8079 * Under windows, the default pinvoke calling convention is STDCALL but
8082 res->call_convention = MONO_CALL_C;
8085 res->ret = type_from_typename (parts [0]);
8086 for (i = 1; i < len; ++i) {
8087 res->params [i - 1] = type_from_typename (parts [i]);
8092 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8094 mono_loader_unlock ();
8100 mono_find_jit_icall_by_name (const char *name)
8102 MonoJitICallInfo *info;
8103 g_assert (jit_icall_hash_name);
8105 mono_loader_lock ();
8106 info = g_hash_table_lookup (jit_icall_hash_name, name);
8107 mono_loader_unlock ();
8112 mono_find_jit_icall_by_addr (gconstpointer addr)
8114 MonoJitICallInfo *info;
8115 g_assert (jit_icall_hash_addr);
8117 mono_loader_lock ();
8118 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8119 mono_loader_unlock ();
8125 * mono_get_jit_icall_info:
8127 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8128 * caller should access it while holding the loader lock.
8131 mono_get_jit_icall_info (void)
8133 return jit_icall_hash_name;
8137 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8139 mono_loader_lock ();
8140 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8141 mono_loader_unlock ();
8145 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8147 MonoJitICallInfo *info;
8152 mono_loader_lock ();
8154 if (!jit_icall_hash_name) {
8155 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8156 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8159 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8160 g_warning ("jit icall already defined \"%s\"\n", name);
8161 g_assert_not_reached ();
8164 info = g_new0 (MonoJitICallInfo, 1);
8171 info->wrapper = func;
8173 info->wrapper = NULL;
8176 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8177 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8179 mono_loader_unlock ();