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 (PLATFORM_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/io-layer/io-layer.h>
71 #include <mono/utils/strtod.h>
72 #include <mono/utils/monobitset.h>
73 #include <mono/utils/mono-time.h>
74 #include <mono/utils/mono-proclib.h>
76 #if defined (PLATFORM_WIN32)
82 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
85 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
87 static inline MonoBoolean
88 is_generic_parameter (MonoType *type)
90 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
94 * We expect a pointer to a char, not a string
97 mono_double_ParseImpl (char *ptr, double *result)
106 *result = strtod (ptr, &endptr);
110 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
111 EnterCriticalSection (&mono_strtod_mutex);
112 *result = mono_strtod (ptr, &endptr);
113 LeaveCriticalSection (&mono_strtod_mutex);
115 *result = mono_strtod (ptr, &endptr);
120 if (!*ptr || (endptr && *endptr))
127 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
136 ao = (MonoArray *)this;
137 ac = (MonoClass *)ao->obj.vtable->klass;
139 esize = mono_array_element_size (ac);
140 ea = (gpointer*)((char*)ao->vector + (pos * esize));
142 if (ac->element_class->valuetype)
143 return mono_value_box (this->vtable->domain, ac->element_class, ea);
149 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
157 MONO_CHECK_ARG_NULL (idxs);
159 io = (MonoArray *)idxs;
160 ic = (MonoClass *)io->obj.vtable->klass;
162 ao = (MonoArray *)this;
163 ac = (MonoClass *)ao->obj.vtable->klass;
165 g_assert (ic->rank == 1);
166 if (io->bounds != NULL || io->max_length != ac->rank)
167 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
169 ind = (gint32 *)io->vector;
171 if (ao->bounds == NULL) {
172 if (*ind < 0 || *ind >= ao->max_length)
173 mono_raise_exception (mono_get_exception_index_out_of_range ());
175 return ves_icall_System_Array_GetValueImpl (this, *ind);
178 for (i = 0; i < ac->rank; i++)
179 if ((ind [i] < ao->bounds [i].lower_bound) ||
180 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
181 mono_raise_exception (mono_get_exception_index_out_of_range ());
183 pos = ind [0] - ao->bounds [0].lower_bound;
184 for (i = 1; i < ac->rank; i++)
185 pos = pos*ao->bounds [i].length + ind [i] -
186 ao->bounds [i].lower_bound;
188 return ves_icall_System_Array_GetValueImpl (this, pos);
192 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
194 MonoClass *ac, *vc, *ec;
206 vc = value->vtable->klass;
210 ac = this->obj.vtable->klass;
211 ec = ac->element_class;
213 esize = mono_array_element_size (ac);
214 ea = (gpointer*)((char*)this->vector + (pos * esize));
215 va = (gpointer*)((char*)value + sizeof (MonoObject));
218 memset (ea, 0, esize);
222 #define NO_WIDENING_CONVERSION G_STMT_START{\
223 mono_raise_exception (mono_get_exception_argument ( \
224 "value", "not a widening conversion")); \
227 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
228 if (esize < vsize + (extra)) \
229 mono_raise_exception (mono_get_exception_argument ( \
230 "value", "not a widening conversion")); \
233 #define INVALID_CAST G_STMT_START{\
234 mono_raise_exception (mono_get_exception_invalid_cast ()); \
237 /* Check element (destination) type. */
238 switch (ec->byval_arg.type) {
239 case MONO_TYPE_STRING:
240 switch (vc->byval_arg.type) {
241 case MONO_TYPE_STRING:
247 case MONO_TYPE_BOOLEAN:
248 switch (vc->byval_arg.type) {
249 case MONO_TYPE_BOOLEAN:
262 NO_WIDENING_CONVERSION;
269 if (!ec->valuetype) {
270 if (!mono_object_isinst (value, ec))
272 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
276 if (mono_object_isinst (value, ec)) {
277 if (ec->has_references)
278 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
280 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
287 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
289 et = ec->byval_arg.type;
290 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
291 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
293 vt = vc->byval_arg.type;
294 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
295 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
297 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
303 case MONO_TYPE_CHAR: \
304 CHECK_WIDENING_CONVERSION(0); \
305 *(etype *) ea = (etype) u64; \
307 /* You can't assign a signed value to an unsigned array. */ \
312 /* You can't assign a floating point number to an integer array. */ \
315 NO_WIDENING_CONVERSION; \
319 #define ASSIGN_SIGNED(etype) G_STMT_START{\
325 CHECK_WIDENING_CONVERSION(0); \
326 *(etype *) ea = (etype) i64; \
328 /* You can assign an unsigned value to a signed array if the array's */ \
329 /* element size is larger than the value size. */ \
334 case MONO_TYPE_CHAR: \
335 CHECK_WIDENING_CONVERSION(1); \
336 *(etype *) ea = (etype) u64; \
338 /* You can't assign a floating point number to an integer array. */ \
341 NO_WIDENING_CONVERSION; \
345 #define ASSIGN_REAL(etype) G_STMT_START{\
349 CHECK_WIDENING_CONVERSION(0); \
350 *(etype *) ea = (etype) r64; \
352 /* All integer values fit into a floating point array, so we don't */ \
353 /* need to CHECK_WIDENING_CONVERSION here. */ \
358 *(etype *) ea = (etype) i64; \
364 case MONO_TYPE_CHAR: \
365 *(etype *) ea = (etype) u64; \
372 u64 = *(guint8 *) va;
375 u64 = *(guint16 *) va;
378 u64 = *(guint32 *) va;
381 u64 = *(guint64 *) va;
387 i64 = *(gint16 *) va;
390 i64 = *(gint32 *) va;
393 i64 = *(gint64 *) va;
396 r64 = *(gfloat *) va;
399 r64 = *(gdouble *) va;
402 u64 = *(guint16 *) va;
404 case MONO_TYPE_BOOLEAN:
405 /* Boolean is only compatible with itself. */
418 NO_WIDENING_CONVERSION;
425 /* If we can't do a direct copy, let's try a widening conversion. */
428 ASSIGN_UNSIGNED (guint16);
430 ASSIGN_UNSIGNED (guint8);
432 ASSIGN_UNSIGNED (guint16);
434 ASSIGN_UNSIGNED (guint32);
436 ASSIGN_UNSIGNED (guint64);
438 ASSIGN_SIGNED (gint8);
440 ASSIGN_SIGNED (gint16);
442 ASSIGN_SIGNED (gint32);
444 ASSIGN_SIGNED (gint64);
446 ASSIGN_REAL (gfloat);
448 ASSIGN_REAL (gdouble);
452 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
456 #undef NO_WIDENING_CONVERSION
457 #undef CHECK_WIDENING_CONVERSION
458 #undef ASSIGN_UNSIGNED
464 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
472 MONO_CHECK_ARG_NULL (idxs);
474 ic = idxs->obj.vtable->klass;
475 ac = this->obj.vtable->klass;
477 g_assert (ic->rank == 1);
478 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
479 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
481 ind = (gint32 *)idxs->vector;
483 if (this->bounds == NULL) {
484 if (*ind < 0 || *ind >= this->max_length)
485 mono_raise_exception (mono_get_exception_index_out_of_range ());
487 ves_icall_System_Array_SetValueImpl (this, value, *ind);
491 for (i = 0; i < ac->rank; i++)
492 if ((ind [i] < this->bounds [i].lower_bound) ||
493 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
494 mono_raise_exception (mono_get_exception_index_out_of_range ());
496 pos = ind [0] - this->bounds [0].lower_bound;
497 for (i = 1; i < ac->rank; i++)
498 pos = pos * this->bounds [i].length + ind [i] -
499 this->bounds [i].lower_bound;
501 ves_icall_System_Array_SetValueImpl (this, value, pos);
505 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
509 mono_array_size_t *sizes, i;
510 gboolean bounded = FALSE;
514 MONO_CHECK_ARG_NULL (type);
515 MONO_CHECK_ARG_NULL (lengths);
517 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
519 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
521 for (i = 0; i < mono_array_length (lengths); i++)
522 if (mono_array_get (lengths, gint32, i) < 0)
523 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
525 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
526 /* vectors are not the same as one dimensional arrays with no-zero bounds */
531 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
533 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
534 for (i = 0; i < aklass->rank; ++i) {
535 sizes [i] = mono_array_get (lengths, guint32, i);
537 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
539 sizes [i + aklass->rank] = 0;
542 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
548 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
552 mono_array_size_t *sizes, i;
553 gboolean bounded = FALSE;
557 MONO_CHECK_ARG_NULL (type);
558 MONO_CHECK_ARG_NULL (lengths);
560 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
562 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
564 for (i = 0; i < mono_array_length (lengths); i++)
565 if ((mono_array_get (lengths, gint64, i) < 0) ||
566 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
567 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
569 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
570 /* vectors are not the same as one dimensional arrays with no-zero bounds */
575 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
577 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
578 for (i = 0; i < aklass->rank; ++i) {
579 sizes [i] = mono_array_get (lengths, guint64, i);
581 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
583 sizes [i + aklass->rank] = 0;
586 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
592 ves_icall_System_Array_GetRank (MonoObject *this)
596 return this->vtable->klass->rank;
600 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
602 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
603 mono_array_size_t length;
607 if ((dimension < 0) || (dimension >= rank))
608 mono_raise_exception (mono_get_exception_index_out_of_range ());
610 if (this->bounds == NULL)
611 length = this->max_length;
613 length = this->bounds [dimension].length;
615 #ifdef MONO_BIG_ARRAYS
616 if (length > G_MAXINT32)
617 mono_raise_exception (mono_get_exception_overflow ());
623 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
625 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
629 if ((dimension < 0) || (dimension >= rank))
630 mono_raise_exception (mono_get_exception_index_out_of_range ());
632 if (this->bounds == NULL)
633 return this->max_length;
635 return this->bounds [dimension].length;
639 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
641 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
645 if ((dimension < 0) || (dimension >= rank))
646 mono_raise_exception (mono_get_exception_index_out_of_range ());
648 if (this->bounds == NULL)
651 return this->bounds [dimension].lower_bound;
655 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
657 int sz = mono_array_element_size (mono_object_class (arr));
658 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
662 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
667 MonoClass *src_class;
668 MonoClass *dest_class;
673 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
676 if (source->bounds || dest->bounds)
679 if ((dest_idx + length > mono_array_length (dest)) ||
680 (source_idx + length > mono_array_length (source)))
683 src_class = source->obj.vtable->klass->element_class;
684 dest_class = dest->obj.vtable->klass->element_class;
687 * Handle common cases.
690 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
691 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
692 int has_refs = dest_class->has_references;
693 for (i = source_idx; i < source_idx + length; ++i) {
694 MonoObject *elem = mono_array_get (source, MonoObject*, i);
695 if (elem && !mono_object_isinst (elem, dest_class))
699 element_size = mono_array_element_size (dest->obj.vtable->klass);
700 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
701 for (i = 0; i < length; ++i) {
702 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
703 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
707 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
709 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
714 /* Check if we're copying a char[] <==> (u)short[] */
715 if (src_class != dest_class) {
716 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
719 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
721 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
722 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
723 for (i = source_idx; i < source_idx + length; ++i) {
724 MonoObject *elem = mono_array_get (source, MonoObject*, i);
725 if (elem && !mono_object_isinst (elem, dest_class))
732 if (dest_class->valuetype) {
733 element_size = mono_array_element_size (source->obj.vtable->klass);
734 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
735 if (dest_class->has_references) {
736 mono_value_copy_array (dest, dest_idx, source_addr, length);
738 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
739 memmove (dest_addr, source_addr, element_size * length);
742 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
749 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
758 ao = (MonoArray *)this;
759 ac = (MonoClass *)ao->obj.vtable->klass;
761 esize = mono_array_element_size (ac);
762 ea = (gpointer*)((char*)ao->vector + (pos * esize));
764 memcpy (value, ea, esize);
768 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
777 ao = (MonoArray *)this;
778 ac = (MonoClass *)ao->obj.vtable->klass;
780 esize = mono_array_element_size (ac);
781 ea = (gpointer*)((char*)ao->vector + (pos * esize));
783 memcpy (ea, value, esize);
787 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
789 MonoClass *klass = array->obj.vtable->klass;
790 guint32 size = mono_array_element_size (klass);
791 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
793 const char *field_data;
795 if (MONO_TYPE_IS_REFERENCE (type) ||
796 (type->type == MONO_TYPE_VALUETYPE &&
797 (!mono_type_get_class (type) ||
798 mono_type_get_class (type)->has_references))) {
799 MonoException *exc = mono_get_exception_argument("array",
800 "Cannot initialize array containing references");
801 mono_raise_exception (exc);
804 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
805 MonoException *exc = mono_get_exception_argument("field_handle",
806 "Field doesn't have an RVA");
807 mono_raise_exception (exc);
810 size *= array->max_length;
811 field_data = mono_field_get_data (field_handle);
813 if (size > mono_type_size (field_handle->type, &align)) {
814 MonoException *exc = mono_get_exception_argument("field_handle",
815 "Field not large enough to fill array");
816 mono_raise_exception (exc);
819 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
821 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
822 guint ## n *src = (guint ## n *) field_data; \
823 guint ## n *end = (guint ## n *)((char*)src + size); \
825 for (; src < end; data++, src++) { \
826 *data = read ## n (src); \
830 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
832 switch (type->type) {
849 memcpy (mono_array_addr (array, char, 0), field_data, size);
853 memcpy (mono_array_addr (array, char, 0), field_data, size);
855 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
858 double *data = (double*)mono_array_addr (array, double, 0);
860 for (i = 0; i < size; i++, data++) {
870 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
874 return offsetof (MonoString, chars);
878 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
882 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
885 return mono_object_clone (obj);
889 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
895 MONO_CHECK_ARG_NULL (handle);
897 klass = mono_class_from_mono_type (handle);
898 MONO_CHECK_ARG (handle, klass);
900 /* This will call the type constructor */
901 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
905 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
909 mono_image_check_for_module_cctor (image);
910 if (image->has_module_cctor) {
911 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
912 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), module_klass));
917 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
921 return mono_object_clone (this);
925 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
928 MonoObject **values = NULL;
932 MonoClassField* field;
937 klass = mono_object_class (this);
939 if (mono_class_num_fields (klass) == 0)
940 return mono_object_hash (this);
943 * Compute the starting value of the hashcode for fields of primitive
944 * types, and return the remaining fields in an array to the managed side.
945 * This way, we can avoid costly reflection operations in managed code.
948 while ((field = mono_class_get_fields (klass, &iter))) {
949 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
951 if (mono_field_is_deleted (field))
953 /* FIXME: Add more types */
954 switch (field->type->type) {
956 result ^= *(gint32*)((guint8*)this + field->offset);
958 case MONO_TYPE_STRING: {
960 s = *(MonoString**)((guint8*)this + field->offset);
962 result ^= mono_string_hash (s);
967 values = g_newa (MonoObject*, mono_class_num_fields (klass));
968 o = mono_field_get_value_object (mono_object_domain (this), field, this);
969 values [count++] = o;
975 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
976 for (i = 0; i < count; ++i)
977 mono_array_setref (*fields, i, values [i]);
985 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
988 MonoObject **values = NULL;
990 MonoClassField* field;
996 MONO_CHECK_ARG_NULL (that);
998 if (this->vtable != that->vtable)
1001 klass = mono_object_class (this);
1003 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1004 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1007 * Do the comparison for fields of primitive type and return a result if
1008 * possible. Otherwise, return the remaining fields in an array to the
1009 * managed side. This way, we can avoid costly reflection operations in
1014 while ((field = mono_class_get_fields (klass, &iter))) {
1015 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1017 if (mono_field_is_deleted (field))
1019 /* FIXME: Add more types */
1020 switch (field->type->type) {
1023 case MONO_TYPE_BOOLEAN:
1024 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1029 case MONO_TYPE_CHAR:
1030 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1035 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1040 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1044 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1048 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1053 case MONO_TYPE_STRING: {
1054 MonoString *s1, *s2;
1055 guint32 s1len, s2len;
1056 s1 = *(MonoString**)((guint8*)this + field->offset);
1057 s2 = *(MonoString**)((guint8*)that + field->offset);
1060 if ((s1 == NULL) || (s2 == NULL))
1062 s1len = mono_string_length (s1);
1063 s2len = mono_string_length (s2);
1067 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1073 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1074 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1075 values [count++] = o;
1076 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1077 values [count++] = o;
1080 if (klass->enumtype)
1081 /* enums only have one non-static field */
1087 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
1088 for (i = 0; i < count; ++i)
1089 mono_array_setref (*fields, i, values [i]);
1096 static MonoReflectionType *
1097 ves_icall_System_Object_GetType (MonoObject *obj)
1099 MONO_ARCH_SAVE_REGS;
1101 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1102 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1104 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1108 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1110 MONO_ARCH_SAVE_REGS;
1112 mtype->type = &obj->vtable->klass->byval_arg;
1113 g_assert (mtype->type->type);
1117 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1119 MONO_ARCH_SAVE_REGS;
1121 MONO_CHECK_ARG_NULL (obj);
1123 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1127 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1128 MonoReflectionMethod *method,
1129 MonoArray *opt_param_types)
1131 MONO_ARCH_SAVE_REGS;
1133 MONO_CHECK_ARG_NULL (method);
1135 return mono_image_create_method_token (
1136 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1140 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1142 MONO_ARCH_SAVE_REGS;
1144 mono_image_create_pefile (mb, file);
1148 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1150 MONO_ARCH_SAVE_REGS;
1152 mono_image_build_metadata (mb);
1156 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1158 MONO_ARCH_SAVE_REGS;
1160 mono_image_register_token (mb->dynamic_image, token, obj);
1164 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1166 MonoMethod **dest = data;
1168 /* skip unmanaged frames */
1184 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1186 MonoMethod **dest = data;
1188 /* skip unmanaged frames */
1193 if (!strcmp (m->klass->name_space, "System.Reflection"))
1202 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1204 MonoMethod **dest = data;
1206 /* skip unmanaged frames */
1210 if (m->wrapper_type != MONO_WRAPPER_NONE)
1213 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1227 static MonoReflectionType *
1228 type_from_name (const char *str, MonoBoolean ignoreCase)
1230 MonoType *type = NULL;
1231 MonoAssembly *assembly = NULL;
1232 MonoTypeNameParse info;
1233 char *temp_str = g_strdup (str);
1234 gboolean type_resolve = FALSE;
1236 MONO_ARCH_SAVE_REGS;
1238 /* mono_reflection_parse_type() mangles the string */
1239 if (!mono_reflection_parse_type (temp_str, &info)) {
1240 mono_reflection_free_type_info (&info);
1245 if (info.assembly.name) {
1246 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1248 MonoMethod *m = mono_method_get_last_managed ();
1249 MonoMethod *dest = m;
1251 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1256 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1257 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1258 * to crash. This only seems to happen in some strange remoting
1259 * scenarios and I was unable to figure out what's happening there.
1260 * Dec 10, 2005 - Martin.
1264 assembly = dest->klass->image->assembly;
1266 g_warning (G_STRLOC);
1271 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1273 if (!info.assembly.name && !type) /* try mscorlib */
1274 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1276 mono_reflection_free_type_info (&info);
1282 return mono_type_get_object (mono_domain_get (), type);
1286 MonoReflectionType *
1287 mono_type_get (const char *str)
1289 char *copy = g_strdup (str);
1290 MonoReflectionType *type = type_from_name (copy, FALSE);
1297 static MonoReflectionType*
1298 ves_icall_type_from_name (MonoString *name,
1299 MonoBoolean throwOnError,
1300 MonoBoolean ignoreCase)
1302 char *str = mono_string_to_utf8 (name);
1303 MonoReflectionType *type;
1305 type = type_from_name (str, ignoreCase);
1308 MonoException *e = NULL;
1311 e = mono_get_exception_type_load (name, NULL);
1313 mono_loader_clear_error ();
1315 mono_raise_exception (e);
1322 static MonoReflectionType*
1323 ves_icall_type_from_handle (MonoType *handle)
1325 MonoDomain *domain = mono_domain_get ();
1326 MonoClass *klass = mono_class_from_mono_type (handle);
1328 MONO_ARCH_SAVE_REGS;
1330 mono_class_init (klass);
1331 return mono_type_get_object (domain, handle);
1335 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1337 MONO_ARCH_SAVE_REGS;
1339 if (c && type->type && c->type)
1340 return mono_metadata_type_equal (type->type, c->type);
1342 return (type == c) ? TRUE : FALSE;
1345 /* System.TypeCode */
1364 TYPECODE_STRING = 18
1368 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1370 int t = type->type->type;
1372 MONO_ARCH_SAVE_REGS;
1374 if (type->type->byref)
1375 return TYPECODE_OBJECT;
1379 case MONO_TYPE_VOID:
1380 return TYPECODE_OBJECT;
1381 case MONO_TYPE_BOOLEAN:
1382 return TYPECODE_BOOLEAN;
1384 return TYPECODE_BYTE;
1386 return TYPECODE_SBYTE;
1388 return TYPECODE_UINT16;
1390 return TYPECODE_INT16;
1391 case MONO_TYPE_CHAR:
1392 return TYPECODE_CHAR;
1396 return TYPECODE_OBJECT;
1398 return TYPECODE_UINT32;
1400 return TYPECODE_INT32;
1402 return TYPECODE_UINT64;
1404 return TYPECODE_INT64;
1406 return TYPECODE_SINGLE;
1408 return TYPECODE_DOUBLE;
1409 case MONO_TYPE_VALUETYPE:
1410 if (type->type->data.klass->enumtype) {
1411 t = mono_class_enum_basetype (type->type->data.klass)->type;
1414 MonoClass *k = type->type->data.klass;
1415 if (strcmp (k->name_space, "System") == 0) {
1416 if (strcmp (k->name, "Decimal") == 0)
1417 return TYPECODE_DECIMAL;
1418 else if (strcmp (k->name, "DateTime") == 0)
1419 return TYPECODE_DATETIME;
1422 return TYPECODE_OBJECT;
1423 case MONO_TYPE_STRING:
1424 return TYPECODE_STRING;
1425 case MONO_TYPE_SZARRAY:
1426 case MONO_TYPE_ARRAY:
1427 case MONO_TYPE_OBJECT:
1429 case MONO_TYPE_MVAR:
1430 case MONO_TYPE_TYPEDBYREF:
1431 return TYPECODE_OBJECT;
1432 case MONO_TYPE_CLASS:
1434 MonoClass *k = type->type->data.klass;
1435 if (strcmp (k->name_space, "System") == 0) {
1436 if (strcmp (k->name, "DBNull") == 0)
1437 return TYPECODE_DBNULL;
1440 return TYPECODE_OBJECT;
1441 case MONO_TYPE_GENERICINST:
1442 return TYPECODE_OBJECT;
1444 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1450 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1456 MONO_ARCH_SAVE_REGS;
1458 g_assert (type != NULL);
1460 domain = ((MonoObject *)type)->vtable->domain;
1462 if (!c) /* FIXME: dont know what do do here */
1465 klass = mono_class_from_mono_type (type->type);
1466 klassc = mono_class_from_mono_type (c->type);
1468 if (type->type->byref)
1469 return klassc == mono_defaults.object_class;
1471 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1475 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1481 MONO_ARCH_SAVE_REGS;
1483 g_assert (type != NULL);
1485 domain = ((MonoObject *)type)->vtable->domain;
1487 klass = mono_class_from_mono_type (type->type);
1488 klassc = mono_class_from_mono_type (c->type);
1490 if (type->type->byref && !c->type->byref)
1493 return mono_class_is_assignable_from (klass, klassc);
1497 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1499 MonoClass *klass = mono_class_from_mono_type (type->type);
1500 return mono_object_isinst (obj, klass) != NULL;
1504 ves_icall_get_attributes (MonoReflectionType *type)
1506 MonoClass *klass = mono_class_from_mono_type (type->type);
1508 MONO_ARCH_SAVE_REGS;
1510 return klass->flags;
1513 static MonoReflectionMarshal*
1514 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1516 MonoClass *klass = field->field->parent;
1517 MonoMarshalType *info;
1520 if (klass->generic_container ||
1521 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1524 info = mono_marshal_load_type_info (klass);
1526 for (i = 0; i < info->num_fields; ++i) {
1527 if (info->fields [i].field == field->field) {
1528 if (!info->fields [i].mspec)
1531 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1538 static MonoReflectionField*
1539 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoClass *klass)
1544 klass = handle->parent;
1546 /* FIXME: check that handle is a field of klass or of a parent: return null
1547 * and throw the exception in managed code.
1549 return mono_field_get_object (mono_domain_get (), klass, handle);
1552 static MonoReflectionField*
1553 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1555 MONO_ARCH_SAVE_REGS;
1559 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1563 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1565 MonoType *type = field->field->type;
1567 return type_array_from_modifiers (field->field->parent->image, type, optional);
1571 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1573 MonoDomain *domain = mono_domain_get ();
1574 MonoMethodSignature* sig;
1575 MONO_ARCH_SAVE_REGS;
1577 sig = mono_method_signature (method);
1579 g_assert (mono_loader_get_last_error ());
1580 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1583 info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
1584 info->ret = mono_type_get_object (domain, sig->ret);
1585 info->attrs = method->flags;
1586 info->implattrs = method->iflags;
1587 if (sig->call_convention == MONO_CALL_DEFAULT)
1588 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1590 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1595 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1599 ves_icall_get_parameter_info (MonoMethod *method)
1601 MonoDomain *domain = mono_domain_get ();
1603 return mono_param_get_objects (domain, method);
1606 static MonoReflectionMarshal*
1607 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1609 MonoDomain *domain = mono_domain_get ();
1610 MonoReflectionMarshal* res = NULL;
1611 MonoMarshalSpec **mspecs;
1614 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1615 mono_method_get_marshal_info (method, mspecs);
1618 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1620 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1622 mono_metadata_free_marshal_spec (mspecs [i]);
1629 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1631 return field->field->offset - sizeof (MonoObject);
1634 static MonoReflectionType*
1635 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1638 MONO_ARCH_SAVE_REGS;
1640 parent = declaring? field->field->parent: field->klass;
1642 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1646 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1649 MonoClassField *cf = field->field;
1653 MonoDomain *domain = mono_object_domain (field);
1655 gboolean is_static = FALSE;
1656 gboolean is_ref = FALSE;
1658 MONO_ARCH_SAVE_REGS;
1660 if (field->klass->image->assembly->ref_only)
1661 mono_raise_exception (mono_get_exception_invalid_operation (
1662 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1664 mono_class_init (field->klass);
1666 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1669 if (obj && !is_static) {
1670 /* Check that the field belongs to the object */
1671 gboolean found = FALSE;
1674 for (k = obj->vtable->klass; k; k = k->parent) {
1675 if (k == cf->parent) {
1682 char *msg = g_strdup_printf ("Field '%s' defined on type '%s' is not a field on the target object which is of type '%s'.", mono_field_get_name (cf), cf->parent->name, obj->vtable->klass->name);
1683 MonoException *ex = mono_get_exception_argument (NULL, msg);
1685 mono_raise_exception (ex);
1689 t = mono_type_get_underlying_type (cf->type);
1691 case MONO_TYPE_STRING:
1692 case MONO_TYPE_OBJECT:
1693 case MONO_TYPE_CLASS:
1694 case MONO_TYPE_ARRAY:
1695 case MONO_TYPE_SZARRAY:
1700 case MONO_TYPE_BOOLEAN:
1703 case MONO_TYPE_CHAR:
1712 case MONO_TYPE_VALUETYPE:
1715 case MONO_TYPE_GENERICINST:
1716 if (mono_type_generic_inst_is_valuetype (t)) {
1723 g_error ("type 0x%x not handled in "
1724 "ves_icall_Monofield_GetValue", t->type);
1730 vtable = mono_class_vtable (domain, cf->parent);
1731 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1732 mono_runtime_class_init (vtable);
1737 mono_field_static_get_value (vtable, cf, &o);
1739 mono_field_get_value (obj, cf, &o);
1744 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1745 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1748 /* Convert the Nullable structure into a boxed vtype */
1750 buf = (guint8*)vtable->data + cf->offset;
1752 buf = (guint8*)obj + cf->offset;
1754 return mono_nullable_box (buf, nklass);
1757 /* boxed value type */
1758 klass = mono_class_from_mono_type (cf->type);
1759 o = mono_object_new (domain, klass);
1760 v = ((gchar *) o) + sizeof (MonoObject);
1762 mono_field_static_get_value (vtable, cf, v);
1764 mono_field_get_value (obj, cf, v);
1771 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1773 MonoClassField *cf = field->field;
1776 MONO_ARCH_SAVE_REGS;
1778 if (field->klass->image->assembly->ref_only)
1779 mono_raise_exception (mono_get_exception_invalid_operation (
1780 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1782 v = (gchar *) value;
1783 if (!cf->type->byref) {
1784 switch (cf->type->type) {
1787 case MONO_TYPE_BOOLEAN:
1790 case MONO_TYPE_CHAR:
1799 case MONO_TYPE_VALUETYPE:
1801 v += sizeof (MonoObject);
1803 case MONO_TYPE_STRING:
1804 case MONO_TYPE_OBJECT:
1805 case MONO_TYPE_CLASS:
1806 case MONO_TYPE_ARRAY:
1807 case MONO_TYPE_SZARRAY:
1810 case MONO_TYPE_GENERICINST: {
1811 MonoGenericClass *gclass = cf->type->data.generic_class;
1812 g_assert (!gclass->context.class_inst->is_open);
1814 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1815 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1816 MonoObject *nullable;
1819 * Convert the boxed vtype into a Nullable structure.
1820 * This is complicated by the fact that Nullables have
1821 * a variable structure.
1823 nullable = mono_object_new (mono_domain_get (), nklass);
1825 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1827 v = mono_object_unbox (nullable);
1830 if (gclass->container_class->valuetype && (v != NULL))
1831 v += sizeof (MonoObject);
1835 g_error ("type 0x%x not handled in "
1836 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1841 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1842 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1843 if (!vtable->initialized)
1844 mono_runtime_class_init (vtable);
1845 mono_field_static_set_value (vtable, cf, v);
1847 mono_field_set_value (obj, cf, v);
1852 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1854 MonoObject *o = NULL;
1855 MonoClassField *field = this->field;
1857 MonoDomain *domain = mono_object_domain (this);
1859 MonoTypeEnum def_type;
1860 const char *def_value;
1862 MONO_ARCH_SAVE_REGS;
1864 mono_class_init (field->parent);
1866 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1867 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1869 if (field->parent->image->dynamic) {
1871 g_assert_not_reached ();
1874 def_value = mono_class_get_field_default_value (field, &def_type);
1879 case MONO_TYPE_BOOLEAN:
1882 case MONO_TYPE_CHAR:
1890 case MONO_TYPE_R8: {
1893 /* boxed value type */
1894 t = g_new0 (MonoType, 1);
1896 klass = mono_class_from_mono_type (t);
1898 o = mono_object_new (domain, klass);
1899 v = ((gchar *) o) + sizeof (MonoObject);
1900 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1903 case MONO_TYPE_STRING:
1904 case MONO_TYPE_CLASS:
1905 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1908 g_assert_not_reached ();
1914 static MonoReflectionType*
1915 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1917 MonoMethod *method = rmethod->method.method;
1919 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1922 /* From MonoProperty.cs */
1924 PInfo_Attributes = 1,
1925 PInfo_GetMethod = 1 << 1,
1926 PInfo_SetMethod = 1 << 2,
1927 PInfo_ReflectedType = 1 << 3,
1928 PInfo_DeclaringType = 1 << 4,
1933 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1935 MonoDomain *domain = mono_object_domain (property);
1937 MONO_ARCH_SAVE_REGS;
1939 if ((req_info & PInfo_ReflectedType) != 0)
1940 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1941 else if ((req_info & PInfo_DeclaringType) != 0)
1942 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1944 if ((req_info & PInfo_Name) != 0)
1945 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1947 if ((req_info & PInfo_Attributes) != 0)
1948 info->attrs = property->property->attrs;
1950 if ((req_info & PInfo_GetMethod) != 0)
1951 MONO_STRUCT_SETREF (info, get, property->property->get ?
1952 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1954 if ((req_info & PInfo_SetMethod) != 0)
1955 MONO_STRUCT_SETREF (info, set, property->property->set ?
1956 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1958 * There may be other methods defined for properties, though, it seems they are not exposed
1959 * in the reflection API
1964 ves_icall_get_event_info (MonoReflectionEvent *event, MonoEventInfo *info)
1966 MonoDomain *domain = mono_object_domain (event);
1968 MONO_ARCH_SAVE_REGS;
1970 info->reflected_type = mono_type_get_object (domain, &event->klass->byval_arg);
1971 info->declaring_type = mono_type_get_object (domain, &event->event->parent->byval_arg);
1973 info->name = mono_string_new (domain, event->event->name);
1974 info->attrs = event->event->attrs;
1975 info->add_method = event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL;
1976 info->remove_method = event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL;
1977 info->raise_method = event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL;
1979 if (event->event->other) {
1981 while (event->event->other [n])
1983 info->other_methods = mono_array_new (domain, mono_defaults.method_info_class, n);
1985 for (i = 0; i < n; i++)
1986 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
1991 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
1993 MonoDomain *domain = mono_object_domain (type);
1995 GPtrArray *ifaces = NULL;
1997 MonoClass *class = mono_class_from_mono_type (type->type);
2000 MonoGenericContext *context = NULL;
2002 MONO_ARCH_SAVE_REGS;
2004 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2005 context = mono_class_get_context (class);
2006 class = class->generic_class->container_class;
2009 mono_class_setup_vtable (class);
2011 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2013 for (parent = class; parent; parent = parent->parent) {
2014 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
2016 for (i = 0; i < tmp_ifaces->len; ++i) {
2017 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2019 if (mono_bitset_test (slots, ic->interface_id))
2022 mono_bitset_set (slots, ic->interface_id);
2024 ifaces = g_ptr_array_new ();
2025 g_ptr_array_add (ifaces, ic);
2027 g_ptr_array_free (tmp_ifaces, TRUE);
2030 mono_bitset_free (slots);
2033 return mono_array_new (domain, mono_defaults.monotype_class, 0);
2035 intf = mono_array_new (domain, mono_defaults.monotype_class, ifaces->len);
2036 for (i = 0; i < ifaces->len; ++i) {
2037 MonoClass *ic = g_ptr_array_index (ifaces, i);
2038 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2039 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2040 inflated = ret = mono_class_inflate_generic_type (ret, context);
2042 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2044 mono_metadata_free_type (inflated);
2046 g_ptr_array_free (ifaces, TRUE);
2052 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2054 MonoClass *class = mono_class_from_mono_type (type->type);
2055 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2056 MonoReflectionMethod *member;
2059 int i = 0, len, ioffset;
2062 MONO_ARCH_SAVE_REGS;
2064 mono_class_setup_vtable (class);
2066 /* type doesn't implement iface: the exception is thrown in managed code */
2067 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2070 len = mono_class_num_methods (iclass);
2071 ioffset = mono_class_interface_offset (class, iclass);
2072 domain = mono_object_domain (type);
2073 *targets = mono_array_new (domain, mono_defaults.method_info_class, len);
2074 *methods = mono_array_new (domain, mono_defaults.method_info_class, len);
2077 while ((method = mono_class_get_methods (iclass, &iter))) {
2078 member = mono_method_get_object (domain, method, iclass);
2079 mono_array_setref (*methods, i, member);
2080 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2081 mono_array_setref (*targets, i, member);
2088 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2090 MonoClass *klass = mono_class_from_mono_type (type->type);
2092 if (klass->image->dynamic) {
2093 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2094 *packing = tb->packing_size;
2095 *size = tb->class_size;
2097 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2101 static MonoReflectionType*
2102 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2104 MonoClass *class = mono_class_from_mono_type (type->type);
2106 MONO_ARCH_SAVE_REGS;
2108 // GetElementType should only return a type for:
2109 // Array Pointer PassedByRef
2110 if (type->type->byref)
2111 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2112 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2113 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2114 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2115 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2120 static MonoReflectionType*
2121 ves_icall_get_type_parent (MonoReflectionType *type)
2123 MonoClass *class = mono_class_from_mono_type (type->type);
2125 MONO_ARCH_SAVE_REGS;
2127 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2131 ves_icall_type_ispointer (MonoReflectionType *type)
2133 MONO_ARCH_SAVE_REGS;
2135 return type->type->type == MONO_TYPE_PTR;
2139 ves_icall_type_isprimitive (MonoReflectionType *type)
2141 MONO_ARCH_SAVE_REGS;
2143 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)));
2147 ves_icall_type_isbyref (MonoReflectionType *type)
2149 MONO_ARCH_SAVE_REGS;
2151 return type->type->byref;
2155 ves_icall_type_iscomobject (MonoReflectionType *type)
2157 MonoClass *klass = mono_class_from_mono_type (type->type);
2158 MONO_ARCH_SAVE_REGS;
2160 return (klass && klass->is_com_object);
2163 static MonoReflectionModule*
2164 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2166 MonoClass *class = mono_class_from_mono_type (type->type);
2168 MONO_ARCH_SAVE_REGS;
2170 return mono_module_get_object (mono_object_domain (type), class->image);
2173 static MonoReflectionAssembly*
2174 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2176 MonoDomain *domain = mono_domain_get ();
2177 MonoClass *class = mono_class_from_mono_type (type->type);
2179 MONO_ARCH_SAVE_REGS;
2181 return mono_assembly_get_object (domain, class->image->assembly);
2184 static MonoReflectionType*
2185 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2187 MonoDomain *domain = mono_domain_get ();
2190 MONO_ARCH_SAVE_REGS;
2192 if (type->type->byref)
2194 if (type->type->type == MONO_TYPE_VAR)
2195 class = type->type->data.generic_param->owner->owner.klass;
2196 else if (type->type->type == MONO_TYPE_MVAR)
2197 class = type->type->data.generic_param->owner->owner.method->klass;
2199 class = mono_class_from_mono_type (type->type)->nested_in;
2201 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2204 static MonoReflectionType*
2205 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2207 MonoDomain *domain = mono_domain_get ();
2208 MonoClass *class = mono_class_from_mono_type (type->type);
2210 MONO_ARCH_SAVE_REGS;
2212 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2213 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2214 else if (class->element_class)
2215 return mono_type_get_object (domain, &class->element_class->byval_arg);
2221 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2223 MonoDomain *domain = mono_domain_get ();
2224 MonoClass *class = mono_class_from_mono_type (type->type);
2226 MONO_ARCH_SAVE_REGS;
2228 if (type->type->byref) {
2229 char *n = g_strdup_printf ("%s&", class->name);
2230 MonoString *res = mono_string_new (domain, n);
2236 return mono_string_new (domain, class->name);
2241 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2243 MonoDomain *domain = mono_domain_get ();
2244 MonoClass *class = mono_class_from_mono_type (type->type);
2246 MONO_ARCH_SAVE_REGS;
2248 while (class->nested_in)
2249 class = class->nested_in;
2251 if (class->name_space [0] == '\0')
2254 return mono_string_new (domain, class->name_space);
2258 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2260 MonoClass *class = mono_class_from_mono_type (type->type);
2262 MONO_ARCH_SAVE_REGS;
2268 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2271 MonoClass *klass, *pklass;
2273 MONO_ARCH_SAVE_REGS;
2275 klass = mono_class_from_mono_type (type->type);
2277 if (klass->generic_container) {
2278 MonoGenericContainer *container = klass->generic_container;
2279 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, container->type_argc);
2280 for (i = 0; i < container->type_argc; ++i) {
2281 pklass = mono_class_from_generic_parameter (&container->type_params [i], klass->image, FALSE);
2282 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), &pklass->byval_arg));
2284 } else if (klass->generic_class) {
2285 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2286 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, inst->type_argc);
2287 for (i = 0; i < inst->type_argc; ++i)
2288 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), inst->type_argv [i]));
2290 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, 0);
2296 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2299 MONO_ARCH_SAVE_REGS;
2301 if (type->type->byref)
2304 klass = mono_class_from_mono_type (type->type);
2306 return klass->generic_container != NULL;
2309 static MonoReflectionType*
2310 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2313 MONO_ARCH_SAVE_REGS;
2315 if (type->type->byref)
2318 klass = mono_class_from_mono_type (type->type);
2319 if (klass->generic_container) {
2320 return type; /* check this one */
2322 if (klass->generic_class) {
2323 MonoClass *generic_class = klass->generic_class->container_class;
2325 if (generic_class->wastypebuilder && generic_class->reflection_info)
2326 return generic_class->reflection_info;
2328 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2333 static MonoReflectionType*
2334 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2336 MonoType *geninst, **types;
2339 MONO_ARCH_SAVE_REGS;
2341 count = mono_array_length (type_array);
2342 types = g_new0 (MonoType *, count);
2344 for (i = 0; i < count; i++) {
2345 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2346 types [i] = t->type;
2349 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2354 return mono_type_get_object (mono_object_domain (type), geninst);
2358 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2361 MONO_ARCH_SAVE_REGS;
2363 if (type->type->byref)
2366 klass = mono_class_from_mono_type (type->type);
2367 return klass->generic_class != NULL;
2371 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2374 MONO_ARCH_SAVE_REGS;
2376 if (type->type->byref)
2379 klass = mono_class_from_mono_type (type->type);
2380 return klass->generic_class != NULL || klass->generic_container != NULL;
2384 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2386 MONO_ARCH_SAVE_REGS;
2388 if (is_generic_parameter (type->type))
2389 return type->type->data.generic_param->num;
2393 static GenericParameterAttributes
2394 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2396 MONO_ARCH_SAVE_REGS;
2397 g_assert (is_generic_parameter (type->type));
2398 return type->type->data.generic_param->flags;
2402 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2404 MonoGenericParam *param;
2410 MONO_ARCH_SAVE_REGS;
2412 domain = mono_object_domain (type);
2413 param = type->type->data.generic_param;
2414 for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
2417 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2418 for (i = 0; i < count; i++)
2419 mono_array_setref (res, i, mono_type_get_object (domain, ¶m->constraints [i]->byval_arg));
2426 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2428 MONO_ARCH_SAVE_REGS;
2429 return is_generic_parameter (type->type);
2433 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2435 MONO_ARCH_SAVE_REGS;
2436 return is_generic_parameter (tb->type.type);
2440 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2441 MonoReflectionType *t)
2443 enumtype->type = t->type;
2446 static MonoReflectionType*
2447 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2449 MonoDynamicGenericClass *gclass;
2450 MonoReflectionType *parent = NULL, *res;
2456 MONO_ARCH_SAVE_REGS;
2458 g_assert (type->type.type->data.generic_class->is_dynamic);
2459 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2461 domain = mono_object_domain (type);
2462 klass = mono_class_from_mono_type (type->generic_type->type.type);
2464 if (!klass->generic_class && !klass->generic_container)
2467 parent = type->generic_type->parent;
2469 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2472 inflated = mono_class_inflate_generic_type (
2473 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2475 res = mono_type_get_object (domain, inflated);
2476 mono_metadata_free_type (inflated);
2481 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2483 static MonoClass *System_Reflection_MonoGenericClass;
2484 MonoGenericClass *gclass;
2485 MonoReflectionTypeBuilder *tb = NULL;
2486 MonoClass *klass = NULL;
2491 MONO_ARCH_SAVE_REGS;
2493 if (!System_Reflection_MonoGenericClass) {
2494 System_Reflection_MonoGenericClass = mono_class_from_name (
2495 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2496 g_assert (System_Reflection_MonoGenericClass);
2499 domain = mono_object_domain (type);
2501 gclass = type->type.type->data.generic_class;
2502 g_assert (gclass->is_dynamic);
2504 tb = type->generic_type;
2505 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2507 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2509 for (i = 0; i < icount; i++) {
2510 MonoReflectionType *iface;
2514 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2517 it = &klass->interfaces [i]->byval_arg;
2519 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2521 iface = mono_type_get_object (domain, it);
2522 mono_array_setref (res, i, iface);
2523 mono_metadata_free_type (it);
2529 static MonoReflectionMethod*
2530 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2531 MonoReflectionMethod* generic)
2533 MonoGenericClass *gclass;
2534 MonoDynamicGenericClass *dgclass;
2538 MONO_ARCH_SAVE_REGS;
2540 gclass = type->type.type->data.generic_class;
2541 g_assert (gclass->is_dynamic);
2543 dgclass = (MonoDynamicGenericClass *) gclass;
2545 domain = mono_object_domain (type);
2547 for (i = 0; i < dgclass->count_methods; i++)
2548 if (generic->method->token == dgclass->methods [i]->token)
2549 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2554 static MonoReflectionMethod*
2555 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2556 MonoReflectionMethod* generic)
2558 MonoGenericClass *gclass;
2559 MonoDynamicGenericClass *dgclass;
2563 MONO_ARCH_SAVE_REGS;
2565 gclass = type->type.type->data.generic_class;
2566 g_assert (gclass->is_dynamic);
2568 dgclass = (MonoDynamicGenericClass *) gclass;
2570 domain = mono_object_domain (type);
2572 for (i = 0; i < dgclass->count_ctors; i++)
2573 if (generic->method->token == dgclass->ctors [i]->token)
2574 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2580 static MonoReflectionField*
2581 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2582 MonoString* generic_name)
2584 MonoGenericClass *gclass;
2585 MonoDynamicGenericClass *dgclass;
2587 MonoClass *refclass;
2588 char *utf8_name = mono_string_to_utf8 (generic_name);
2591 MONO_ARCH_SAVE_REGS;
2593 gclass = type->type.type->data.generic_class;
2594 g_assert (gclass->is_dynamic);
2596 dgclass = (MonoDynamicGenericClass *) gclass;
2598 refclass = mono_class_from_mono_type (type->type.type);
2600 domain = mono_object_domain (type);
2602 for (i = 0; i < dgclass->count_fields; i++)
2603 if (strcmp (utf8_name, mono_field_get_name (&dgclass->fields [i])) == 0) {
2605 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2614 static MonoReflectionMethod*
2615 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2616 MonoReflectionMethod* generic)
2623 MONO_ARCH_SAVE_REGS;
2625 domain = ((MonoObject *)type)->vtable->domain;
2627 klass = mono_class_from_mono_type (type->type);
2630 while ((method = mono_class_get_methods (klass, &iter))) {
2631 if (method->token == generic->method->token)
2632 return mono_method_get_object (domain, method, klass);
2639 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2640 MonoReflectionType *reflected_type)
2642 MonoGenericClass *gclass;
2643 MonoDynamicGenericClass *dgclass;
2645 MonoClass *refclass;
2649 MONO_ARCH_SAVE_REGS;
2651 gclass = type->type.type->data.generic_class;
2652 g_assert (gclass->is_dynamic);
2653 dgclass = (MonoDynamicGenericClass *) gclass;
2655 refclass = mono_class_from_mono_type (reflected_type->type);
2657 domain = mono_object_domain (type);
2658 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2660 for (i = 0; i < dgclass->count_methods; i++)
2661 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2667 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2668 MonoReflectionType *reflected_type)
2670 static MonoClass *System_Reflection_ConstructorInfo;
2671 MonoGenericClass *gclass;
2672 MonoDynamicGenericClass *dgclass;
2674 MonoClass *refclass;
2678 MONO_ARCH_SAVE_REGS;
2680 if (!System_Reflection_ConstructorInfo)
2681 System_Reflection_ConstructorInfo = mono_class_from_name (
2682 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2684 gclass = type->type.type->data.generic_class;
2685 g_assert (gclass->is_dynamic);
2686 dgclass = (MonoDynamicGenericClass *) gclass;
2688 refclass = mono_class_from_mono_type (reflected_type->type);
2690 domain = mono_object_domain (type);
2691 res = mono_array_new (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2693 for (i = 0; i < dgclass->count_ctors; i++)
2694 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2700 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2701 MonoReflectionType *reflected_type)
2703 MonoGenericClass *gclass;
2704 MonoDynamicGenericClass *dgclass;
2706 MonoClass *refclass;
2710 MONO_ARCH_SAVE_REGS;
2712 gclass = type->type.type->data.generic_class;
2713 g_assert (gclass->is_dynamic);
2714 dgclass = (MonoDynamicGenericClass *) gclass;
2716 refclass = mono_class_from_mono_type (reflected_type->type);
2718 domain = mono_object_domain (type);
2719 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2721 for (i = 0; i < dgclass->count_fields; i++)
2722 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2728 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2729 MonoReflectionType *reflected_type)
2731 static MonoClass *System_Reflection_PropertyInfo;
2732 MonoGenericClass *gclass;
2733 MonoDynamicGenericClass *dgclass;
2735 MonoClass *refclass;
2739 MONO_ARCH_SAVE_REGS;
2741 if (!System_Reflection_PropertyInfo)
2742 System_Reflection_PropertyInfo = mono_class_from_name (
2743 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2745 gclass = type->type.type->data.generic_class;
2746 g_assert (gclass->is_dynamic);
2747 dgclass = (MonoDynamicGenericClass *) gclass;
2749 refclass = mono_class_from_mono_type (reflected_type->type);
2751 domain = mono_object_domain (type);
2752 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2754 for (i = 0; i < dgclass->count_properties; i++)
2755 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2761 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2762 MonoReflectionType *reflected_type)
2764 static MonoClass *System_Reflection_EventInfo;
2765 MonoGenericClass *gclass;
2766 MonoDynamicGenericClass *dgclass;
2768 MonoClass *refclass;
2772 MONO_ARCH_SAVE_REGS;
2774 if (!System_Reflection_EventInfo)
2775 System_Reflection_EventInfo = mono_class_from_name (
2776 mono_defaults.corlib, "System.Reflection", "EventInfo");
2778 gclass = type->type.type->data.generic_class;
2779 g_assert (gclass->is_dynamic);
2780 dgclass = (MonoDynamicGenericClass *) gclass;
2782 refclass = mono_class_from_mono_type (reflected_type->type);
2784 domain = mono_object_domain (type);
2785 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2787 for (i = 0; i < dgclass->count_events; i++)
2788 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2793 static MonoReflectionType*
2794 ves_icall_MonoGenericClass_InflateType (MonoReflectionGenericClass *type,
2795 MonoReflectionType *target)
2799 MonoReflectionType *res;
2801 MONO_ARCH_SAVE_REGS;
2803 gklass = mono_class_from_mono_type (type->type.type);
2804 res_type = mono_class_inflate_generic_type (target->type, mono_class_get_context (gklass));
2805 res = mono_type_get_object (mono_object_domain (type), res_type);
2806 mono_metadata_free_type (res_type);
2810 static MonoReflectionMethod *
2811 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2816 MONO_ARCH_SAVE_REGS;
2818 if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2821 method = type->type->data.generic_param->owner->owner.method;
2823 klass = mono_class_from_mono_type (type->type);
2824 return mono_method_get_object (mono_object_domain (type), method, klass);
2827 static MonoReflectionDllImportAttribute*
2828 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2830 static MonoClass *DllImportAttributeClass = NULL;
2831 MonoDomain *domain = mono_domain_get ();
2832 MonoReflectionDllImportAttribute *attr;
2833 MonoImage *image = method->klass->image;
2834 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2835 MonoTableInfo *tables = image->tables;
2836 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2837 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2838 guint32 im_cols [MONO_IMPLMAP_SIZE];
2839 guint32 scope_token;
2840 const char *import = NULL;
2841 const char *scope = NULL;
2844 if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2847 if (!DllImportAttributeClass) {
2848 DllImportAttributeClass =
2849 mono_class_from_name (mono_defaults.corlib,
2850 "System.Runtime.InteropServices", "DllImportAttribute");
2851 g_assert (DllImportAttributeClass);
2854 if (method->klass->image->dynamic) {
2855 MonoReflectionMethodAux *method_aux =
2856 g_hash_table_lookup (
2857 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2859 import = method_aux->dllentry;
2860 scope = method_aux->dll;
2864 if (piinfo->implmap_idx) {
2865 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2867 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2868 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2869 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2870 scope = mono_metadata_string_heap (image, scope_token);
2873 flags = piinfo->piflags;
2875 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2877 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2878 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2879 attr->call_conv = (flags & 0x700) >> 8;
2880 attr->charset = ((flags & 0x6) >> 1) + 1;
2881 if (attr->charset == 1)
2883 attr->exact_spelling = (flags & 0x1) != 0;
2884 attr->set_last_error = (flags & 0x40) != 0;
2885 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2886 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2887 attr->preserve_sig = FALSE;
2892 static MonoReflectionMethod *
2893 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2895 MonoMethodInflated *imethod;
2898 MONO_ARCH_SAVE_REGS;
2900 if (method->method->is_generic)
2903 if (!method->method->is_inflated)
2906 imethod = (MonoMethodInflated *) method->method;
2908 result = imethod->declaring;
2909 /* Not a generic method. */
2910 if (!result->is_generic)
2913 if (method->method->klass->image->dynamic) {
2914 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2915 MonoReflectionMethod *res;
2918 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2919 * the dynamic case as well ?
2921 mono_loader_lock ();
2922 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2923 mono_loader_unlock ();
2929 if (imethod->context.class_inst) {
2930 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2931 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2934 return mono_method_get_object (mono_object_domain (method), result, NULL);
2938 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2940 MONO_ARCH_SAVE_REGS;
2942 return mono_method_signature (method->method)->generic_param_count != 0;
2946 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2948 MONO_ARCH_SAVE_REGS;
2950 return method->method->is_generic;
2954 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2959 MONO_ARCH_SAVE_REGS;
2961 domain = mono_object_domain (method);
2963 if (method->method->is_inflated) {
2964 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2967 count = inst->type_argc;
2968 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2970 for (i = 0; i < count; i++)
2971 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2977 count = mono_method_signature (method->method)->generic_param_count;
2978 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2980 for (i = 0; i < count; i++) {
2981 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2982 MonoGenericParam *param = &container->type_params [i];
2983 MonoClass *pklass = mono_class_from_generic_parameter (
2984 param, method->method->klass->image, TRUE);
2985 mono_array_setref (res, i,
2986 mono_type_get_object (domain, &pklass->byval_arg));
2993 ensure_reflection_security (void)
2995 MonoMethod *m = mono_method_get_last_managed ();
2999 g_print ("method %s.%s.%s in image %s\n",
3000 m->klass->name_space, m->klass->name, m->name, m->klass->image->name);
3003 /* We stop at the first method which is not in
3004 System.Reflection or which is not in a platform
3006 if (strcmp (m->klass->name_space, "System.Reflection") != 0 ||
3007 !mono_security_core_clr_is_platform_image (m->klass->image)) {
3008 /* If the method is transparent we throw an exception. */
3009 if (mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_TRANSPARENT ) {
3010 MonoException *ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", "Reflection called from transparent code");
3012 mono_raise_exception (ex);
3017 mono_stack_walk_no_il (get_caller, &m);
3022 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
3025 * Invoke from reflection is supposed to always be a virtual call (the API
3026 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3027 * greater flexibility.
3029 MonoMethod *m = method->method;
3033 MONO_ARCH_SAVE_REGS;
3037 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR &&
3038 mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL)
3039 ensure_reflection_security ();
3041 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3043 if (!mono_object_isinst (this, m->klass)) {
3044 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type.");
3047 m = mono_object_get_virtual_method (this, m);
3048 /* must pass the pointer to the value for valuetype methods */
3049 if (m->klass->valuetype)
3050 obj = mono_object_unbox (this);
3051 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3052 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target.");
3057 pcount = params? mono_array_length (params): 0;
3058 if (pcount != mono_method_signature (m)->param_count) {
3059 *exc = mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException");
3063 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
3064 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class.");
3068 if (m->klass->image->assembly->ref_only) {
3069 *exc = mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api.");
3073 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3075 mono_array_size_t *lengths;
3076 mono_array_size_t *lower_bounds;
3077 pcount = mono_array_length (params);
3078 lengths = alloca (sizeof (mono_array_size_t) * pcount);
3079 for (i = 0; i < pcount; ++i)
3080 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3082 if (m->klass->rank == pcount) {
3083 /* Only lengths provided. */
3084 lower_bounds = NULL;
3086 g_assert (pcount == (m->klass->rank * 2));
3087 /* lower bounds are first. */
3088 lower_bounds = lengths;
3089 lengths += m->klass->rank;
3092 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
3094 return mono_runtime_invoke_array (m, obj, params, NULL);
3098 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
3100 MonoDomain *domain = mono_object_domain (method);
3101 MonoMethod *m = method->method;
3102 MonoMethodSignature *sig = mono_method_signature (m);
3103 MonoArray *out_args;
3105 int i, j, outarg_count = 0;
3107 MONO_ARCH_SAVE_REGS;
3109 if (m->klass == mono_defaults.object_class) {
3111 if (!strcmp (m->name, "FieldGetter")) {
3112 MonoClass *k = this->vtable->klass;
3116 /* If this is a proxy, then it must be a CBO */
3117 if (k == mono_defaults.transparent_proxy_class) {
3118 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3119 this = tp->rp->unwrapped_server;
3121 k = this->vtable->klass;
3124 name = mono_array_get (params, MonoString *, 1);
3125 str = mono_string_to_utf8 (name);
3128 MonoClassField* field = mono_class_get_field_from_name (k, str);
3130 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3131 if (field_klass->valuetype)
3132 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
3134 result = *((gpointer *)((char *)this + field->offset));
3136 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3137 *outArgs = out_args;
3138 mono_array_setref (out_args, 0, result);
3146 g_assert_not_reached ();
3148 } else if (!strcmp (m->name, "FieldSetter")) {
3149 MonoClass *k = this->vtable->klass;
3155 /* If this is a proxy, then it must be a CBO */
3156 if (k == mono_defaults.transparent_proxy_class) {
3157 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3158 this = tp->rp->unwrapped_server;
3160 k = this->vtable->klass;
3163 name = mono_array_get (params, MonoString *, 1);
3164 str = mono_string_to_utf8 (name);
3167 MonoClassField* field = mono_class_get_field_from_name (k, str);
3169 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3170 MonoObject *val = mono_array_get (params, gpointer, 2);
3172 if (field_klass->valuetype) {
3173 size = mono_type_size (field->type, &align);
3175 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3177 memcpy ((char *)this + field->offset,
3178 ((char *)val) + sizeof (MonoObject), size);
3180 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
3183 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3184 *outArgs = out_args;
3194 g_assert_not_reached ();
3199 for (i = 0; i < mono_array_length (params); i++) {
3200 if (sig->params [i]->byref)
3204 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3206 /* handle constructors only for objects already allocated */
3207 if (!strcmp (method->method->name, ".ctor"))
3210 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3211 g_assert (!method->method->klass->valuetype);
3212 result = mono_runtime_invoke_array (method->method, this, params, NULL);
3214 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3215 if (sig->params [i]->byref) {
3217 arg = mono_array_get (params, gpointer, i);
3218 mono_array_setref (out_args, j, arg);
3223 *outArgs = out_args;
3229 read_enum_value (char *mem, int type)
3233 return *(guint8*)mem;
3235 return *(gint8*)mem;
3237 return *(guint16*)mem;
3239 return *(gint16*)mem;
3241 return *(guint32*)mem;
3243 return *(gint32*)mem;
3245 return *(guint64*)mem;
3247 return *(gint64*)mem;
3249 g_assert_not_reached ();
3255 write_enum_value (char *mem, int type, guint64 value)
3259 case MONO_TYPE_I1: {
3260 guint8 *p = (guint8*)mem;
3265 case MONO_TYPE_I2: {
3266 guint16 *p = (void*)mem;
3271 case MONO_TYPE_I4: {
3272 guint32 *p = (void*)mem;
3277 case MONO_TYPE_I8: {
3278 guint64 *p = (void*)mem;
3283 g_assert_not_reached ();
3289 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3292 MonoClass *enumc, *objc;
3296 MONO_ARCH_SAVE_REGS;
3298 MONO_CHECK_ARG_NULL (enumType);
3299 MONO_CHECK_ARG_NULL (value);
3301 domain = mono_object_domain (enumType);
3302 enumc = mono_class_from_mono_type (enumType->type);
3303 objc = value->vtable->klass;
3305 if (!enumc->enumtype)
3306 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3307 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3308 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."));
3310 res = mono_object_new (domain, enumc);
3311 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3312 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3318 ves_icall_System_Enum_get_value (MonoObject *this)
3326 MONO_ARCH_SAVE_REGS;
3331 g_assert (this->vtable->klass->enumtype);
3333 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3334 res = mono_object_new (mono_object_domain (this), enumc);
3335 dst = (char *)res + sizeof (MonoObject);
3336 src = (char *)this + sizeof (MonoObject);
3337 size = mono_class_value_size (enumc, NULL);
3339 memcpy (dst, src, size);
3344 static MonoReflectionType *
3345 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3347 MONO_ARCH_SAVE_REGS;
3349 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3353 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3355 gpointer data = (char *)this + sizeof (MonoObject);
3356 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3357 g_assert (basetype);
3359 switch (basetype->type) {
3361 return *((gint8*)data);
3363 return *((guint8*)data);
3364 case MONO_TYPE_CHAR:
3366 return *((guint16*)data);
3369 return *((gint16*)data);
3371 return *((guint32*)data);
3373 return *((gint32*)data);
3375 case MONO_TYPE_I8: {
3376 gint64 value = *((gint64*)data);
3377 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3380 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3386 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3388 MonoDomain *domain = mono_object_domain (type);
3389 MonoClass *enumc = mono_class_from_mono_type (type->type);
3390 guint j = 0, nvalues, crow;
3392 MonoClassField *field;
3394 MONO_ARCH_SAVE_REGS;
3396 info->utype = mono_type_get_object (domain, mono_class_enum_basetype (enumc));
3397 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3398 info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3399 info->values = mono_array_new (domain, enumc, nvalues);
3403 while ((field = mono_class_get_fields (enumc, &iter))) {
3406 MonoTypeEnum def_type;
3408 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3410 if (mono_field_is_deleted (field))
3412 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3414 p = mono_class_get_field_default_value (field, &def_type);
3415 len = mono_metadata_decode_blob_size (p, &p);
3416 switch (mono_class_enum_basetype (enumc)->type) {
3419 mono_array_set (info->values, gchar, j, *p);
3421 case MONO_TYPE_CHAR:
3424 mono_array_set (info->values, gint16, j, read16 (p));
3428 mono_array_set (info->values, gint32, j, read32 (p));
3432 mono_array_set (info->values, gint64, j, read64 (p));
3435 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3442 BFLAGS_IgnoreCase = 1,
3443 BFLAGS_DeclaredOnly = 2,
3444 BFLAGS_Instance = 4,
3446 BFLAGS_Public = 0x10,
3447 BFLAGS_NonPublic = 0x20,
3448 BFLAGS_FlattenHierarchy = 0x40,
3449 BFLAGS_InvokeMethod = 0x100,
3450 BFLAGS_CreateInstance = 0x200,
3451 BFLAGS_GetField = 0x400,
3452 BFLAGS_SetField = 0x800,
3453 BFLAGS_GetProperty = 0x1000,
3454 BFLAGS_SetProperty = 0x2000,
3455 BFLAGS_ExactBinding = 0x10000,
3456 BFLAGS_SuppressChangeType = 0x20000,
3457 BFLAGS_OptionalParamBinding = 0x40000
3460 static MonoReflectionField *
3461 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3464 MonoClass *startklass, *klass;
3466 MonoClassField *field;
3469 int (*compare_func) (const char *s1, const char *s2) = NULL;
3470 domain = ((MonoObject *)type)->vtable->domain;
3471 klass = startklass = mono_class_from_mono_type (type->type);
3473 MONO_ARCH_SAVE_REGS;
3476 mono_raise_exception (mono_get_exception_argument_null ("name"));
3477 if (type->type->byref)
3480 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3483 if (klass->exception_type != MONO_EXCEPTION_NONE)
3484 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3487 while ((field = mono_class_get_fields (klass, &iter))) {
3490 if (field->type == NULL)
3492 if (mono_field_is_deleted (field))
3494 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3495 if (bflags & BFLAGS_Public)
3497 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3498 if (bflags & BFLAGS_NonPublic) {
3505 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3506 if (bflags & BFLAGS_Static)
3507 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3510 if (bflags & BFLAGS_Instance)
3517 utf8_name = mono_string_to_utf8 (name);
3519 if (compare_func (mono_field_get_name (field), utf8_name)) {
3525 return mono_field_get_object (domain, klass, field);
3527 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3534 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3537 MonoClass *startklass, *klass, *refklass;
3542 MonoClassField *field;
3544 MONO_ARCH_SAVE_REGS;
3546 domain = ((MonoObject *)type)->vtable->domain;
3547 if (type->type->byref)
3548 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3549 klass = startklass = mono_class_from_mono_type (type->type);
3550 refklass = mono_class_from_mono_type (reftype->type);
3554 res = mono_array_new (domain, mono_defaults.field_info_class, len);
3556 if (klass->exception_type != MONO_EXCEPTION_NONE)
3557 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3560 while ((field = mono_class_get_fields (klass, &iter))) {
3562 if (mono_field_is_deleted (field))
3564 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3565 if (bflags & BFLAGS_Public)
3567 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3568 if (bflags & BFLAGS_NonPublic) {
3575 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3576 if (bflags & BFLAGS_Static)
3577 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3580 if (bflags & BFLAGS_Instance)
3586 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3588 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, len * 2);
3589 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3593 mono_array_setref (res, i, member);
3596 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3599 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, i);
3600 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3603 * Better solution for the new GC.
3604 * res->max_length = i;
3611 method_nonpublic (MonoMethod* method, gboolean start_klass)
3613 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3614 case METHOD_ATTRIBUTE_ASSEM:
3615 return (start_klass || mono_defaults.generic_ilist_class);
3616 case METHOD_ATTRIBUTE_PRIVATE:
3618 case METHOD_ATTRIBUTE_PUBLIC:
3626 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3628 static MonoClass *MethodInfo_array;
3630 MonoClass *startklass, *klass, *refklass;
3635 int i, len, match, nslots;
3636 guint32 method_slots_default [8];
3637 guint32 *method_slots;
3638 gchar *mname = NULL;
3639 int (*compare_func) (const char *s1, const char *s2) = NULL;
3640 MonoVTable *array_vtable;
3642 MONO_ARCH_SAVE_REGS;
3644 if (!MethodInfo_array) {
3645 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3646 mono_memory_barrier ();
3647 MethodInfo_array = klass;
3650 domain = ((MonoObject *)type)->vtable->domain;
3651 array_vtable = mono_class_vtable (domain, MethodInfo_array);
3652 if (type->type->byref)
3653 return mono_array_new_specific (array_vtable, 0);
3654 klass = startklass = mono_class_from_mono_type (type->type);
3655 refklass = mono_class_from_mono_type (reftype->type);
3658 mname = mono_string_to_utf8 (name);
3659 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3662 /* An optimization for calls made from Delegate:CreateDelegate () */
3663 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3664 method = mono_get_delegate_invoke (klass);
3666 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3668 res = mono_array_new_specific (array_vtable, 1);
3669 mono_array_setref (res, 0, member);
3673 mono_class_setup_vtable (klass);
3675 if (is_generic_parameter (type->type))
3676 nslots = klass->parent->vtable_size;
3678 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3679 if (nslots >= sizeof (method_slots_default) * 8) {
3680 method_slots = g_new0 (guint32, nslots / 32 + 1);
3682 method_slots = method_slots_default;
3683 memset (method_slots, 0, sizeof (method_slots_default));
3687 res = mono_array_new_specific (array_vtable, len);
3689 mono_class_setup_vtable (klass);
3690 if (klass->exception_type != MONO_EXCEPTION_NONE)
3691 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3694 while ((method = mono_class_get_methods (klass, &iter))) {
3696 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3698 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3699 if (bflags & BFLAGS_Public)
3701 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3707 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3708 if (bflags & BFLAGS_Static)
3709 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3712 if (bflags & BFLAGS_Instance)
3720 if (compare_func (mname, method->name))
3725 if (method->slot != -1) {
3726 g_assert (method->slot < nslots);
3727 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3729 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3732 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3735 MonoArray *new_res = mono_array_new_specific (array_vtable, len * 2);
3736 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3740 mono_array_setref (res, i, member);
3743 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3747 if (method_slots != method_slots_default)
3748 g_free (method_slots);
3750 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, i);
3751 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3754 * Better solution for the new GC.
3755 * res->max_length = i;
3762 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3765 static MonoClass *System_Reflection_ConstructorInfo;
3766 MonoClass *startklass, *klass, *refklass;
3771 gpointer iter = NULL;
3773 MONO_ARCH_SAVE_REGS;
3775 domain = ((MonoObject *)type)->vtable->domain;
3776 if (type->type->byref)
3777 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3778 klass = startklass = mono_class_from_mono_type (type->type);
3779 refklass = mono_class_from_mono_type (reftype->type);
3781 if (klass->exception_type != MONO_EXCEPTION_NONE)
3782 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3784 if (!System_Reflection_ConstructorInfo)
3785 System_Reflection_ConstructorInfo = mono_class_from_name (
3786 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3790 res = mono_array_new (domain, System_Reflection_ConstructorInfo, len);
3792 while ((method = mono_class_get_methods (klass, &iter))) {
3794 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3796 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3797 if (bflags & BFLAGS_Public)
3800 if (bflags & BFLAGS_NonPublic)
3806 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3807 if (bflags & BFLAGS_Static)
3808 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3811 if (bflags & BFLAGS_Instance)
3817 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3820 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, len * 2);
3821 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3825 mono_array_setref (res, i, member);
3829 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, i);
3830 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3833 * Better solution for the new GC.
3834 * res->max_length = i;
3841 property_hash (gconstpointer data)
3843 MonoProperty *prop = (MonoProperty*)data;
3845 return g_str_hash (prop->name);
3849 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3851 // Properties are hide-by-name-and-signature
3852 if (!g_str_equal (prop1->name, prop2->name))
3855 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3857 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3863 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3868 return method_nonpublic (accessor, start_klass);
3872 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3875 static MonoClass *System_Reflection_PropertyInfo;
3876 MonoClass *startklass, *klass;
3883 gchar *propname = NULL;
3884 int (*compare_func) (const char *s1, const char *s2) = NULL;
3886 GHashTable *properties;
3888 MONO_ARCH_SAVE_REGS;
3890 if (!System_Reflection_PropertyInfo)
3891 System_Reflection_PropertyInfo = mono_class_from_name (
3892 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3894 domain = ((MonoObject *)type)->vtable->domain;
3895 if (type->type->byref)
3896 return mono_array_new (domain, System_Reflection_PropertyInfo, 0);
3897 klass = startklass = mono_class_from_mono_type (type->type);
3899 propname = mono_string_to_utf8 (name);
3900 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3903 mono_class_setup_vtable (klass);
3905 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3908 res = mono_array_new (domain, System_Reflection_PropertyInfo, len);
3910 mono_class_setup_vtable (klass);
3911 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3912 g_hash_table_destroy (properties);
3915 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3919 while ((prop = mono_class_get_properties (klass, &iter))) {
3925 flags = method->flags;
3928 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3929 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3930 if (bflags & BFLAGS_Public)
3932 } else if (bflags & BFLAGS_NonPublic) {
3933 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3934 property_accessor_nonpublic(prop->set, startklass == klass)) {
3941 if (flags & METHOD_ATTRIBUTE_STATIC) {
3942 if (bflags & BFLAGS_Static)
3943 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3946 if (bflags & BFLAGS_Instance)
3955 if (compare_func (propname, prop->name))
3959 if (g_hash_table_lookup (properties, prop))
3963 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, len * 2);
3964 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3968 mono_array_setref (res, i, mono_property_get_object (domain, startklass, prop));
3971 g_hash_table_insert (properties, prop, prop);
3973 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3976 g_hash_table_destroy (properties);
3979 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, i);
3980 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3983 * Better solution for the new GC.
3984 * res->max_length = i;
3990 static MonoReflectionEvent *
3991 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3994 MonoClass *klass, *startklass;
4000 MONO_ARCH_SAVE_REGS;
4002 event_name = mono_string_to_utf8 (name);
4003 if (type->type->byref)
4005 klass = startklass = mono_class_from_mono_type (type->type);
4006 domain = mono_object_domain (type);
4009 if (klass->exception_type != MONO_EXCEPTION_NONE)
4010 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4013 while ((event = mono_class_get_events (klass, &iter))) {
4014 if (strcmp (event->name, event_name))
4017 method = event->add;
4019 method = event->remove;
4021 method = event->raise;
4023 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4024 if (!(bflags & BFLAGS_Public))
4027 if (!(bflags & BFLAGS_NonPublic))
4029 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4034 if (!(bflags & BFLAGS_NonPublic))
4037 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4038 if (!(bflags & BFLAGS_Static))
4040 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4043 if (!(bflags & BFLAGS_Instance))
4047 g_free (event_name);
4048 return mono_event_get_object (domain, startklass, event);
4051 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4054 g_free (event_name);
4059 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4062 static MonoClass *System_Reflection_EventInfo;
4063 MonoClass *startklass, *klass;
4070 MONO_ARCH_SAVE_REGS;
4072 if (!System_Reflection_EventInfo)
4073 System_Reflection_EventInfo = mono_class_from_name (
4074 mono_defaults.corlib, "System.Reflection", "EventInfo");
4076 domain = mono_object_domain (type);
4077 if (type->type->byref)
4078 return mono_array_new (domain, System_Reflection_EventInfo, 0);
4079 klass = startklass = mono_class_from_mono_type (type->type);
4083 res = mono_array_new (domain, System_Reflection_EventInfo, len);
4085 if (klass->exception_type != MONO_EXCEPTION_NONE)
4086 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4089 while ((event = mono_class_get_events (klass, &iter))) {
4091 method = event->add;
4093 method = event->remove;
4095 method = event->raise;
4097 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4098 if (bflags & BFLAGS_Public)
4100 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4101 if (bflags & BFLAGS_NonPublic)
4106 if (bflags & BFLAGS_NonPublic)
4112 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4113 if (bflags & BFLAGS_Static)
4114 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4117 if (bflags & BFLAGS_Instance)
4122 if (bflags & BFLAGS_Instance)
4128 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, len * 2);
4129 mono_array_memcpy_refs (new_res, 0, res, 0, len);
4133 mono_array_setref (res, i, mono_event_get_object (domain, startklass, event));
4136 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4139 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, i);
4140 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4143 * Better solution for the new GC.
4144 * res->max_length = i;
4150 static MonoReflectionType *
4151 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4159 MONO_ARCH_SAVE_REGS;
4161 domain = ((MonoObject *)type)->vtable->domain;
4162 if (type->type->byref)
4164 klass = mono_class_from_mono_type (type->type);
4165 str = mono_string_to_utf8 (name);
4168 if (klass->exception_type != MONO_EXCEPTION_NONE)
4169 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4172 * If a nested type is generic, return its generic type definition.
4173 * Note that this means that the return value is essentially a
4174 * nested type of the generic type definition of @klass.
4176 * A note in MSDN claims that a generic type definition can have
4177 * nested types that aren't generic. In any case, the container of that
4178 * nested type would be the generic type definition.
4180 if (klass->generic_class)
4181 klass = klass->generic_class->container_class;
4184 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4186 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4187 if (bflags & BFLAGS_Public)
4190 if (bflags & BFLAGS_NonPublic)
4195 if (strcmp (nested->name, str) == 0){
4197 return mono_type_get_object (domain, &nested->byval_arg);
4200 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4207 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4217 MONO_ARCH_SAVE_REGS;
4219 domain = ((MonoObject *)type)->vtable->domain;
4220 if (type->type->byref)
4221 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4222 klass = mono_class_from_mono_type (type->type);
4223 if (klass->exception_type != MONO_EXCEPTION_NONE)
4224 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4227 * If a nested type is generic, return its generic type definition.
4228 * Note that this means that the return value is essentially the set
4229 * of nested types of the generic type definition of @klass.
4231 * A note in MSDN claims that a generic type definition can have
4232 * nested types that aren't generic. In any case, the container of that
4233 * nested type would be the generic type definition.
4235 if (klass->generic_class)
4236 klass = klass->generic_class->container_class;
4240 res = mono_array_new (domain, mono_defaults.monotype_class, len);
4242 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4244 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4245 if (bflags & BFLAGS_Public)
4248 if (bflags & BFLAGS_NonPublic)
4253 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4255 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, len * 2);
4256 mono_array_memcpy_refs (new_res, 0, res, 0, len);
4260 mono_array_setref (res, i, member);
4264 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, i);
4265 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4268 * Better solution for the new GC.
4269 * res->max_length = i;
4275 static MonoReflectionType*
4276 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4279 MonoType *type = NULL;
4280 MonoTypeNameParse info;
4281 gboolean type_resolve;
4283 MONO_ARCH_SAVE_REGS;
4285 /* On MS.NET, this does not fire a TypeResolve event */
4286 type_resolve = TRUE;
4287 str = mono_string_to_utf8 (name);
4288 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4289 if (!mono_reflection_parse_type (str, &info)) {
4291 mono_reflection_free_type_info (&info);
4292 if (throwOnError) /* uhm: this is a parse error, though... */
4293 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4294 /*g_print ("failed parse\n");*/
4298 if (info.assembly.name) {
4300 mono_reflection_free_type_info (&info);
4302 /* 1.0 and 2.0 throw different exceptions */
4303 if (mono_defaults.generic_ilist_class)
4304 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4306 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4311 if (module != NULL) {
4313 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4318 if (assembly->assembly->dynamic) {
4319 /* Enumerate all modules */
4320 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4324 if (abuilder->modules) {
4325 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4326 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4327 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4333 if (!type && abuilder->loaded_modules) {
4334 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4335 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4336 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4343 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4345 mono_reflection_free_type_info (&info);
4347 MonoException *e = NULL;
4350 e = mono_get_exception_type_load (name, NULL);
4352 mono_loader_clear_error ();
4355 mono_raise_exception (e);
4360 if (type->type == MONO_TYPE_CLASS) {
4361 MonoClass *klass = mono_type_get_class (type);
4363 if (mono_is_security_manager_active () && !klass->exception_type)
4364 /* Some security problems are detected during generic vtable construction */
4365 mono_class_setup_vtable (klass);
4366 /* need to report exceptions ? */
4367 if (throwOnError && klass->exception_type) {
4368 /* report SecurityException (or others) that occured when loading the assembly */
4369 MonoException *exc = mono_class_get_exception_for_failure (klass);
4370 mono_loader_clear_error ();
4371 mono_raise_exception (exc);
4372 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4377 /* g_print ("got it\n"); */
4378 return mono_type_get_object (mono_object_domain (assembly), type);
4382 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4384 MonoDomain *domain = mono_object_domain (assembly);
4385 MonoAssembly *mass = assembly->assembly;
4386 MonoString *res = NULL;
4390 gchar *shadow_ini_file;
4394 MONO_ARCH_SAVE_REGS;
4396 if (g_path_is_absolute (mass->image->name)) {
4397 absolute = g_strdup (mass->image->name);
4398 dirname = g_path_get_dirname (absolute);
4400 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4401 dirname = g_strdup (mass->basedir);
4404 /* Check for shadow-copied assembly */
4405 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4406 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4408 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4409 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4415 g_free (shadow_ini_file);
4416 if (content != NULL) {
4426 for (i = strlen (absolute) - 1; i >= 0; i--)
4427 if (absolute [i] == '\\')
4432 uri = g_filename_to_uri (absolute, NULL, NULL);
4434 const char *prepend = "file://";
4436 if (*absolute == '/' && *(absolute + 1) == '/') {
4439 prepend = "file:///";
4442 uri = g_strconcat (prepend, absolute, NULL);
4446 res = mono_string_new (domain, uri);
4454 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4456 MonoAssembly *mass = assembly->assembly;
4458 MONO_ARCH_SAVE_REGS;
4460 return mass->in_gac;
4463 static MonoReflectionAssembly*
4464 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4468 MonoImageOpenStatus status;
4470 MONO_ARCH_SAVE_REGS;
4472 name = mono_string_to_utf8 (mname);
4473 res = mono_assembly_load_with_partial_name (name, &status);
4479 return mono_assembly_get_object (mono_domain_get (), res);
4483 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4485 MonoDomain *domain = mono_object_domain (assembly);
4488 MONO_ARCH_SAVE_REGS;
4490 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4496 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4498 MONO_ARCH_SAVE_REGS;
4500 return assembly->assembly->ref_only;
4504 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4506 MonoDomain *domain = mono_object_domain (assembly);
4508 MONO_ARCH_SAVE_REGS;
4510 return mono_string_new (domain, assembly->assembly->image->version);
4513 static MonoReflectionMethod*
4514 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4516 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4518 MONO_ARCH_SAVE_REGS;
4522 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4525 static MonoReflectionModule*
4526 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4528 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4532 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4534 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4535 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4539 MONO_ARCH_SAVE_REGS;
4541 for (i = 0; i < table->rows; ++i) {
4542 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4543 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4549 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4551 static MonoClass *System_Version = NULL;
4552 static MonoMethod *create_version = NULL;
4556 if (!System_Version) {
4557 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4558 g_assert (System_Version);
4561 if (!create_version) {
4562 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4563 create_version = mono_method_desc_search_in_class (desc, System_Version);
4564 g_assert (create_version);
4565 mono_method_desc_free (desc);
4571 args [3] = &revision;
4572 result = mono_object_new (domain, System_Version);
4573 mono_runtime_invoke (create_version, result, args, NULL);
4579 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4581 static MonoClass *System_Reflection_AssemblyName;
4583 MonoDomain *domain = mono_object_domain (assembly);
4585 static MonoMethod *create_culture = NULL;
4586 MonoImage *image = assembly->assembly->image;
4589 MONO_ARCH_SAVE_REGS;
4591 if (!System_Reflection_AssemblyName)
4592 System_Reflection_AssemblyName = mono_class_from_name (
4593 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4595 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4598 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4601 MonoMethodDesc *desc = mono_method_desc_new (
4602 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4603 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4604 g_assert (create_culture);
4605 mono_method_desc_free (desc);
4608 for (i = 0; i < count; i++) {
4609 MonoReflectionAssemblyName *aname;
4610 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4612 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4614 aname = (MonoReflectionAssemblyName *) mono_object_new (
4615 domain, System_Reflection_AssemblyName);
4617 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4619 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4620 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4621 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4622 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4623 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4624 aname->versioncompat = 1; /* SameMachine (default) */
4625 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4626 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4628 if (create_culture) {
4630 MonoBoolean assembly_ref = 1;
4631 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4632 args [1] = &assembly_ref;
4633 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4636 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4637 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4638 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4640 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4641 /* public key token isn't copied - the class library will
4642 automatically generate it from the public key if required */
4643 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4644 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4646 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4647 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4650 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4653 /* note: this function doesn't return the codebase on purpose (i.e. it can
4654 be used under partial trust as path information isn't present). */
4656 mono_array_setref (result, i, aname);
4667 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4669 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4671 mono_array_setref (info->res, info->idx, name);
4676 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4678 MonoImage *img = assembly->assembly->image;
4682 MONO_ARCH_SAVE_REGS;
4684 if (!img->name_cache)
4685 mono_image_init_name_cache (img);
4687 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4690 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4695 /* move this in some file in mono/util/ */
4697 g_concat_dir_and_file (const char *dir, const char *file)
4699 g_return_val_if_fail (dir != NULL, NULL);
4700 g_return_val_if_fail (file != NULL, NULL);
4703 * If the directory name doesn't have a / on the end, we need
4704 * to add one so we get a proper path to the file
4706 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4707 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4709 return g_strconcat (dir, file, NULL);
4713 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4715 char *n = mono_string_to_utf8 (name);
4716 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4718 guint32 cols [MONO_MANIFEST_SIZE];
4719 guint32 impl, file_idx;
4723 MONO_ARCH_SAVE_REGS;
4725 for (i = 0; i < table->rows; ++i) {
4726 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4727 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4728 if (strcmp (val, n) == 0)
4732 if (i == table->rows)
4735 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4738 * this code should only be called after obtaining the
4739 * ResourceInfo and handling the other cases.
4741 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4742 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4744 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4749 module = assembly->assembly->image;
4751 *ref_module = mono_module_get_object (mono_domain_get (), module);
4753 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4757 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4759 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4761 guint32 cols [MONO_MANIFEST_SIZE];
4762 guint32 file_cols [MONO_FILE_SIZE];
4766 MONO_ARCH_SAVE_REGS;
4768 n = mono_string_to_utf8 (name);
4769 for (i = 0; i < table->rows; ++i) {
4770 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4771 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4772 if (strcmp (val, n) == 0)
4776 if (i == table->rows)
4779 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4780 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4783 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4784 case MONO_IMPLEMENTATION_FILE:
4785 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4786 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4787 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4788 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4789 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4790 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4793 info->location = RESOURCE_LOCATION_EMBEDDED;
4796 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4797 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4798 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4799 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4800 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4801 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4803 mono_raise_exception (ex);
4805 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4807 /* Obtain info recursively */
4808 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4809 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4812 case MONO_IMPLEMENTATION_EXP_TYPE:
4813 g_assert_not_reached ();
4822 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4824 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4825 MonoArray *result = NULL;
4830 MONO_ARCH_SAVE_REGS;
4832 /* check hash if needed */
4834 n = mono_string_to_utf8 (name);
4835 for (i = 0; i < table->rows; ++i) {
4836 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4837 if (strcmp (val, n) == 0) {
4840 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4841 fn = mono_string_new (mono_object_domain (assembly), n);
4843 return (MonoObject*)fn;
4851 for (i = 0; i < table->rows; ++i) {
4852 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4856 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4859 for (i = 0; i < table->rows; ++i) {
4860 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4861 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4862 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4863 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4868 return (MonoObject*)result;
4872 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4874 MonoDomain *domain = mono_domain_get();
4877 int i, j, file_count = 0;
4878 MonoImage **modules;
4879 guint32 module_count, real_module_count;
4880 MonoTableInfo *table;
4881 guint32 cols [MONO_FILE_SIZE];
4882 MonoImage *image = assembly->assembly->image;
4884 g_assert (image != NULL);
4885 g_assert (!assembly->assembly->dynamic);
4887 table = &image->tables [MONO_TABLE_FILE];
4888 file_count = table->rows;
4890 modules = image->modules;
4891 module_count = image->module_count;
4893 real_module_count = 0;
4894 for (i = 0; i < module_count; ++i)
4896 real_module_count ++;
4898 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4899 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4901 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4903 for (i = 0; i < module_count; ++i)
4905 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4909 for (i = 0; i < file_count; ++i, ++j) {
4910 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4911 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4912 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4914 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4916 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4917 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4919 mono_array_setref (res, j, mono_module_get_object (domain, m));
4926 static MonoReflectionMethod*
4927 ves_icall_GetCurrentMethod (void)
4929 MonoMethod *m = mono_method_get_last_managed ();
4931 MONO_ARCH_SAVE_REGS;
4933 return mono_method_get_object (mono_domain_get (), m, NULL);
4938 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4941 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4942 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4943 //method is inflated, we should inflate it on the other class
4944 MonoGenericContext ctx;
4945 ctx.method_inst = inflated->context.method_inst;
4946 ctx.class_inst = inflated->context.class_inst;
4947 if (klass->generic_class)
4948 ctx.class_inst = klass->generic_class->context.class_inst;
4949 else if (klass->generic_container)
4950 ctx.class_inst = klass->generic_container->context.class_inst;
4951 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4954 mono_class_setup_methods (method->klass);
4955 for (i = 0; i < method->klass->method.count; ++i) {
4956 if (method->klass->methods [i] == method) {
4961 mono_class_setup_methods (klass);
4962 g_assert (offset >= 0 && offset < klass->method.count);
4963 return klass->methods [offset];
4966 static MonoReflectionMethod*
4967 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4971 klass = mono_class_from_mono_type (type);
4972 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4974 if (method->klass != klass)
4975 method = mono_method_get_equivalent_method (method, klass);
4977 klass = method->klass;
4978 return mono_method_get_object (mono_domain_get (), method, klass);
4981 static MonoReflectionMethod*
4982 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4984 return mono_method_get_object (mono_domain_get (), method, NULL);
4987 static MonoReflectionMethodBody*
4988 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4990 return mono_method_body_get_object (mono_domain_get (), method);
4993 static MonoReflectionAssembly*
4994 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4996 MonoMethod *dest = NULL;
4998 MONO_ARCH_SAVE_REGS;
5000 mono_stack_walk_no_il (get_executing, &dest);
5001 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5005 static MonoReflectionAssembly*
5006 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5008 MonoDomain* domain = mono_domain_get ();
5010 MONO_ARCH_SAVE_REGS;
5012 if (!domain->entry_assembly)
5015 return mono_assembly_get_object (domain, domain->entry_assembly);
5018 static MonoReflectionAssembly*
5019 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5024 MONO_ARCH_SAVE_REGS;
5027 mono_stack_walk_no_il (get_executing, &dest);
5029 mono_stack_walk_no_il (get_caller, &dest);
5032 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5036 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5037 gboolean assembly_qualified)
5039 MonoDomain *domain = mono_object_domain (object);
5040 MonoTypeNameFormat format;
5044 MONO_ARCH_SAVE_REGS;
5046 format = assembly_qualified ?
5047 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5048 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5050 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5052 name = mono_type_get_name_full (object->type, format);
5056 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5061 res = mono_string_new (domain, name);
5068 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5070 static MonoMethod *create_culture = NULL;
5073 const char *pkey_ptr;
5075 MonoBoolean assembly_ref = 0;
5077 MONO_ARCH_SAVE_REGS;
5079 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5080 aname->major = name->major;
5081 aname->minor = name->minor;
5082 aname->build = name->build;
5083 aname->flags = name->flags;
5084 aname->revision = name->revision;
5085 aname->hashalg = name->hash_alg;
5086 aname->versioncompat = 1; /* SameMachine (default) */
5088 if (by_default_version)
5089 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5092 if (absolute != NULL && *absolute != '\0') {
5093 const gchar *prepend = "file://";
5096 codebase = g_strdup (absolute);
5101 for (i = strlen (codebase) - 1; i >= 0; i--)
5102 if (codebase [i] == '\\')
5105 if (*codebase == '/' && *(codebase + 1) == '/') {
5108 prepend = "file:///";
5112 result = g_strconcat (prepend, codebase, NULL);
5118 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5122 if (!create_culture) {
5123 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5124 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5125 g_assert (create_culture);
5126 mono_method_desc_free (desc);
5129 if (name->culture) {
5130 args [0] = mono_string_new (domain, name->culture);
5131 args [1] = &assembly_ref;
5132 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5135 if (name->public_key) {
5136 pkey_ptr = (char*)name->public_key;
5137 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5139 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5140 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5141 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5142 } else if (default_publickey) {
5143 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5144 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5147 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5148 if (name->public_key_token [0]) {
5152 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5153 p = mono_array_addr (aname->keyToken, char, 0);
5155 for (i = 0, j = 0; i < 8; i++) {
5156 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5157 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5160 } else if (default_token) {
5161 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5166 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5168 MonoDomain *domain = mono_object_domain (assembly);
5169 MonoAssembly *mass = assembly->assembly;
5173 name = g_strdup_printf (
5174 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5176 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5177 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5178 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5179 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5181 res = mono_string_new (domain, name);
5188 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5191 MonoAssembly *mass = assembly->assembly;
5193 MONO_ARCH_SAVE_REGS;
5195 if (g_path_is_absolute (mass->image->name)) {
5196 fill_reflection_assembly_name (mono_object_domain (assembly),
5197 aname, &mass->aname, mass->image->name, TRUE,
5198 TRUE, mono_framework_version () >= 2);
5201 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5203 fill_reflection_assembly_name (mono_object_domain (assembly),
5204 aname, &mass->aname, absolute, TRUE, TRUE,
5205 mono_framework_version () >= 2);
5211 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5214 MonoImageOpenStatus status = MONO_IMAGE_OK;
5217 MonoAssemblyName name;
5219 MONO_ARCH_SAVE_REGS;
5221 filename = mono_string_to_utf8 (fname);
5223 image = mono_image_open (filename, &status);
5229 if (status == MONO_IMAGE_IMAGE_INVALID)
5230 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5232 exc = mono_get_exception_file_not_found2 (NULL, fname);
5233 mono_raise_exception (exc);
5236 res = mono_assembly_fill_assembly_name (image, &name);
5238 mono_image_close (image);
5240 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5243 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5244 TRUE, mono_framework_version () == 1,
5245 mono_framework_version () >= 2);
5248 mono_image_close (image);
5252 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5253 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5255 MonoBoolean result = FALSE;
5256 MonoDeclSecurityEntry entry;
5258 /* SecurityAction.RequestMinimum */
5259 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5260 *minimum = entry.blob;
5261 *minLength = entry.size;
5264 /* SecurityAction.RequestOptional */
5265 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5266 *optional = entry.blob;
5267 *optLength = entry.size;
5270 /* SecurityAction.RequestRefuse */
5271 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5272 *refused = entry.blob;
5273 *refLength = entry.size;
5281 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5285 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5287 guint32 attrs, visibility;
5289 /* we start the count from 1 because we skip the special type <Module> */
5292 for (i = 1; i < tdef->rows; ++i) {
5293 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5294 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5295 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5299 count = tdef->rows - 1;
5301 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5302 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5304 for (i = 1; i < tdef->rows; ++i) {
5305 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5306 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5307 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5308 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5310 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5312 MonoLoaderError *error;
5315 error = mono_loader_get_last_error ();
5316 g_assert (error != NULL);
5318 ex = mono_loader_error_prepare_exception (error);
5319 mono_array_setref (*exceptions, count, ex);
5321 if (mono_loader_get_last_error ())
5322 mono_loader_clear_error ();
5331 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5333 MonoArray *res = NULL;
5334 MonoArray *exceptions = NULL;
5335 MonoImage *image = NULL;
5336 MonoTableInfo *table = NULL;
5339 int i, len, ex_count;
5341 MONO_ARCH_SAVE_REGS;
5343 domain = mono_object_domain (assembly);
5345 g_assert (!assembly->assembly->dynamic);
5346 image = assembly->assembly->image;
5347 table = &image->tables [MONO_TABLE_FILE];
5348 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5350 /* Append data from all modules in the assembly */
5351 for (i = 0; i < table->rows; ++i) {
5352 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5353 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5356 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5357 /* Append the new types to the end of the array */
5358 if (mono_array_length (res2) > 0) {
5360 MonoArray *res3, *ex3;
5362 len1 = mono_array_length (res);
5363 len2 = mono_array_length (res2);
5365 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5366 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5367 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5370 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5371 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5372 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5379 /* the ReflectionTypeLoadException must have all the types (Types property),
5380 * NULL replacing types which throws an exception. The LoaderException must
5381 * contain all exceptions for NULL items.
5384 len = mono_array_length (res);
5387 for (i = 0; i < len; i++) {
5388 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5392 klass = mono_type_get_class (t->type);
5393 if ((klass != NULL) && klass->exception_type) {
5394 /* keep the class in the list */
5395 list = g_list_append (list, klass);
5396 /* and replace Type with NULL */
5397 mono_array_setref (res, i, NULL);
5404 if (list || ex_count) {
5406 MonoException *exc = NULL;
5407 MonoArray *exl = NULL;
5408 int j, length = g_list_length (list) + ex_count;
5410 mono_loader_clear_error ();
5412 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5413 /* Types for which mono_class_get () succeeded */
5414 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5415 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5416 mono_array_setref (exl, i, exc);
5418 /* Types for which it don't */
5419 for (j = 0; j < mono_array_length (exceptions); ++j) {
5420 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5422 g_assert (i < length);
5423 mono_array_setref (exl, i, exc);
5430 exc = mono_get_exception_reflection_type_load (res, exl);
5431 mono_loader_clear_error ();
5432 mono_raise_exception (exc);
5439 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5441 MonoAssemblyName aname;
5442 MonoDomain *domain = mono_object_domain (name);
5444 gboolean is_version_defined;
5445 gboolean is_token_defined;
5447 aname.public_key = NULL;
5448 val = mono_string_to_utf8 (assname);
5449 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5450 g_free ((guint8*) aname.public_key);
5455 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5456 FALSE, is_token_defined);
5458 mono_assembly_name_free (&aname);
5459 g_free ((guint8*) aname.public_key);
5465 static MonoReflectionType*
5466 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5468 MonoDomain *domain = mono_object_domain (module);
5471 MONO_ARCH_SAVE_REGS;
5473 g_assert (module->image);
5475 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5476 /* These images do not have a global type */
5479 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5480 return mono_type_get_object (domain, &klass->byval_arg);
5484 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5486 /*if (module->image)
5487 mono_image_close (module->image);*/
5491 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5493 MonoDomain *domain = mono_object_domain (module);
5495 MONO_ARCH_SAVE_REGS;
5497 g_assert (module->image);
5498 return mono_string_new (domain, module->image->guid);
5502 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5504 #ifdef PLATFORM_WIN32
5505 if (module->image && module->image->is_module_handle)
5506 return module->image->raw_data;
5509 return (gpointer) (-1);
5513 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5515 if (image->dynamic) {
5516 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5517 *pe_kind = dyn->pe_kind;
5518 *machine = dyn->machine;
5521 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5522 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5527 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5529 return (image->md_version_major << 16) | (image->md_version_minor);
5533 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5535 MonoArray *exceptions;
5538 MONO_ARCH_SAVE_REGS;
5541 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5543 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5544 for (i = 0; i < mono_array_length (exceptions); ++i) {
5545 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5547 mono_raise_exception (ex);
5554 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5556 guint32 cols [MONO_MEMBERREF_SIZE];
5558 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5559 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5560 mono_metadata_decode_blob_size (sig, &sig);
5561 return (*sig != 0x6);
5565 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5568 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5569 mono_array_addr (type_args, MonoType*, 0));
5571 context->class_inst = NULL;
5573 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5574 mono_array_addr (method_args, MonoType*, 0));
5576 context->method_inst = NULL;
5580 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5583 int table = mono_metadata_token_table (token);
5584 int index = mono_metadata_token_index (token);
5585 MonoGenericContext context;
5587 *error = ResolveTokenError_Other;
5589 /* Validate token */
5590 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5591 (table != MONO_TABLE_TYPESPEC)) {
5592 *error = ResolveTokenError_BadTable;
5596 if (image->dynamic) {
5597 if (type_args || method_args)
5598 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5599 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5602 return &klass->byval_arg;
5605 if ((index <= 0) || (index > image->tables [table].rows)) {
5606 *error = ResolveTokenError_OutOfRange;
5610 init_generic_context_from_args (&context, type_args, method_args);
5611 klass = mono_class_get_full (image, token, &context);
5613 if (mono_loader_get_last_error ())
5614 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5617 return &klass->byval_arg;
5623 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5625 int table = mono_metadata_token_table (token);
5626 int index = mono_metadata_token_index (token);
5627 MonoGenericContext context;
5630 *error = ResolveTokenError_Other;
5632 /* Validate token */
5633 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5634 (table != MONO_TABLE_MEMBERREF)) {
5635 *error = ResolveTokenError_BadTable;
5639 if (image->dynamic) {
5640 if (type_args || method_args)
5641 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5642 /* FIXME: validate memberref token type */
5643 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5646 if ((index <= 0) || (index > image->tables [table].rows)) {
5647 *error = ResolveTokenError_OutOfRange;
5650 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5651 *error = ResolveTokenError_BadTable;
5655 init_generic_context_from_args (&context, type_args, method_args);
5656 method = mono_get_method_full (image, token, NULL, &context);
5658 if (mono_loader_get_last_error ())
5659 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5665 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5667 int index = mono_metadata_token_index (token);
5669 *error = ResolveTokenError_Other;
5671 /* Validate token */
5672 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5673 *error = ResolveTokenError_BadTable;
5678 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5680 if ((index <= 0) || (index >= image->heap_us.size)) {
5681 *error = ResolveTokenError_OutOfRange;
5685 /* FIXME: What to do if the index points into the middle of a string ? */
5687 return mono_ldstr (mono_domain_get (), image, index);
5690 static MonoClassField*
5691 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5694 int table = mono_metadata_token_table (token);
5695 int index = mono_metadata_token_index (token);
5696 MonoGenericContext context;
5697 MonoClassField *field;
5699 *error = ResolveTokenError_Other;
5701 /* Validate token */
5702 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5703 *error = ResolveTokenError_BadTable;
5707 if (image->dynamic) {
5708 if (type_args || method_args)
5709 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5710 /* FIXME: validate memberref token type */
5711 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5714 if ((index <= 0) || (index > image->tables [table].rows)) {
5715 *error = ResolveTokenError_OutOfRange;
5718 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5719 *error = ResolveTokenError_BadTable;
5723 init_generic_context_from_args (&context, type_args, method_args);
5724 field = mono_field_from_token (image, token, &klass, &context);
5726 if (mono_loader_get_last_error ())
5727 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5734 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5736 int table = mono_metadata_token_table (token);
5738 *error = ResolveTokenError_Other;
5741 case MONO_TABLE_TYPEDEF:
5742 case MONO_TABLE_TYPEREF:
5743 case MONO_TABLE_TYPESPEC: {
5744 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5746 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5750 case MONO_TABLE_METHOD:
5751 case MONO_TABLE_METHODSPEC: {
5752 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5754 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5758 case MONO_TABLE_FIELD: {
5759 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5761 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5765 case MONO_TABLE_MEMBERREF:
5766 if (mono_metadata_memberref_is_method (image, token)) {
5767 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5769 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5774 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5776 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5783 *error = ResolveTokenError_BadTable;
5790 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5792 int table = mono_metadata_token_table (token);
5793 int idx = mono_metadata_token_index (token);
5794 MonoTableInfo *tables = image->tables;
5799 *error = ResolveTokenError_OutOfRange;
5801 /* FIXME: Support other tables ? */
5802 if (table != MONO_TABLE_STANDALONESIG)
5808 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5811 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5813 ptr = mono_metadata_blob_heap (image, sig);
5814 len = mono_metadata_decode_blob_size (ptr, &ptr);
5816 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5817 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5821 static MonoReflectionType*
5822 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5825 int isbyref = 0, rank;
5826 char *str = mono_string_to_utf8 (smodifiers);
5829 MONO_ARCH_SAVE_REGS;
5831 klass = mono_class_from_mono_type (tb->type.type);
5833 /* logic taken from mono_reflection_parse_type(): keep in sync */
5837 if (isbyref) { /* only one level allowed by the spec */
5844 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5847 klass = mono_ptr_class_get (&klass->byval_arg);
5848 mono_class_init (klass);
5859 else if (*p != '*') { /* '*' means unknown lower bound */
5870 klass = mono_array_class_get (klass, rank);
5871 mono_class_init (klass);
5878 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5882 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5887 MONO_ARCH_SAVE_REGS;
5890 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5895 static MonoReflectionType *
5896 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5898 MonoClass *klass, *aklass;
5900 MONO_ARCH_SAVE_REGS;
5902 klass = mono_class_from_mono_type (type->type);
5903 aklass = mono_array_class_get (klass, rank);
5905 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5908 static MonoReflectionType *
5909 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5913 MONO_ARCH_SAVE_REGS;
5915 klass = mono_class_from_mono_type (type->type);
5917 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5920 static MonoReflectionType *
5921 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5925 MONO_ARCH_SAVE_REGS;
5927 pklass = mono_ptr_class_get (type->type);
5929 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5933 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5934 MonoReflectionMethod *info)
5936 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5937 MonoObject *delegate;
5939 MonoMethod *method = info->method;
5941 MONO_ARCH_SAVE_REGS;
5943 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5945 /* FIME: We must check if target is visible to the caller under coreclr.
5946 * The check should be disabled otherwise as it shouldn't raise expection under fulltrust.
5949 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5951 if (mono_method_needs_static_rgctx_invoke (method, FALSE)) {
5952 method = mono_marshal_get_static_rgctx_invoke (method);
5953 func = mono_compile_method (method);
5954 } else if (method->dynamic) {
5955 /* Creating a trampoline would leak memory */
5956 func = mono_compile_method (method);
5958 func = mono_create_ftnptr (mono_domain_get (),
5959 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5962 mono_delegate_ctor_with_method (delegate, target, func, method);
5968 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5970 /* Reset the invoke impl to the default one */
5971 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5975 * Magic number to convert a time which is relative to
5976 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5978 #define EPOCH_ADJUST ((guint64)62135596800LL)
5981 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5983 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5985 #ifdef PLATFORM_WIN32
5986 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5988 convert_to_absolute_date(SYSTEMTIME *date)
5990 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5991 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5992 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5993 /* from the calendar FAQ */
5994 int a = (14 - date->wMonth) / 12;
5995 int y = date->wYear - a;
5996 int m = date->wMonth + 12 * a - 2;
5997 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5999 /* d is now the day of the week for the first of the month (0 == Sunday) */
6001 int day_of_week = date->wDayOfWeek;
6003 /* set day_in_month to the first day in the month which falls on day_of_week */
6004 int day_in_month = 1 + (day_of_week - d);
6005 if (day_in_month <= 0)
6008 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
6009 date->wDay = day_in_month + (date->wDay - 1) * 7;
6010 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6015 #ifndef PLATFORM_WIN32
6017 * Return's the offset from GMT of a local time.
6019 * tm is a local time
6020 * t is the same local time as seconds.
6023 gmt_offset(struct tm *tm, time_t t)
6025 #if defined (HAVE_TM_GMTOFF)
6026 return tm->tm_gmtoff;
6031 g.tm_isdst = tm->tm_isdst;
6033 return (int)difftime(t, t2);
6038 * This is heavily based on zdump.c from glibc 2.2.
6040 * * data[0]: start of daylight saving time (in DateTime ticks).
6041 * * data[1]: end of daylight saving time (in DateTime ticks).
6042 * * data[2]: utcoffset (in TimeSpan ticks).
6043 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
6044 * * name[0]: name of this timezone when not daylight saving.
6045 * * name[1]: name of this timezone when daylight saving.
6047 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6048 * the class library allows years between 1 and 9999.
6050 * Returns true on success and zero on failure.
6053 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6055 #ifndef PLATFORM_WIN32
6056 MonoDomain *domain = mono_domain_get ();
6057 struct tm start, tt;
6061 int is_daylight = 0, day;
6064 MONO_ARCH_SAVE_REGS;
6066 MONO_CHECK_ARG_NULL (data);
6067 MONO_CHECK_ARG_NULL (names);
6069 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6070 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6073 * no info is better than crashing: we'll need our own tz data
6074 * to make this work properly, anyway. The range is probably
6075 * reduced to 1970 .. 2037 because that is what mktime is
6076 * guaranteed to support (we get into an infinite loop
6080 memset (&start, 0, sizeof (start));
6083 start.tm_year = year-1900;
6085 t = mktime (&start);
6087 if ((year < 1970) || (year > 2037) || (t == -1)) {
6089 tt = *localtime (&t);
6090 strftime (tzone, sizeof (tzone), "%Z", &tt);
6091 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6092 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6096 gmtoff = gmt_offset (&start, t);
6098 /* For each day of the year, calculate the tm_gmtoff. */
6099 for (day = 0; day < 365; day++) {
6102 tt = *localtime (&t);
6104 /* Daylight saving starts or ends here. */
6105 if (gmt_offset (&tt, t) != gmtoff) {
6109 /* Try to find the exact hour when daylight saving starts/ends. */
6113 tt1 = *localtime (&t1);
6114 } while (gmt_offset (&tt1, t1) != gmtoff);
6116 /* Try to find the exact minute when daylight saving starts/ends. */
6119 tt1 = *localtime (&t1);
6120 } while (gmt_offset (&tt1, t1) == gmtoff);
6122 strftime (tzone, sizeof (tzone), "%Z", &tt);
6124 /* Write data, if we're already in daylight saving, we're done. */
6126 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6127 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6130 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6131 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6135 /* This is only set once when we enter daylight saving. */
6136 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6137 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6139 gmtoff = gmt_offset (&tt, t);
6144 strftime (tzone, sizeof (tzone), "%Z", &tt);
6145 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6146 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6147 mono_array_set ((*data), gint64, 0, 0);
6148 mono_array_set ((*data), gint64, 1, 0);
6149 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6150 mono_array_set ((*data), gint64, 3, 0);
6155 MonoDomain *domain = mono_domain_get ();
6156 TIME_ZONE_INFORMATION tz_info;
6161 tz_id = GetTimeZoneInformation (&tz_info);
6162 if (tz_id == TIME_ZONE_ID_INVALID)
6165 MONO_CHECK_ARG_NULL (data);
6166 MONO_CHECK_ARG_NULL (names);
6168 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6169 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6171 for (i = 0; i < 32; ++i)
6172 if (!tz_info.DaylightName [i])
6174 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6175 for (i = 0; i < 32; ++i)
6176 if (!tz_info.StandardName [i])
6178 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6180 if ((year <= 1601) || (year > 30827)) {
6182 * According to MSDN, the MS time functions can't handle dates outside
6188 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6189 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6190 tz_info.StandardDate.wYear = year;
6191 convert_to_absolute_date(&tz_info.StandardDate);
6192 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6197 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6198 tz_info.DaylightDate.wYear = year;
6199 convert_to_absolute_date(&tz_info.DaylightDate);
6200 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6205 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6207 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6208 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6215 ves_icall_System_Object_obj_address (MonoObject *this)
6217 MONO_ARCH_SAVE_REGS;
6224 static inline gint32
6225 mono_array_get_byte_length (MonoArray *array)
6231 klass = array->obj.vtable->klass;
6233 if (array->bounds == NULL)
6234 length = array->max_length;
6237 for (i = 0; i < klass->rank; ++ i)
6238 length *= array->bounds [i].length;
6241 switch (klass->element_class->byval_arg.type) {
6244 case MONO_TYPE_BOOLEAN:
6248 case MONO_TYPE_CHAR:
6256 return length * sizeof (gpointer);
6267 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6269 MONO_ARCH_SAVE_REGS;
6271 return mono_array_get_byte_length (array);
6275 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6277 MONO_ARCH_SAVE_REGS;
6279 return mono_array_get (array, gint8, idx);
6283 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6285 MONO_ARCH_SAVE_REGS;
6287 mono_array_set (array, gint8, idx, value);
6291 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6293 guint8 *src_buf, *dest_buf;
6295 MONO_ARCH_SAVE_REGS;
6297 /* watch out for integer overflow */
6298 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6301 src_buf = (guint8 *)src->vector + src_offset;
6302 dest_buf = (guint8 *)dest->vector + dest_offset;
6305 memcpy (dest_buf, src_buf, count);
6307 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6313 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6315 MonoDomain *domain = mono_object_domain (this);
6317 MonoRealProxy *rp = ((MonoRealProxy *)this);
6318 MonoTransparentProxy *tp;
6322 MONO_ARCH_SAVE_REGS;
6324 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6325 tp = (MonoTransparentProxy*) res;
6327 MONO_OBJECT_SETREF (tp, rp, rp);
6328 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6329 klass = mono_class_from_mono_type (type);
6331 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6332 tp->remote_class = mono_remote_class (domain, class_name, klass);
6334 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6338 static MonoReflectionType *
6339 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6341 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6344 /* System.Environment */
6347 ves_icall_System_Environment_get_MachineName (void)
6349 #if defined (PLATFORM_WIN32)
6354 len = MAX_COMPUTERNAME_LENGTH + 1;
6355 buf = g_new (gunichar2, len);
6358 if (GetComputerName (buf, (PDWORD) &len))
6359 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6363 #elif !defined(DISABLE_SOCKETS)
6367 if (gethostname (buf, sizeof (buf)) == 0)
6368 result = mono_string_new (mono_domain_get (), buf);
6374 return mono_string_new (mono_domain_get (), "mono");
6379 ves_icall_System_Environment_get_Platform (void)
6381 #if defined (PLATFORM_WIN32)
6384 #elif defined(__MACH__)
6386 if (mono_framework_version () < 2)
6390 // For compatibility with our client code, this will be 4 for a while.
6391 // We will eventually move to 6 to match .NET, but it requires all client
6392 // code to be updated and the documentation everywhere to be updated
6398 if (mono_framework_version () < 2)
6405 ves_icall_System_Environment_get_NewLine (void)
6407 MONO_ARCH_SAVE_REGS;
6409 #if defined (PLATFORM_WIN32)
6410 return mono_string_new (mono_domain_get (), "\r\n");
6412 return mono_string_new (mono_domain_get (), "\n");
6417 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6422 MONO_ARCH_SAVE_REGS;
6427 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6428 value = g_getenv (utf8_name);
6435 return mono_string_new (mono_domain_get (), value);
6439 * There is no standard way to get at environ.
6442 #ifndef __MINGW32_VERSION
6444 /* Apple defines this in crt_externs.h but doesn't provide that header for
6445 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6446 * in fact exist on all implementations (so far)
6448 gchar ***_NSGetEnviron();
6449 #define environ (*_NSGetEnviron())
6458 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6460 #ifdef PLATFORM_WIN32
6469 env_strings = GetEnvironmentStrings();
6472 env_string = env_strings;
6473 while (*env_string != '\0') {
6474 /* weird case that MS seems to skip */
6475 if (*env_string != '=')
6477 while (*env_string != '\0')
6483 domain = mono_domain_get ();
6484 names = mono_array_new (domain, mono_defaults.string_class, n);
6488 env_string = env_strings;
6489 while (*env_string != '\0') {
6490 /* weird case that MS seems to skip */
6491 if (*env_string != '=') {
6492 equal_str = wcschr(env_string, '=');
6493 g_assert(equal_str);
6494 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6495 mono_array_setref (names, n, str);
6498 while (*env_string != '\0')
6503 FreeEnvironmentStrings (env_strings);
6515 MONO_ARCH_SAVE_REGS;
6518 for (e = environ; *e != 0; ++ e)
6521 domain = mono_domain_get ();
6522 names = mono_array_new (domain, mono_defaults.string_class, n);
6525 for (e = environ; *e != 0; ++ e) {
6526 parts = g_strsplit (*e, "=", 2);
6528 str = mono_string_new (domain, *parts);
6529 mono_array_setref (names, n, str);
6542 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6544 #if !GLIB_CHECK_VERSION(2,4,0)
6545 #define g_setenv(a,b,c) setenv(a,b,c)
6546 #define g_unsetenv(a) unsetenv(a)
6550 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6552 #ifdef PLATFORM_WIN32
6553 gunichar2 *utf16_name, *utf16_value;
6555 gchar *utf8_name, *utf8_value;
6558 MONO_ARCH_SAVE_REGS;
6560 #ifdef PLATFORM_WIN32
6561 utf16_name = mono_string_to_utf16 (name);
6562 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6563 SetEnvironmentVariable (utf16_name, NULL);
6564 g_free (utf16_name);
6568 utf16_value = mono_string_to_utf16 (value);
6570 SetEnvironmentVariable (utf16_name, utf16_value);
6572 g_free (utf16_name);
6573 g_free (utf16_value);
6575 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6577 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6578 g_unsetenv (utf8_name);
6583 utf8_value = mono_string_to_utf8 (value);
6584 g_setenv (utf8_name, utf8_value, TRUE);
6587 g_free (utf8_value);
6592 ves_icall_System_Environment_Exit (int result)
6594 MONO_ARCH_SAVE_REGS;
6596 mono_threads_set_shutting_down ();
6598 mono_runtime_set_shutting_down ();
6600 /* Suspend all managed threads since the runtime is going away */
6601 mono_thread_suspend_all_other_threads ();
6603 mono_runtime_quit ();
6605 /* we may need to do some cleanup here... */
6610 ves_icall_System_Environment_GetGacPath (void)
6612 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6616 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6618 #if defined (PLATFORM_WIN32)
6619 #ifndef CSIDL_FLAG_CREATE
6620 #define CSIDL_FLAG_CREATE 0x8000
6623 WCHAR path [MAX_PATH];
6624 /* Create directory if no existing */
6625 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6629 return mono_string_new_utf16 (mono_domain_get (), path, len);
6632 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6634 return mono_string_new (mono_domain_get (), "");
6638 ves_icall_System_Environment_GetLogicalDrives (void)
6640 gunichar2 buf [128], *ptr, *dname;
6642 guint initial_size = 127, size = 128;
6645 MonoString *drivestr;
6646 MonoDomain *domain = mono_domain_get ();
6649 MONO_ARCH_SAVE_REGS;
6654 while (size > initial_size) {
6655 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6656 if (size > initial_size) {
6659 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6660 initial_size = size;
6674 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6679 while (*u16) { u16++; len ++; }
6680 drivestr = mono_string_new_utf16 (domain, dname, len);
6681 mono_array_setref (result, ndrives++, drivestr);
6692 ves_icall_System_Environment_InternalGetHome (void)
6694 MONO_ARCH_SAVE_REGS;
6696 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6699 static const char *encodings [] = {
6701 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6702 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6703 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6705 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6706 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6707 "x_unicode_2_0_utf_7",
6709 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6710 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6712 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6715 "unicodefffe", "utf_16be",
6722 * Returns the internal codepage, if the value of "int_code_page" is
6723 * 1 at entry, and we can not compute a suitable code page number,
6724 * returns the code page as a string
6727 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6732 char *codepage = NULL;
6734 int want_name = *int_code_page;
6737 *int_code_page = -1;
6738 MONO_ARCH_SAVE_REGS;
6740 g_get_charset (&cset);
6741 c = codepage = strdup (cset);
6742 for (c = codepage; *c; c++){
6743 if (isascii (*c) && isalpha (*c))
6748 /* g_print ("charset: %s\n", cset); */
6750 /* handle some common aliases */
6753 for (i = 0; p != 0; ){
6754 if ((gssize) p < 7){
6756 p = encodings [++i];
6759 if (strcmp (p, codepage) == 0){
6760 *int_code_page = code;
6763 p = encodings [++i];
6766 if (strstr (codepage, "utf_8") != NULL)
6767 *int_code_page |= 0x10000000;
6770 if (want_name && *int_code_page == -1)
6771 return mono_string_new (mono_domain_get (), cset);
6777 ves_icall_System_Environment_get_HasShutdownStarted (void)
6779 if (mono_runtime_is_shutting_down ())
6782 if (mono_domain_is_unloading (mono_domain_get ()))
6789 ves_icall_System_Environment_BroadcastSettingChange (void)
6791 #ifdef PLATFORM_WIN32
6792 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6797 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6798 MonoReflectionMethod *method,
6799 MonoArray *out_args)
6801 MONO_ARCH_SAVE_REGS;
6803 mono_message_init (mono_object_domain (this), this, method, out_args);
6807 ves_icall_IsTransparentProxy (MonoObject *proxy)
6809 MONO_ARCH_SAVE_REGS;
6814 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6820 static MonoReflectionMethod *
6821 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6822 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6826 MonoMethod **vtable;
6827 MonoMethod *res = NULL;
6829 MONO_CHECK_ARG_NULL (rtype);
6830 MONO_CHECK_ARG_NULL (rmethod);
6832 method = rmethod->method;
6833 klass = mono_class_from_mono_type (rtype->type);
6835 if (MONO_CLASS_IS_INTERFACE (klass))
6838 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6841 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6842 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6848 mono_class_setup_vtable (klass);
6849 vtable = klass->vtable;
6851 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6852 int offs = mono_class_interface_offset (klass, method->klass);
6854 res = vtable [offs + method->slot];
6856 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6859 if (method->slot != -1)
6860 res = vtable [method->slot];
6866 return mono_method_get_object (mono_domain_get (), res, NULL);
6870 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6875 MONO_ARCH_SAVE_REGS;
6877 klass = mono_class_from_mono_type (type->type);
6878 vtable = mono_class_vtable (mono_domain_get (), klass);
6880 if (enable) vtable->remote = 1;
6881 else vtable->remote = 0;
6885 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6890 MONO_ARCH_SAVE_REGS;
6892 domain = mono_object_domain (type);
6893 klass = mono_class_from_mono_type (type->type);
6895 if (klass->rank >= 1) {
6896 g_assert (klass->rank == 1);
6897 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6899 /* Bypass remoting object creation check */
6900 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6905 ves_icall_System_IO_get_temp_path (void)
6907 MONO_ARCH_SAVE_REGS;
6909 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6913 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6914 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6918 ULARGE_INTEGER wapi_free_bytes_avail;
6919 ULARGE_INTEGER wapi_total_number_of_bytes;
6920 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6922 MONO_ARCH_SAVE_REGS;
6924 *error = ERROR_SUCCESS;
6925 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6926 &wapi_total_number_of_free_bytes);
6929 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6930 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6931 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6933 *free_bytes_avail = 0;
6934 *total_number_of_bytes = 0;
6935 *total_number_of_free_bytes = 0;
6936 *error = GetLastError ();
6943 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6945 MONO_ARCH_SAVE_REGS;
6947 return GetDriveType (mono_string_chars (root_path_name));
6951 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6953 MONO_ARCH_SAVE_REGS;
6955 return mono_compile_method (method);
6959 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6964 MONO_ARCH_SAVE_REGS;
6966 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6968 #if defined (PLATFORM_WIN32)
6969 /* Avoid mixing '/' and '\\' */
6972 for (i = strlen (path) - 1; i >= 0; i--)
6973 if (path [i] == '/')
6977 mcpath = mono_string_new (mono_domain_get (), path);
6984 get_bundled_machine_config (void)
6986 const gchar *machine_config;
6988 MONO_ARCH_SAVE_REGS;
6990 machine_config = mono_get_machine_config ();
6992 if (!machine_config)
6995 return mono_string_new (mono_domain_get (), machine_config);
6999 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7004 MONO_ARCH_SAVE_REGS;
7006 path = g_path_get_dirname (mono_get_config_dir ());
7008 #if defined (PLATFORM_WIN32)
7009 /* Avoid mixing '/' and '\\' */
7012 for (i = strlen (path) - 1; i >= 0; i--)
7013 if (path [i] == '/')
7017 ipath = mono_string_new (mono_domain_get (), path);
7024 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7026 return mono_debug_using_mono_debugger ();
7030 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7032 #if defined (PLATFORM_WIN32)
7033 OutputDebugString (mono_string_chars (message));
7035 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7039 /* Only used for value types */
7041 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7046 MONO_ARCH_SAVE_REGS;
7048 domain = mono_object_domain (type);
7049 klass = mono_class_from_mono_type (type->type);
7051 if (mono_class_is_nullable (klass))
7052 /* No arguments -> null */
7055 return mono_object_new (domain, klass);
7058 static MonoReflectionMethod *
7059 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7061 MonoClass *klass, *parent;
7062 MonoMethod *method = m->method;
7063 MonoMethod *result = NULL;
7065 MONO_ARCH_SAVE_REGS;
7067 if (method->klass == NULL)
7070 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7071 MONO_CLASS_IS_INTERFACE (method->klass) ||
7072 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7075 klass = method->klass;
7076 if (klass->generic_class)
7077 klass = klass->generic_class->container_class;
7079 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7080 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7081 mono_class_setup_vtable (parent);
7082 if (parent->vtable_size <= method->slot)
7087 if (klass == method->klass)
7090 result = klass->vtable [method->slot];
7091 if (result == NULL) {
7092 /* It is an abstract method */
7093 gpointer iter = NULL;
7094 while ((result = mono_class_get_methods (klass, &iter)))
7095 if (result->slot == method->slot)
7102 return mono_method_get_object (mono_domain_get (), result, NULL);
7106 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7108 MonoMethod *method = m->method;
7110 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7115 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7117 MONO_ARCH_SAVE_REGS;
7119 iter->sig = *(MonoMethodSignature**)argsp;
7121 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7122 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7125 /* FIXME: it's not documented what start is exactly... */
7129 guint32 i, arg_size;
7131 iter->args = argsp + sizeof (gpointer);
7132 #ifndef MONO_ARCH_REGPARMS
7133 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7134 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7135 iter->args = (char*)iter->args + arg_size;
7139 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7141 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7145 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7147 guint32 i, arg_size;
7150 MONO_ARCH_SAVE_REGS;
7152 i = iter->sig->sentinelpos + iter->next_arg;
7154 g_assert (i < iter->sig->param_count);
7156 res.type = iter->sig->params [i];
7157 res.klass = mono_class_from_mono_type (res.type);
7158 res.value = iter->args;
7159 arg_size = mono_type_stack_size (res.type, &align);
7160 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7161 if (arg_size <= sizeof (gpointer)) {
7163 int padding = arg_size - mono_type_size (res.type, &dummy);
7164 res.value = (guint8*)res.value + padding;
7167 iter->args = (char*)iter->args + arg_size;
7170 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7176 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7178 guint32 i, arg_size;
7181 MONO_ARCH_SAVE_REGS;
7183 i = iter->sig->sentinelpos + iter->next_arg;
7185 g_assert (i < iter->sig->param_count);
7187 while (i < iter->sig->param_count) {
7188 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7190 res.type = iter->sig->params [i];
7191 res.klass = mono_class_from_mono_type (res.type);
7192 /* FIXME: endianess issue... */
7193 res.value = iter->args;
7194 arg_size = mono_type_stack_size (res.type, &align);
7195 iter->args = (char*)iter->args + arg_size;
7197 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7200 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7209 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7212 MONO_ARCH_SAVE_REGS;
7214 i = iter->sig->sentinelpos + iter->next_arg;
7216 g_assert (i < iter->sig->param_count);
7218 return iter->sig->params [i];
7222 mono_TypedReference_ToObject (MonoTypedRef tref)
7224 MONO_ARCH_SAVE_REGS;
7226 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7227 MonoObject** objp = tref.value;
7231 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7235 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7237 MONO_ARCH_SAVE_REGS;
7239 if (MONO_TYPE_IS_REFERENCE (type)) {
7240 MonoObject** objp = value;
7244 return mono_value_box (mono_domain_get (), klass, value);
7248 prelink_method (MonoMethod *method)
7250 const char *exc_class, *exc_arg;
7251 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7253 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7255 mono_raise_exception(
7256 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7258 /* create the wrapper, too? */
7262 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7264 MONO_ARCH_SAVE_REGS;
7265 prelink_method (method->method);
7269 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7271 MonoClass *klass = mono_class_from_mono_type (type->type);
7273 gpointer iter = NULL;
7274 MONO_ARCH_SAVE_REGS;
7276 while ((m = mono_class_get_methods (klass, &iter)))
7280 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7282 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7283 gint32 const **exponents,
7284 gunichar2 const **digitLowerTable,
7285 gunichar2 const **digitUpperTable,
7286 gint64 const **tenPowersList,
7287 gint32 const **decHexDigits)
7289 *mantissas = Formatter_MantissaBitsTable;
7290 *exponents = Formatter_TensExponentTable;
7291 *digitLowerTable = Formatter_DigitLowerTable;
7292 *digitUpperTable = Formatter_DigitUpperTable;
7293 *tenPowersList = Formatter_TenPowersList;
7294 *decHexDigits = Formatter_DecHexDigits;
7297 /* These parameters are "readonly" in corlib/System/Char.cs */
7299 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7300 guint8 const **numeric_data,
7301 gdouble const **numeric_data_values,
7302 guint16 const **to_lower_data_low,
7303 guint16 const **to_lower_data_high,
7304 guint16 const **to_upper_data_low,
7305 guint16 const **to_upper_data_high)
7307 *category_data = CategoryData;
7308 *numeric_data = NumericData;
7309 *numeric_data_values = NumericDataValues;
7310 *to_lower_data_low = ToLowerDataLow;
7311 *to_lower_data_high = ToLowerDataHigh;
7312 *to_upper_data_low = ToUpperDataLow;
7313 *to_upper_data_high = ToUpperDataHigh;
7317 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7319 return method->method->token;
7323 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7324 * and avoid useless allocations.
7327 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7331 for (i = 0; i < type->num_mods; ++i) {
7332 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7337 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7339 for (i = 0; i < type->num_mods; ++i) {
7340 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7341 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7342 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7350 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7352 MonoType *type = param->ClassImpl->type;
7353 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7354 MonoImage *image = method->method->klass->image;
7355 int pos = param->PositionImpl;
7356 MonoMethodSignature *sig = mono_method_signature (method->method);
7360 type = sig->params [pos];
7362 return type_array_from_modifiers (image, type, optional);
7366 get_property_type (MonoProperty *prop)
7368 MonoMethodSignature *sig;
7370 sig = mono_method_signature (prop->get);
7372 } else if (prop->set) {
7373 sig = mono_method_signature (prop->set);
7374 return sig->params [sig->param_count - 1];
7380 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7382 MonoType *type = get_property_type (property->property);
7383 MonoImage *image = property->klass->image;
7387 return type_array_from_modifiers (image, type, optional);
7391 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7393 MonoCustomAttrInfo *cinfo;
7396 cinfo = mono_reflection_get_custom_attrs_info (obj);
7399 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7401 mono_custom_attrs_free (cinfo);
7406 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7408 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7410 if (mono_loader_get_last_error ()) {
7411 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7412 g_assert_not_reached ();
7419 GCHandle_CheckCurrentDomain (guint32 gchandle)
7421 return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
7425 ves_icall_Mono_Runtime_GetDisplayName (void)
7427 static const char display_name_str [] = "Mono " VERSION;
7428 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7429 return display_name;
7433 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7435 MonoString *message;
7439 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7440 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7443 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7445 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7453 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7454 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7455 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7456 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7457 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7458 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7459 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7460 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7464 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7469 gunichar2 last, prev_last, prev2_last;
7477 last = prev_last = 0, prev2_last = 0;
7478 for (i = 0; i < ilength; i++) {
7480 if (c >= sizeof (dbase64)) {
7481 exc = mono_exception_from_name_msg (mono_get_corlib (),
7482 "System", "FormatException",
7483 "Invalid character found.");
7484 mono_raise_exception (exc);
7485 } else if (isspace (c)) {
7488 prev2_last = prev_last;
7494 olength = ilength - ignored;
7496 if (allowWhitespaceOnly && olength == 0) {
7497 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7500 if ((olength & 3) != 0 || olength <= 0) {
7501 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7502 "FormatException", "Invalid length.");
7503 mono_raise_exception (exc);
7506 if (prev2_last == '=') {
7507 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7508 mono_raise_exception (exc);
7511 olength = (olength * 3) / 4;
7515 if (prev_last == '=')
7518 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7519 res_ptr = mono_array_addr (result, guchar, 0);
7520 for (i = 0; i < ilength; ) {
7523 for (k = 0; k < 4 && i < ilength;) {
7529 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7530 exc = mono_exception_from_name_msg (mono_get_corlib (),
7531 "System", "FormatException",
7532 "Invalid character found.");
7533 mono_raise_exception (exc);
7538 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7540 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7542 *res_ptr++ = (b [2] << 6) | b [3];
7544 while (i < ilength && isspace (start [i]))
7552 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7554 MONO_ARCH_SAVE_REGS;
7556 return base64_to_byte_array (mono_string_chars (str),
7557 mono_string_length (str), allowWhitespaceOnly);
7561 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7563 MONO_ARCH_SAVE_REGS;
7565 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7569 #define ICALL_TYPE(id,name,first)
7570 #define ICALL(id,name,func) Icall_ ## id,
7573 #include "metadata/icall-def.h"
7579 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7580 #define ICALL(id,name,func)
7582 #include "metadata/icall-def.h"
7588 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7589 #define ICALL(id,name,func)
7591 guint16 first_icall;
7594 static const IcallTypeDesc
7595 icall_type_descs [] = {
7596 #include "metadata/icall-def.h"
7600 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7603 #define ICALL_TYPE(id,name,first)
7606 #ifdef HAVE_ARRAY_ELEM_INIT
7607 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7608 #define MSGSTRFIELD1(line) str##line
7610 static const struct msgstrtn_t {
7611 #define ICALL(id,name,func)
7613 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7614 #include "metadata/icall-def.h"
7616 } icall_type_names_str = {
7617 #define ICALL_TYPE(id,name,first) (name),
7618 #include "metadata/icall-def.h"
7621 static const guint16 icall_type_names_idx [] = {
7622 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7623 #include "metadata/icall-def.h"
7626 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7628 static const struct msgstr_t {
7630 #define ICALL_TYPE(id,name,first)
7631 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7632 #include "metadata/icall-def.h"
7634 } icall_names_str = {
7635 #define ICALL(id,name,func) (name),
7636 #include "metadata/icall-def.h"
7639 static const guint16 icall_names_idx [] = {
7640 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7641 #include "metadata/icall-def.h"
7644 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7650 #define ICALL_TYPE(id,name,first) name,
7651 #define ICALL(id,name,func)
7652 static const char* const
7653 icall_type_names [] = {
7654 #include "metadata/icall-def.h"
7658 #define icall_type_name_get(id) (icall_type_names [(id)])
7662 #define ICALL_TYPE(id,name,first)
7663 #define ICALL(id,name,func) name,
7664 static const char* const
7666 #include "metadata/icall-def.h"
7669 #define icall_name_get(id) icall_names [(id)]
7671 #endif /* !HAVE_ARRAY_ELEM_INIT */
7675 #define ICALL_TYPE(id,name,first)
7676 #define ICALL(id,name,func) func,
7677 static const gconstpointer
7678 icall_functions [] = {
7679 #include "metadata/icall-def.h"
7683 static GHashTable *icall_hash = NULL;
7684 static GHashTable *jit_icall_hash_name = NULL;
7685 static GHashTable *jit_icall_hash_addr = NULL;
7688 mono_icall_init (void)
7692 /* check that tables are sorted: disable in release */
7695 const char *prev_class = NULL;
7696 const char *prev_method;
7698 for (i = 0; i < Icall_type_num; ++i) {
7699 const IcallTypeDesc *desc;
7702 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7703 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7704 prev_class = icall_type_name_get (i);
7705 desc = &icall_type_descs [i];
7706 num_icalls = icall_desc_num_icalls (desc);
7707 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7708 for (j = 0; j < num_icalls; ++j) {
7709 const char *methodn = icall_name_get (desc->first_icall + j);
7710 if (prev_method && strcmp (prev_method, methodn) >= 0)
7711 g_print ("method %s should come before method %s\n", methodn, prev_method);
7712 prev_method = methodn;
7717 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7721 mono_icall_cleanup (void)
7723 g_hash_table_destroy (icall_hash);
7724 g_hash_table_destroy (jit_icall_hash_name);
7725 g_hash_table_destroy (jit_icall_hash_addr);
7729 mono_add_internal_call (const char *name, gconstpointer method)
7731 mono_loader_lock ();
7733 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7735 mono_loader_unlock ();
7738 #ifdef HAVE_ARRAY_ELEM_INIT
7740 compare_method_imap (const void *key, const void *elem)
7742 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7743 return strcmp (key, method_name);
7747 find_method_icall (const IcallTypeDesc *imap, const char *name)
7749 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7752 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7756 compare_class_imap (const void *key, const void *elem)
7758 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7759 return strcmp (key, class_name);
7762 static const IcallTypeDesc*
7763 find_class_icalls (const char *name)
7765 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7768 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7773 compare_method_imap (const void *key, const void *elem)
7775 const char** method_name = (const char**)elem;
7776 return strcmp (key, *method_name);
7780 find_method_icall (const IcallTypeDesc *imap, const char *name)
7782 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7785 return (gpointer)icall_functions [(nameslot - icall_names)];
7789 compare_class_imap (const void *key, const void *elem)
7791 const char** class_name = (const char**)elem;
7792 return strcmp (key, *class_name);
7795 static const IcallTypeDesc*
7796 find_class_icalls (const char *name)
7798 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7801 return &icall_type_descs [nameslot - icall_type_names];
7807 * we should probably export this as an helper (handle nested types).
7808 * Returns the number of chars written in buf.
7811 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7813 int nspacelen, cnamelen;
7814 nspacelen = strlen (klass->name_space);
7815 cnamelen = strlen (klass->name);
7816 if (nspacelen + cnamelen + 2 > bufsize)
7819 memcpy (buf, klass->name_space, nspacelen);
7820 buf [nspacelen ++] = '.';
7822 memcpy (buf + nspacelen, klass->name, cnamelen);
7823 buf [nspacelen + cnamelen] = 0;
7824 return nspacelen + cnamelen;
7828 mono_lookup_internal_call (MonoMethod *method)
7833 int typelen = 0, mlen, siglen;
7835 const IcallTypeDesc *imap;
7837 g_assert (method != NULL);
7839 if (method->is_inflated)
7840 method = ((MonoMethodInflated *) method)->declaring;
7842 if (method->klass->nested_in) {
7843 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7847 mname [pos++] = '/';
7850 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7856 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7861 imap = find_class_icalls (mname);
7863 mname [typelen] = ':';
7864 mname [typelen + 1] = ':';
7866 mlen = strlen (method->name);
7867 memcpy (mname + typelen + 2, method->name, mlen);
7868 sigstart = mname + typelen + 2 + mlen;
7871 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7872 siglen = strlen (tmpsig);
7873 if (typelen + mlen + siglen + 6 > sizeof (mname))
7876 memcpy (sigstart + 1, tmpsig, siglen);
7877 sigstart [siglen + 1] = ')';
7878 sigstart [siglen + 2] = 0;
7881 mono_loader_lock ();
7883 res = g_hash_table_lookup (icall_hash, mname);
7885 mono_loader_unlock ();
7888 /* try without signature */
7890 res = g_hash_table_lookup (icall_hash, mname);
7892 mono_loader_unlock ();
7896 /* it wasn't found in the static call tables */
7898 mono_loader_unlock ();
7901 res = find_method_icall (imap, sigstart - mlen);
7903 mono_loader_unlock ();
7906 /* try _with_ signature */
7908 res = find_method_icall (imap, sigstart - mlen);
7910 mono_loader_unlock ();
7914 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7915 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7916 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7917 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7918 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");
7919 g_print ("If you see other errors or faults after this message they are probably related\n");
7920 g_print ("and you need to fix your mono install first.\n");
7922 mono_loader_unlock ();
7928 type_from_typename (char *typename)
7930 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7932 if (!strcmp (typename, "int"))
7933 klass = mono_defaults.int_class;
7934 else if (!strcmp (typename, "ptr"))
7935 klass = mono_defaults.int_class;
7936 else if (!strcmp (typename, "void"))
7937 klass = mono_defaults.void_class;
7938 else if (!strcmp (typename, "int32"))
7939 klass = mono_defaults.int32_class;
7940 else if (!strcmp (typename, "uint32"))
7941 klass = mono_defaults.uint32_class;
7942 else if (!strcmp (typename, "int8"))
7943 klass = mono_defaults.sbyte_class;
7944 else if (!strcmp (typename, "uint8"))
7945 klass = mono_defaults.byte_class;
7946 else if (!strcmp (typename, "int16"))
7947 klass = mono_defaults.int16_class;
7948 else if (!strcmp (typename, "uint16"))
7949 klass = mono_defaults.uint16_class;
7950 else if (!strcmp (typename, "long"))
7951 klass = mono_defaults.int64_class;
7952 else if (!strcmp (typename, "ulong"))
7953 klass = mono_defaults.uint64_class;
7954 else if (!strcmp (typename, "float"))
7955 klass = mono_defaults.single_class;
7956 else if (!strcmp (typename, "double"))
7957 klass = mono_defaults.double_class;
7958 else if (!strcmp (typename, "object"))
7959 klass = mono_defaults.object_class;
7960 else if (!strcmp (typename, "obj"))
7961 klass = mono_defaults.object_class;
7962 else if (!strcmp (typename, "string"))
7963 klass = mono_defaults.string_class;
7964 else if (!strcmp (typename, "bool"))
7965 klass = mono_defaults.boolean_class;
7966 else if (!strcmp (typename, "boolean"))
7967 klass = mono_defaults.boolean_class;
7969 g_error ("%s", typename);
7970 g_assert_not_reached ();
7972 return &klass->byval_arg;
7975 MonoMethodSignature*
7976 mono_create_icall_signature (const char *sigstr)
7981 MonoMethodSignature *res;
7983 mono_loader_lock ();
7984 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7986 mono_loader_unlock ();
7990 parts = g_strsplit (sigstr, " ", 256);
7999 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8002 #ifdef PLATFORM_WIN32
8004 * Under windows, the default pinvoke calling convention is STDCALL but
8007 res->call_convention = MONO_CALL_C;
8010 res->ret = type_from_typename (parts [0]);
8011 for (i = 1; i < len; ++i) {
8012 res->params [i - 1] = type_from_typename (parts [i]);
8017 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8019 mono_loader_unlock ();
8025 mono_find_jit_icall_by_name (const char *name)
8027 MonoJitICallInfo *info;
8028 g_assert (jit_icall_hash_name);
8030 mono_loader_lock ();
8031 info = g_hash_table_lookup (jit_icall_hash_name, name);
8032 mono_loader_unlock ();
8037 mono_find_jit_icall_by_addr (gconstpointer addr)
8039 MonoJitICallInfo *info;
8040 g_assert (jit_icall_hash_addr);
8042 mono_loader_lock ();
8043 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8044 mono_loader_unlock ();
8050 * mono_get_jit_icall_info:
8052 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8053 * caller should access it while holding the loader lock.
8056 mono_get_jit_icall_info (void)
8058 return jit_icall_hash_name;
8062 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8064 mono_loader_lock ();
8065 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8066 mono_loader_unlock ();
8070 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8072 MonoJitICallInfo *info;
8077 mono_loader_lock ();
8079 if (!jit_icall_hash_name) {
8080 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8081 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8084 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8085 g_warning ("jit icall already defined \"%s\"\n", name);
8086 g_assert_not_reached ();
8089 info = g_new0 (MonoJitICallInfo, 1);
8096 info->wrapper = func;
8098 info->wrapper = NULL;
8101 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8102 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8104 mono_loader_unlock ();