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;
693 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
696 if (source->bounds || dest->bounds)
699 /* there's no integer overflow since mono_array_length returns an unsigned integer */
700 if ((dest_idx + length > mono_array_length (dest)) ||
701 (source_idx + length > mono_array_length (source)))
704 src_class = source->obj.vtable->klass->element_class;
705 dest_class = dest->obj.vtable->klass->element_class;
708 * Handle common cases.
711 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
712 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
713 // FIXME: This is racy
717 int has_refs = dest_class->has_references;
718 for (i = source_idx; i < source_idx + length; ++i) {
719 MonoObject *elem = mono_array_get (source, MonoObject*, i);
720 if (elem && !mono_object_isinst (elem, dest_class))
724 element_size = mono_array_element_size (dest->obj.vtable->klass);
725 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
726 for (i = 0; i < length; ++i) {
727 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
728 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
732 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
734 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
740 /* Check if we're copying a char[] <==> (u)short[] */
741 if (src_class != dest_class) {
742 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
745 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
747 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
748 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
749 // FIXME: This is racy
753 for (i = source_idx; i < source_idx + length; ++i) {
754 MonoObject *elem = mono_array_get (source, MonoObject*, i);
755 if (elem && !mono_object_isinst (elem, dest_class))
763 if (dest_class->valuetype) {
764 element_size = mono_array_element_size (source->obj.vtable->klass);
765 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
766 if (dest_class->has_references) {
767 mono_value_copy_array (dest, dest_idx, source_addr, length);
769 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
770 memmove (dest_addr, source_addr, element_size * length);
773 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
780 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
789 ao = (MonoArray *)this;
790 ac = (MonoClass *)ao->obj.vtable->klass;
792 esize = mono_array_element_size (ac);
793 ea = (gpointer*)((char*)ao->vector + (pos * esize));
795 memcpy (value, ea, esize);
799 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
808 ao = (MonoArray *)this;
809 ac = (MonoClass *)ao->obj.vtable->klass;
810 ec = ac->element_class;
812 esize = mono_array_element_size (ac);
813 ea = (gpointer*)((char*)ao->vector + (pos * esize));
815 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
816 g_assert (esize == sizeof (gpointer));
817 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
819 g_assert (ec->inited);
820 g_assert (esize == mono_class_value_size (ec, NULL));
821 if (ec->has_references)
822 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
824 memcpy (ea, value, esize);
829 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
831 MonoClass *klass = array->obj.vtable->klass;
832 guint32 size = mono_array_element_size (klass);
833 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
835 const char *field_data;
837 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
838 MonoException *exc = mono_get_exception_argument("array",
839 "Cannot initialize array of non-primitive type.");
840 mono_raise_exception (exc);
843 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
844 MonoException *exc = mono_get_exception_argument("field_handle",
845 "Field doesn't have an RVA");
846 mono_raise_exception (exc);
849 size *= array->max_length;
850 field_data = mono_field_get_data (field_handle);
852 if (size > mono_type_size (field_handle->type, &align)) {
853 MonoException *exc = mono_get_exception_argument("field_handle",
854 "Field not large enough to fill array");
855 mono_raise_exception (exc);
858 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
860 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
861 guint ## n *src = (guint ## n *) field_data; \
862 guint ## n *end = (guint ## n *)((char*)src + size); \
864 for (; src < end; data++, src++) { \
865 *data = read ## n (src); \
869 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
871 switch (type->type) {
888 memcpy (mono_array_addr (array, char, 0), field_data, size);
892 memcpy (mono_array_addr (array, char, 0), field_data, size);
894 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
897 double *data = (double*)mono_array_addr (array, double, 0);
899 for (i = 0; i < size; i++, data++) {
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
913 return offsetof (MonoString, chars);
917 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
921 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
924 return mono_object_clone (obj);
928 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
933 MONO_CHECK_ARG_NULL (handle);
935 klass = mono_class_from_mono_type (handle);
936 MONO_CHECK_ARG (handle, klass);
938 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
940 /* This will call the type constructor */
941 mono_runtime_class_init (vtable);
945 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
949 mono_image_check_for_module_cctor (image);
950 if (image->has_module_cctor) {
951 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
952 /*It's fine to raise the exception here*/
953 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
958 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
963 /* later make this configurable and per-arch */
964 int min_size = 4096 * 4 * sizeof (void*);
965 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
966 /* if we have no info we are optimistic and assume there is enough room */
969 current = (guint8 *)&stack_addr;
970 if (current > stack_addr) {
971 if ((current - stack_addr) < min_size)
974 if (current - (stack_addr - stack_size) < min_size)
981 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
985 return mono_object_clone (this);
989 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
992 MonoObject **values = NULL;
996 MonoClassField* field;
1001 klass = mono_object_class (this);
1003 if (mono_class_num_fields (klass) == 0)
1004 return mono_object_hash (this);
1007 * Compute the starting value of the hashcode for fields of primitive
1008 * types, and return the remaining fields in an array to the managed side.
1009 * This way, we can avoid costly reflection operations in managed code.
1012 while ((field = mono_class_get_fields (klass, &iter))) {
1013 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1015 if (mono_field_is_deleted (field))
1017 /* FIXME: Add more types */
1018 switch (field->type->type) {
1020 result ^= *(gint32*)((guint8*)this + field->offset);
1022 case MONO_TYPE_STRING: {
1024 s = *(MonoString**)((guint8*)this + field->offset);
1026 result ^= mono_string_hash (s);
1031 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1032 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1033 values [count++] = o;
1039 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1040 for (i = 0; i < count; ++i)
1041 mono_array_setref (*fields, i, values [i]);
1049 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1052 MonoObject **values = NULL;
1054 MonoClassField* field;
1058 MONO_ARCH_SAVE_REGS;
1060 MONO_CHECK_ARG_NULL (that);
1062 if (this->vtable != that->vtable)
1065 klass = mono_object_class (this);
1067 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1068 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1071 * Do the comparison for fields of primitive type and return a result if
1072 * possible. Otherwise, return the remaining fields in an array to the
1073 * managed side. This way, we can avoid costly reflection operations in
1078 while ((field = mono_class_get_fields (klass, &iter))) {
1079 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1081 if (mono_field_is_deleted (field))
1083 /* FIXME: Add more types */
1084 switch (field->type->type) {
1087 case MONO_TYPE_BOOLEAN:
1088 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1093 case MONO_TYPE_CHAR:
1094 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1099 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1104 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1108 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1112 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1117 case MONO_TYPE_STRING: {
1118 MonoString *s1, *s2;
1119 guint32 s1len, s2len;
1120 s1 = *(MonoString**)((guint8*)this + field->offset);
1121 s2 = *(MonoString**)((guint8*)that + field->offset);
1124 if ((s1 == NULL) || (s2 == NULL))
1126 s1len = mono_string_length (s1);
1127 s2len = mono_string_length (s2);
1131 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1137 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1138 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1139 values [count++] = o;
1140 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1141 values [count++] = o;
1144 if (klass->enumtype)
1145 /* enums only have one non-static field */
1151 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1152 for (i = 0; i < count; ++i)
1153 mono_array_setref (*fields, i, values [i]);
1160 static MonoReflectionType *
1161 ves_icall_System_Object_GetType (MonoObject *obj)
1163 MONO_ARCH_SAVE_REGS;
1165 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1166 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1168 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1172 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1174 MONO_ARCH_SAVE_REGS;
1176 mtype->type = &obj->vtable->klass->byval_arg;
1177 g_assert (mtype->type->type);
1181 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1183 MONO_ARCH_SAVE_REGS;
1185 MONO_CHECK_ARG_NULL (obj);
1187 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1191 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1192 MonoReflectionMethod *method,
1193 MonoArray *opt_param_types)
1195 MONO_ARCH_SAVE_REGS;
1197 MONO_CHECK_ARG_NULL (method);
1199 return mono_image_create_method_token (
1200 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1204 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1206 MONO_ARCH_SAVE_REGS;
1208 mono_image_create_pefile (mb, file);
1212 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1214 MONO_ARCH_SAVE_REGS;
1216 mono_image_build_metadata (mb);
1220 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1222 MONO_ARCH_SAVE_REGS;
1224 mono_image_register_token (mb->dynamic_image, token, obj);
1228 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1230 MonoMethod **dest = data;
1232 /* skip unmanaged frames */
1248 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1250 MonoMethod **dest = data;
1252 /* skip unmanaged frames */
1257 if (!strcmp (m->klass->name_space, "System.Reflection"))
1266 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1268 MonoMethod **dest = data;
1270 /* skip unmanaged frames */
1274 if (m->wrapper_type != MONO_WRAPPER_NONE)
1277 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1291 static MonoReflectionType *
1292 type_from_name (const char *str, MonoBoolean ignoreCase)
1294 MonoType *type = NULL;
1295 MonoAssembly *assembly = NULL;
1296 MonoTypeNameParse info;
1297 char *temp_str = g_strdup (str);
1298 gboolean type_resolve = FALSE;
1300 MONO_ARCH_SAVE_REGS;
1302 /* mono_reflection_parse_type() mangles the string */
1303 if (!mono_reflection_parse_type (temp_str, &info)) {
1304 mono_reflection_free_type_info (&info);
1309 if (info.assembly.name) {
1310 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1312 MonoMethod *m = mono_method_get_last_managed ();
1313 MonoMethod *dest = m;
1315 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1320 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1321 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1322 * to crash. This only seems to happen in some strange remoting
1323 * scenarios and I was unable to figure out what's happening there.
1324 * Dec 10, 2005 - Martin.
1328 assembly = dest->klass->image->assembly;
1329 type_resolve = TRUE;
1331 g_warning (G_STRLOC);
1336 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1337 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1340 if (!info.assembly.name && !type) /* try mscorlib */
1341 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1343 if (assembly && !type && type_resolve) {
1344 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1345 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1348 mono_reflection_free_type_info (&info);
1354 return mono_type_get_object (mono_domain_get (), type);
1358 MonoReflectionType *
1359 mono_type_get (const char *str)
1361 char *copy = g_strdup (str);
1362 MonoReflectionType *type = type_from_name (copy, FALSE);
1369 static MonoReflectionType*
1370 ves_icall_type_from_name (MonoString *name,
1371 MonoBoolean throwOnError,
1372 MonoBoolean ignoreCase)
1374 char *str = mono_string_to_utf8 (name);
1375 MonoReflectionType *type;
1377 type = type_from_name (str, ignoreCase);
1380 MonoException *e = NULL;
1383 e = mono_get_exception_type_load (name, NULL);
1385 mono_loader_clear_error ();
1387 mono_raise_exception (e);
1394 static MonoReflectionType*
1395 ves_icall_type_from_handle (MonoType *handle)
1397 MonoDomain *domain = mono_domain_get ();
1399 MONO_ARCH_SAVE_REGS;
1401 return mono_type_get_object (domain, handle);
1405 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1407 MONO_ARCH_SAVE_REGS;
1409 if (c && type->type && c->type)
1410 return mono_metadata_type_equal (type->type, c->type);
1412 return (type == c) ? TRUE : FALSE;
1415 /* System.TypeCode */
1434 TYPECODE_STRING = 18
1438 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1440 int t = type->type->type;
1442 MONO_ARCH_SAVE_REGS;
1444 if (type->type->byref)
1445 return TYPECODE_OBJECT;
1449 case MONO_TYPE_VOID:
1450 return TYPECODE_OBJECT;
1451 case MONO_TYPE_BOOLEAN:
1452 return TYPECODE_BOOLEAN;
1454 return TYPECODE_BYTE;
1456 return TYPECODE_SBYTE;
1458 return TYPECODE_UINT16;
1460 return TYPECODE_INT16;
1461 case MONO_TYPE_CHAR:
1462 return TYPECODE_CHAR;
1466 return TYPECODE_OBJECT;
1468 return TYPECODE_UINT32;
1470 return TYPECODE_INT32;
1472 return TYPECODE_UINT64;
1474 return TYPECODE_INT64;
1476 return TYPECODE_SINGLE;
1478 return TYPECODE_DOUBLE;
1479 case MONO_TYPE_VALUETYPE: {
1480 MonoClass *klass = type->type->data.klass;
1482 if (klass->enumtype) {
1483 t = mono_class_enum_basetype (klass)->type;
1485 } else if (mono_is_corlib_image (klass->image)) {
1486 if (strcmp (klass->name_space, "System") == 0) {
1487 if (strcmp (klass->name, "Decimal") == 0)
1488 return TYPECODE_DECIMAL;
1489 else if (strcmp (klass->name, "DateTime") == 0)
1490 return TYPECODE_DATETIME;
1493 return TYPECODE_OBJECT;
1495 case MONO_TYPE_STRING:
1496 return TYPECODE_STRING;
1497 case MONO_TYPE_SZARRAY:
1498 case MONO_TYPE_ARRAY:
1499 case MONO_TYPE_OBJECT:
1501 case MONO_TYPE_MVAR:
1502 case MONO_TYPE_TYPEDBYREF:
1503 return TYPECODE_OBJECT;
1504 case MONO_TYPE_CLASS:
1506 MonoClass *klass = type->type->data.klass;
1507 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1508 if (strcmp (klass->name, "DBNull") == 0)
1509 return TYPECODE_DBNULL;
1512 return TYPECODE_OBJECT;
1513 case MONO_TYPE_GENERICINST:
1514 return TYPECODE_OBJECT;
1516 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1522 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1528 MONO_ARCH_SAVE_REGS;
1530 g_assert (type != NULL);
1532 domain = ((MonoObject *)type)->vtable->domain;
1534 if (!c) /* FIXME: dont know what do do here */
1537 klass = mono_class_from_mono_type (type->type);
1538 klassc = mono_class_from_mono_type (c->type);
1540 /* Interface check requires a more complex setup so we
1541 * only do for them. Otherwise we simply avoid mono_class_init.
1543 if (check_interfaces) {
1544 mono_class_init_or_throw (klass);
1545 mono_class_init_or_throw (klassc);
1546 } else if (!klass->supertypes || !klassc->supertypes) {
1547 mono_loader_lock ();
1548 mono_class_setup_supertypes (klass);
1549 mono_class_setup_supertypes (klassc);
1550 mono_loader_unlock ();
1553 if (type->type->byref)
1554 return klassc == mono_defaults.object_class;
1556 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1560 mono_type_is_primitive (MonoType *type)
1562 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1563 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1567 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1569 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1570 return mono_class_enum_basetype (type->data.klass);
1571 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1572 return mono_class_enum_basetype (type->data.generic_class->container_class);
1577 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1583 MONO_ARCH_SAVE_REGS;
1585 g_assert (type != NULL);
1587 domain = ((MonoObject *)type)->vtable->domain;
1589 klass = mono_class_from_mono_type (type->type);
1590 klassc = mono_class_from_mono_type (c->type);
1592 mono_class_init_or_throw (klass);
1593 mono_class_init_or_throw (klassc);
1595 if (type->type->byref ^ c->type->byref)
1598 if (type->type->byref) {
1599 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1600 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1602 klass = mono_class_from_mono_type (t);
1603 klassc = mono_class_from_mono_type (ot);
1605 if (mono_type_is_primitive (t)) {
1606 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1607 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1608 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1609 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1610 return t->type == ot->type;
1612 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1615 if (klass->valuetype)
1616 return klass == klassc;
1617 return klass->valuetype == klassc->valuetype;
1620 return mono_class_is_assignable_from (klass, klassc);
1624 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1626 MonoClass *klass = mono_class_from_mono_type (type->type);
1627 mono_class_init_or_throw (klass);
1628 return mono_object_isinst (obj, klass) != NULL;
1632 ves_icall_get_attributes (MonoReflectionType *type)
1634 MonoClass *klass = mono_class_from_mono_type (type->type);
1635 return klass->flags;
1638 static MonoReflectionMarshal*
1639 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1641 MonoClass *klass = field->field->parent;
1642 MonoMarshalType *info;
1645 if (klass->generic_container ||
1646 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1649 info = mono_marshal_load_type_info (klass);
1651 for (i = 0; i < info->num_fields; ++i) {
1652 if (info->fields [i].field == field->field) {
1653 if (!info->fields [i].mspec)
1656 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1663 static MonoReflectionField*
1664 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1666 gboolean found = FALSE;
1673 klass = handle->parent;
1675 klass = mono_class_from_mono_type (type);
1677 /* Check that the field belongs to the class */
1678 for (k = klass; k; k = k->parent) {
1679 if (k == handle->parent) {
1686 /* The managed code will throw the exception */
1690 return mono_field_get_object (mono_domain_get (), klass, handle);
1694 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1697 MonoType *type = mono_field_get_type_checked (field->field, &error);
1698 if (!mono_error_ok (&error))
1699 mono_error_raise_exception (&error);
1701 return type_array_from_modifiers (field->field->parent->image, type, optional);
1705 vell_icall_get_method_attributes (MonoMethod *method)
1707 return method->flags;
1711 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1714 MonoDomain *domain = mono_domain_get ();
1715 MonoMethodSignature* sig;
1716 MONO_ARCH_SAVE_REGS;
1718 sig = mono_method_signature_checked (method, &error);
1719 if (!mono_error_ok (&error))
1720 mono_error_raise_exception (&error);
1723 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1724 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1725 info->attrs = method->flags;
1726 info->implattrs = method->iflags;
1727 if (sig->call_convention == MONO_CALL_DEFAULT)
1728 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1730 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1735 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1739 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1741 MonoDomain *domain = mono_domain_get ();
1743 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1746 static MonoReflectionMarshal*
1747 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1749 MonoDomain *domain = mono_domain_get ();
1750 MonoReflectionMarshal* res = NULL;
1751 MonoMarshalSpec **mspecs;
1754 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1755 mono_method_get_marshal_info (method, mspecs);
1758 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1760 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1762 mono_metadata_free_marshal_spec (mspecs [i]);
1769 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1771 MonoClass *parent = field->field->parent;
1772 if (!parent->size_inited)
1773 mono_class_init (parent);
1775 return field->field->offset - sizeof (MonoObject);
1778 static MonoReflectionType*
1779 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1782 MONO_ARCH_SAVE_REGS;
1784 parent = declaring? field->field->parent: field->klass;
1786 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1790 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1792 MonoClass *fklass = field->klass;
1793 MonoClassField *cf = field->field;
1794 MonoDomain *domain = mono_object_domain (field);
1796 if (fklass->image->assembly->ref_only)
1797 mono_raise_exception (mono_get_exception_invalid_operation (
1798 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1800 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1801 mono_security_core_clr_ensure_reflection_access_field (cf);
1803 return mono_field_get_value_object (domain, cf, obj);
1807 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1810 MonoClassField *cf = field->field;
1814 MONO_ARCH_SAVE_REGS;
1816 if (field->klass->image->assembly->ref_only)
1817 mono_raise_exception (mono_get_exception_invalid_operation (
1818 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1820 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1821 mono_security_core_clr_ensure_reflection_access_field (cf);
1823 type = mono_field_get_type_checked (cf, &error);
1824 if (!mono_error_ok (&error))
1825 mono_error_raise_exception (&error);
1827 v = (gchar *) value;
1829 switch (type->type) {
1832 case MONO_TYPE_BOOLEAN:
1835 case MONO_TYPE_CHAR:
1844 case MONO_TYPE_VALUETYPE:
1847 v += sizeof (MonoObject);
1849 case MONO_TYPE_STRING:
1850 case MONO_TYPE_OBJECT:
1851 case MONO_TYPE_CLASS:
1852 case MONO_TYPE_ARRAY:
1853 case MONO_TYPE_SZARRAY:
1856 case MONO_TYPE_GENERICINST: {
1857 MonoGenericClass *gclass = type->data.generic_class;
1858 g_assert (!gclass->context.class_inst->is_open);
1860 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1861 MonoClass *nklass = mono_class_from_mono_type (type);
1862 MonoObject *nullable;
1865 * Convert the boxed vtype into a Nullable structure.
1866 * This is complicated by the fact that Nullables have
1867 * a variable structure.
1869 nullable = mono_object_new (mono_domain_get (), nklass);
1871 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1873 v = mono_object_unbox (nullable);
1876 if (gclass->container_class->valuetype && (v != NULL))
1877 v += sizeof (MonoObject);
1881 g_error ("type 0x%x not handled in "
1882 "ves_icall_FieldInfo_SetValueInternal", type->type);
1887 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1888 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1889 if (!vtable->initialized)
1890 mono_runtime_class_init (vtable);
1891 mono_field_static_set_value (vtable, cf, v);
1893 mono_field_set_value (obj, cf, v);
1898 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1900 MonoObject *o = NULL;
1901 MonoClassField *field = this->field;
1903 MonoDomain *domain = mono_object_domain (this);
1905 MonoTypeEnum def_type;
1906 const char *def_value;
1908 MONO_ARCH_SAVE_REGS;
1910 mono_class_init (field->parent);
1912 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1913 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1915 if (field->parent->image->dynamic) {
1917 g_assert_not_reached ();
1920 def_value = mono_class_get_field_default_value (field, &def_type);
1922 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1926 case MONO_TYPE_BOOLEAN:
1929 case MONO_TYPE_CHAR:
1937 case MONO_TYPE_R8: {
1940 /* boxed value type */
1941 t = g_new0 (MonoType, 1);
1943 klass = mono_class_from_mono_type (t);
1945 o = mono_object_new (domain, klass);
1946 v = ((gchar *) o) + sizeof (MonoObject);
1947 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1950 case MONO_TYPE_STRING:
1951 case MONO_TYPE_CLASS:
1952 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1955 g_assert_not_reached ();
1961 static MonoReflectionType*
1962 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1965 MonoClassField *field = ref_field->field;
1966 MonoType *type = mono_field_get_type_checked (field, &error);
1967 if (!mono_error_ok (&error))
1968 mono_error_raise_exception (&error);
1969 return mono_type_get_object (mono_object_domain (ref_field), type);
1972 static MonoReflectionType*
1973 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1975 MonoMethod *method = rmethod->method.method;
1977 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1980 /* From MonoProperty.cs */
1982 PInfo_Attributes = 1,
1983 PInfo_GetMethod = 1 << 1,
1984 PInfo_SetMethod = 1 << 2,
1985 PInfo_ReflectedType = 1 << 3,
1986 PInfo_DeclaringType = 1 << 4,
1991 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1993 MonoDomain *domain = mono_object_domain (property);
1995 MONO_ARCH_SAVE_REGS;
1997 if ((req_info & PInfo_ReflectedType) != 0)
1998 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1999 if ((req_info & PInfo_DeclaringType) != 0)
2000 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2002 if ((req_info & PInfo_Name) != 0)
2003 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2005 if ((req_info & PInfo_Attributes) != 0)
2006 info->attrs = property->property->attrs;
2008 if ((req_info & PInfo_GetMethod) != 0)
2009 MONO_STRUCT_SETREF (info, get, property->property->get ?
2010 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2012 if ((req_info & PInfo_SetMethod) != 0)
2013 MONO_STRUCT_SETREF (info, set, property->property->set ?
2014 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2016 * There may be other methods defined for properties, though, it seems they are not exposed
2017 * in the reflection API
2022 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2024 MonoDomain *domain = mono_object_domain (event);
2026 MONO_ARCH_SAVE_REGS;
2028 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2029 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2031 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2032 info->attrs = event->event->attrs;
2033 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2034 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2035 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2037 #ifndef MONO_SMALL_CONFIG
2038 if (event->event->other) {
2040 while (event->event->other [n])
2042 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2044 for (i = 0; i < n; i++)
2045 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2051 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2056 mono_class_setup_interfaces (klass, error);
2057 if (!mono_error_ok (error))
2060 for (i = 0; i < klass->interface_count; i++) {
2061 ic = klass->interfaces [i];
2062 g_hash_table_insert (ifaces, ic, ic);
2064 collect_interfaces (ic, ifaces, error);
2065 if (!mono_error_ok (error))
2071 MonoArray *iface_array;
2072 MonoGenericContext *context;
2076 } FillIfaceArrayData;
2079 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2081 FillIfaceArrayData *data = user_data;
2082 MonoClass *ic = key;
2083 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2085 if (!mono_error_ok (data->error))
2088 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2089 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2090 if (!mono_error_ok (data->error))
2094 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2097 mono_metadata_free_type (inflated);
2101 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2104 MonoClass *class = mono_class_from_mono_type (type->type);
2106 FillIfaceArrayData data = { 0 };
2109 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2111 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2112 data.context = mono_class_get_context (class);
2113 class = class->generic_class->container_class;
2116 for (parent = class; parent; parent = parent->parent) {
2117 mono_class_setup_interfaces (parent, &error);
2118 if (!mono_error_ok (&error))
2120 collect_interfaces (parent, iface_hash, &error);
2121 if (!mono_error_ok (&error))
2125 data.error = &error;
2126 data.domain = mono_object_domain (type);
2128 len = g_hash_table_size (iface_hash);
2130 g_hash_table_destroy (iface_hash);
2131 if (!data.domain->empty_types)
2132 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2133 return data.domain->empty_types;
2136 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2137 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2138 if (!mono_error_ok (&error))
2141 g_hash_table_destroy (iface_hash);
2142 return data.iface_array;
2145 g_hash_table_destroy (iface_hash);
2146 mono_error_raise_exception (&error);
2151 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2153 gboolean variance_used;
2154 MonoClass *class = mono_class_from_mono_type (type->type);
2155 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2156 MonoReflectionMethod *member;
2159 int i = 0, len, ioffset;
2162 MONO_ARCH_SAVE_REGS;
2163 mono_class_init_or_throw (class);
2164 mono_class_init_or_throw (iclass);
2166 mono_class_setup_vtable (class);
2168 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2172 len = mono_class_num_methods (iclass);
2173 domain = mono_object_domain (type);
2174 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2175 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2177 while ((method = mono_class_get_methods (iclass, &iter))) {
2178 member = mono_method_get_object (domain, method, iclass);
2179 mono_array_setref (*methods, i, member);
2180 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2181 mono_array_setref (*targets, i, member);
2188 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2190 MonoClass *klass = mono_class_from_mono_type (type->type);
2191 mono_class_init_or_throw (klass);
2193 if (klass->image->dynamic) {
2194 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2195 *packing = tb->packing_size;
2196 *size = tb->class_size;
2198 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2202 static MonoReflectionType*
2203 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2207 MONO_ARCH_SAVE_REGS;
2209 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2210 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2212 class = mono_class_from_mono_type (type->type);
2213 mono_class_init_or_throw (class);
2215 // GetElementType should only return a type for:
2216 // Array Pointer PassedByRef
2217 if (type->type->byref)
2218 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2219 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2220 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2221 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2222 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2227 static MonoReflectionType*
2228 ves_icall_get_type_parent (MonoReflectionType *type)
2230 MonoClass *class = mono_class_from_mono_type (type->type);
2231 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2235 ves_icall_type_ispointer (MonoReflectionType *type)
2237 MONO_ARCH_SAVE_REGS;
2239 return type->type->type == MONO_TYPE_PTR;
2243 ves_icall_type_isprimitive (MonoReflectionType *type)
2245 MONO_ARCH_SAVE_REGS;
2247 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)));
2251 ves_icall_type_isbyref (MonoReflectionType *type)
2253 MONO_ARCH_SAVE_REGS;
2255 return type->type->byref;
2259 ves_icall_type_iscomobject (MonoReflectionType *type)
2261 MonoClass *klass = mono_class_from_mono_type (type->type);
2262 mono_class_init_or_throw (klass);
2264 return (klass && klass->is_com_object);
2267 static MonoReflectionModule*
2268 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2270 MonoClass *class = mono_class_from_mono_type (type->type);
2271 return mono_module_get_object (mono_object_domain (type), class->image);
2274 static MonoReflectionAssembly*
2275 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2277 MonoDomain *domain = mono_domain_get ();
2278 MonoClass *class = mono_class_from_mono_type (type->type);
2279 return mono_assembly_get_object (domain, class->image->assembly);
2282 static MonoReflectionType*
2283 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2285 MonoDomain *domain = mono_domain_get ();
2288 MONO_ARCH_SAVE_REGS;
2290 if (type->type->byref)
2292 if (type->type->type == MONO_TYPE_VAR)
2293 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2294 else if (type->type->type == MONO_TYPE_MVAR)
2295 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2297 class = mono_class_from_mono_type (type->type)->nested_in;
2299 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2303 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2305 MonoDomain *domain = mono_domain_get ();
2306 MonoClass *class = mono_class_from_mono_type (type->type);
2308 if (type->type->byref) {
2309 char *n = g_strdup_printf ("%s&", class->name);
2310 MonoString *res = mono_string_new (domain, n);
2316 return mono_string_new (domain, class->name);
2321 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2323 MonoDomain *domain = mono_domain_get ();
2324 MonoClass *class = mono_class_from_mono_type (type->type);
2326 while (class->nested_in)
2327 class = class->nested_in;
2329 if (class->name_space [0] == '\0')
2332 return mono_string_new (domain, class->name_space);
2336 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2340 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2341 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2343 class = mono_class_from_mono_type (type->type);
2349 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2352 MonoClass *klass, *pklass;
2353 MonoDomain *domain = mono_object_domain (type);
2354 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2356 MONO_ARCH_SAVE_REGS;
2358 klass = mono_class_from_mono_type (type->type);
2360 if (klass->generic_container) {
2361 MonoGenericContainer *container = klass->generic_container;
2362 res = mono_array_new_specific (array_vtable, container->type_argc);
2363 for (i = 0; i < container->type_argc; ++i) {
2364 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2365 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2367 } else if (klass->generic_class) {
2368 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2369 res = mono_array_new_specific (array_vtable, inst->type_argc);
2370 for (i = 0; i < inst->type_argc; ++i)
2371 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2373 res = mono_array_new_specific (array_vtable, 0);
2379 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2382 MONO_ARCH_SAVE_REGS;
2384 if (!IS_MONOTYPE (type))
2387 if (type->type->byref)
2390 klass = mono_class_from_mono_type (type->type);
2391 return klass->generic_container != NULL;
2394 static MonoReflectionType*
2395 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2398 MONO_ARCH_SAVE_REGS;
2400 if (type->type->byref)
2403 klass = mono_class_from_mono_type (type->type);
2405 if (klass->generic_container) {
2406 return type; /* check this one */
2408 if (klass->generic_class) {
2409 MonoClass *generic_class = klass->generic_class->container_class;
2412 tb = mono_class_get_ref_info (generic_class);
2414 if (generic_class->wastypebuilder && tb)
2417 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2422 static MonoReflectionType*
2423 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2426 MonoType *geninst, **types;
2429 g_assert (IS_MONOTYPE (type));
2430 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2432 count = mono_array_length (type_array);
2433 types = g_new0 (MonoType *, count);
2435 for (i = 0; i < count; i++) {
2436 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2437 types [i] = t->type;
2440 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2445 class = mono_class_from_mono_type (geninst);
2447 /*we might inflate to the GTD*/
2448 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2449 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2451 return mono_type_get_object (mono_object_domain (type), geninst);
2455 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2458 MONO_ARCH_SAVE_REGS;
2460 if (type->type->byref)
2463 klass = mono_class_from_mono_type (type->type);
2465 return klass->generic_class != NULL;
2469 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2472 MONO_ARCH_SAVE_REGS;
2474 if (!IS_MONOTYPE (type))
2477 if (type->type->byref)
2480 klass = mono_class_from_mono_type (type->type);
2481 return klass->generic_class != NULL || klass->generic_container != NULL;
2485 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2487 MONO_ARCH_SAVE_REGS;
2489 if (!IS_MONOTYPE (type))
2492 if (is_generic_parameter (type->type))
2493 return mono_type_get_generic_param_num (type->type);
2497 static GenericParameterAttributes
2498 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2500 MONO_ARCH_SAVE_REGS;
2502 g_assert (IS_MONOTYPE (type));
2503 g_assert (is_generic_parameter (type->type));
2504 return mono_generic_param_info (type->type->data.generic_param)->flags;
2508 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2510 MonoGenericParamInfo *param_info;
2516 MONO_ARCH_SAVE_REGS;
2518 g_assert (IS_MONOTYPE (type));
2520 domain = mono_object_domain (type);
2521 param_info = mono_generic_param_info (type->type->data.generic_param);
2522 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2525 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2526 for (i = 0; i < count; i++)
2527 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2534 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2536 MONO_ARCH_SAVE_REGS;
2537 return is_generic_parameter (type->type);
2541 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2543 MONO_ARCH_SAVE_REGS;
2544 return is_generic_parameter (tb->type.type);
2548 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2549 MonoReflectionType *t)
2551 enumtype->type = t->type;
2554 static MonoReflectionMethod*
2555 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2556 MonoReflectionMethod* generic)
2563 MONO_ARCH_SAVE_REGS;
2565 domain = ((MonoObject *)type)->vtable->domain;
2567 klass = mono_class_from_mono_type (type->type);
2568 mono_class_init_or_throw (klass);
2571 while ((method = mono_class_get_methods (klass, &iter))) {
2572 if (method->token == generic->method->token)
2573 return mono_method_get_object (domain, method, klass);
2581 static MonoReflectionMethod *
2582 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2585 MonoType *type = ref_type->type;
2587 MONO_ARCH_SAVE_REGS;
2589 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2590 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2591 if (type->type == MONO_TYPE_VAR)
2594 method = mono_type_get_generic_param_owner (type)->owner.method;
2596 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2599 static MonoReflectionDllImportAttribute*
2600 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2602 static MonoClass *DllImportAttributeClass = NULL;
2603 MonoDomain *domain = mono_domain_get ();
2604 MonoReflectionDllImportAttribute *attr;
2605 MonoImage *image = method->klass->image;
2606 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2607 MonoTableInfo *tables = image->tables;
2608 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2609 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2610 guint32 im_cols [MONO_IMPLMAP_SIZE];
2611 guint32 scope_token;
2612 const char *import = NULL;
2613 const char *scope = NULL;
2616 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2619 if (!DllImportAttributeClass) {
2620 DllImportAttributeClass =
2621 mono_class_from_name (mono_defaults.corlib,
2622 "System.Runtime.InteropServices", "DllImportAttribute");
2623 g_assert (DllImportAttributeClass);
2626 if (method->klass->image->dynamic) {
2627 MonoReflectionMethodAux *method_aux =
2628 g_hash_table_lookup (
2629 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2631 import = method_aux->dllentry;
2632 scope = method_aux->dll;
2635 if (!import || !scope) {
2636 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2641 if (piinfo->implmap_idx) {
2642 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2644 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2645 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2646 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2647 scope = mono_metadata_string_heap (image, scope_token);
2650 flags = piinfo->piflags;
2652 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2654 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2655 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2656 attr->call_conv = (flags & 0x700) >> 8;
2657 attr->charset = ((flags & 0x6) >> 1) + 1;
2658 if (attr->charset == 1)
2660 attr->exact_spelling = (flags & 0x1) != 0;
2661 attr->set_last_error = (flags & 0x40) != 0;
2662 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2663 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2664 attr->preserve_sig = FALSE;
2669 static MonoReflectionMethod *
2670 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2672 MonoMethodInflated *imethod;
2675 MONO_ARCH_SAVE_REGS;
2677 if (method->method->is_generic)
2680 if (!method->method->is_inflated)
2683 imethod = (MonoMethodInflated *) method->method;
2685 result = imethod->declaring;
2686 /* Not a generic method. */
2687 if (!result->is_generic)
2690 if (method->method->klass->image->dynamic) {
2691 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2692 MonoReflectionMethod *res;
2695 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2696 * the dynamic case as well ?
2698 mono_loader_lock ();
2699 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2700 mono_loader_unlock ();
2706 if (imethod->context.class_inst) {
2707 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2708 /*Generic methods gets the context of the GTD.*/
2709 if (mono_class_get_context (klass))
2710 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2713 return mono_method_get_object (mono_object_domain (method), result, NULL);
2717 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2719 MONO_ARCH_SAVE_REGS;
2721 return mono_method_signature (method->method)->generic_param_count != 0;
2725 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2727 MONO_ARCH_SAVE_REGS;
2729 return method->method->is_generic;
2733 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2738 MONO_ARCH_SAVE_REGS;
2740 domain = mono_object_domain (method);
2742 if (method->method->is_inflated) {
2743 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2746 count = inst->type_argc;
2747 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2749 for (i = 0; i < count; i++)
2750 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2756 count = mono_method_signature (method->method)->generic_param_count;
2757 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2759 for (i = 0; i < count; i++) {
2760 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2761 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2762 MonoClass *pklass = mono_class_from_generic_parameter (
2763 param, method->method->klass->image, TRUE);
2764 mono_array_setref (res, i,
2765 mono_type_get_object (domain, &pklass->byval_arg));
2772 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2775 * Invoke from reflection is supposed to always be a virtual call (the API
2776 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2777 * greater flexibility.
2779 MonoMethod *m = method->method;
2783 MONO_ARCH_SAVE_REGS;
2787 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2788 mono_security_core_clr_ensure_reflection_access_method (m);
2790 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2791 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2792 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2797 if (!mono_object_isinst (this, m->klass)) {
2798 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2801 m = mono_object_get_virtual_method (this, m);
2802 /* must pass the pointer to the value for valuetype methods */
2803 if (m->klass->valuetype)
2804 obj = mono_object_unbox (this);
2805 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2806 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2811 pcount = params? mono_array_length (params): 0;
2812 if (pcount != mono_method_signature (m)->param_count) {
2813 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2817 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2818 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."));
2822 if (m->klass->image->assembly->ref_only) {
2823 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."));
2827 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2830 intptr_t *lower_bounds;
2831 pcount = mono_array_length (params);
2832 lengths = alloca (sizeof (uintptr_t) * pcount);
2833 /* Note: the synthetized array .ctors have int32 as argument type */
2834 for (i = 0; i < pcount; ++i)
2835 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2837 if (m->klass->rank == pcount) {
2838 /* Only lengths provided. */
2839 lower_bounds = NULL;
2841 g_assert (pcount == (m->klass->rank * 2));
2842 /* lower bounds are first. */
2843 lower_bounds = (intptr_t*)lengths;
2844 lengths += m->klass->rank;
2847 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2849 return mono_runtime_invoke_array (m, obj, params, NULL);
2853 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2855 MonoDomain *domain = mono_object_domain (method);
2856 MonoMethod *m = method->method;
2857 MonoMethodSignature *sig = mono_method_signature (m);
2858 MonoArray *out_args;
2860 int i, j, outarg_count = 0;
2862 MONO_ARCH_SAVE_REGS;
2864 if (m->klass == mono_defaults.object_class) {
2866 if (!strcmp (m->name, "FieldGetter")) {
2867 MonoClass *k = this->vtable->klass;
2871 /* If this is a proxy, then it must be a CBO */
2872 if (k == mono_defaults.transparent_proxy_class) {
2873 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2874 this = tp->rp->unwrapped_server;
2876 k = this->vtable->klass;
2879 name = mono_array_get (params, MonoString *, 1);
2880 str = mono_string_to_utf8 (name);
2883 MonoClassField* field = mono_class_get_field_from_name (k, str);
2885 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2886 if (field_klass->valuetype)
2887 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2889 result = *((gpointer *)((char *)this + field->offset));
2891 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2892 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2893 mono_array_setref (out_args, 0, result);
2901 g_assert_not_reached ();
2903 } else if (!strcmp (m->name, "FieldSetter")) {
2904 MonoClass *k = this->vtable->klass;
2910 /* If this is a proxy, then it must be a CBO */
2911 if (k == mono_defaults.transparent_proxy_class) {
2912 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2913 this = tp->rp->unwrapped_server;
2915 k = this->vtable->klass;
2918 name = mono_array_get (params, MonoString *, 1);
2919 str = mono_string_to_utf8 (name);
2922 MonoClassField* field = mono_class_get_field_from_name (k, str);
2924 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2925 MonoObject *val = mono_array_get (params, gpointer, 2);
2927 if (field_klass->valuetype) {
2928 size = mono_type_size (field->type, &align);
2929 g_assert (size == mono_class_value_size (field_klass, NULL));
2930 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2932 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2935 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2936 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2946 g_assert_not_reached ();
2951 for (i = 0; i < mono_array_length (params); i++) {
2952 if (sig->params [i]->byref)
2956 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2958 /* handle constructors only for objects already allocated */
2959 if (!strcmp (method->method->name, ".ctor"))
2962 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2963 g_assert (!method->method->klass->valuetype);
2964 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2966 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2967 if (sig->params [i]->byref) {
2969 arg = mono_array_get (params, gpointer, i);
2970 mono_array_setref (out_args, j, arg);
2975 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2981 read_enum_value (char *mem, int type)
2985 return *(guint8*)mem;
2987 return *(gint8*)mem;
2989 return *(guint16*)mem;
2991 return *(gint16*)mem;
2993 return *(guint32*)mem;
2995 return *(gint32*)mem;
2997 return *(guint64*)mem;
2999 return *(gint64*)mem;
3001 g_assert_not_reached ();
3007 write_enum_value (char *mem, int type, guint64 value)
3011 case MONO_TYPE_I1: {
3012 guint8 *p = (guint8*)mem;
3017 case MONO_TYPE_I2: {
3018 guint16 *p = (void*)mem;
3023 case MONO_TYPE_I4: {
3024 guint32 *p = (void*)mem;
3029 case MONO_TYPE_I8: {
3030 guint64 *p = (void*)mem;
3035 g_assert_not_reached ();
3041 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3044 MonoClass *enumc, *objc;
3049 MONO_ARCH_SAVE_REGS;
3051 MONO_CHECK_ARG_NULL (enumType);
3052 MONO_CHECK_ARG_NULL (value);
3054 domain = mono_object_domain (enumType);
3055 enumc = mono_class_from_mono_type (enumType->type);
3057 mono_class_init_or_throw (enumc);
3059 objc = value->vtable->klass;
3061 if (!enumc->enumtype)
3062 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3063 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3064 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."));
3066 etype = mono_class_enum_basetype (enumc);
3068 /* MS throws this for typebuilders */
3069 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3071 res = mono_object_new (domain, enumc);
3072 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3073 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3079 ves_icall_System_Enum_get_value (MonoObject *this)
3087 MONO_ARCH_SAVE_REGS;
3092 g_assert (this->vtable->klass->enumtype);
3094 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3095 res = mono_object_new (mono_object_domain (this), enumc);
3096 dst = (char *)res + sizeof (MonoObject);
3097 src = (char *)this + sizeof (MonoObject);
3098 size = mono_class_value_size (enumc, NULL);
3100 memcpy (dst, src, size);
3105 static MonoReflectionType *
3106 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3111 MONO_ARCH_SAVE_REGS;
3113 klass = mono_class_from_mono_type (type->type);
3114 mono_class_init_or_throw (klass);
3116 etype = mono_class_enum_basetype (klass);
3118 /* MS throws this for typebuilders */
3119 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3121 return mono_type_get_object (mono_object_domain (type), etype);
3125 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3127 gpointer tdata = (char *)this + sizeof (MonoObject);
3128 gpointer odata = (char *)other + sizeof (MonoObject);
3129 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3130 g_assert (basetype);
3132 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3133 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3134 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3137 return me > other ? 1 : -1; \
3140 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3141 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3142 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3145 return me - other; \
3148 switch (basetype->type) {
3150 COMPARE_ENUM_VALUES (guint8);
3152 COMPARE_ENUM_VALUES (gint8);
3153 case MONO_TYPE_CHAR:
3155 COMPARE_ENUM_VALUES_RANGE (guint16);
3157 COMPARE_ENUM_VALUES (gint16);
3159 COMPARE_ENUM_VALUES (guint32);
3161 COMPARE_ENUM_VALUES (gint32);
3163 COMPARE_ENUM_VALUES (guint64);
3165 COMPARE_ENUM_VALUES (gint64);
3167 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3169 #undef COMPARE_ENUM_VALUES_RANGE
3170 #undef COMPARE_ENUM_VALUES
3175 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3177 gpointer data = (char *)this + sizeof (MonoObject);
3178 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3179 g_assert (basetype);
3181 switch (basetype->type) {
3183 return *((gint8*)data);
3185 return *((guint8*)data);
3186 case MONO_TYPE_CHAR:
3188 return *((guint16*)data);
3191 return *((gint16*)data);
3193 return *((guint32*)data);
3195 return *((gint32*)data);
3197 case MONO_TYPE_I8: {
3198 gint64 value = *((gint64*)data);
3199 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3202 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3208 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3210 MonoDomain *domain = mono_object_domain (type);
3211 MonoClass *enumc = mono_class_from_mono_type (type->type);
3212 guint j = 0, nvalues, crow;
3214 MonoClassField *field;
3216 MONO_ARCH_SAVE_REGS;
3218 mono_class_init_or_throw (enumc);
3220 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3221 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3222 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3223 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3227 while ((field = mono_class_get_fields (enumc, &iter))) {
3230 MonoTypeEnum def_type;
3232 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3234 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3236 if (mono_field_is_deleted (field))
3238 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3240 p = mono_class_get_field_default_value (field, &def_type);
3241 len = mono_metadata_decode_blob_size (p, &p);
3242 switch (mono_class_enum_basetype (enumc)->type) {
3245 mono_array_set (info->values, gchar, j, *p);
3247 case MONO_TYPE_CHAR:
3250 mono_array_set (info->values, gint16, j, read16 (p));
3254 mono_array_set (info->values, gint32, j, read32 (p));
3258 mono_array_set (info->values, gint64, j, read64 (p));
3261 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3268 BFLAGS_IgnoreCase = 1,
3269 BFLAGS_DeclaredOnly = 2,
3270 BFLAGS_Instance = 4,
3272 BFLAGS_Public = 0x10,
3273 BFLAGS_NonPublic = 0x20,
3274 BFLAGS_FlattenHierarchy = 0x40,
3275 BFLAGS_InvokeMethod = 0x100,
3276 BFLAGS_CreateInstance = 0x200,
3277 BFLAGS_GetField = 0x400,
3278 BFLAGS_SetField = 0x800,
3279 BFLAGS_GetProperty = 0x1000,
3280 BFLAGS_SetProperty = 0x2000,
3281 BFLAGS_ExactBinding = 0x10000,
3282 BFLAGS_SuppressChangeType = 0x20000,
3283 BFLAGS_OptionalParamBinding = 0x40000
3286 static MonoReflectionField *
3287 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3290 MonoClass *startklass, *klass;
3292 MonoClassField *field;
3295 int (*compare_func) (const char *s1, const char *s2) = NULL;
3296 domain = ((MonoObject *)type)->vtable->domain;
3297 klass = startklass = mono_class_from_mono_type (type->type);
3300 mono_raise_exception (mono_get_exception_argument_null ("name"));
3301 if (type->type->byref)
3304 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3307 if (klass->exception_type != MONO_EXCEPTION_NONE)
3308 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3311 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3312 guint32 flags = mono_field_get_flags (field);
3315 if (mono_field_is_deleted_with_flags (field, flags))
3317 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3318 if (bflags & BFLAGS_Public)
3320 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3321 if (bflags & BFLAGS_NonPublic) {
3328 if (flags & FIELD_ATTRIBUTE_STATIC) {
3329 if (bflags & BFLAGS_Static)
3330 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3333 if (bflags & BFLAGS_Instance)
3340 utf8_name = mono_string_to_utf8 (name);
3342 if (compare_func (mono_field_get_name (field), utf8_name)) {
3348 return mono_field_get_object (domain, klass, field);
3350 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3357 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3360 MonoClass *startklass, *klass, *refklass;
3365 MonoClassField *field;
3366 MonoPtrArray tmp_array;
3368 MONO_ARCH_SAVE_REGS;
3370 domain = ((MonoObject *)type)->vtable->domain;
3371 if (type->type->byref)
3372 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3373 klass = startklass = mono_class_from_mono_type (type->type);
3374 refklass = mono_class_from_mono_type (reftype->type);
3376 mono_ptr_array_init (tmp_array, 2);
3379 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3380 mono_ptr_array_destroy (tmp_array);
3381 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3385 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3386 guint32 flags = mono_field_get_flags (field);
3388 if (mono_field_is_deleted_with_flags (field, flags))
3390 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3391 if (bflags & BFLAGS_Public)
3393 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3394 if (bflags & BFLAGS_NonPublic) {
3401 if (flags & FIELD_ATTRIBUTE_STATIC) {
3402 if (bflags & BFLAGS_Static)
3403 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3406 if (bflags & BFLAGS_Instance)
3412 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3413 mono_ptr_array_append (tmp_array, member);
3415 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3418 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3420 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3421 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3423 mono_ptr_array_destroy (tmp_array);
3429 method_nonpublic (MonoMethod* method, gboolean start_klass)
3431 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3432 case METHOD_ATTRIBUTE_ASSEM:
3433 return (start_klass || mono_defaults.generic_ilist_class);
3434 case METHOD_ATTRIBUTE_PRIVATE:
3436 case METHOD_ATTRIBUTE_PUBLIC:
3444 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3446 static MonoClass *MethodInfo_array;
3448 MonoClass *startklass, *klass, *refklass;
3453 int i, len, match, nslots;
3454 /*FIXME, use MonoBitSet*/
3455 guint32 method_slots_default [8];
3456 guint32 *method_slots = NULL;
3457 gchar *mname = NULL;
3458 int (*compare_func) (const char *s1, const char *s2) = NULL;
3459 MonoVTable *array_vtable;
3461 MonoPtrArray tmp_array;
3463 mono_ptr_array_init (tmp_array, 4);
3465 if (!MethodInfo_array) {
3466 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3467 mono_memory_barrier ();
3468 MethodInfo_array = klass;
3471 domain = ((MonoObject *)type)->vtable->domain;
3472 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3473 if (type->type->byref)
3474 return mono_array_new_specific (array_vtable, 0);
3475 klass = startklass = mono_class_from_mono_type (type->type);
3476 refklass = mono_class_from_mono_type (reftype->type);
3480 mname = mono_string_to_utf8 (name);
3481 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3484 /* An optimization for calls made from Delegate:CreateDelegate () */
3485 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3486 method = mono_get_delegate_invoke (klass);
3487 if (mono_loader_get_last_error ())
3490 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3492 res = mono_array_new_specific (array_vtable, 1);
3493 mono_array_setref (res, 0, member);
3498 mono_class_setup_vtable (klass);
3499 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3502 if (is_generic_parameter (type->type))
3503 nslots = mono_class_get_vtable_size (klass->parent);
3505 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3506 if (nslots >= sizeof (method_slots_default) * 8) {
3507 method_slots = g_new0 (guint32, nslots / 32 + 1);
3509 method_slots = method_slots_default;
3510 memset (method_slots, 0, sizeof (method_slots_default));
3513 mono_class_setup_vtable (klass);
3514 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3518 while ((method = mono_class_get_methods (klass, &iter))) {
3520 if (method->slot != -1) {
3521 g_assert (method->slot < nslots);
3522 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3524 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3525 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3528 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3530 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3531 if (bflags & BFLAGS_Public)
3533 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3539 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3540 if (bflags & BFLAGS_Static)
3541 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3544 if (bflags & BFLAGS_Instance)
3552 if (compare_func (mname, method->name))
3558 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3560 mono_ptr_array_append (tmp_array, member);
3562 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3566 if (method_slots != method_slots_default)
3567 g_free (method_slots);
3569 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3571 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3572 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3574 mono_ptr_array_destroy (tmp_array);
3579 if (method_slots != method_slots_default)
3580 g_free (method_slots);
3581 mono_ptr_array_destroy (tmp_array);
3582 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3583 ex = mono_class_get_exception_for_failure (klass);
3585 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3586 mono_loader_clear_error ();
3588 mono_raise_exception (ex);
3593 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3596 static MonoClass *System_Reflection_ConstructorInfo;
3597 MonoClass *startklass, *klass, *refklass;
3602 gpointer iter = NULL;
3603 MonoPtrArray tmp_array;
3605 MONO_ARCH_SAVE_REGS;
3607 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3609 domain = ((MonoObject *)type)->vtable->domain;
3610 if (type->type->byref)
3611 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3612 klass = startklass = mono_class_from_mono_type (type->type);
3613 refklass = mono_class_from_mono_type (reftype->type);
3615 if (!System_Reflection_ConstructorInfo)
3616 System_Reflection_ConstructorInfo = mono_class_from_name (
3617 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3620 while ((method = mono_class_get_methods (klass, &iter))) {
3622 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3624 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3625 if (bflags & BFLAGS_Public)
3628 if (bflags & BFLAGS_NonPublic)
3634 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3635 if (bflags & BFLAGS_Static)
3636 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3639 if (bflags & BFLAGS_Instance)
3645 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3647 mono_ptr_array_append (tmp_array, member);
3650 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3652 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3653 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3655 mono_ptr_array_destroy (tmp_array);
3661 property_hash (gconstpointer data)
3663 MonoProperty *prop = (MonoProperty*)data;
3665 return g_str_hash (prop->name);
3669 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3671 // Properties are hide-by-name-and-signature
3672 if (!g_str_equal (prop1->name, prop2->name))
3675 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3677 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3683 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3688 return method_nonpublic (accessor, start_klass);
3692 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3696 static MonoClass *System_Reflection_PropertyInfo;
3697 MonoClass *startklass, *klass;
3703 gchar *propname = NULL;
3704 int (*compare_func) (const char *s1, const char *s2) = NULL;
3706 GHashTable *properties = NULL;
3707 MonoPtrArray tmp_array;
3709 MONO_ARCH_SAVE_REGS;
3711 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3713 if (!System_Reflection_PropertyInfo)
3714 System_Reflection_PropertyInfo = mono_class_from_name (
3715 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3717 domain = ((MonoObject *)type)->vtable->domain;
3718 if (type->type->byref)
3719 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3720 klass = startklass = mono_class_from_mono_type (type->type);
3723 propname = mono_string_to_utf8 (name);
3724 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3727 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3729 mono_class_setup_vtable (klass);
3730 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3734 while ((prop = mono_class_get_properties (klass, &iter))) {
3740 flags = method->flags;
3743 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3744 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3745 if (bflags & BFLAGS_Public)
3747 } else if (bflags & BFLAGS_NonPublic) {
3748 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3749 property_accessor_nonpublic(prop->set, startklass == klass)) {
3756 if (flags & METHOD_ATTRIBUTE_STATIC) {
3757 if (bflags & BFLAGS_Static)
3758 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3761 if (bflags & BFLAGS_Instance)
3770 if (compare_func (propname, prop->name))
3774 if (g_hash_table_lookup (properties, prop))
3777 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3779 g_hash_table_insert (properties, prop, prop);
3781 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3784 g_hash_table_destroy (properties);
3787 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3788 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3789 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3791 mono_ptr_array_destroy (tmp_array);
3797 g_hash_table_destroy (properties);
3800 mono_ptr_array_destroy (tmp_array);
3802 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3803 ex = mono_class_get_exception_for_failure (klass);
3805 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3806 mono_loader_clear_error ();
3808 mono_raise_exception (ex);
3812 static MonoReflectionEvent *
3813 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3816 MonoClass *klass, *startklass;
3821 int (*compare_func) (const char *s1, const char *s2);
3823 MONO_ARCH_SAVE_REGS;
3825 event_name = mono_string_to_utf8 (name);
3826 if (type->type->byref)
3828 klass = startklass = mono_class_from_mono_type (type->type);
3829 domain = mono_object_domain (type);
3831 mono_class_init_or_throw (klass);
3833 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3835 if (klass->exception_type != MONO_EXCEPTION_NONE)
3836 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3839 while ((event = mono_class_get_events (klass, &iter))) {
3840 if (compare_func (event->name, event_name))
3843 method = event->add;
3845 method = event->remove;
3847 method = event->raise;
3849 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3850 if (!(bflags & BFLAGS_Public))
3853 if (!(bflags & BFLAGS_NonPublic))
3855 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3859 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3860 if (!(bflags & BFLAGS_Static))
3862 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3865 if (!(bflags & BFLAGS_Instance))
3869 if (!(bflags & BFLAGS_NonPublic))
3872 g_free (event_name);
3873 return mono_event_get_object (domain, startklass, event);
3876 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3879 g_free (event_name);
3884 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3888 static MonoClass *System_Reflection_EventInfo;
3889 MonoClass *startklass, *klass;
3896 MonoPtrArray tmp_array;
3898 MONO_ARCH_SAVE_REGS;
3900 mono_ptr_array_init (tmp_array, 4);
3902 if (!System_Reflection_EventInfo)
3903 System_Reflection_EventInfo = mono_class_from_name (
3904 mono_defaults.corlib, "System.Reflection", "EventInfo");
3906 domain = mono_object_domain (type);
3907 if (type->type->byref)
3908 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3909 klass = startklass = mono_class_from_mono_type (type->type);
3912 mono_class_setup_vtable (klass);
3913 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3917 while ((event = mono_class_get_events (klass, &iter))) {
3919 method = event->add;
3921 method = event->remove;
3923 method = event->raise;
3925 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3926 if (bflags & BFLAGS_Public)
3928 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3929 if (bflags & BFLAGS_NonPublic)
3934 if (bflags & BFLAGS_NonPublic)
3940 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3941 if (bflags & BFLAGS_Static)
3942 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3945 if (bflags & BFLAGS_Instance)
3950 if (bflags & BFLAGS_Instance)
3954 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3956 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3959 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3961 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3962 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3964 mono_ptr_array_destroy (tmp_array);
3969 mono_ptr_array_destroy (tmp_array);
3970 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3971 ex = mono_class_get_exception_for_failure (klass);
3973 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3974 mono_loader_clear_error ();
3976 mono_raise_exception (ex);
3980 static MonoReflectionType *
3981 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3989 MONO_ARCH_SAVE_REGS;
3992 mono_raise_exception (mono_get_exception_argument_null ("name"));
3994 domain = ((MonoObject *)type)->vtable->domain;
3995 if (type->type->byref)
3997 klass = mono_class_from_mono_type (type->type);
3999 str = mono_string_to_utf8 (name);
4002 if (klass->exception_type != MONO_EXCEPTION_NONE)
4003 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4006 * If a nested type is generic, return its generic type definition.
4007 * Note that this means that the return value is essentially a
4008 * nested type of the generic type definition of @klass.
4010 * A note in MSDN claims that a generic type definition can have
4011 * nested types that aren't generic. In any case, the container of that
4012 * nested type would be the generic type definition.
4014 if (klass->generic_class)
4015 klass = klass->generic_class->container_class;
4018 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4020 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4021 if (bflags & BFLAGS_Public)
4024 if (bflags & BFLAGS_NonPublic)
4029 if (strcmp (nested->name, str) == 0){
4031 return mono_type_get_object (domain, &nested->byval_arg);
4034 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4041 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4050 MonoPtrArray tmp_array;
4052 MONO_ARCH_SAVE_REGS;
4054 domain = ((MonoObject *)type)->vtable->domain;
4055 if (type->type->byref)
4056 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4057 klass = mono_class_from_mono_type (type->type);
4060 * If a nested type is generic, return its generic type definition.
4061 * Note that this means that the return value is essentially the set
4062 * of nested types of the generic type definition of @klass.
4064 * A note in MSDN claims that a generic type definition can have
4065 * nested types that aren't generic. In any case, the container of that
4066 * nested type would be the generic type definition.
4068 if (klass->generic_class)
4069 klass = klass->generic_class->container_class;
4071 mono_ptr_array_init (tmp_array, 1);
4073 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4075 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4076 if (bflags & BFLAGS_Public)
4079 if (bflags & BFLAGS_NonPublic)
4084 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4085 mono_ptr_array_append (tmp_array, member);
4088 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4090 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4091 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4093 mono_ptr_array_destroy (tmp_array);
4098 static MonoReflectionType*
4099 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4102 MonoType *type = NULL;
4103 MonoTypeNameParse info;
4104 gboolean type_resolve;
4106 MONO_ARCH_SAVE_REGS;
4108 /* On MS.NET, this does not fire a TypeResolve event */
4109 type_resolve = TRUE;
4110 str = mono_string_to_utf8 (name);
4111 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4112 if (!mono_reflection_parse_type (str, &info)) {
4114 mono_reflection_free_type_info (&info);
4115 if (throwOnError) /* uhm: this is a parse error, though... */
4116 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4117 /*g_print ("failed parse\n");*/
4121 if (info.assembly.name) {
4123 mono_reflection_free_type_info (&info);
4125 /* 1.0 and 2.0 throw different exceptions */
4126 if (mono_defaults.generic_ilist_class)
4127 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4129 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4134 if (module != NULL) {
4136 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4141 if (assembly->assembly->dynamic) {
4142 /* Enumerate all modules */
4143 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4147 if (abuilder->modules) {
4148 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4149 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4150 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4156 if (!type && abuilder->loaded_modules) {
4157 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4158 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4159 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4166 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4168 mono_reflection_free_type_info (&info);
4170 MonoException *e = NULL;
4173 e = mono_get_exception_type_load (name, NULL);
4175 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4176 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4178 mono_loader_clear_error ();
4181 mono_raise_exception (e);
4184 } else if (mono_loader_get_last_error ()) {
4186 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4187 mono_loader_clear_error ();
4190 if (type->type == MONO_TYPE_CLASS) {
4191 MonoClass *klass = mono_type_get_class (type);
4193 if (mono_is_security_manager_active () && !klass->exception_type)
4194 /* Some security problems are detected during generic vtable construction */
4195 mono_class_setup_vtable (klass);
4196 /* need to report exceptions ? */
4197 if (throwOnError && klass->exception_type) {
4198 /* report SecurityException (or others) that occured when loading the assembly */
4199 MonoException *exc = mono_class_get_exception_for_failure (klass);
4200 mono_loader_clear_error ();
4201 mono_raise_exception (exc);
4202 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4207 /* g_print ("got it\n"); */
4208 return mono_type_get_object (mono_object_domain (assembly), type);
4212 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4215 gchar *shadow_ini_file;
4218 /* Check for shadow-copied assembly */
4219 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4220 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4222 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4223 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4229 g_free (shadow_ini_file);
4230 if (content != NULL) {
4233 *filename = content;
4241 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4243 MonoDomain *domain = mono_object_domain (assembly);
4244 MonoAssembly *mass = assembly->assembly;
4245 MonoString *res = NULL;
4250 MONO_ARCH_SAVE_REGS;
4252 if (g_path_is_absolute (mass->image->name)) {
4253 absolute = g_strdup (mass->image->name);
4254 dirname = g_path_get_dirname (absolute);
4256 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4257 dirname = g_strdup (mass->basedir);
4260 replace_shadow_path (domain, dirname, &absolute);
4265 for (i = strlen (absolute) - 1; i >= 0; i--)
4266 if (absolute [i] == '\\')
4271 uri = g_filename_to_uri (absolute, NULL, NULL);
4273 const char *prepend = "file://";
4275 if (*absolute == '/' && *(absolute + 1) == '/') {
4278 prepend = "file:///";
4281 uri = g_strconcat (prepend, absolute, NULL);
4285 res = mono_string_new (domain, uri);
4293 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4295 MonoAssembly *mass = assembly->assembly;
4297 MONO_ARCH_SAVE_REGS;
4299 return mass->in_gac;
4302 static MonoReflectionAssembly*
4303 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4307 MonoImageOpenStatus status;
4309 MONO_ARCH_SAVE_REGS;
4311 name = mono_string_to_utf8 (mname);
4312 res = mono_assembly_load_with_partial_name (name, &status);
4318 return mono_assembly_get_object (mono_domain_get (), res);
4322 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4324 MonoDomain *domain = mono_object_domain (assembly);
4327 MONO_ARCH_SAVE_REGS;
4329 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4335 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4337 MONO_ARCH_SAVE_REGS;
4339 return assembly->assembly->ref_only;
4343 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4345 MonoDomain *domain = mono_object_domain (assembly);
4347 MONO_ARCH_SAVE_REGS;
4349 return mono_string_new (domain, assembly->assembly->image->version);
4352 static MonoReflectionMethod*
4353 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4355 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4357 MONO_ARCH_SAVE_REGS;
4361 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4364 static MonoReflectionModule*
4365 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4367 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4371 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4373 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4374 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4378 MONO_ARCH_SAVE_REGS;
4380 for (i = 0; i < table->rows; ++i) {
4381 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4382 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4388 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4390 static MonoClass *System_Version = NULL;
4391 static MonoMethod *create_version = NULL;
4395 if (!System_Version) {
4396 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4397 g_assert (System_Version);
4400 if (!create_version) {
4401 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4402 create_version = mono_method_desc_search_in_class (desc, System_Version);
4403 g_assert (create_version);
4404 mono_method_desc_free (desc);
4410 args [3] = &revision;
4411 result = mono_object_new (domain, System_Version);
4412 mono_runtime_invoke (create_version, result, args, NULL);
4418 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4420 static MonoClass *System_Reflection_AssemblyName;
4422 MonoDomain *domain = mono_object_domain (assembly);
4424 static MonoMethod *create_culture = NULL;
4425 MonoImage *image = assembly->assembly->image;
4428 MONO_ARCH_SAVE_REGS;
4430 if (!System_Reflection_AssemblyName)
4431 System_Reflection_AssemblyName = mono_class_from_name (
4432 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4434 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4437 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4439 if (count > 0 && !create_culture) {
4440 MonoMethodDesc *desc = mono_method_desc_new (
4441 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4442 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4443 g_assert (create_culture);
4444 mono_method_desc_free (desc);
4447 for (i = 0; i < count; i++) {
4448 MonoReflectionAssemblyName *aname;
4449 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4451 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4453 aname = (MonoReflectionAssemblyName *) mono_object_new (
4454 domain, System_Reflection_AssemblyName);
4456 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4458 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4459 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4460 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4461 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4462 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4463 aname->versioncompat = 1; /* SameMachine (default) */
4464 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4465 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4467 if (create_culture) {
4469 MonoBoolean assembly_ref = 1;
4470 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4471 args [1] = &assembly_ref;
4472 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4475 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4476 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4477 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4479 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4480 /* public key token isn't copied - the class library will
4481 automatically generate it from the public key if required */
4482 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4483 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4485 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4486 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4489 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4492 /* note: this function doesn't return the codebase on purpose (i.e. it can
4493 be used under partial trust as path information isn't present). */
4495 mono_array_setref (result, i, aname);
4506 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4508 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4510 mono_array_setref (info->res, info->idx, name);
4515 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4517 MonoImage *img = assembly->assembly->image;
4522 MONO_ARCH_SAVE_REGS;
4524 mono_image_lock (img);
4525 mono_image_init_name_cache (img);
4528 len = g_hash_table_size (img->name_cache);
4529 mono_image_unlock (img);
4531 /*we can't create objects holding the image lock */
4532 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4534 mono_image_lock (img);
4535 /*len might have changed, create a new array*/
4536 if (len != g_hash_table_size (img->name_cache))
4541 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4542 mono_image_unlock (img);
4547 /* move this in some file in mono/util/ */
4549 g_concat_dir_and_file (const char *dir, const char *file)
4551 g_return_val_if_fail (dir != NULL, NULL);
4552 g_return_val_if_fail (file != NULL, NULL);
4555 * If the directory name doesn't have a / on the end, we need
4556 * to add one so we get a proper path to the file
4558 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4559 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4561 return g_strconcat (dir, file, NULL);
4565 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4567 char *n = mono_string_to_utf8 (name);
4568 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4570 guint32 cols [MONO_MANIFEST_SIZE];
4571 guint32 impl, file_idx;
4575 MONO_ARCH_SAVE_REGS;
4577 for (i = 0; i < table->rows; ++i) {
4578 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4579 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4580 if (strcmp (val, n) == 0)
4584 if (i == table->rows)
4587 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4590 * this code should only be called after obtaining the
4591 * ResourceInfo and handling the other cases.
4593 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4594 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4596 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4601 module = assembly->assembly->image;
4603 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4605 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4609 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4611 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4613 guint32 cols [MONO_MANIFEST_SIZE];
4614 guint32 file_cols [MONO_FILE_SIZE];
4618 MONO_ARCH_SAVE_REGS;
4620 n = mono_string_to_utf8 (name);
4621 for (i = 0; i < table->rows; ++i) {
4622 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4623 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4624 if (strcmp (val, n) == 0)
4628 if (i == table->rows)
4631 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4632 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4635 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4636 case MONO_IMPLEMENTATION_FILE:
4637 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4638 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4639 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4640 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4641 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4642 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4645 info->location = RESOURCE_LOCATION_EMBEDDED;
4648 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4649 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4650 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4651 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4652 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4653 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4655 mono_raise_exception (ex);
4657 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4659 /* Obtain info recursively */
4660 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4661 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4664 case MONO_IMPLEMENTATION_EXP_TYPE:
4665 g_assert_not_reached ();
4674 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4676 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4677 MonoArray *result = NULL;
4682 MONO_ARCH_SAVE_REGS;
4684 /* check hash if needed */
4686 n = mono_string_to_utf8 (name);
4687 for (i = 0; i < table->rows; ++i) {
4688 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4689 if (strcmp (val, n) == 0) {
4692 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4693 fn = mono_string_new (mono_object_domain (assembly), n);
4695 return (MonoObject*)fn;
4703 for (i = 0; i < table->rows; ++i) {
4704 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4708 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4711 for (i = 0; i < table->rows; ++i) {
4712 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4713 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4714 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4715 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4720 return (MonoObject*)result;
4724 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4726 MonoDomain *domain = mono_domain_get();
4729 int i, j, file_count = 0;
4730 MonoImage **modules;
4731 guint32 module_count, real_module_count;
4732 MonoTableInfo *table;
4733 guint32 cols [MONO_FILE_SIZE];
4734 MonoImage *image = assembly->assembly->image;
4736 g_assert (image != NULL);
4737 g_assert (!assembly->assembly->dynamic);
4739 table = &image->tables [MONO_TABLE_FILE];
4740 file_count = table->rows;
4742 modules = image->modules;
4743 module_count = image->module_count;
4745 real_module_count = 0;
4746 for (i = 0; i < module_count; ++i)
4748 real_module_count ++;
4750 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4751 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4753 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4755 for (i = 0; i < module_count; ++i)
4757 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4761 for (i = 0; i < file_count; ++i, ++j) {
4762 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4763 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4764 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4766 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4768 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4769 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4771 mono_array_setref (res, j, mono_module_get_object (domain, m));
4778 static MonoReflectionMethod*
4779 ves_icall_GetCurrentMethod (void)
4781 MonoMethod *m = mono_method_get_last_managed ();
4783 while (m->is_inflated)
4784 m = ((MonoMethodInflated*)m)->declaring;
4786 return mono_method_get_object (mono_domain_get (), m, NULL);
4791 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4794 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4795 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4796 //method is inflated, we should inflate it on the other class
4797 MonoGenericContext ctx;
4798 ctx.method_inst = inflated->context.method_inst;
4799 ctx.class_inst = inflated->context.class_inst;
4800 if (klass->generic_class)
4801 ctx.class_inst = klass->generic_class->context.class_inst;
4802 else if (klass->generic_container)
4803 ctx.class_inst = klass->generic_container->context.class_inst;
4804 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4807 mono_class_setup_methods (method->klass);
4808 if (method->klass->exception_type)
4810 for (i = 0; i < method->klass->method.count; ++i) {
4811 if (method->klass->methods [i] == method) {
4816 mono_class_setup_methods (klass);
4817 if (klass->exception_type)
4819 g_assert (offset >= 0 && offset < klass->method.count);
4820 return klass->methods [offset];
4823 static MonoReflectionMethod*
4824 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4828 klass = mono_class_from_mono_type (type);
4829 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4831 if (method->klass != klass) {
4832 method = mono_method_get_equivalent_method (method, klass);
4837 klass = method->klass;
4838 return mono_method_get_object (mono_domain_get (), method, klass);
4841 static MonoReflectionMethod*
4842 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4844 return mono_method_get_object (mono_domain_get (), method, NULL);
4847 static MonoReflectionMethodBody*
4848 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4850 return mono_method_body_get_object (mono_domain_get (), method);
4853 static MonoReflectionAssembly*
4854 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4856 MonoMethod *dest = NULL;
4858 MONO_ARCH_SAVE_REGS;
4860 mono_stack_walk_no_il (get_executing, &dest);
4861 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4865 static MonoReflectionAssembly*
4866 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4868 MonoDomain* domain = mono_domain_get ();
4870 MONO_ARCH_SAVE_REGS;
4872 if (!domain->entry_assembly)
4875 return mono_assembly_get_object (domain, domain->entry_assembly);
4878 static MonoReflectionAssembly*
4879 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4884 MONO_ARCH_SAVE_REGS;
4887 mono_stack_walk_no_il (get_executing, &dest);
4889 mono_stack_walk_no_il (get_caller, &dest);
4892 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4896 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4897 gboolean assembly_qualified)
4899 MonoDomain *domain = mono_object_domain (object);
4900 MonoTypeNameFormat format;
4905 format = assembly_qualified ?
4906 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4907 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4909 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4911 name = mono_type_get_name_full (object->type, format);
4915 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4920 res = mono_string_new (domain, name);
4927 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4929 MonoClass *klass = mono_class_from_mono_type (this->type);
4930 mono_class_init_or_throw (klass);
4931 return mono_security_core_clr_class_level (klass);
4935 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4937 static MonoMethod *create_culture = NULL;
4940 const char *pkey_ptr;
4942 MonoBoolean assembly_ref = 0;
4944 MONO_ARCH_SAVE_REGS;
4946 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4947 aname->major = name->major;
4948 aname->minor = name->minor;
4949 aname->build = name->build;
4950 aname->flags = name->flags;
4951 aname->revision = name->revision;
4952 aname->hashalg = name->hash_alg;
4953 aname->versioncompat = 1; /* SameMachine (default) */
4954 aname->processor_architecture = name->arch;
4956 if (by_default_version)
4957 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4960 if (absolute != NULL && *absolute != '\0') {
4961 const gchar *prepend = "file://";
4964 codebase = g_strdup (absolute);
4969 for (i = strlen (codebase) - 1; i >= 0; i--)
4970 if (codebase [i] == '\\')
4973 if (*codebase == '/' && *(codebase + 1) == '/') {
4976 prepend = "file:///";
4980 result = g_strconcat (prepend, codebase, NULL);
4986 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4990 if (!create_culture) {
4991 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4992 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4993 g_assert (create_culture);
4994 mono_method_desc_free (desc);
4997 if (name->culture) {
4998 args [0] = mono_string_new (domain, name->culture);
4999 args [1] = &assembly_ref;
5000 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5003 if (name->public_key) {
5004 pkey_ptr = (char*)name->public_key;
5005 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5007 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5008 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5009 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5010 } else if (default_publickey) {
5011 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5012 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5015 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5016 if (name->public_key_token [0]) {
5020 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5021 p = mono_array_addr (aname->keyToken, char, 0);
5023 for (i = 0, j = 0; i < 8; i++) {
5024 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5025 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5028 } else if (default_token) {
5029 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5034 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5036 MonoDomain *domain = mono_object_domain (assembly);
5037 MonoAssembly *mass = assembly->assembly;
5041 name = mono_stringify_assembly_name (&mass->aname);
5042 res = mono_string_new (domain, name);
5049 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5052 MonoAssembly *mass = assembly->assembly;
5054 MONO_ARCH_SAVE_REGS;
5056 if (g_path_is_absolute (mass->image->name)) {
5057 fill_reflection_assembly_name (mono_object_domain (assembly),
5058 aname, &mass->aname, mass->image->name, TRUE,
5062 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5064 fill_reflection_assembly_name (mono_object_domain (assembly),
5065 aname, &mass->aname, absolute, TRUE, TRUE,
5072 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5075 MonoImageOpenStatus status = MONO_IMAGE_OK;
5078 MonoAssemblyName name;
5081 MONO_ARCH_SAVE_REGS;
5083 filename = mono_string_to_utf8 (fname);
5085 dirname = g_path_get_dirname (filename);
5086 replace_shadow_path (mono_domain_get (), dirname, &filename);
5089 image = mono_image_open (filename, &status);
5095 if (status == MONO_IMAGE_IMAGE_INVALID)
5096 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5098 exc = mono_get_exception_file_not_found2 (NULL, fname);
5099 mono_raise_exception (exc);
5102 res = mono_assembly_fill_assembly_name (image, &name);
5104 mono_image_close (image);
5106 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5109 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5113 mono_image_close (image);
5117 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5118 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5120 MonoBoolean result = FALSE;
5121 MonoDeclSecurityEntry entry;
5123 /* SecurityAction.RequestMinimum */
5124 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5125 *minimum = entry.blob;
5126 *minLength = entry.size;
5129 /* SecurityAction.RequestOptional */
5130 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5131 *optional = entry.blob;
5132 *optLength = entry.size;
5135 /* SecurityAction.RequestRefuse */
5136 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5137 *refused = entry.blob;
5138 *refLength = entry.size;
5146 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5150 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5152 guint32 attrs, visibility;
5154 /* we start the count from 1 because we skip the special type <Module> */
5157 for (i = 1; i < tdef->rows; ++i) {
5158 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5159 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5160 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5164 count = tdef->rows - 1;
5166 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5167 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5169 for (i = 1; i < tdef->rows; ++i) {
5170 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5171 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5172 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5173 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5175 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5177 MonoLoaderError *error;
5180 error = mono_loader_get_last_error ();
5181 g_assert (error != NULL);
5183 ex = mono_loader_error_prepare_exception (error);
5184 mono_array_setref (*exceptions, count, ex);
5186 if (mono_loader_get_last_error ())
5187 mono_loader_clear_error ();
5196 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5198 MonoArray *res = NULL;
5199 MonoArray *exceptions = NULL;
5200 MonoImage *image = NULL;
5201 MonoTableInfo *table = NULL;
5204 int i, len, ex_count;
5206 MONO_ARCH_SAVE_REGS;
5208 domain = mono_object_domain (assembly);
5210 g_assert (!assembly->assembly->dynamic);
5211 image = assembly->assembly->image;
5212 table = &image->tables [MONO_TABLE_FILE];
5213 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5215 /* Append data from all modules in the assembly */
5216 for (i = 0; i < table->rows; ++i) {
5217 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5218 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5221 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5222 /* Append the new types to the end of the array */
5223 if (mono_array_length (res2) > 0) {
5225 MonoArray *res3, *ex3;
5227 len1 = mono_array_length (res);
5228 len2 = mono_array_length (res2);
5230 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5231 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5232 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5235 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5236 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5237 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5244 /* the ReflectionTypeLoadException must have all the types (Types property),
5245 * NULL replacing types which throws an exception. The LoaderException must
5246 * contain all exceptions for NULL items.
5249 len = mono_array_length (res);
5252 for (i = 0; i < len; i++) {
5253 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5257 klass = mono_type_get_class (t->type);
5258 if ((klass != NULL) && klass->exception_type) {
5259 /* keep the class in the list */
5260 list = g_list_append (list, klass);
5261 /* and replace Type with NULL */
5262 mono_array_setref (res, i, NULL);
5269 if (list || ex_count) {
5271 MonoException *exc = NULL;
5272 MonoArray *exl = NULL;
5273 int j, length = g_list_length (list) + ex_count;
5275 mono_loader_clear_error ();
5277 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5278 /* Types for which mono_class_get () succeeded */
5279 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5280 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5281 mono_array_setref (exl, i, exc);
5283 /* Types for which it don't */
5284 for (j = 0; j < mono_array_length (exceptions); ++j) {
5285 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5287 g_assert (i < length);
5288 mono_array_setref (exl, i, exc);
5295 exc = mono_get_exception_reflection_type_load (res, exl);
5296 mono_loader_clear_error ();
5297 mono_raise_exception (exc);
5304 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5306 MonoAssemblyName aname;
5307 MonoDomain *domain = mono_object_domain (name);
5309 gboolean is_version_defined;
5310 gboolean is_token_defined;
5312 aname.public_key = NULL;
5313 val = mono_string_to_utf8 (assname);
5314 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5315 g_free ((guint8*) aname.public_key);
5320 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5321 FALSE, is_token_defined);
5323 mono_assembly_name_free (&aname);
5324 g_free ((guint8*) aname.public_key);
5330 static MonoReflectionType*
5331 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5333 MonoDomain *domain = mono_object_domain (module);
5336 MONO_ARCH_SAVE_REGS;
5338 g_assert (module->image);
5340 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5341 /* These images do not have a global type */
5344 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5345 return mono_type_get_object (domain, &klass->byval_arg);
5349 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5351 /*if (module->image)
5352 mono_image_close (module->image);*/
5356 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5358 MonoDomain *domain = mono_object_domain (module);
5360 MONO_ARCH_SAVE_REGS;
5362 g_assert (module->image);
5363 return mono_string_new (domain, module->image->guid);
5367 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5370 if (module->image && module->image->is_module_handle)
5371 return module->image->raw_data;
5374 return (gpointer) (-1);
5378 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5380 if (image->dynamic) {
5381 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5382 *pe_kind = dyn->pe_kind;
5383 *machine = dyn->machine;
5386 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5387 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5392 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5394 return (image->md_version_major << 16) | (image->md_version_minor);
5398 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5400 MonoArray *exceptions;
5403 MONO_ARCH_SAVE_REGS;
5406 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5408 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5409 for (i = 0; i < mono_array_length (exceptions); ++i) {
5410 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5412 mono_raise_exception (ex);
5419 mono_memberref_is_method (MonoImage *image, guint32 token)
5421 if (!image->dynamic) {
5422 guint32 cols [MONO_MEMBERREF_SIZE];
5424 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5425 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5426 mono_metadata_decode_blob_size (sig, &sig);
5427 return (*sig != 0x6);
5429 MonoClass *handle_class;
5431 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5434 return mono_defaults.methodhandle_class == handle_class;
5439 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5442 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5443 mono_array_addr (type_args, MonoType*, 0));
5445 context->class_inst = NULL;
5447 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5448 mono_array_addr (method_args, MonoType*, 0));
5450 context->method_inst = NULL;
5454 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5457 int table = mono_metadata_token_table (token);
5458 int index = mono_metadata_token_index (token);
5459 MonoGenericContext context;
5461 *error = ResolveTokenError_Other;
5463 /* Validate token */
5464 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5465 (table != MONO_TABLE_TYPESPEC)) {
5466 *error = ResolveTokenError_BadTable;
5470 if (image->dynamic) {
5471 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5472 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5473 return klass ? &klass->byval_arg : NULL;
5476 init_generic_context_from_args (&context, type_args, method_args);
5477 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5478 return klass ? &klass->byval_arg : NULL;
5481 if ((index <= 0) || (index > image->tables [table].rows)) {
5482 *error = ResolveTokenError_OutOfRange;
5486 init_generic_context_from_args (&context, type_args, method_args);
5487 klass = mono_class_get_full (image, token, &context);
5489 if (mono_loader_get_last_error ())
5490 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5493 return &klass->byval_arg;
5499 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5501 int table = mono_metadata_token_table (token);
5502 int index = mono_metadata_token_index (token);
5503 MonoGenericContext context;
5506 *error = ResolveTokenError_Other;
5508 /* Validate token */
5509 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5510 (table != MONO_TABLE_MEMBERREF)) {
5511 *error = ResolveTokenError_BadTable;
5515 if (image->dynamic) {
5516 if (table == MONO_TABLE_METHOD)
5517 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5519 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5520 *error = ResolveTokenError_BadTable;
5524 init_generic_context_from_args (&context, type_args, method_args);
5525 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5528 if ((index <= 0) || (index > image->tables [table].rows)) {
5529 *error = ResolveTokenError_OutOfRange;
5532 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5533 *error = ResolveTokenError_BadTable;
5537 init_generic_context_from_args (&context, type_args, method_args);
5538 method = mono_get_method_full (image, token, NULL, &context);
5540 if (mono_loader_get_last_error ())
5541 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5547 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5549 int index = mono_metadata_token_index (token);
5551 *error = ResolveTokenError_Other;
5553 /* Validate token */
5554 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5555 *error = ResolveTokenError_BadTable;
5560 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5562 if ((index <= 0) || (index >= image->heap_us.size)) {
5563 *error = ResolveTokenError_OutOfRange;
5567 /* FIXME: What to do if the index points into the middle of a string ? */
5569 return mono_ldstr (mono_domain_get (), image, index);
5572 static MonoClassField*
5573 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5576 int table = mono_metadata_token_table (token);
5577 int index = mono_metadata_token_index (token);
5578 MonoGenericContext context;
5579 MonoClassField *field;
5581 *error = ResolveTokenError_Other;
5583 /* Validate token */
5584 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5585 *error = ResolveTokenError_BadTable;
5589 if (image->dynamic) {
5590 if (table == MONO_TABLE_FIELD)
5591 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5593 if (mono_memberref_is_method (image, token)) {
5594 *error = ResolveTokenError_BadTable;
5598 init_generic_context_from_args (&context, type_args, method_args);
5599 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5602 if ((index <= 0) || (index > image->tables [table].rows)) {
5603 *error = ResolveTokenError_OutOfRange;
5606 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5607 *error = ResolveTokenError_BadTable;
5611 init_generic_context_from_args (&context, type_args, method_args);
5612 field = mono_field_from_token (image, token, &klass, &context);
5614 if (mono_loader_get_last_error ())
5615 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5622 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5624 int table = mono_metadata_token_table (token);
5626 *error = ResolveTokenError_Other;
5629 case MONO_TABLE_TYPEDEF:
5630 case MONO_TABLE_TYPEREF:
5631 case MONO_TABLE_TYPESPEC: {
5632 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5634 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5638 case MONO_TABLE_METHOD:
5639 case MONO_TABLE_METHODSPEC: {
5640 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5642 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5646 case MONO_TABLE_FIELD: {
5647 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5649 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5653 case MONO_TABLE_MEMBERREF:
5654 if (mono_memberref_is_method (image, token)) {
5655 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5657 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5662 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5664 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5671 *error = ResolveTokenError_BadTable;
5678 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5680 int table = mono_metadata_token_table (token);
5681 int idx = mono_metadata_token_index (token);
5682 MonoTableInfo *tables = image->tables;
5687 *error = ResolveTokenError_OutOfRange;
5689 /* FIXME: Support other tables ? */
5690 if (table != MONO_TABLE_STANDALONESIG)
5696 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5699 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5701 ptr = mono_metadata_blob_heap (image, sig);
5702 len = mono_metadata_decode_blob_size (ptr, &ptr);
5704 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5705 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5709 static MonoReflectionType*
5710 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5713 int isbyref = 0, rank;
5714 char *str = mono_string_to_utf8 (smodifiers);
5717 MONO_ARCH_SAVE_REGS;
5719 klass = mono_class_from_mono_type (tb->type.type);
5721 /* logic taken from mono_reflection_parse_type(): keep in sync */
5725 if (isbyref) { /* only one level allowed by the spec */
5732 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5735 klass = mono_ptr_class_get (&klass->byval_arg);
5736 mono_class_init (klass);
5747 else if (*p != '*') { /* '*' means unknown lower bound */
5758 klass = mono_array_class_get (klass, rank);
5759 mono_class_init (klass);
5766 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5770 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5775 MONO_ARCH_SAVE_REGS;
5778 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5784 check_for_invalid_type (MonoClass *klass)
5788 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5791 name = mono_type_get_full_name (klass);
5792 str = mono_string_new (mono_domain_get (), name);
5794 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5797 static MonoReflectionType *
5798 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5800 MonoClass *klass, *aklass;
5802 MONO_ARCH_SAVE_REGS;
5804 klass = mono_class_from_mono_type (type->type);
5805 check_for_invalid_type (klass);
5807 if (rank == 0) //single dimentional array
5808 aklass = mono_array_class_get (klass, 1);
5810 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5812 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5815 static MonoReflectionType *
5816 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5820 MONO_ARCH_SAVE_REGS;
5822 klass = mono_class_from_mono_type (type->type);
5823 mono_class_init_or_throw (klass);
5824 check_for_invalid_type (klass);
5826 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5829 static MonoReflectionType *
5830 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5832 MonoClass *klass, *pklass;
5834 klass = mono_class_from_mono_type (type->type);
5835 mono_class_init_or_throw (klass);
5836 check_for_invalid_type (klass);
5838 pklass = mono_ptr_class_get (type->type);
5840 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5844 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5845 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5847 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5848 MonoObject *delegate;
5850 MonoMethod *method = info->method;
5852 MONO_ARCH_SAVE_REGS;
5854 mono_class_init_or_throw (delegate_class);
5856 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5858 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5859 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5863 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5865 if (method->dynamic) {
5866 /* Creating a trampoline would leak memory */
5867 func = mono_compile_method (method);
5869 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5870 method = mono_object_get_virtual_method (target, method);
5871 func = mono_create_ftnptr (mono_domain_get (),
5872 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5875 mono_delegate_ctor_with_method (delegate, target, func, method);
5881 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5883 /* Reset the invoke impl to the default one */
5884 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5888 * Magic number to convert a time which is relative to
5889 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5891 #define EPOCH_ADJUST ((guint64)62135596800LL)
5894 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5896 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5899 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5901 convert_to_absolute_date(SYSTEMTIME *date)
5903 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5904 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5905 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5906 /* from the calendar FAQ */
5907 int a = (14 - date->wMonth) / 12;
5908 int y = date->wYear - a;
5909 int m = date->wMonth + 12 * a - 2;
5910 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5912 /* d is now the day of the week for the first of the month (0 == Sunday) */
5914 int day_of_week = date->wDayOfWeek;
5916 /* set day_in_month to the first day in the month which falls on day_of_week */
5917 int day_in_month = 1 + (day_of_week - d);
5918 if (day_in_month <= 0)
5921 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5922 date->wDay = day_in_month + (date->wDay - 1) * 7;
5923 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5930 * Return's the offset from GMT of a local time.
5932 * tm is a local time
5933 * t is the same local time as seconds.
5936 gmt_offset(struct tm *tm, time_t t)
5938 #if defined (HAVE_TM_GMTOFF)
5939 return tm->tm_gmtoff;
5944 g.tm_isdst = tm->tm_isdst;
5946 return (int)difftime(t, t2);
5951 * This is heavily based on zdump.c from glibc 2.2.
5953 * * data[0]: start of daylight saving time (in DateTime ticks).
5954 * * data[1]: end of daylight saving time (in DateTime ticks).
5955 * * data[2]: utcoffset (in TimeSpan ticks).
5956 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5957 * * name[0]: name of this timezone when not daylight saving.
5958 * * name[1]: name of this timezone when daylight saving.
5960 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5961 * the class library allows years between 1 and 9999.
5963 * Returns true on success and zero on failure.
5966 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5969 MonoDomain *domain = mono_domain_get ();
5970 struct tm start, tt;
5974 int is_daylight = 0, day;
5977 MONO_ARCH_SAVE_REGS;
5979 MONO_CHECK_ARG_NULL (data);
5980 MONO_CHECK_ARG_NULL (names);
5982 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5983 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5986 * no info is better than crashing: we'll need our own tz data
5987 * to make this work properly, anyway. The range is probably
5988 * reduced to 1970 .. 2037 because that is what mktime is
5989 * guaranteed to support (we get into an infinite loop
5993 memset (&start, 0, sizeof (start));
5996 start.tm_year = year-1900;
5998 t = mktime (&start);
6000 if ((year < 1970) || (year > 2037) || (t == -1)) {
6002 tt = *localtime (&t);
6003 strftime (tzone, sizeof (tzone), "%Z", &tt);
6004 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6005 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6009 gmtoff = gmt_offset (&start, t);
6011 /* For each day of the year, calculate the tm_gmtoff. */
6012 for (day = 0; day < 365; day++) {
6015 tt = *localtime (&t);
6017 /* Daylight saving starts or ends here. */
6018 if (gmt_offset (&tt, t) != gmtoff) {
6022 /* Try to find the exact hour when daylight saving starts/ends. */
6026 tt1 = *localtime (&t1);
6027 } while (gmt_offset (&tt1, t1) != gmtoff);
6029 /* Try to find the exact minute when daylight saving starts/ends. */
6032 tt1 = *localtime (&t1);
6033 } while (gmt_offset (&tt1, t1) == gmtoff);
6035 strftime (tzone, sizeof (tzone), "%Z", &tt);
6037 /* Write data, if we're already in daylight saving, we're done. */
6039 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6040 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6043 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6044 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6048 /* This is only set once when we enter daylight saving. */
6049 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6050 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6052 gmtoff = gmt_offset (&tt, t);
6057 strftime (tzone, sizeof (tzone), "%Z", &tt);
6058 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6059 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6060 mono_array_set ((*data), gint64, 0, 0);
6061 mono_array_set ((*data), gint64, 1, 0);
6062 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6063 mono_array_set ((*data), gint64, 3, 0);
6068 MonoDomain *domain = mono_domain_get ();
6069 TIME_ZONE_INFORMATION tz_info;
6074 tz_id = GetTimeZoneInformation (&tz_info);
6075 if (tz_id == TIME_ZONE_ID_INVALID)
6078 MONO_CHECK_ARG_NULL (data);
6079 MONO_CHECK_ARG_NULL (names);
6081 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6082 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6084 for (i = 0; i < 32; ++i)
6085 if (!tz_info.DaylightName [i])
6087 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6088 for (i = 0; i < 32; ++i)
6089 if (!tz_info.StandardName [i])
6091 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6093 if ((year <= 1601) || (year > 30827)) {
6095 * According to MSDN, the MS time functions can't handle dates outside
6101 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6102 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6103 tz_info.StandardDate.wYear = year;
6104 convert_to_absolute_date(&tz_info.StandardDate);
6105 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6110 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6111 tz_info.DaylightDate.wYear = year;
6112 convert_to_absolute_date(&tz_info.DaylightDate);
6113 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6118 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6120 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6121 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6128 ves_icall_System_Object_obj_address (MonoObject *this)
6130 MONO_ARCH_SAVE_REGS;
6137 static inline gint32
6138 mono_array_get_byte_length (MonoArray *array)
6144 klass = array->obj.vtable->klass;
6146 if (array->bounds == NULL)
6147 length = array->max_length;
6150 for (i = 0; i < klass->rank; ++ i)
6151 length *= array->bounds [i].length;
6154 switch (klass->element_class->byval_arg.type) {
6157 case MONO_TYPE_BOOLEAN:
6161 case MONO_TYPE_CHAR:
6169 return length * sizeof (gpointer);
6180 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6182 MONO_ARCH_SAVE_REGS;
6184 return mono_array_get_byte_length (array);
6188 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6190 MONO_ARCH_SAVE_REGS;
6192 return mono_array_get (array, gint8, idx);
6196 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6198 MONO_ARCH_SAVE_REGS;
6200 mono_array_set (array, gint8, idx, value);
6204 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6206 guint8 *src_buf, *dest_buf;
6208 MONO_ARCH_SAVE_REGS;
6210 /* watch out for integer overflow */
6211 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6214 src_buf = (guint8 *)src->vector + src_offset;
6215 dest_buf = (guint8 *)dest->vector + dest_offset;
6218 memcpy (dest_buf, src_buf, count);
6220 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6226 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6228 MonoDomain *domain = mono_object_domain (this);
6230 MonoRealProxy *rp = ((MonoRealProxy *)this);
6231 MonoTransparentProxy *tp;
6235 MONO_ARCH_SAVE_REGS;
6237 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6238 tp = (MonoTransparentProxy*) res;
6240 MONO_OBJECT_SETREF (tp, rp, rp);
6241 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6242 klass = mono_class_from_mono_type (type);
6244 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6245 tp->remote_class = mono_remote_class (domain, class_name, klass);
6247 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6251 static MonoReflectionType *
6252 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6254 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6257 /* System.Environment */
6260 ves_icall_System_Environment_get_UserName (void)
6262 MONO_ARCH_SAVE_REGS;
6264 /* using glib is more portable */
6265 return mono_string_new (mono_domain_get (), g_get_user_name ());
6270 ves_icall_System_Environment_get_MachineName (void)
6272 #if defined (HOST_WIN32)
6277 len = MAX_COMPUTERNAME_LENGTH + 1;
6278 buf = g_new (gunichar2, len);
6281 if (GetComputerName (buf, (PDWORD) &len))
6282 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6286 #elif !defined(DISABLE_SOCKETS)
6290 if (gethostname (buf, sizeof (buf)) == 0)
6291 result = mono_string_new (mono_domain_get (), buf);
6297 return mono_string_new (mono_domain_get (), "mono");
6302 ves_icall_System_Environment_get_Platform (void)
6304 #if defined (TARGET_WIN32)
6307 #elif defined(__MACH__)
6310 // Notice that the value is hidden from user code, and only exposed
6311 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6312 // define and making assumptions based on Unix/128/4 values before there
6313 // was a MacOS define. Lots of code would assume that not-Unix meant
6314 // Windows, but in this case, it would be OSX.
6324 ves_icall_System_Environment_get_NewLine (void)
6326 MONO_ARCH_SAVE_REGS;
6328 #if defined (HOST_WIN32)
6329 return mono_string_new (mono_domain_get (), "\r\n");
6331 return mono_string_new (mono_domain_get (), "\n");
6336 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6341 MONO_ARCH_SAVE_REGS;
6346 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6347 value = g_getenv (utf8_name);
6354 return mono_string_new (mono_domain_get (), value);
6358 * There is no standard way to get at environ.
6361 #ifndef __MINGW32_VERSION
6362 #if defined(__APPLE__) && !defined (__arm__)
6363 /* Apple defines this in crt_externs.h but doesn't provide that header for
6364 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6365 * in fact exist on all implementations (so far)
6367 gchar ***_NSGetEnviron(void);
6368 #define environ (*_NSGetEnviron())
6377 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6388 env_strings = GetEnvironmentStrings();
6391 env_string = env_strings;
6392 while (*env_string != '\0') {
6393 /* weird case that MS seems to skip */
6394 if (*env_string != '=')
6396 while (*env_string != '\0')
6402 domain = mono_domain_get ();
6403 names = mono_array_new (domain, mono_defaults.string_class, n);
6407 env_string = env_strings;
6408 while (*env_string != '\0') {
6409 /* weird case that MS seems to skip */
6410 if (*env_string != '=') {
6411 equal_str = wcschr(env_string, '=');
6412 g_assert(equal_str);
6413 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6414 mono_array_setref (names, n, str);
6417 while (*env_string != '\0')
6422 FreeEnvironmentStrings (env_strings);
6434 MONO_ARCH_SAVE_REGS;
6437 for (e = environ; *e != 0; ++ e)
6440 domain = mono_domain_get ();
6441 names = mono_array_new (domain, mono_defaults.string_class, n);
6444 for (e = environ; *e != 0; ++ e) {
6445 parts = g_strsplit (*e, "=", 2);
6447 str = mono_string_new (domain, *parts);
6448 mono_array_setref (names, n, str);
6461 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6463 #if !GLIB_CHECK_VERSION(2,4,0)
6464 #define g_setenv(a,b,c) setenv(a,b,c)
6465 #define g_unsetenv(a) unsetenv(a)
6469 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6474 gunichar2 *utf16_name, *utf16_value;
6476 gchar *utf8_name, *utf8_value;
6479 MONO_ARCH_SAVE_REGS;
6482 utf16_name = mono_string_to_utf16 (name);
6483 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6484 SetEnvironmentVariable (utf16_name, NULL);
6485 g_free (utf16_name);
6489 utf16_value = mono_string_to_utf16 (value);
6491 SetEnvironmentVariable (utf16_name, utf16_value);
6493 g_free (utf16_name);
6494 g_free (utf16_value);
6496 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6498 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6499 g_unsetenv (utf8_name);
6504 utf8_value = mono_string_to_utf8_checked (value, &error);
6505 if (!mono_error_ok (&error)) {
6507 mono_error_raise_exception (&error);
6509 g_setenv (utf8_name, utf8_value, TRUE);
6512 g_free (utf8_value);
6517 ves_icall_System_Environment_Exit (int result)
6519 MONO_ARCH_SAVE_REGS;
6521 mono_threads_set_shutting_down ();
6523 mono_runtime_set_shutting_down ();
6525 /* This will kill the tp threads which cannot be suspended */
6526 mono_thread_pool_cleanup ();
6528 /* Suspend all managed threads since the runtime is going away */
6529 mono_thread_suspend_all_other_threads ();
6531 mono_runtime_quit ();
6533 /* we may need to do some cleanup here... */
6538 ves_icall_System_Environment_GetGacPath (void)
6540 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6544 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6546 #if defined (HOST_WIN32)
6547 #ifndef CSIDL_FLAG_CREATE
6548 #define CSIDL_FLAG_CREATE 0x8000
6551 WCHAR path [MAX_PATH];
6552 /* Create directory if no existing */
6553 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6557 return mono_string_new_utf16 (mono_domain_get (), path, len);
6560 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6562 return mono_string_new (mono_domain_get (), "");
6566 ves_icall_System_Environment_GetLogicalDrives (void)
6568 gunichar2 buf [256], *ptr, *dname;
6570 guint initial_size = 127, size = 128;
6573 MonoString *drivestr;
6574 MonoDomain *domain = mono_domain_get ();
6577 MONO_ARCH_SAVE_REGS;
6582 while (size > initial_size) {
6583 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6584 if (size > initial_size) {
6587 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6588 initial_size = size;
6602 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6607 while (*u16) { u16++; len ++; }
6608 drivestr = mono_string_new_utf16 (domain, dname, len);
6609 mono_array_setref (result, ndrives++, drivestr);
6620 ves_icall_System_Environment_InternalGetHome (void)
6622 MONO_ARCH_SAVE_REGS;
6624 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6627 static const char *encodings [] = {
6629 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6630 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6631 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6633 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6634 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6635 "x_unicode_2_0_utf_7",
6637 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6638 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6640 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6643 "unicodefffe", "utf_16be",
6650 * Returns the internal codepage, if the value of "int_code_page" is
6651 * 1 at entry, and we can not compute a suitable code page number,
6652 * returns the code page as a string
6655 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6660 char *codepage = NULL;
6662 int want_name = *int_code_page;
6665 *int_code_page = -1;
6666 MONO_ARCH_SAVE_REGS;
6668 g_get_charset (&cset);
6669 c = codepage = strdup (cset);
6670 for (c = codepage; *c; c++){
6671 if (isascii (*c) && isalpha (*c))
6676 /* g_print ("charset: %s\n", cset); */
6678 /* handle some common aliases */
6681 for (i = 0; p != 0; ){
6682 if ((gssize) p < 7){
6684 p = encodings [++i];
6687 if (strcmp (p, codepage) == 0){
6688 *int_code_page = code;
6691 p = encodings [++i];
6694 if (strstr (codepage, "utf_8") != NULL)
6695 *int_code_page |= 0x10000000;
6698 if (want_name && *int_code_page == -1)
6699 return mono_string_new (mono_domain_get (), cset);
6705 ves_icall_System_Environment_get_HasShutdownStarted (void)
6707 if (mono_runtime_is_shutting_down ())
6710 if (mono_domain_is_unloading (mono_domain_get ()))
6717 ves_icall_System_Environment_BroadcastSettingChange (void)
6720 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6725 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6726 MonoReflectionMethod *method,
6727 MonoArray *out_args)
6729 MONO_ARCH_SAVE_REGS;
6731 mono_message_init (mono_object_domain (this), this, method, out_args);
6735 ves_icall_IsTransparentProxy (MonoObject *proxy)
6737 MONO_ARCH_SAVE_REGS;
6742 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6748 static MonoReflectionMethod *
6749 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6750 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6754 MonoMethod **vtable;
6755 MonoMethod *res = NULL;
6757 MONO_CHECK_ARG_NULL (rtype);
6758 MONO_CHECK_ARG_NULL (rmethod);
6760 method = rmethod->method;
6761 klass = mono_class_from_mono_type (rtype->type);
6762 mono_class_init_or_throw (klass);
6764 if (MONO_CLASS_IS_INTERFACE (klass))
6767 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6770 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6771 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6777 mono_class_setup_vtable (klass);
6778 vtable = klass->vtable;
6780 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6781 gboolean variance_used = FALSE;
6782 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6783 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6785 res = vtable [offs + method->slot];
6787 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6790 if (method->slot != -1)
6791 res = vtable [method->slot];
6797 return mono_method_get_object (mono_domain_get (), res, NULL);
6801 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6806 MONO_ARCH_SAVE_REGS;
6808 klass = mono_class_from_mono_type (type->type);
6809 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6811 if (enable) vtable->remote = 1;
6812 else vtable->remote = 0;
6816 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6821 MONO_ARCH_SAVE_REGS;
6823 domain = mono_object_domain (type);
6824 klass = mono_class_from_mono_type (type->type);
6825 mono_class_init_or_throw (klass);
6827 if (klass->rank >= 1) {
6828 g_assert (klass->rank == 1);
6829 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6831 /* Bypass remoting object creation check */
6832 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6837 ves_icall_System_IO_get_temp_path (void)
6839 MONO_ARCH_SAVE_REGS;
6841 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6844 #ifndef PLATFORM_NO_DRIVEINFO
6846 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6847 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6851 ULARGE_INTEGER wapi_free_bytes_avail;
6852 ULARGE_INTEGER wapi_total_number_of_bytes;
6853 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6855 MONO_ARCH_SAVE_REGS;
6857 *error = ERROR_SUCCESS;
6858 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6859 &wapi_total_number_of_free_bytes);
6862 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6863 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6864 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6866 *free_bytes_avail = 0;
6867 *total_number_of_bytes = 0;
6868 *total_number_of_free_bytes = 0;
6869 *error = GetLastError ();
6876 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6878 MONO_ARCH_SAVE_REGS;
6880 return GetDriveType (mono_string_chars (root_path_name));
6885 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6887 MONO_ARCH_SAVE_REGS;
6889 return mono_compile_method (method);
6893 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6898 MONO_ARCH_SAVE_REGS;
6900 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6902 #if defined (HOST_WIN32)
6903 /* Avoid mixing '/' and '\\' */
6906 for (i = strlen (path) - 1; i >= 0; i--)
6907 if (path [i] == '/')
6911 mcpath = mono_string_new (mono_domain_get (), path);
6918 get_bundled_app_config (void)
6920 const gchar *app_config;
6927 MONO_ARCH_SAVE_REGS;
6929 domain = mono_domain_get ();
6930 file = domain->setup->configuration_file;
6934 // Retrieve config file and remove the extension
6935 config_file = mono_string_to_utf8 (file);
6936 len = strlen (config_file) - strlen (".config");
6937 module = g_malloc0 (len + 1);
6938 memcpy (module, config_file, len);
6939 // Get the config file from the module name
6940 app_config = mono_config_string_for_assembly_file (module);
6943 g_free (config_file);
6948 return mono_string_new (mono_domain_get (), app_config);
6952 get_bundled_machine_config (void)
6954 const gchar *machine_config;
6956 MONO_ARCH_SAVE_REGS;
6958 machine_config = mono_get_machine_config ();
6960 if (!machine_config)
6963 return mono_string_new (mono_domain_get (), machine_config);
6967 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6972 MONO_ARCH_SAVE_REGS;
6974 path = g_path_get_dirname (mono_get_config_dir ());
6976 #if defined (HOST_WIN32)
6977 /* Avoid mixing '/' and '\\' */
6980 for (i = strlen (path) - 1; i >= 0; i--)
6981 if (path [i] == '/')
6985 ipath = mono_string_new (mono_domain_get (), path);
6992 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6994 MonoPEResourceDataEntry *entry;
6997 MONO_ARCH_SAVE_REGS;
6999 if (!assembly || !result || !size)
7004 image = assembly->assembly->image;
7005 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7009 *result = mono_image_rva_map (image, entry->rde_data_offset);
7014 *size = entry->rde_size;
7020 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7022 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7026 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7028 #if defined (HOST_WIN32)
7029 OutputDebugString (mono_string_chars (message));
7031 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7035 /* Only used for value types */
7037 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7042 MONO_ARCH_SAVE_REGS;
7044 domain = mono_object_domain (type);
7045 klass = mono_class_from_mono_type (type->type);
7046 mono_class_init_or_throw (klass);
7048 if (mono_class_is_nullable (klass))
7049 /* No arguments -> null */
7052 return mono_object_new (domain, klass);
7055 static MonoReflectionMethod *
7056 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7058 MonoClass *klass, *parent;
7059 MonoMethod *method = m->method;
7060 MonoMethod *result = NULL;
7062 MONO_ARCH_SAVE_REGS;
7064 if (method->klass == NULL)
7067 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7068 MONO_CLASS_IS_INTERFACE (method->klass) ||
7069 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7072 klass = method->klass;
7073 if (klass->generic_class)
7074 klass = klass->generic_class->container_class;
7077 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7078 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7079 mono_class_setup_vtable (parent);
7080 if (parent->vtable_size <= method->slot)
7085 klass = klass->parent;
7090 if (klass == method->klass)
7093 /*This is possible if definition == FALSE.
7094 * Do it here to be really sure we don't read invalid memory.
7096 if (method->slot >= klass->vtable_size)
7099 mono_class_setup_vtable (klass);
7101 result = klass->vtable [method->slot];
7102 if (result == NULL) {
7103 /* It is an abstract method */
7104 gpointer iter = NULL;
7105 while ((result = mono_class_get_methods (klass, &iter)))
7106 if (result->slot == method->slot)
7113 return mono_method_get_object (mono_domain_get (), result, NULL);
7117 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7119 MonoMethod *method = m->method;
7121 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7126 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7128 MONO_ARCH_SAVE_REGS;
7130 iter->sig = *(MonoMethodSignature**)argsp;
7132 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7133 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7136 /* FIXME: it's not documented what start is exactly... */
7140 iter->args = argsp + sizeof (gpointer);
7142 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7144 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7148 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7150 guint32 i, arg_size;
7153 MONO_ARCH_SAVE_REGS;
7155 i = iter->sig->sentinelpos + iter->next_arg;
7157 g_assert (i < iter->sig->param_count);
7159 res.type = iter->sig->params [i];
7160 res.klass = mono_class_from_mono_type (res.type);
7161 res.value = iter->args;
7162 arg_size = mono_type_stack_size (res.type, &align);
7163 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7164 if (arg_size <= sizeof (gpointer)) {
7166 int padding = arg_size - mono_type_size (res.type, &dummy);
7167 res.value = (guint8*)res.value + padding;
7170 iter->args = (char*)iter->args + arg_size;
7173 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7179 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7181 guint32 i, arg_size;
7184 MONO_ARCH_SAVE_REGS;
7186 i = iter->sig->sentinelpos + iter->next_arg;
7188 g_assert (i < iter->sig->param_count);
7190 while (i < iter->sig->param_count) {
7191 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7193 res.type = iter->sig->params [i];
7194 res.klass = mono_class_from_mono_type (res.type);
7195 /* FIXME: endianess issue... */
7196 res.value = iter->args;
7197 arg_size = mono_type_stack_size (res.type, &align);
7198 iter->args = (char*)iter->args + arg_size;
7200 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7203 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7212 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7215 MONO_ARCH_SAVE_REGS;
7217 i = iter->sig->sentinelpos + iter->next_arg;
7219 g_assert (i < iter->sig->param_count);
7221 return iter->sig->params [i];
7225 mono_TypedReference_ToObject (MonoTypedRef tref)
7227 MONO_ARCH_SAVE_REGS;
7229 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7230 MonoObject** objp = tref.value;
7234 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7238 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7240 MONO_ARCH_SAVE_REGS;
7242 if (MONO_TYPE_IS_REFERENCE (type)) {
7243 MonoObject** objp = value;
7247 return mono_value_box (mono_domain_get (), klass, value);
7251 prelink_method (MonoMethod *method)
7253 const char *exc_class, *exc_arg;
7254 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7256 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7258 mono_raise_exception(
7259 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7261 /* create the wrapper, too? */
7265 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7267 MONO_ARCH_SAVE_REGS;
7268 prelink_method (method->method);
7272 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7274 MonoClass *klass = mono_class_from_mono_type (type->type);
7276 gpointer iter = NULL;
7277 MONO_ARCH_SAVE_REGS;
7279 mono_class_init_or_throw (klass);
7281 while ((m = mono_class_get_methods (klass, &iter)))
7285 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7287 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7288 gint32 const **exponents,
7289 gunichar2 const **digitLowerTable,
7290 gunichar2 const **digitUpperTable,
7291 gint64 const **tenPowersList,
7292 gint32 const **decHexDigits)
7294 *mantissas = Formatter_MantissaBitsTable;
7295 *exponents = Formatter_TensExponentTable;
7296 *digitLowerTable = Formatter_DigitLowerTable;
7297 *digitUpperTable = Formatter_DigitUpperTable;
7298 *tenPowersList = Formatter_TenPowersList;
7299 *decHexDigits = Formatter_DecHexDigits;
7302 /* These parameters are "readonly" in corlib/System/Char.cs */
7304 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7305 guint8 const **numeric_data,
7306 gdouble const **numeric_data_values,
7307 guint16 const **to_lower_data_low,
7308 guint16 const **to_lower_data_high,
7309 guint16 const **to_upper_data_low,
7310 guint16 const **to_upper_data_high)
7312 *category_data = CategoryData;
7313 *numeric_data = NumericData;
7314 *numeric_data_values = NumericDataValues;
7315 *to_lower_data_low = ToLowerDataLow;
7316 *to_lower_data_high = ToLowerDataHigh;
7317 *to_upper_data_low = ToUpperDataLow;
7318 *to_upper_data_high = ToUpperDataHigh;
7322 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7324 return method->method->token;
7328 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7329 * and avoid useless allocations.
7332 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7336 for (i = 0; i < type->num_mods; ++i) {
7337 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7342 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7344 for (i = 0; i < type->num_mods; ++i) {
7345 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7346 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7347 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7355 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7357 MonoType *type = param->ClassImpl->type;
7358 MonoClass *member_class = mono_object_class (param->MemberImpl);
7359 MonoMethod *method = NULL;
7362 MonoMethodSignature *sig;
7364 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7365 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7366 method = rmethod->method;
7367 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7368 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7369 if (!(method = prop->property->get))
7370 method = prop->property->set;
7373 char *type_name = mono_type_get_full_name (member_class);
7374 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7375 MonoException *ex = mono_get_exception_not_supported (msg);
7378 mono_raise_exception (ex);
7381 image = method->klass->image;
7382 pos = param->PositionImpl;
7383 sig = mono_method_signature (method);
7387 type = sig->params [pos];
7389 return type_array_from_modifiers (image, type, optional);
7393 get_property_type (MonoProperty *prop)
7395 MonoMethodSignature *sig;
7397 sig = mono_method_signature (prop->get);
7399 } else if (prop->set) {
7400 sig = mono_method_signature (prop->set);
7401 return sig->params [sig->param_count - 1];
7407 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7409 MonoType *type = get_property_type (property->property);
7410 MonoImage *image = property->klass->image;
7414 return type_array_from_modifiers (image, type, optional);
7418 *Construct a MonoType suited to be used to decode a constant blob object.
7420 * @type is the target type which will be constructed
7421 * @blob_type is the blob type, for example, that comes from the constant table
7422 * @real_type is the expected constructed type.
7425 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7427 type->type = blob_type;
7428 type->data.klass = NULL;
7429 if (blob_type == MONO_TYPE_CLASS)
7430 type->data.klass = mono_defaults.object_class;
7431 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7432 /* For enums, we need to use the base type */
7433 type->type = MONO_TYPE_VALUETYPE;
7434 type->data.klass = mono_class_from_mono_type (real_type);
7436 type->data.klass = mono_class_from_mono_type (real_type);
7440 property_info_get_default_value (MonoReflectionProperty *property)
7443 MonoProperty *prop = property->property;
7444 MonoType *type = get_property_type (prop);
7445 MonoDomain *domain = mono_object_domain (property);
7446 MonoTypeEnum def_type;
7447 const char *def_value;
7450 mono_class_init (prop->parent);
7452 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7453 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7455 def_value = mono_class_get_property_default_value (prop, &def_type);
7457 mono_type_from_blob_type (&blob_type, def_type, type);
7458 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7464 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7466 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7467 MonoCustomAttrInfo *cinfo;
7470 mono_class_init_or_throw (attr_class);
7472 cinfo = mono_reflection_get_custom_attrs_info (obj);
7475 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7477 mono_custom_attrs_free (cinfo);
7482 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7484 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7489 mono_class_init_or_throw (attr_class);
7491 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7492 if (!mono_error_ok (&error))
7493 mono_error_raise_exception (&error);
7494 if (mono_loader_get_last_error ()) {
7495 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7496 g_assert_not_reached ();
7505 ves_icall_Mono_Runtime_GetDisplayName (void)
7508 MonoString *display_name;
7510 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7511 display_name = mono_string_new (mono_domain_get (), info);
7513 return display_name;
7517 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7519 MonoString *message;
7523 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7524 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7527 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7529 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7537 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7538 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7539 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7540 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7541 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7542 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7543 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7544 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7548 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7553 gunichar2 last, prev_last, prev2_last;
7561 last = prev_last = 0, prev2_last = 0;
7562 for (i = 0; i < ilength; i++) {
7564 if (c >= sizeof (dbase64)) {
7565 exc = mono_exception_from_name_msg (mono_get_corlib (),
7566 "System", "FormatException",
7567 "Invalid character found.");
7568 mono_raise_exception (exc);
7569 } else if (isspace (c)) {
7572 prev2_last = prev_last;
7578 olength = ilength - ignored;
7580 if (allowWhitespaceOnly && olength == 0) {
7581 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7584 if ((olength & 3) != 0 || olength <= 0) {
7585 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7586 "FormatException", "Invalid length.");
7587 mono_raise_exception (exc);
7590 if (prev2_last == '=') {
7591 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7592 mono_raise_exception (exc);
7595 olength = (olength * 3) / 4;
7599 if (prev_last == '=')
7602 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7603 res_ptr = mono_array_addr (result, guchar, 0);
7604 for (i = 0; i < ilength; ) {
7607 for (k = 0; k < 4 && i < ilength;) {
7613 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7614 exc = mono_exception_from_name_msg (mono_get_corlib (),
7615 "System", "FormatException",
7616 "Invalid character found.");
7617 mono_raise_exception (exc);
7622 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7624 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7626 *res_ptr++ = (b [2] << 6) | b [3];
7628 while (i < ilength && isspace (start [i]))
7636 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7638 MONO_ARCH_SAVE_REGS;
7640 return base64_to_byte_array (mono_string_chars (str),
7641 mono_string_length (str), allowWhitespaceOnly);
7645 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7647 MONO_ARCH_SAVE_REGS;
7649 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7653 #define ICALL_TYPE(id,name,first)
7654 #define ICALL(id,name,func) Icall_ ## id,
7657 #include "metadata/icall-def.h"
7663 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7664 #define ICALL(id,name,func)
7666 #include "metadata/icall-def.h"
7672 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7673 #define ICALL(id,name,func)
7675 guint16 first_icall;
7678 static const IcallTypeDesc
7679 icall_type_descs [] = {
7680 #include "metadata/icall-def.h"
7684 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7687 #define ICALL_TYPE(id,name,first)
7690 #ifdef HAVE_ARRAY_ELEM_INIT
7691 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7692 #define MSGSTRFIELD1(line) str##line
7694 static const struct msgstrtn_t {
7695 #define ICALL(id,name,func)
7697 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7698 #include "metadata/icall-def.h"
7700 } icall_type_names_str = {
7701 #define ICALL_TYPE(id,name,first) (name),
7702 #include "metadata/icall-def.h"
7705 static const guint16 icall_type_names_idx [] = {
7706 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7707 #include "metadata/icall-def.h"
7710 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7712 static const struct msgstr_t {
7714 #define ICALL_TYPE(id,name,first)
7715 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7716 #include "metadata/icall-def.h"
7718 } icall_names_str = {
7719 #define ICALL(id,name,func) (name),
7720 #include "metadata/icall-def.h"
7723 static const guint16 icall_names_idx [] = {
7724 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7725 #include "metadata/icall-def.h"
7728 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7734 #define ICALL_TYPE(id,name,first) name,
7735 #define ICALL(id,name,func)
7736 static const char* const
7737 icall_type_names [] = {
7738 #include "metadata/icall-def.h"
7742 #define icall_type_name_get(id) (icall_type_names [(id)])
7746 #define ICALL_TYPE(id,name,first)
7747 #define ICALL(id,name,func) name,
7748 static const char* const
7750 #include "metadata/icall-def.h"
7753 #define icall_name_get(id) icall_names [(id)]
7755 #endif /* !HAVE_ARRAY_ELEM_INIT */
7759 #define ICALL_TYPE(id,name,first)
7760 #define ICALL(id,name,func) func,
7761 static const gconstpointer
7762 icall_functions [] = {
7763 #include "metadata/icall-def.h"
7767 static GHashTable *icall_hash = NULL;
7768 static GHashTable *jit_icall_hash_name = NULL;
7769 static GHashTable *jit_icall_hash_addr = NULL;
7772 mono_icall_init (void)
7776 /* check that tables are sorted: disable in release */
7779 const char *prev_class = NULL;
7780 const char *prev_method;
7782 for (i = 0; i < Icall_type_num; ++i) {
7783 const IcallTypeDesc *desc;
7786 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7787 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7788 prev_class = icall_type_name_get (i);
7789 desc = &icall_type_descs [i];
7790 num_icalls = icall_desc_num_icalls (desc);
7791 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7792 for (j = 0; j < num_icalls; ++j) {
7793 const char *methodn = icall_name_get (desc->first_icall + j);
7794 if (prev_method && strcmp (prev_method, methodn) >= 0)
7795 g_print ("method %s should come before method %s\n", methodn, prev_method);
7796 prev_method = methodn;
7801 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7805 mono_icall_cleanup (void)
7807 g_hash_table_destroy (icall_hash);
7808 g_hash_table_destroy (jit_icall_hash_name);
7809 g_hash_table_destroy (jit_icall_hash_addr);
7813 mono_add_internal_call (const char *name, gconstpointer method)
7815 mono_loader_lock ();
7817 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7819 mono_loader_unlock ();
7822 #ifdef HAVE_ARRAY_ELEM_INIT
7824 compare_method_imap (const void *key, const void *elem)
7826 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7827 return strcmp (key, method_name);
7831 find_method_icall (const IcallTypeDesc *imap, const char *name)
7833 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7836 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7840 compare_class_imap (const void *key, const void *elem)
7842 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7843 return strcmp (key, class_name);
7846 static const IcallTypeDesc*
7847 find_class_icalls (const char *name)
7849 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7852 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7857 compare_method_imap (const void *key, const void *elem)
7859 const char** method_name = (const char**)elem;
7860 return strcmp (key, *method_name);
7864 find_method_icall (const IcallTypeDesc *imap, const char *name)
7866 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7869 return (gpointer)icall_functions [(nameslot - icall_names)];
7873 compare_class_imap (const void *key, const void *elem)
7875 const char** class_name = (const char**)elem;
7876 return strcmp (key, *class_name);
7879 static const IcallTypeDesc*
7880 find_class_icalls (const char *name)
7882 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7885 return &icall_type_descs [nameslot - icall_type_names];
7891 * we should probably export this as an helper (handle nested types).
7892 * Returns the number of chars written in buf.
7895 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7897 int nspacelen, cnamelen;
7898 nspacelen = strlen (klass->name_space);
7899 cnamelen = strlen (klass->name);
7900 if (nspacelen + cnamelen + 2 > bufsize)
7903 memcpy (buf, klass->name_space, nspacelen);
7904 buf [nspacelen ++] = '.';
7906 memcpy (buf + nspacelen, klass->name, cnamelen);
7907 buf [nspacelen + cnamelen] = 0;
7908 return nspacelen + cnamelen;
7912 mono_lookup_internal_call (MonoMethod *method)
7917 int typelen = 0, mlen, siglen;
7919 const IcallTypeDesc *imap;
7921 g_assert (method != NULL);
7923 if (method->is_inflated)
7924 method = ((MonoMethodInflated *) method)->declaring;
7926 if (method->klass->nested_in) {
7927 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7931 mname [pos++] = '/';
7934 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7940 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7945 imap = find_class_icalls (mname);
7947 mname [typelen] = ':';
7948 mname [typelen + 1] = ':';
7950 mlen = strlen (method->name);
7951 memcpy (mname + typelen + 2, method->name, mlen);
7952 sigstart = mname + typelen + 2 + mlen;
7955 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7956 siglen = strlen (tmpsig);
7957 if (typelen + mlen + siglen + 6 > sizeof (mname))
7960 memcpy (sigstart + 1, tmpsig, siglen);
7961 sigstart [siglen + 1] = ')';
7962 sigstart [siglen + 2] = 0;
7965 mono_loader_lock ();
7967 res = g_hash_table_lookup (icall_hash, mname);
7969 mono_loader_unlock ();
7972 /* try without signature */
7974 res = g_hash_table_lookup (icall_hash, mname);
7976 mono_loader_unlock ();
7980 /* it wasn't found in the static call tables */
7982 mono_loader_unlock ();
7985 res = find_method_icall (imap, sigstart - mlen);
7987 mono_loader_unlock ();
7990 /* try _with_ signature */
7992 res = find_method_icall (imap, sigstart - mlen);
7994 mono_loader_unlock ();
7998 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7999 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8000 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8001 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8002 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");
8003 g_print ("If you see other errors or faults after this message they are probably related\n");
8004 g_print ("and you need to fix your mono install first.\n");
8006 mono_loader_unlock ();
8012 type_from_typename (char *typename)
8014 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8016 if (!strcmp (typename, "int"))
8017 klass = mono_defaults.int_class;
8018 else if (!strcmp (typename, "ptr"))
8019 klass = mono_defaults.int_class;
8020 else if (!strcmp (typename, "void"))
8021 klass = mono_defaults.void_class;
8022 else if (!strcmp (typename, "int32"))
8023 klass = mono_defaults.int32_class;
8024 else if (!strcmp (typename, "uint32"))
8025 klass = mono_defaults.uint32_class;
8026 else if (!strcmp (typename, "int8"))
8027 klass = mono_defaults.sbyte_class;
8028 else if (!strcmp (typename, "uint8"))
8029 klass = mono_defaults.byte_class;
8030 else if (!strcmp (typename, "int16"))
8031 klass = mono_defaults.int16_class;
8032 else if (!strcmp (typename, "uint16"))
8033 klass = mono_defaults.uint16_class;
8034 else if (!strcmp (typename, "long"))
8035 klass = mono_defaults.int64_class;
8036 else if (!strcmp (typename, "ulong"))
8037 klass = mono_defaults.uint64_class;
8038 else if (!strcmp (typename, "float"))
8039 klass = mono_defaults.single_class;
8040 else if (!strcmp (typename, "double"))
8041 klass = mono_defaults.double_class;
8042 else if (!strcmp (typename, "object"))
8043 klass = mono_defaults.object_class;
8044 else if (!strcmp (typename, "obj"))
8045 klass = mono_defaults.object_class;
8046 else if (!strcmp (typename, "string"))
8047 klass = mono_defaults.string_class;
8048 else if (!strcmp (typename, "bool"))
8049 klass = mono_defaults.boolean_class;
8050 else if (!strcmp (typename, "boolean"))
8051 klass = mono_defaults.boolean_class;
8053 g_error ("%s", typename);
8054 g_assert_not_reached ();
8056 return &klass->byval_arg;
8059 MonoMethodSignature*
8060 mono_create_icall_signature (const char *sigstr)
8065 MonoMethodSignature *res;
8067 mono_loader_lock ();
8068 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8070 mono_loader_unlock ();
8074 parts = g_strsplit (sigstr, " ", 256);
8083 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8088 * Under windows, the default pinvoke calling convention is STDCALL but
8091 res->call_convention = MONO_CALL_C;
8094 res->ret = type_from_typename (parts [0]);
8095 for (i = 1; i < len; ++i) {
8096 res->params [i - 1] = type_from_typename (parts [i]);
8101 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8103 mono_loader_unlock ();
8109 mono_find_jit_icall_by_name (const char *name)
8111 MonoJitICallInfo *info;
8112 g_assert (jit_icall_hash_name);
8114 mono_loader_lock ();
8115 info = g_hash_table_lookup (jit_icall_hash_name, name);
8116 mono_loader_unlock ();
8121 mono_find_jit_icall_by_addr (gconstpointer addr)
8123 MonoJitICallInfo *info;
8124 g_assert (jit_icall_hash_addr);
8126 mono_loader_lock ();
8127 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8128 mono_loader_unlock ();
8134 * mono_get_jit_icall_info:
8136 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8137 * caller should access it while holding the loader lock.
8140 mono_get_jit_icall_info (void)
8142 return jit_icall_hash_name;
8146 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8148 mono_loader_lock ();
8149 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8150 mono_loader_unlock ();
8154 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8156 MonoJitICallInfo *info;
8161 mono_loader_lock ();
8163 if (!jit_icall_hash_name) {
8164 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8165 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8168 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8169 g_warning ("jit icall already defined \"%s\"\n", name);
8170 g_assert_not_reached ();
8173 info = g_new0 (MonoJitICallInfo, 1);
8180 info->wrapper = func;
8182 info->wrapper = NULL;
8185 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8186 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8188 mono_loader_unlock ();