5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * (C) 2001 Ximian, Inc.
17 #ifdef HAVE_SYS_TIME_H
23 #if defined (PLATFORM_WIN32)
27 #include "mono/utils/mono-membar.h"
28 #include <mono/metadata/object.h>
29 #include <mono/metadata/threads.h>
30 #include <mono/metadata/threads-types.h>
31 #include <mono/metadata/threadpool.h>
32 #include <mono/metadata/monitor.h>
33 #include <mono/metadata/reflection.h>
34 #include <mono/metadata/assembly.h>
35 #include <mono/metadata/tabledefs.h>
36 #include <mono/metadata/exception.h>
37 #include <mono/metadata/file-io.h>
38 #include <mono/metadata/console-io.h>
39 #include <mono/metadata/socket-io.h>
40 #include <mono/metadata/mono-endian.h>
41 #include <mono/metadata/tokentype.h>
42 #include <mono/metadata/domain-internals.h>
43 #include <mono/metadata/metadata-internals.h>
44 #include <mono/metadata/class-internals.h>
45 #include <mono/metadata/marshal.h>
46 #include <mono/metadata/gc-internal.h>
47 #include <mono/metadata/mono-gc.h>
48 #include <mono/metadata/rand.h>
49 #include <mono/metadata/sysmath.h>
50 #include <mono/metadata/string-icalls.h>
51 #include <mono/metadata/debug-helpers.h>
52 #include <mono/metadata/process.h>
53 #include <mono/metadata/environment.h>
54 #include <mono/metadata/profiler-private.h>
55 #include <mono/metadata/locales.h>
56 #include <mono/metadata/filewatcher.h>
57 #include <mono/metadata/char-conversions.h>
58 #include <mono/metadata/security.h>
59 #include <mono/metadata/mono-config.h>
60 #include <mono/metadata/cil-coff.h>
61 #include <mono/metadata/number-formatter.h>
62 #include <mono/metadata/security-manager.h>
63 #include <mono/metadata/security-core-clr.h>
64 #include <mono/metadata/mono-perfcounters.h>
65 #include <mono/metadata/mono-debug.h>
66 #include <mono/io-layer/io-layer.h>
67 #include <mono/utils/strtod.h>
68 #include <mono/utils/monobitset.h>
69 #include <mono/utils/mono-time.h>
70 #include <mono/utils/mono-proclib.h>
72 #if defined (PLATFORM_WIN32)
78 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
81 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
83 static inline MonoBoolean
84 is_generic_parameter (MonoType *type)
86 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
90 * We expect a pointer to a char, not a string
93 mono_double_ParseImpl (char *ptr, double *result)
102 *result = strtod (ptr, &endptr);
106 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
107 EnterCriticalSection (&mono_strtod_mutex);
108 *result = mono_strtod (ptr, &endptr);
109 LeaveCriticalSection (&mono_strtod_mutex);
111 *result = mono_strtod (ptr, &endptr);
116 if (!*ptr || (endptr && *endptr))
123 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
132 ao = (MonoArray *)this;
133 ac = (MonoClass *)ao->obj.vtable->klass;
135 esize = mono_array_element_size (ac);
136 ea = (gpointer*)((char*)ao->vector + (pos * esize));
138 if (ac->element_class->valuetype)
139 return mono_value_box (this->vtable->domain, ac->element_class, ea);
145 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
153 MONO_CHECK_ARG_NULL (idxs);
155 io = (MonoArray *)idxs;
156 ic = (MonoClass *)io->obj.vtable->klass;
158 ao = (MonoArray *)this;
159 ac = (MonoClass *)ao->obj.vtable->klass;
161 g_assert (ic->rank == 1);
162 if (io->bounds != NULL || io->max_length != ac->rank)
163 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
165 ind = (gint32 *)io->vector;
167 if (ao->bounds == NULL) {
168 if (*ind < 0 || *ind >= ao->max_length)
169 mono_raise_exception (mono_get_exception_index_out_of_range ());
171 return ves_icall_System_Array_GetValueImpl (this, *ind);
174 for (i = 0; i < ac->rank; i++)
175 if ((ind [i] < ao->bounds [i].lower_bound) ||
176 (ind [i] >= ao->bounds [i].length + ao->bounds [i].lower_bound))
177 mono_raise_exception (mono_get_exception_index_out_of_range ());
179 pos = ind [0] - ao->bounds [0].lower_bound;
180 for (i = 1; i < ac->rank; i++)
181 pos = pos*ao->bounds [i].length + ind [i] -
182 ao->bounds [i].lower_bound;
184 return ves_icall_System_Array_GetValueImpl (this, pos);
188 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
190 MonoClass *ac, *vc, *ec;
202 vc = value->vtable->klass;
206 ac = this->obj.vtable->klass;
207 ec = ac->element_class;
209 esize = mono_array_element_size (ac);
210 ea = (gpointer*)((char*)this->vector + (pos * esize));
211 va = (gpointer*)((char*)value + sizeof (MonoObject));
214 memset (ea, 0, esize);
218 #define NO_WIDENING_CONVERSION G_STMT_START{\
219 mono_raise_exception (mono_get_exception_argument ( \
220 "value", "not a widening conversion")); \
223 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
224 if (esize < vsize + (extra)) \
225 mono_raise_exception (mono_get_exception_argument ( \
226 "value", "not a widening conversion")); \
229 #define INVALID_CAST G_STMT_START{\
230 mono_raise_exception (mono_get_exception_invalid_cast ()); \
233 /* Check element (destination) type. */
234 switch (ec->byval_arg.type) {
235 case MONO_TYPE_STRING:
236 switch (vc->byval_arg.type) {
237 case MONO_TYPE_STRING:
243 case MONO_TYPE_BOOLEAN:
244 switch (vc->byval_arg.type) {
245 case MONO_TYPE_BOOLEAN:
258 NO_WIDENING_CONVERSION;
265 if (!ec->valuetype) {
266 if (!mono_object_isinst (value, ec))
268 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
272 if (mono_object_isinst (value, ec)) {
273 if (ec->has_references)
274 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
276 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
283 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
285 et = ec->byval_arg.type;
286 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
287 et = ec->byval_arg.data.klass->enum_basetype->type;
289 vt = vc->byval_arg.type;
290 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
291 vt = vc->byval_arg.data.klass->enum_basetype->type;
293 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
299 case MONO_TYPE_CHAR: \
300 CHECK_WIDENING_CONVERSION(0); \
301 *(etype *) ea = (etype) u64; \
303 /* You can't assign a signed value to an unsigned array. */ \
308 /* You can't assign a floating point number to an integer array. */ \
311 NO_WIDENING_CONVERSION; \
315 #define ASSIGN_SIGNED(etype) G_STMT_START{\
321 CHECK_WIDENING_CONVERSION(0); \
322 *(etype *) ea = (etype) i64; \
324 /* You can assign an unsigned value to a signed array if the array's */ \
325 /* element size is larger than the value size. */ \
330 case MONO_TYPE_CHAR: \
331 CHECK_WIDENING_CONVERSION(1); \
332 *(etype *) ea = (etype) u64; \
334 /* You can't assign a floating point number to an integer array. */ \
337 NO_WIDENING_CONVERSION; \
341 #define ASSIGN_REAL(etype) G_STMT_START{\
345 CHECK_WIDENING_CONVERSION(0); \
346 *(etype *) ea = (etype) r64; \
348 /* All integer values fit into a floating point array, so we don't */ \
349 /* need to CHECK_WIDENING_CONVERSION here. */ \
354 *(etype *) ea = (etype) i64; \
360 case MONO_TYPE_CHAR: \
361 *(etype *) ea = (etype) u64; \
368 u64 = *(guint8 *) va;
371 u64 = *(guint16 *) va;
374 u64 = *(guint32 *) va;
377 u64 = *(guint64 *) va;
383 i64 = *(gint16 *) va;
386 i64 = *(gint32 *) va;
389 i64 = *(gint64 *) va;
392 r64 = *(gfloat *) va;
395 r64 = *(gdouble *) va;
398 u64 = *(guint16 *) va;
400 case MONO_TYPE_BOOLEAN:
401 /* Boolean is only compatible with itself. */
414 NO_WIDENING_CONVERSION;
421 /* If we can't do a direct copy, let's try a widening conversion. */
424 ASSIGN_UNSIGNED (guint16);
426 ASSIGN_UNSIGNED (guint8);
428 ASSIGN_UNSIGNED (guint16);
430 ASSIGN_UNSIGNED (guint32);
432 ASSIGN_UNSIGNED (guint64);
434 ASSIGN_SIGNED (gint8);
436 ASSIGN_SIGNED (gint16);
438 ASSIGN_SIGNED (gint32);
440 ASSIGN_SIGNED (gint64);
442 ASSIGN_REAL (gfloat);
444 ASSIGN_REAL (gdouble);
448 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
452 #undef NO_WIDENING_CONVERSION
453 #undef CHECK_WIDENING_CONVERSION
454 #undef ASSIGN_UNSIGNED
460 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
468 MONO_CHECK_ARG_NULL (idxs);
470 ic = idxs->obj.vtable->klass;
471 ac = this->obj.vtable->klass;
473 g_assert (ic->rank == 1);
474 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
475 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
477 ind = (gint32 *)idxs->vector;
479 if (this->bounds == NULL) {
480 if (*ind < 0 || *ind >= this->max_length)
481 mono_raise_exception (mono_get_exception_index_out_of_range ());
483 ves_icall_System_Array_SetValueImpl (this, value, *ind);
487 for (i = 0; i < ac->rank; i++)
488 if ((ind [i] < this->bounds [i].lower_bound) ||
489 (ind [i] >= this->bounds [i].length + this->bounds [i].lower_bound))
490 mono_raise_exception (mono_get_exception_index_out_of_range ());
492 pos = ind [0] - this->bounds [0].lower_bound;
493 for (i = 1; i < ac->rank; i++)
494 pos = pos * this->bounds [i].length + ind [i] -
495 this->bounds [i].lower_bound;
497 ves_icall_System_Array_SetValueImpl (this, value, pos);
501 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
505 mono_array_size_t *sizes, i;
506 gboolean bounded = FALSE;
510 MONO_CHECK_ARG_NULL (type);
511 MONO_CHECK_ARG_NULL (lengths);
513 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
515 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
517 for (i = 0; i < mono_array_length (lengths); i++)
518 if (mono_array_get (lengths, gint32, i) < 0)
519 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
521 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
522 /* vectors are not the same as one dimensional arrays with no-zero bounds */
527 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
529 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
530 for (i = 0; i < aklass->rank; ++i) {
531 sizes [i] = mono_array_get (lengths, guint32, i);
533 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
535 sizes [i + aklass->rank] = 0;
538 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
544 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
548 mono_array_size_t *sizes, i;
549 gboolean bounded = FALSE;
553 MONO_CHECK_ARG_NULL (type);
554 MONO_CHECK_ARG_NULL (lengths);
556 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
558 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
560 for (i = 0; i < mono_array_length (lengths); i++)
561 if ((mono_array_get (lengths, gint64, i) < 0) ||
562 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
563 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
565 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
566 /* vectors are not the same as one dimensional arrays with no-zero bounds */
571 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
573 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
574 for (i = 0; i < aklass->rank; ++i) {
575 sizes [i] = mono_array_get (lengths, guint64, i);
577 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
579 sizes [i + aklass->rank] = 0;
582 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
588 ves_icall_System_Array_GetRank (MonoObject *this)
592 return this->vtable->klass->rank;
596 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
598 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
599 mono_array_size_t length;
603 if ((dimension < 0) || (dimension >= rank))
604 mono_raise_exception (mono_get_exception_index_out_of_range ());
606 if (this->bounds == NULL)
607 length = this->max_length;
609 length = this->bounds [dimension].length;
611 #ifdef MONO_BIG_ARRAYS
612 if (length > G_MAXINT32)
613 mono_raise_exception (mono_get_exception_overflow ());
619 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
621 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
625 if ((dimension < 0) || (dimension >= rank))
626 mono_raise_exception (mono_get_exception_index_out_of_range ());
628 if (this->bounds == NULL)
629 return this->max_length;
631 return this->bounds [dimension].length;
635 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
637 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
641 if ((dimension < 0) || (dimension >= rank))
642 mono_raise_exception (mono_get_exception_index_out_of_range ());
644 if (this->bounds == NULL)
647 return this->bounds [dimension].lower_bound;
651 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
653 int sz = mono_array_element_size (mono_object_class (arr));
654 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
658 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
663 MonoClass *src_class;
664 MonoClass *dest_class;
669 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
672 if (source->bounds || dest->bounds)
675 if ((dest_idx + length > mono_array_length (dest)) ||
676 (source_idx + length > mono_array_length (source)))
679 src_class = source->obj.vtable->klass->element_class;
680 dest_class = dest->obj.vtable->klass->element_class;
683 * Handle common cases.
686 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
687 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
688 int has_refs = dest_class->has_references;
689 for (i = source_idx; i < source_idx + length; ++i) {
690 MonoObject *elem = mono_array_get (source, MonoObject*, i);
691 if (elem && !mono_object_isinst (elem, dest_class))
695 element_size = mono_array_element_size (dest->obj.vtable->klass);
696 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
697 for (i = 0; i < length; ++i) {
698 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
699 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
703 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
705 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
710 /* Check if we're copying a char[] <==> (u)short[] */
711 if (src_class != dest_class) {
712 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
715 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
717 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
718 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
719 for (i = source_idx; i < source_idx + length; ++i) {
720 MonoObject *elem = mono_array_get (source, MonoObject*, i);
721 if (elem && !mono_object_isinst (elem, dest_class))
728 if (dest_class->valuetype) {
729 element_size = mono_array_element_size (source->obj.vtable->klass);
730 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
731 if (dest_class->has_references) {
732 mono_value_copy_array (dest, dest_idx, source_addr, length);
734 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
735 memmove (dest_addr, source_addr, element_size * length);
738 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
745 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
754 ao = (MonoArray *)this;
755 ac = (MonoClass *)ao->obj.vtable->klass;
757 esize = mono_array_element_size (ac);
758 ea = (gpointer*)((char*)ao->vector + (pos * esize));
760 memcpy (value, ea, esize);
764 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
773 ao = (MonoArray *)this;
774 ac = (MonoClass *)ao->obj.vtable->klass;
776 esize = mono_array_element_size (ac);
777 ea = (gpointer*)((char*)ao->vector + (pos * esize));
779 memcpy (ea, value, esize);
783 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
785 MonoClass *klass = array->obj.vtable->klass;
786 guint32 size = mono_array_element_size (klass);
787 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
789 const char *field_data;
791 if (MONO_TYPE_IS_REFERENCE (type) ||
792 (type->type == MONO_TYPE_VALUETYPE &&
793 (!mono_type_get_class (type) ||
794 mono_type_get_class (type)->has_references))) {
795 MonoException *exc = mono_get_exception_argument("array",
796 "Cannot initialize array containing references");
797 mono_raise_exception (exc);
800 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
801 MonoException *exc = mono_get_exception_argument("field_handle",
802 "Field doesn't have an RVA");
803 mono_raise_exception (exc);
806 size *= array->max_length;
807 field_data = mono_field_get_data (field_handle);
809 if (size > mono_type_size (field_handle->type, &align)) {
810 MonoException *exc = mono_get_exception_argument("field_handle",
811 "Field not large enough to fill array");
812 mono_raise_exception (exc);
815 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
817 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
818 guint ## n *src = (guint ## n *) field_data; \
819 guint ## n *end = (guint ## n *)((char*)src + size); \
821 for (; src < end; data++, src++) { \
822 *data = read ## n (src); \
826 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
828 switch (type->type) {
845 memcpy (mono_array_addr (array, char, 0), field_data, size);
849 memcpy (mono_array_addr (array, char, 0), field_data, size);
851 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
854 double *data = (double*)mono_array_addr (array, double, 0);
856 for (i = 0; i < size; i++, data++) {
866 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
870 return offsetof (MonoString, chars);
874 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
878 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
881 return mono_object_clone (obj);
885 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
891 MONO_CHECK_ARG_NULL (handle);
893 klass = mono_class_from_mono_type (handle);
894 MONO_CHECK_ARG (handle, klass);
896 /* This will call the type constructor */
897 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
901 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
905 mono_image_check_for_module_cctor (image);
906 if (image->has_module_cctor) {
907 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
908 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), module_klass));
913 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
917 return mono_object_clone (this);
921 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
924 MonoObject **values = NULL;
928 MonoClassField* field;
933 klass = mono_object_class (this);
935 if (mono_class_num_fields (klass) == 0)
936 return mono_object_hash (this);
939 * Compute the starting value of the hashcode for fields of primitive
940 * types, and return the remaining fields in an array to the managed side.
941 * This way, we can avoid costly reflection operations in managed code.
944 while ((field = mono_class_get_fields (klass, &iter))) {
945 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
947 if (mono_field_is_deleted (field))
949 /* FIXME: Add more types */
950 switch (field->type->type) {
952 result ^= *(gint32*)((guint8*)this + field->offset);
954 case MONO_TYPE_STRING: {
956 s = *(MonoString**)((guint8*)this + field->offset);
958 result ^= mono_string_hash (s);
963 values = g_newa (MonoObject*, mono_class_num_fields (klass));
964 o = mono_field_get_value_object (mono_object_domain (this), field, this);
965 values [count++] = o;
971 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
972 for (i = 0; i < count; ++i)
973 mono_array_setref (*fields, i, values [i]);
981 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
984 MonoObject **values = NULL;
986 MonoClassField* field;
992 MONO_CHECK_ARG_NULL (that);
994 if (this->vtable != that->vtable)
997 klass = mono_object_class (this);
999 if (klass->enumtype && klass->enum_basetype && klass->enum_basetype->type == MONO_TYPE_I4)
1000 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1003 * Do the comparison for fields of primitive type and return a result if
1004 * possible. Otherwise, return the remaining fields in an array to the
1005 * managed side. This way, we can avoid costly reflection operations in
1010 while ((field = mono_class_get_fields (klass, &iter))) {
1011 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1013 if (mono_field_is_deleted (field))
1015 /* FIXME: Add more types */
1016 switch (field->type->type) {
1019 case MONO_TYPE_BOOLEAN:
1020 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1025 case MONO_TYPE_CHAR:
1026 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1031 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1036 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1040 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1044 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1049 case MONO_TYPE_STRING: {
1050 MonoString *s1, *s2;
1051 guint32 s1len, s2len;
1052 s1 = *(MonoString**)((guint8*)this + field->offset);
1053 s2 = *(MonoString**)((guint8*)that + field->offset);
1056 if ((s1 == NULL) || (s2 == NULL))
1058 s1len = mono_string_length (s1);
1059 s2len = mono_string_length (s2);
1063 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1069 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1070 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1071 values [count++] = o;
1072 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1073 values [count++] = o;
1076 if (klass->enumtype)
1077 /* enums only have one non-static field */
1083 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
1084 for (i = 0; i < count; ++i)
1085 mono_array_setref (*fields, i, values [i]);
1092 static MonoReflectionType *
1093 ves_icall_System_Object_GetType (MonoObject *obj)
1095 MONO_ARCH_SAVE_REGS;
1097 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1098 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1100 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1104 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1106 MONO_ARCH_SAVE_REGS;
1108 mtype->type = &obj->vtable->klass->byval_arg;
1109 g_assert (mtype->type->type);
1113 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1115 MONO_ARCH_SAVE_REGS;
1117 MONO_CHECK_ARG_NULL (obj);
1119 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1123 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1124 MonoReflectionMethod *method,
1125 MonoArray *opt_param_types)
1127 MONO_ARCH_SAVE_REGS;
1129 MONO_CHECK_ARG_NULL (method);
1131 return mono_image_create_method_token (
1132 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1136 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1138 MONO_ARCH_SAVE_REGS;
1140 mono_image_create_pefile (mb, file);
1144 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1146 MONO_ARCH_SAVE_REGS;
1148 mono_image_build_metadata (mb);
1152 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1154 MONO_ARCH_SAVE_REGS;
1156 mono_image_register_token (mb->dynamic_image, token, obj);
1160 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1162 MonoMethod **dest = data;
1164 /* skip unmanaged frames */
1180 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1182 MonoMethod **dest = data;
1184 /* skip unmanaged frames */
1189 if (!strcmp (m->klass->name_space, "System.Reflection"))
1198 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1200 MonoMethod **dest = data;
1202 /* skip unmanaged frames */
1206 if (m->wrapper_type != MONO_WRAPPER_NONE)
1209 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1223 static MonoReflectionType *
1224 type_from_name (const char *str, MonoBoolean ignoreCase)
1226 MonoType *type = NULL;
1227 MonoAssembly *assembly = NULL;
1228 MonoTypeNameParse info;
1229 char *temp_str = g_strdup (str);
1230 gboolean type_resolve = FALSE;
1232 MONO_ARCH_SAVE_REGS;
1234 /* mono_reflection_parse_type() mangles the string */
1235 if (!mono_reflection_parse_type (temp_str, &info)) {
1236 mono_reflection_free_type_info (&info);
1241 if (info.assembly.name) {
1242 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1244 MonoMethod *m = mono_method_get_last_managed ();
1245 MonoMethod *dest = m;
1247 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1252 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1253 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1254 * to crash. This only seems to happen in some strange remoting
1255 * scenarios and I was unable to figure out what's happening there.
1256 * Dec 10, 2005 - Martin.
1260 assembly = dest->klass->image->assembly;
1262 g_warning (G_STRLOC);
1267 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1269 if (!info.assembly.name && !type) /* try mscorlib */
1270 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1272 mono_reflection_free_type_info (&info);
1278 return mono_type_get_object (mono_domain_get (), type);
1282 MonoReflectionType *
1283 mono_type_get (const char *str)
1285 char *copy = g_strdup (str);
1286 MonoReflectionType *type = type_from_name (copy, FALSE);
1293 static MonoReflectionType*
1294 ves_icall_type_from_name (MonoString *name,
1295 MonoBoolean throwOnError,
1296 MonoBoolean ignoreCase)
1298 char *str = mono_string_to_utf8 (name);
1299 MonoReflectionType *type;
1301 type = type_from_name (str, ignoreCase);
1304 MonoException *e = NULL;
1307 e = mono_get_exception_type_load (name, NULL);
1309 mono_loader_clear_error ();
1311 mono_raise_exception (e);
1318 static MonoReflectionType*
1319 ves_icall_type_from_handle (MonoType *handle)
1321 MonoDomain *domain = mono_domain_get ();
1322 MonoClass *klass = mono_class_from_mono_type (handle);
1324 MONO_ARCH_SAVE_REGS;
1326 mono_class_init (klass);
1327 return mono_type_get_object (domain, handle);
1331 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1333 MONO_ARCH_SAVE_REGS;
1335 if (c && type->type && c->type)
1336 return mono_metadata_type_equal (type->type, c->type);
1338 return (type == c) ? TRUE : FALSE;
1341 /* System.TypeCode */
1360 TYPECODE_STRING = 18
1364 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1366 int t = type->type->type;
1368 MONO_ARCH_SAVE_REGS;
1370 if (type->type->byref)
1371 return TYPECODE_OBJECT;
1375 case MONO_TYPE_VOID:
1376 return TYPECODE_OBJECT;
1377 case MONO_TYPE_BOOLEAN:
1378 return TYPECODE_BOOLEAN;
1380 return TYPECODE_BYTE;
1382 return TYPECODE_SBYTE;
1384 return TYPECODE_UINT16;
1386 return TYPECODE_INT16;
1387 case MONO_TYPE_CHAR:
1388 return TYPECODE_CHAR;
1392 return TYPECODE_OBJECT;
1394 return TYPECODE_UINT32;
1396 return TYPECODE_INT32;
1398 return TYPECODE_UINT64;
1400 return TYPECODE_INT64;
1402 return TYPECODE_SINGLE;
1404 return TYPECODE_DOUBLE;
1405 case MONO_TYPE_VALUETYPE:
1406 if (type->type->data.klass->enumtype) {
1407 t = type->type->data.klass->enum_basetype->type;
1410 MonoClass *k = type->type->data.klass;
1411 if (strcmp (k->name_space, "System") == 0) {
1412 if (strcmp (k->name, "Decimal") == 0)
1413 return TYPECODE_DECIMAL;
1414 else if (strcmp (k->name, "DateTime") == 0)
1415 return TYPECODE_DATETIME;
1418 return TYPECODE_OBJECT;
1419 case MONO_TYPE_STRING:
1420 return TYPECODE_STRING;
1421 case MONO_TYPE_SZARRAY:
1422 case MONO_TYPE_ARRAY:
1423 case MONO_TYPE_OBJECT:
1425 case MONO_TYPE_MVAR:
1426 case MONO_TYPE_TYPEDBYREF:
1427 return TYPECODE_OBJECT;
1428 case MONO_TYPE_CLASS:
1430 MonoClass *k = type->type->data.klass;
1431 if (strcmp (k->name_space, "System") == 0) {
1432 if (strcmp (k->name, "DBNull") == 0)
1433 return TYPECODE_DBNULL;
1436 return TYPECODE_OBJECT;
1437 case MONO_TYPE_GENERICINST:
1438 return TYPECODE_OBJECT;
1440 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1446 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1452 MONO_ARCH_SAVE_REGS;
1454 g_assert (type != NULL);
1456 domain = ((MonoObject *)type)->vtable->domain;
1458 if (!c) /* FIXME: dont know what do do here */
1461 klass = mono_class_from_mono_type (type->type);
1462 klassc = mono_class_from_mono_type (c->type);
1464 if (type->type->byref)
1465 return klassc == mono_defaults.object_class;
1467 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1471 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1477 MONO_ARCH_SAVE_REGS;
1479 g_assert (type != NULL);
1481 domain = ((MonoObject *)type)->vtable->domain;
1483 klass = mono_class_from_mono_type (type->type);
1484 klassc = mono_class_from_mono_type (c->type);
1486 if (type->type->byref && !c->type->byref)
1489 return mono_class_is_assignable_from (klass, klassc);
1493 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1495 MonoClass *klass = mono_class_from_mono_type (type->type);
1496 return mono_object_isinst (obj, klass) != NULL;
1500 ves_icall_get_attributes (MonoReflectionType *type)
1502 MonoClass *klass = mono_class_from_mono_type (type->type);
1504 MONO_ARCH_SAVE_REGS;
1506 return klass->flags;
1509 static MonoReflectionMarshal*
1510 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1512 MonoClass *klass = field->field->parent;
1513 MonoMarshalType *info;
1516 if (klass->generic_container ||
1517 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1520 info = mono_marshal_load_type_info (klass);
1522 for (i = 0; i < info->num_fields; ++i) {
1523 if (info->fields [i].field == field->field) {
1524 if (!info->fields [i].mspec)
1527 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1534 static MonoReflectionField*
1535 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoClass *klass)
1540 klass = handle->parent;
1542 /* FIXME: check that handle is a field of klass or of a parent: return null
1543 * and throw the exception in managed code.
1545 return mono_field_get_object (mono_domain_get (), klass, handle);
1548 static MonoReflectionField*
1549 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1551 MONO_ARCH_SAVE_REGS;
1555 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1559 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1561 MonoType *type = field->field->type;
1563 return type_array_from_modifiers (field->field->parent->image, type, optional);
1567 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1569 MonoDomain *domain = mono_domain_get ();
1570 MonoMethodSignature* sig;
1571 MONO_ARCH_SAVE_REGS;
1573 sig = mono_method_signature (method);
1575 g_assert (mono_loader_get_last_error ());
1576 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1579 info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
1580 info->ret = mono_type_get_object (domain, sig->ret);
1581 info->attrs = method->flags;
1582 info->implattrs = method->iflags;
1583 if (sig->call_convention == MONO_CALL_DEFAULT)
1584 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1586 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1591 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1595 ves_icall_get_parameter_info (MonoMethod *method)
1597 MonoDomain *domain = mono_domain_get ();
1599 return mono_param_get_objects (domain, method);
1602 static MonoReflectionMarshal*
1603 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1605 MonoDomain *domain = mono_domain_get ();
1606 MonoReflectionMarshal* res = NULL;
1607 MonoMarshalSpec **mspecs;
1610 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1611 mono_method_get_marshal_info (method, mspecs);
1614 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1616 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1618 mono_metadata_free_marshal_spec (mspecs [i]);
1625 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1627 return field->field->offset - sizeof (MonoObject);
1630 static MonoReflectionType*
1631 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1634 MONO_ARCH_SAVE_REGS;
1636 parent = declaring? field->field->parent: field->klass;
1638 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1642 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1645 MonoClassField *cf = field->field;
1649 MonoDomain *domain = mono_object_domain (field);
1651 gboolean is_static = FALSE;
1652 gboolean is_ref = FALSE;
1654 MONO_ARCH_SAVE_REGS;
1656 if (field->klass->image->assembly->ref_only)
1657 mono_raise_exception (mono_get_exception_invalid_operation (
1658 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1660 mono_class_init (field->klass);
1662 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1665 if (obj && !is_static) {
1666 /* Check that the field belongs to the object */
1667 gboolean found = FALSE;
1670 for (k = obj->vtable->klass; k; k = k->parent) {
1671 if (k == cf->parent) {
1678 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);
1679 MonoException *ex = mono_get_exception_argument (NULL, msg);
1681 mono_raise_exception (ex);
1685 t = mono_type_get_underlying_type (cf->type);
1687 case MONO_TYPE_STRING:
1688 case MONO_TYPE_OBJECT:
1689 case MONO_TYPE_CLASS:
1690 case MONO_TYPE_ARRAY:
1691 case MONO_TYPE_SZARRAY:
1696 case MONO_TYPE_BOOLEAN:
1699 case MONO_TYPE_CHAR:
1708 case MONO_TYPE_VALUETYPE:
1711 case MONO_TYPE_GENERICINST:
1712 if (mono_type_generic_inst_is_valuetype (t)) {
1719 g_error ("type 0x%x not handled in "
1720 "ves_icall_Monofield_GetValue", t->type);
1726 vtable = mono_class_vtable (domain, cf->parent);
1727 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1728 mono_runtime_class_init (vtable);
1733 mono_field_static_get_value (vtable, cf, &o);
1735 mono_field_get_value (obj, cf, &o);
1740 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1741 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1744 /* Convert the Nullable structure into a boxed vtype */
1746 buf = (guint8*)vtable->data + cf->offset;
1748 buf = (guint8*)obj + cf->offset;
1750 return mono_nullable_box (buf, nklass);
1753 /* boxed value type */
1754 klass = mono_class_from_mono_type (cf->type);
1755 o = mono_object_new (domain, klass);
1756 v = ((gchar *) o) + sizeof (MonoObject);
1758 mono_field_static_get_value (vtable, cf, v);
1760 mono_field_get_value (obj, cf, v);
1767 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1769 MonoClassField *cf = field->field;
1772 MONO_ARCH_SAVE_REGS;
1774 if (field->klass->image->assembly->ref_only)
1775 mono_raise_exception (mono_get_exception_invalid_operation (
1776 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1778 v = (gchar *) value;
1779 if (!cf->type->byref) {
1780 switch (cf->type->type) {
1783 case MONO_TYPE_BOOLEAN:
1786 case MONO_TYPE_CHAR:
1795 case MONO_TYPE_VALUETYPE:
1797 v += sizeof (MonoObject);
1799 case MONO_TYPE_STRING:
1800 case MONO_TYPE_OBJECT:
1801 case MONO_TYPE_CLASS:
1802 case MONO_TYPE_ARRAY:
1803 case MONO_TYPE_SZARRAY:
1806 case MONO_TYPE_GENERICINST: {
1807 MonoGenericClass *gclass = cf->type->data.generic_class;
1808 g_assert (!gclass->context.class_inst->is_open);
1810 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1811 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1812 MonoObject *nullable;
1815 * Convert the boxed vtype into a Nullable structure.
1816 * This is complicated by the fact that Nullables have
1817 * a variable structure.
1819 nullable = mono_object_new (mono_domain_get (), nklass);
1821 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1823 v = mono_object_unbox (nullable);
1826 if (gclass->container_class->valuetype && (v != NULL))
1827 v += sizeof (MonoObject);
1831 g_error ("type 0x%x not handled in "
1832 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1837 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1838 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1839 if (!vtable->initialized)
1840 mono_runtime_class_init (vtable);
1841 mono_field_static_set_value (vtable, cf, v);
1843 mono_field_set_value (obj, cf, v);
1848 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1850 MonoObject *o = NULL;
1851 MonoClassField *field = this->field;
1853 MonoDomain *domain = mono_object_domain (this);
1855 MonoTypeEnum def_type;
1856 const char *def_value;
1858 MONO_ARCH_SAVE_REGS;
1860 mono_class_init (field->parent);
1862 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1863 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1865 if (field->parent->image->dynamic) {
1867 g_assert_not_reached ();
1870 def_value = mono_class_get_field_default_value (field, &def_type);
1875 case MONO_TYPE_BOOLEAN:
1878 case MONO_TYPE_CHAR:
1886 case MONO_TYPE_R8: {
1889 /* boxed value type */
1890 t = g_new0 (MonoType, 1);
1892 klass = mono_class_from_mono_type (t);
1894 o = mono_object_new (domain, klass);
1895 v = ((gchar *) o) + sizeof (MonoObject);
1896 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1899 case MONO_TYPE_STRING:
1900 case MONO_TYPE_CLASS:
1901 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1904 g_assert_not_reached ();
1910 static MonoReflectionType*
1911 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1913 MonoMethod *method = rmethod->method.method;
1915 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1918 /* From MonoProperty.cs */
1920 PInfo_Attributes = 1,
1921 PInfo_GetMethod = 1 << 1,
1922 PInfo_SetMethod = 1 << 2,
1923 PInfo_ReflectedType = 1 << 3,
1924 PInfo_DeclaringType = 1 << 4,
1929 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1931 MonoDomain *domain = mono_object_domain (property);
1933 MONO_ARCH_SAVE_REGS;
1935 if ((req_info & PInfo_ReflectedType) != 0)
1936 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1937 else if ((req_info & PInfo_DeclaringType) != 0)
1938 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1940 if ((req_info & PInfo_Name) != 0)
1941 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1943 if ((req_info & PInfo_Attributes) != 0)
1944 info->attrs = property->property->attrs;
1946 if ((req_info & PInfo_GetMethod) != 0)
1947 MONO_STRUCT_SETREF (info, get, property->property->get ?
1948 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1950 if ((req_info & PInfo_SetMethod) != 0)
1951 MONO_STRUCT_SETREF (info, set, property->property->set ?
1952 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1954 * There may be other methods defined for properties, though, it seems they are not exposed
1955 * in the reflection API
1960 ves_icall_get_event_info (MonoReflectionEvent *event, MonoEventInfo *info)
1962 MonoDomain *domain = mono_object_domain (event);
1964 MONO_ARCH_SAVE_REGS;
1966 info->reflected_type = mono_type_get_object (domain, &event->klass->byval_arg);
1967 info->declaring_type = mono_type_get_object (domain, &event->event->parent->byval_arg);
1969 info->name = mono_string_new (domain, event->event->name);
1970 info->attrs = event->event->attrs;
1971 info->add_method = event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL;
1972 info->remove_method = event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL;
1973 info->raise_method = event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL;
1975 if (event->event->other) {
1977 while (event->event->other [n])
1979 info->other_methods = mono_array_new (domain, mono_defaults.method_info_class, n);
1981 for (i = 0; i < n; i++)
1982 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
1987 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
1989 MonoDomain *domain = mono_object_domain (type);
1991 GPtrArray *ifaces = NULL;
1993 MonoClass *class = mono_class_from_mono_type (type->type);
1996 MonoGenericContext *context = NULL;
1998 MONO_ARCH_SAVE_REGS;
2000 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2001 context = mono_class_get_context (class);
2002 class = class->generic_class->container_class;
2005 mono_class_setup_vtable (class);
2007 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2009 for (parent = class; parent; parent = parent->parent) {
2010 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
2012 for (i = 0; i < tmp_ifaces->len; ++i) {
2013 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2015 if (mono_bitset_test (slots, ic->interface_id))
2018 mono_bitset_set (slots, ic->interface_id);
2020 ifaces = g_ptr_array_new ();
2021 g_ptr_array_add (ifaces, ic);
2023 g_ptr_array_free (tmp_ifaces, TRUE);
2026 mono_bitset_free (slots);
2029 return mono_array_new (domain, mono_defaults.monotype_class, 0);
2031 intf = mono_array_new (domain, mono_defaults.monotype_class, ifaces->len);
2032 for (i = 0; i < ifaces->len; ++i) {
2033 MonoClass *ic = g_ptr_array_index (ifaces, i);
2034 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2035 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2036 inflated = ret = mono_class_inflate_generic_type (ret, context);
2038 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2040 mono_metadata_free_type (inflated);
2042 g_ptr_array_free (ifaces, TRUE);
2048 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2050 MonoClass *class = mono_class_from_mono_type (type->type);
2051 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2052 MonoReflectionMethod *member;
2055 int i = 0, len, ioffset;
2058 MONO_ARCH_SAVE_REGS;
2060 mono_class_setup_vtable (class);
2062 /* type doesn't implement iface: the exception is thrown in managed code */
2063 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2066 len = mono_class_num_methods (iclass);
2067 ioffset = mono_class_interface_offset (class, iclass);
2068 domain = mono_object_domain (type);
2069 *targets = mono_array_new (domain, mono_defaults.method_info_class, len);
2070 *methods = mono_array_new (domain, mono_defaults.method_info_class, len);
2073 while ((method = mono_class_get_methods (iclass, &iter))) {
2074 member = mono_method_get_object (domain, method, iclass);
2075 mono_array_setref (*methods, i, member);
2076 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2077 mono_array_setref (*targets, i, member);
2084 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2086 MonoClass *klass = mono_class_from_mono_type (type->type);
2088 if (klass->image->dynamic) {
2089 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2090 *packing = tb->packing_size;
2091 *size = tb->class_size;
2093 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2097 static MonoReflectionType*
2098 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2100 MonoClass *class = mono_class_from_mono_type (type->type);
2102 MONO_ARCH_SAVE_REGS;
2104 // GetElementType should only return a type for:
2105 // Array Pointer PassedByRef
2106 if (type->type->byref)
2107 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2108 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2109 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2110 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2111 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2116 static MonoReflectionType*
2117 ves_icall_get_type_parent (MonoReflectionType *type)
2119 MonoClass *class = mono_class_from_mono_type (type->type);
2121 MONO_ARCH_SAVE_REGS;
2123 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2127 ves_icall_type_ispointer (MonoReflectionType *type)
2129 MONO_ARCH_SAVE_REGS;
2131 return type->type->type == MONO_TYPE_PTR;
2135 ves_icall_type_isprimitive (MonoReflectionType *type)
2137 MONO_ARCH_SAVE_REGS;
2139 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)));
2143 ves_icall_type_isbyref (MonoReflectionType *type)
2145 MONO_ARCH_SAVE_REGS;
2147 return type->type->byref;
2151 ves_icall_type_iscomobject (MonoReflectionType *type)
2153 MonoClass *klass = mono_class_from_mono_type (type->type);
2154 MONO_ARCH_SAVE_REGS;
2156 return (klass && klass->is_com_object);
2159 static MonoReflectionModule*
2160 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2162 MonoClass *class = mono_class_from_mono_type (type->type);
2164 MONO_ARCH_SAVE_REGS;
2166 return mono_module_get_object (mono_object_domain (type), class->image);
2169 static MonoReflectionAssembly*
2170 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2172 MonoDomain *domain = mono_domain_get ();
2173 MonoClass *class = mono_class_from_mono_type (type->type);
2175 MONO_ARCH_SAVE_REGS;
2177 return mono_assembly_get_object (domain, class->image->assembly);
2180 static MonoReflectionType*
2181 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2183 MonoDomain *domain = mono_domain_get ();
2186 MONO_ARCH_SAVE_REGS;
2188 if (type->type->byref)
2190 if (type->type->type == MONO_TYPE_VAR)
2191 class = type->type->data.generic_param->owner->owner.klass;
2192 else if (type->type->type == MONO_TYPE_MVAR)
2193 class = type->type->data.generic_param->owner->owner.method->klass;
2195 class = mono_class_from_mono_type (type->type)->nested_in;
2197 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2200 static MonoReflectionType*
2201 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2203 MonoDomain *domain = mono_domain_get ();
2204 MonoClass *class = mono_class_from_mono_type (type->type);
2206 MONO_ARCH_SAVE_REGS;
2208 if (class->enumtype && class->enum_basetype) /* types that are modified typebuilders may not have enum_basetype set */
2209 return mono_type_get_object (domain, class->enum_basetype);
2210 else if (class->element_class)
2211 return mono_type_get_object (domain, &class->element_class->byval_arg);
2217 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2219 MonoDomain *domain = mono_domain_get ();
2220 MonoClass *class = mono_class_from_mono_type (type->type);
2222 MONO_ARCH_SAVE_REGS;
2224 if (type->type->byref) {
2225 char *n = g_strdup_printf ("%s&", class->name);
2226 MonoString *res = mono_string_new (domain, n);
2232 return mono_string_new (domain, class->name);
2237 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2239 MonoDomain *domain = mono_domain_get ();
2240 MonoClass *class = mono_class_from_mono_type (type->type);
2242 MONO_ARCH_SAVE_REGS;
2244 while (class->nested_in)
2245 class = class->nested_in;
2247 if (class->name_space [0] == '\0')
2250 return mono_string_new (domain, class->name_space);
2254 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2256 MonoClass *class = mono_class_from_mono_type (type->type);
2258 MONO_ARCH_SAVE_REGS;
2264 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2267 MonoClass *klass, *pklass;
2269 MONO_ARCH_SAVE_REGS;
2271 klass = mono_class_from_mono_type (type->type);
2273 if (klass->generic_container) {
2274 MonoGenericContainer *container = klass->generic_container;
2275 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, container->type_argc);
2276 for (i = 0; i < container->type_argc; ++i) {
2277 pklass = mono_class_from_generic_parameter (&container->type_params [i], klass->image, FALSE);
2278 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), &pklass->byval_arg));
2280 } else if (klass->generic_class) {
2281 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2282 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, inst->type_argc);
2283 for (i = 0; i < inst->type_argc; ++i)
2284 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), inst->type_argv [i]));
2286 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, 0);
2292 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2295 MONO_ARCH_SAVE_REGS;
2297 if (type->type->byref)
2300 klass = mono_class_from_mono_type (type->type);
2302 return klass->generic_container != NULL;
2305 static MonoReflectionType*
2306 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2309 MONO_ARCH_SAVE_REGS;
2311 if (type->type->byref)
2314 klass = mono_class_from_mono_type (type->type);
2315 if (klass->generic_container) {
2316 return type; /* check this one */
2318 if (klass->generic_class) {
2319 MonoClass *generic_class = klass->generic_class->container_class;
2321 if (generic_class->wastypebuilder && generic_class->reflection_info)
2322 return generic_class->reflection_info;
2324 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2329 static MonoReflectionType*
2330 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2332 MonoType *geninst, **types;
2335 MONO_ARCH_SAVE_REGS;
2337 count = mono_array_length (type_array);
2338 types = g_new0 (MonoType *, count);
2340 for (i = 0; i < count; i++) {
2341 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2342 types [i] = t->type;
2345 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2350 return mono_type_get_object (mono_object_domain (type), geninst);
2354 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2357 MONO_ARCH_SAVE_REGS;
2359 if (type->type->byref)
2362 klass = mono_class_from_mono_type (type->type);
2363 return klass->generic_class != NULL;
2367 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2370 MONO_ARCH_SAVE_REGS;
2372 if (type->type->byref)
2375 klass = mono_class_from_mono_type (type->type);
2376 return klass->generic_class != NULL || klass->generic_container != NULL;
2380 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2382 MONO_ARCH_SAVE_REGS;
2384 if (is_generic_parameter (type->type))
2385 return type->type->data.generic_param->num;
2389 static GenericParameterAttributes
2390 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2392 MONO_ARCH_SAVE_REGS;
2393 g_assert (is_generic_parameter (type->type));
2394 return type->type->data.generic_param->flags;
2398 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2400 MonoGenericParam *param;
2406 MONO_ARCH_SAVE_REGS;
2408 domain = mono_object_domain (type);
2409 param = type->type->data.generic_param;
2410 for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
2413 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2414 for (i = 0; i < count; i++)
2415 mono_array_setref (res, i, mono_type_get_object (domain, ¶m->constraints [i]->byval_arg));
2422 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2424 MONO_ARCH_SAVE_REGS;
2425 return is_generic_parameter (type->type);
2429 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2431 MONO_ARCH_SAVE_REGS;
2432 return is_generic_parameter (tb->type.type);
2436 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2437 MonoReflectionType *t)
2439 enumtype->type = t->type;
2442 static MonoReflectionType*
2443 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2445 MonoDynamicGenericClass *gclass;
2446 MonoReflectionType *parent = NULL, *res;
2452 MONO_ARCH_SAVE_REGS;
2454 g_assert (type->type.type->data.generic_class->is_dynamic);
2455 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2457 domain = mono_object_domain (type);
2458 klass = mono_class_from_mono_type (type->generic_type->type.type);
2460 if (!klass->generic_class && !klass->generic_container)
2463 parent = type->generic_type->parent;
2465 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2468 inflated = mono_class_inflate_generic_type (
2469 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2471 res = mono_type_get_object (domain, inflated);
2472 mono_metadata_free_type (inflated);
2477 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2479 static MonoClass *System_Reflection_MonoGenericClass;
2480 MonoGenericClass *gclass;
2481 MonoReflectionTypeBuilder *tb = NULL;
2482 MonoClass *klass = NULL;
2487 MONO_ARCH_SAVE_REGS;
2489 if (!System_Reflection_MonoGenericClass) {
2490 System_Reflection_MonoGenericClass = mono_class_from_name (
2491 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2492 g_assert (System_Reflection_MonoGenericClass);
2495 domain = mono_object_domain (type);
2497 gclass = type->type.type->data.generic_class;
2498 g_assert (gclass->is_dynamic);
2500 tb = type->generic_type;
2501 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2503 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2505 for (i = 0; i < icount; i++) {
2506 MonoReflectionType *iface;
2510 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2513 it = &klass->interfaces [i]->byval_arg;
2515 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2517 iface = mono_type_get_object (domain, it);
2518 mono_array_setref (res, i, iface);
2519 mono_metadata_free_type (it);
2525 static MonoReflectionMethod*
2526 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2527 MonoReflectionMethod* generic)
2529 MonoGenericClass *gclass;
2530 MonoDynamicGenericClass *dgclass;
2534 MONO_ARCH_SAVE_REGS;
2536 gclass = type->type.type->data.generic_class;
2537 g_assert (gclass->is_dynamic);
2539 dgclass = (MonoDynamicGenericClass *) gclass;
2541 domain = mono_object_domain (type);
2543 for (i = 0; i < dgclass->count_methods; i++)
2544 if (generic->method->token == dgclass->methods [i]->token)
2545 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2550 static MonoReflectionMethod*
2551 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2552 MonoReflectionMethod* generic)
2554 MonoGenericClass *gclass;
2555 MonoDynamicGenericClass *dgclass;
2559 MONO_ARCH_SAVE_REGS;
2561 gclass = type->type.type->data.generic_class;
2562 g_assert (gclass->is_dynamic);
2564 dgclass = (MonoDynamicGenericClass *) gclass;
2566 domain = mono_object_domain (type);
2568 for (i = 0; i < dgclass->count_ctors; i++)
2569 if (generic->method->token == dgclass->ctors [i]->token)
2570 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2576 static MonoReflectionField*
2577 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2578 MonoString* generic_name)
2580 MonoGenericClass *gclass;
2581 MonoDynamicGenericClass *dgclass;
2583 MonoClass *refclass;
2584 char *utf8_name = mono_string_to_utf8 (generic_name);
2587 MONO_ARCH_SAVE_REGS;
2589 gclass = type->type.type->data.generic_class;
2590 g_assert (gclass->is_dynamic);
2592 dgclass = (MonoDynamicGenericClass *) gclass;
2594 refclass = mono_class_from_mono_type (type->type.type);
2596 domain = mono_object_domain (type);
2598 for (i = 0; i < dgclass->count_fields; i++)
2599 if (strcmp (utf8_name, mono_field_get_name (&dgclass->fields [i])) == 0) {
2601 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2610 static MonoReflectionMethod*
2611 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2612 MonoReflectionMethod* generic)
2619 MONO_ARCH_SAVE_REGS;
2621 domain = ((MonoObject *)type)->vtable->domain;
2623 klass = mono_class_from_mono_type (type->type);
2626 while ((method = mono_class_get_methods (klass, &iter))) {
2627 if (method->token == generic->method->token)
2628 return mono_method_get_object (domain, method, klass);
2635 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2636 MonoReflectionType *reflected_type)
2638 MonoGenericClass *gclass;
2639 MonoDynamicGenericClass *dgclass;
2641 MonoClass *refclass;
2645 MONO_ARCH_SAVE_REGS;
2647 gclass = type->type.type->data.generic_class;
2648 g_assert (gclass->is_dynamic);
2649 dgclass = (MonoDynamicGenericClass *) gclass;
2651 refclass = mono_class_from_mono_type (reflected_type->type);
2653 domain = mono_object_domain (type);
2654 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2656 for (i = 0; i < dgclass->count_methods; i++)
2657 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2663 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2664 MonoReflectionType *reflected_type)
2666 static MonoClass *System_Reflection_ConstructorInfo;
2667 MonoGenericClass *gclass;
2668 MonoDynamicGenericClass *dgclass;
2670 MonoClass *refclass;
2674 MONO_ARCH_SAVE_REGS;
2676 if (!System_Reflection_ConstructorInfo)
2677 System_Reflection_ConstructorInfo = mono_class_from_name (
2678 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2680 gclass = type->type.type->data.generic_class;
2681 g_assert (gclass->is_dynamic);
2682 dgclass = (MonoDynamicGenericClass *) gclass;
2684 refclass = mono_class_from_mono_type (reflected_type->type);
2686 domain = mono_object_domain (type);
2687 res = mono_array_new (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2689 for (i = 0; i < dgclass->count_ctors; i++)
2690 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2696 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2697 MonoReflectionType *reflected_type)
2699 MonoGenericClass *gclass;
2700 MonoDynamicGenericClass *dgclass;
2702 MonoClass *refclass;
2706 MONO_ARCH_SAVE_REGS;
2708 gclass = type->type.type->data.generic_class;
2709 g_assert (gclass->is_dynamic);
2710 dgclass = (MonoDynamicGenericClass *) gclass;
2712 refclass = mono_class_from_mono_type (reflected_type->type);
2714 domain = mono_object_domain (type);
2715 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2717 for (i = 0; i < dgclass->count_fields; i++)
2718 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2724 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2725 MonoReflectionType *reflected_type)
2727 static MonoClass *System_Reflection_PropertyInfo;
2728 MonoGenericClass *gclass;
2729 MonoDynamicGenericClass *dgclass;
2731 MonoClass *refclass;
2735 MONO_ARCH_SAVE_REGS;
2737 if (!System_Reflection_PropertyInfo)
2738 System_Reflection_PropertyInfo = mono_class_from_name (
2739 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2741 gclass = type->type.type->data.generic_class;
2742 g_assert (gclass->is_dynamic);
2743 dgclass = (MonoDynamicGenericClass *) gclass;
2745 refclass = mono_class_from_mono_type (reflected_type->type);
2747 domain = mono_object_domain (type);
2748 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2750 for (i = 0; i < dgclass->count_properties; i++)
2751 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2757 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2758 MonoReflectionType *reflected_type)
2760 static MonoClass *System_Reflection_EventInfo;
2761 MonoGenericClass *gclass;
2762 MonoDynamicGenericClass *dgclass;
2764 MonoClass *refclass;
2768 MONO_ARCH_SAVE_REGS;
2770 if (!System_Reflection_EventInfo)
2771 System_Reflection_EventInfo = mono_class_from_name (
2772 mono_defaults.corlib, "System.Reflection", "EventInfo");
2774 gclass = type->type.type->data.generic_class;
2775 g_assert (gclass->is_dynamic);
2776 dgclass = (MonoDynamicGenericClass *) gclass;
2778 refclass = mono_class_from_mono_type (reflected_type->type);
2780 domain = mono_object_domain (type);
2781 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2783 for (i = 0; i < dgclass->count_events; i++)
2784 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2789 static MonoReflectionType*
2790 ves_icall_MonoGenericClass_InflateType (MonoReflectionGenericClass *type,
2791 MonoReflectionType *target)
2795 MonoReflectionType *res;
2797 MONO_ARCH_SAVE_REGS;
2799 gklass = mono_class_from_mono_type (type->type.type);
2800 res_type = mono_class_inflate_generic_type (target->type, mono_class_get_context (gklass));
2801 res = mono_type_get_object (mono_object_domain (type), res_type);
2802 mono_metadata_free_type (res_type);
2806 static MonoReflectionMethod *
2807 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2812 MONO_ARCH_SAVE_REGS;
2814 if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2817 method = type->type->data.generic_param->owner->owner.method;
2819 klass = mono_class_from_mono_type (type->type);
2820 return mono_method_get_object (mono_object_domain (type), method, klass);
2823 static MonoReflectionDllImportAttribute*
2824 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2826 static MonoClass *DllImportAttributeClass = NULL;
2827 MonoDomain *domain = mono_domain_get ();
2828 MonoReflectionDllImportAttribute *attr;
2829 MonoImage *image = method->klass->image;
2830 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2831 MonoTableInfo *tables = image->tables;
2832 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2833 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2834 guint32 im_cols [MONO_IMPLMAP_SIZE];
2835 guint32 scope_token;
2836 const char *import = NULL;
2837 const char *scope = NULL;
2840 if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2843 if (!DllImportAttributeClass) {
2844 DllImportAttributeClass =
2845 mono_class_from_name (mono_defaults.corlib,
2846 "System.Runtime.InteropServices", "DllImportAttribute");
2847 g_assert (DllImportAttributeClass);
2850 if (method->klass->image->dynamic) {
2851 MonoReflectionMethodAux *method_aux =
2852 g_hash_table_lookup (
2853 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2855 import = method_aux->dllentry;
2856 scope = method_aux->dll;
2860 if (piinfo->implmap_idx) {
2861 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2863 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2864 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2865 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2866 scope = mono_metadata_string_heap (image, scope_token);
2869 flags = piinfo->piflags;
2871 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2873 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2874 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2875 attr->call_conv = (flags & 0x700) >> 8;
2876 attr->charset = ((flags & 0x6) >> 1) + 1;
2877 if (attr->charset == 1)
2879 attr->exact_spelling = (flags & 0x1) != 0;
2880 attr->set_last_error = (flags & 0x40) != 0;
2881 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2882 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2883 attr->preserve_sig = FALSE;
2888 static MonoReflectionMethod *
2889 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2891 MonoMethodInflated *imethod;
2894 MONO_ARCH_SAVE_REGS;
2896 if (method->method->is_generic)
2899 if (!method->method->is_inflated)
2902 imethod = (MonoMethodInflated *) method->method;
2904 result = imethod->declaring;
2905 /* Not a generic method. */
2906 if (!result->is_generic)
2909 if (method->method->klass->image->dynamic) {
2910 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2911 MonoReflectionMethod *res;
2914 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2915 * the dynamic case as well ?
2917 mono_loader_lock ();
2918 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2919 mono_loader_unlock ();
2925 if (imethod->context.class_inst) {
2926 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2927 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2930 return mono_method_get_object (mono_object_domain (method), result, NULL);
2934 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2936 MONO_ARCH_SAVE_REGS;
2938 return mono_method_signature (method->method)->generic_param_count != 0;
2942 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2944 MONO_ARCH_SAVE_REGS;
2946 return method->method->is_generic;
2950 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2955 MONO_ARCH_SAVE_REGS;
2957 domain = mono_object_domain (method);
2959 if (method->method->is_inflated) {
2960 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2963 count = inst->type_argc;
2964 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2966 for (i = 0; i < count; i++)
2967 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2973 count = mono_method_signature (method->method)->generic_param_count;
2974 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2976 for (i = 0; i < count; i++) {
2977 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2978 MonoGenericParam *param = &container->type_params [i];
2979 MonoClass *pklass = mono_class_from_generic_parameter (
2980 param, method->method->klass->image, TRUE);
2981 mono_array_setref (res, i,
2982 mono_type_get_object (domain, &pklass->byval_arg));
2989 ensure_reflection_security (void)
2991 MonoMethod *m = mono_method_get_last_managed ();
2995 g_print ("method %s.%s.%s in image %s\n",
2996 m->klass->name_space, m->klass->name, m->name, m->klass->image->name);
2999 /* We stop at the first method which is not in
3000 System.Reflection or which is not in a platform
3002 if (strcmp (m->klass->name_space, "System.Reflection") != 0 ||
3003 !mono_security_core_clr_is_platform_image (m->klass->image)) {
3004 /* If the method is transparent we throw an exception. */
3005 if (mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_TRANSPARENT ) {
3006 MonoException *ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", "Reflection called from transparent code");
3008 mono_raise_exception (ex);
3013 mono_stack_walk_no_il (get_caller, &m);
3018 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
3021 * Invoke from reflection is supposed to always be a virtual call (the API
3022 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3023 * greater flexibility.
3025 MonoMethod *m = method->method;
3029 MONO_ARCH_SAVE_REGS;
3033 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR &&
3034 mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL)
3035 ensure_reflection_security ();
3037 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3039 if (!mono_object_isinst (this, m->klass)) {
3040 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type.");
3043 m = mono_object_get_virtual_method (this, m);
3044 /* must pass the pointer to the value for valuetype methods */
3045 if (m->klass->valuetype)
3046 obj = mono_object_unbox (this);
3047 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3048 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target.");
3053 pcount = params? mono_array_length (params): 0;
3054 if (pcount != mono_method_signature (m)->param_count) {
3055 *exc = mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException");
3059 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
3060 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class.");
3064 if (m->klass->image->assembly->ref_only) {
3065 *exc = mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api.");
3069 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3071 mono_array_size_t *lengths;
3072 mono_array_size_t *lower_bounds;
3073 pcount = mono_array_length (params);
3074 lengths = alloca (sizeof (mono_array_size_t) * pcount);
3075 for (i = 0; i < pcount; ++i)
3076 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3078 if (m->klass->rank == pcount) {
3079 /* Only lengths provided. */
3080 lower_bounds = NULL;
3082 g_assert (pcount == (m->klass->rank * 2));
3083 /* lower bounds are first. */
3084 lower_bounds = lengths;
3085 lengths += m->klass->rank;
3088 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
3090 return mono_runtime_invoke_array (m, obj, params, NULL);
3094 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
3096 MonoDomain *domain = mono_object_domain (method);
3097 MonoMethod *m = method->method;
3098 MonoMethodSignature *sig = mono_method_signature (m);
3099 MonoArray *out_args;
3101 int i, j, outarg_count = 0;
3103 MONO_ARCH_SAVE_REGS;
3105 if (m->klass == mono_defaults.object_class) {
3107 if (!strcmp (m->name, "FieldGetter")) {
3108 MonoClass *k = this->vtable->klass;
3112 /* If this is a proxy, then it must be a CBO */
3113 if (k == mono_defaults.transparent_proxy_class) {
3114 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3115 this = tp->rp->unwrapped_server;
3117 k = this->vtable->klass;
3120 name = mono_array_get (params, MonoString *, 1);
3121 str = mono_string_to_utf8 (name);
3124 MonoClassField* field = mono_class_get_field_from_name (k, str);
3126 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3127 if (field_klass->valuetype)
3128 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
3130 result = *((gpointer *)((char *)this + field->offset));
3132 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3133 *outArgs = out_args;
3134 mono_array_setref (out_args, 0, result);
3142 g_assert_not_reached ();
3144 } else if (!strcmp (m->name, "FieldSetter")) {
3145 MonoClass *k = this->vtable->klass;
3151 /* If this is a proxy, then it must be a CBO */
3152 if (k == mono_defaults.transparent_proxy_class) {
3153 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3154 this = tp->rp->unwrapped_server;
3156 k = this->vtable->klass;
3159 name = mono_array_get (params, MonoString *, 1);
3160 str = mono_string_to_utf8 (name);
3163 MonoClassField* field = mono_class_get_field_from_name (k, str);
3165 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3166 MonoObject *val = mono_array_get (params, gpointer, 2);
3168 if (field_klass->valuetype) {
3169 size = mono_type_size (field->type, &align);
3171 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3173 memcpy ((char *)this + field->offset,
3174 ((char *)val) + sizeof (MonoObject), size);
3176 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
3179 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3180 *outArgs = out_args;
3190 g_assert_not_reached ();
3195 for (i = 0; i < mono_array_length (params); i++) {
3196 if (sig->params [i]->byref)
3200 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3202 /* handle constructors only for objects already allocated */
3203 if (!strcmp (method->method->name, ".ctor"))
3206 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3207 g_assert (!method->method->klass->valuetype);
3208 result = mono_runtime_invoke_array (method->method, this, params, NULL);
3210 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3211 if (sig->params [i]->byref) {
3213 arg = mono_array_get (params, gpointer, i);
3214 mono_array_setref (out_args, j, arg);
3219 *outArgs = out_args;
3225 read_enum_value (char *mem, int type)
3229 return *(guint8*)mem;
3231 return *(gint8*)mem;
3233 return *(guint16*)mem;
3235 return *(gint16*)mem;
3237 return *(guint32*)mem;
3239 return *(gint32*)mem;
3241 return *(guint64*)mem;
3243 return *(gint64*)mem;
3245 g_assert_not_reached ();
3251 write_enum_value (char *mem, int type, guint64 value)
3255 case MONO_TYPE_I1: {
3256 guint8 *p = (guint8*)mem;
3261 case MONO_TYPE_I2: {
3262 guint16 *p = (void*)mem;
3267 case MONO_TYPE_I4: {
3268 guint32 *p = (void*)mem;
3273 case MONO_TYPE_I8: {
3274 guint64 *p = (void*)mem;
3279 g_assert_not_reached ();
3285 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3288 MonoClass *enumc, *objc;
3292 MONO_ARCH_SAVE_REGS;
3294 MONO_CHECK_ARG_NULL (enumType);
3295 MONO_CHECK_ARG_NULL (value);
3297 domain = mono_object_domain (enumType);
3298 enumc = mono_class_from_mono_type (enumType->type);
3299 objc = value->vtable->klass;
3301 if (!enumc->enumtype)
3302 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3303 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3304 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."));
3306 res = mono_object_new (domain, enumc);
3307 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? objc->enum_basetype->type: objc->byval_arg.type);
3308 write_enum_value ((char *)res + sizeof (MonoObject), enumc->enum_basetype->type, val);
3314 ves_icall_System_Enum_get_value (MonoObject *this)
3322 MONO_ARCH_SAVE_REGS;
3327 g_assert (this->vtable->klass->enumtype);
3329 enumc = mono_class_from_mono_type (this->vtable->klass->enum_basetype);
3330 res = mono_object_new (mono_object_domain (this), enumc);
3331 dst = (char *)res + sizeof (MonoObject);
3332 src = (char *)this + sizeof (MonoObject);
3333 size = mono_class_value_size (enumc, NULL);
3335 memcpy (dst, src, size);
3340 static MonoReflectionType *
3341 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3343 MONO_ARCH_SAVE_REGS;
3345 return mono_type_get_object (mono_object_domain (type), mono_class_from_mono_type (type->type)->enum_basetype);
3349 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3351 gpointer data = (char *)this + sizeof (MonoObject);
3352 MonoType *basetype = this->vtable->klass->enum_basetype;
3353 g_assert (basetype);
3355 switch (basetype->type) {
3357 return *((gint8*)data);
3359 return *((guint8*)data);
3360 case MONO_TYPE_CHAR:
3362 return *((guint16*)data);
3365 return *((gint16*)data);
3367 return *((guint32*)data);
3369 return *((gint32*)data);
3371 case MONO_TYPE_I8: {
3372 gint64 value = *((gint64*)data);
3373 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3376 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3382 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3384 MonoDomain *domain = mono_object_domain (type);
3385 MonoClass *enumc = mono_class_from_mono_type (type->type);
3386 guint j = 0, nvalues, crow;
3388 MonoClassField *field;
3390 MONO_ARCH_SAVE_REGS;
3392 info->utype = mono_type_get_object (domain, enumc->enum_basetype);
3393 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3394 info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3395 info->values = mono_array_new (domain, enumc, nvalues);
3399 while ((field = mono_class_get_fields (enumc, &iter))) {
3402 MonoTypeEnum def_type;
3404 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3406 if (mono_field_is_deleted (field))
3408 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3410 p = mono_class_get_field_default_value (field, &def_type);
3411 len = mono_metadata_decode_blob_size (p, &p);
3412 switch (enumc->enum_basetype->type) {
3415 mono_array_set (info->values, gchar, j, *p);
3417 case MONO_TYPE_CHAR:
3420 mono_array_set (info->values, gint16, j, read16 (p));
3424 mono_array_set (info->values, gint32, j, read32 (p));
3428 mono_array_set (info->values, gint64, j, read64 (p));
3431 g_error ("Implement type 0x%02x in get_enum_info", enumc->enum_basetype->type);
3438 BFLAGS_IgnoreCase = 1,
3439 BFLAGS_DeclaredOnly = 2,
3440 BFLAGS_Instance = 4,
3442 BFLAGS_Public = 0x10,
3443 BFLAGS_NonPublic = 0x20,
3444 BFLAGS_FlattenHierarchy = 0x40,
3445 BFLAGS_InvokeMethod = 0x100,
3446 BFLAGS_CreateInstance = 0x200,
3447 BFLAGS_GetField = 0x400,
3448 BFLAGS_SetField = 0x800,
3449 BFLAGS_GetProperty = 0x1000,
3450 BFLAGS_SetProperty = 0x2000,
3451 BFLAGS_ExactBinding = 0x10000,
3452 BFLAGS_SuppressChangeType = 0x20000,
3453 BFLAGS_OptionalParamBinding = 0x40000
3456 static MonoReflectionField *
3457 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3460 MonoClass *startklass, *klass;
3462 MonoClassField *field;
3465 int (*compare_func) (const char *s1, const char *s2) = NULL;
3466 domain = ((MonoObject *)type)->vtable->domain;
3467 klass = startklass = mono_class_from_mono_type (type->type);
3469 MONO_ARCH_SAVE_REGS;
3472 mono_raise_exception (mono_get_exception_argument_null ("name"));
3473 if (type->type->byref)
3476 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3479 if (klass->exception_type != MONO_EXCEPTION_NONE)
3480 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3483 while ((field = mono_class_get_fields (klass, &iter))) {
3486 if (field->type == NULL)
3488 if (mono_field_is_deleted (field))
3490 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3491 if (bflags & BFLAGS_Public)
3493 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3494 if (bflags & BFLAGS_NonPublic) {
3501 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3502 if (bflags & BFLAGS_Static)
3503 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3506 if (bflags & BFLAGS_Instance)
3513 utf8_name = mono_string_to_utf8 (name);
3515 if (compare_func (mono_field_get_name (field), utf8_name)) {
3521 return mono_field_get_object (domain, klass, field);
3523 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3530 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3533 MonoClass *startklass, *klass, *refklass;
3538 MonoClassField *field;
3540 MONO_ARCH_SAVE_REGS;
3542 domain = ((MonoObject *)type)->vtable->domain;
3543 if (type->type->byref)
3544 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3545 klass = startklass = mono_class_from_mono_type (type->type);
3546 refklass = mono_class_from_mono_type (reftype->type);
3550 res = mono_array_new (domain, mono_defaults.field_info_class, len);
3552 if (klass->exception_type != MONO_EXCEPTION_NONE)
3553 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3556 while ((field = mono_class_get_fields (klass, &iter))) {
3558 if (mono_field_is_deleted (field))
3560 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3561 if (bflags & BFLAGS_Public)
3563 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3564 if (bflags & BFLAGS_NonPublic) {
3571 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3572 if (bflags & BFLAGS_Static)
3573 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3576 if (bflags & BFLAGS_Instance)
3582 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3584 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, len * 2);
3585 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3589 mono_array_setref (res, i, member);
3592 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3595 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, i);
3596 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3599 * Better solution for the new GC.
3600 * res->max_length = i;
3607 method_nonpublic (MonoMethod* method, gboolean start_klass)
3609 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3610 case METHOD_ATTRIBUTE_ASSEM:
3611 return (start_klass || mono_defaults.generic_ilist_class);
3612 case METHOD_ATTRIBUTE_PRIVATE:
3614 case METHOD_ATTRIBUTE_PUBLIC:
3622 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3624 static MonoClass *MethodInfo_array;
3626 MonoClass *startklass, *klass, *refklass;
3631 int i, len, match, nslots;
3632 guint32 method_slots_default [8];
3633 guint32 *method_slots;
3634 gchar *mname = NULL;
3635 int (*compare_func) (const char *s1, const char *s2) = NULL;
3636 MonoVTable *array_vtable;
3638 MONO_ARCH_SAVE_REGS;
3640 if (!MethodInfo_array) {
3641 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3642 mono_memory_barrier ();
3643 MethodInfo_array = klass;
3646 domain = ((MonoObject *)type)->vtable->domain;
3647 array_vtable = mono_class_vtable (domain, MethodInfo_array);
3648 if (type->type->byref)
3649 return mono_array_new_specific (array_vtable, 0);
3650 klass = startklass = mono_class_from_mono_type (type->type);
3651 refklass = mono_class_from_mono_type (reftype->type);
3654 mname = mono_string_to_utf8 (name);
3655 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3658 mono_class_setup_vtable (klass);
3660 if (is_generic_parameter (type->type))
3661 nslots = klass->parent->vtable_size;
3663 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3664 if (nslots >= sizeof (method_slots_default) * 8) {
3665 method_slots = g_new0 (guint32, nslots / 32 + 1);
3667 method_slots = method_slots_default;
3668 memset (method_slots, 0, sizeof (method_slots_default));
3672 res = mono_array_new_specific (array_vtable, len);
3674 mono_class_setup_vtable (klass);
3675 if (klass->exception_type != MONO_EXCEPTION_NONE)
3676 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3679 while ((method = mono_class_get_methods (klass, &iter))) {
3681 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3683 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3684 if (bflags & BFLAGS_Public)
3686 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3692 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3693 if (bflags & BFLAGS_Static)
3694 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3697 if (bflags & BFLAGS_Instance)
3705 if (compare_func (mname, method->name))
3710 if (method->slot != -1) {
3711 g_assert (method->slot < nslots);
3712 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3714 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3717 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3720 MonoArray *new_res = mono_array_new_specific (array_vtable, len * 2);
3721 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3725 mono_array_setref (res, i, member);
3728 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3732 if (method_slots != method_slots_default)
3733 g_free (method_slots);
3735 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, i);
3736 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3739 * Better solution for the new GC.
3740 * res->max_length = i;
3747 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3750 static MonoClass *System_Reflection_ConstructorInfo;
3751 MonoClass *startklass, *klass, *refklass;
3756 gpointer iter = NULL;
3758 MONO_ARCH_SAVE_REGS;
3760 domain = ((MonoObject *)type)->vtable->domain;
3761 if (type->type->byref)
3762 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3763 klass = startklass = mono_class_from_mono_type (type->type);
3764 refklass = mono_class_from_mono_type (reftype->type);
3766 if (klass->exception_type != MONO_EXCEPTION_NONE)
3767 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3769 if (!System_Reflection_ConstructorInfo)
3770 System_Reflection_ConstructorInfo = mono_class_from_name (
3771 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3775 res = mono_array_new (domain, System_Reflection_ConstructorInfo, len);
3777 while ((method = mono_class_get_methods (klass, &iter))) {
3779 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3781 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3782 if (bflags & BFLAGS_Public)
3785 if (bflags & BFLAGS_NonPublic)
3791 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3792 if (bflags & BFLAGS_Static)
3793 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3796 if (bflags & BFLAGS_Instance)
3802 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3805 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, len * 2);
3806 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3810 mono_array_setref (res, i, member);
3814 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, i);
3815 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3818 * Better solution for the new GC.
3819 * res->max_length = i;
3826 property_hash (gconstpointer data)
3828 MonoProperty *prop = (MonoProperty*)data;
3830 return g_str_hash (prop->name);
3834 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3836 // Properties are hide-by-name-and-signature
3837 if (!g_str_equal (prop1->name, prop2->name))
3840 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3842 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3848 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3853 return method_nonpublic (accessor, start_klass);
3857 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3860 static MonoClass *System_Reflection_PropertyInfo;
3861 MonoClass *startklass, *klass;
3868 gchar *propname = NULL;
3869 int (*compare_func) (const char *s1, const char *s2) = NULL;
3871 GHashTable *properties;
3873 MONO_ARCH_SAVE_REGS;
3875 if (!System_Reflection_PropertyInfo)
3876 System_Reflection_PropertyInfo = mono_class_from_name (
3877 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3879 domain = ((MonoObject *)type)->vtable->domain;
3880 if (type->type->byref)
3881 return mono_array_new (domain, System_Reflection_PropertyInfo, 0);
3882 klass = startklass = mono_class_from_mono_type (type->type);
3884 propname = mono_string_to_utf8 (name);
3885 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3888 mono_class_setup_vtable (klass);
3890 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3893 res = mono_array_new (domain, System_Reflection_PropertyInfo, len);
3895 mono_class_setup_vtable (klass);
3896 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3897 g_hash_table_destroy (properties);
3900 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3904 while ((prop = mono_class_get_properties (klass, &iter))) {
3910 flags = method->flags;
3913 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3914 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3915 if (bflags & BFLAGS_Public)
3917 } else if (bflags & BFLAGS_NonPublic) {
3918 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3919 property_accessor_nonpublic(prop->set, startklass == klass)) {
3926 if (flags & METHOD_ATTRIBUTE_STATIC) {
3927 if (bflags & BFLAGS_Static)
3928 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3931 if (bflags & BFLAGS_Instance)
3940 if (compare_func (propname, prop->name))
3944 if (g_hash_table_lookup (properties, prop))
3948 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, len * 2);
3949 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3953 mono_array_setref (res, i, mono_property_get_object (domain, startklass, prop));
3956 g_hash_table_insert (properties, prop, prop);
3958 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3961 g_hash_table_destroy (properties);
3964 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, i);
3965 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3968 * Better solution for the new GC.
3969 * res->max_length = i;
3975 static MonoReflectionEvent *
3976 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3979 MonoClass *klass, *startklass;
3985 MONO_ARCH_SAVE_REGS;
3987 event_name = mono_string_to_utf8 (name);
3988 if (type->type->byref)
3990 klass = startklass = mono_class_from_mono_type (type->type);
3991 domain = mono_object_domain (type);
3994 if (klass->exception_type != MONO_EXCEPTION_NONE)
3995 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3998 while ((event = mono_class_get_events (klass, &iter))) {
3999 if (strcmp (event->name, event_name))
4002 method = event->add;
4004 method = event->remove;
4006 method = event->raise;
4008 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4009 if (!(bflags & BFLAGS_Public))
4012 if (!(bflags & BFLAGS_NonPublic))
4014 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4019 if (!(bflags & BFLAGS_NonPublic))
4022 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4023 if (!(bflags & BFLAGS_Static))
4025 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4028 if (!(bflags & BFLAGS_Instance))
4032 g_free (event_name);
4033 return mono_event_get_object (domain, startklass, event);
4036 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4039 g_free (event_name);
4044 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4047 static MonoClass *System_Reflection_EventInfo;
4048 MonoClass *startklass, *klass;
4055 MONO_ARCH_SAVE_REGS;
4057 if (!System_Reflection_EventInfo)
4058 System_Reflection_EventInfo = mono_class_from_name (
4059 mono_defaults.corlib, "System.Reflection", "EventInfo");
4061 domain = mono_object_domain (type);
4062 if (type->type->byref)
4063 return mono_array_new (domain, System_Reflection_EventInfo, 0);
4064 klass = startklass = mono_class_from_mono_type (type->type);
4068 res = mono_array_new (domain, System_Reflection_EventInfo, len);
4070 if (klass->exception_type != MONO_EXCEPTION_NONE)
4071 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4074 while ((event = mono_class_get_events (klass, &iter))) {
4076 method = event->add;
4078 method = event->remove;
4080 method = event->raise;
4082 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4083 if (bflags & BFLAGS_Public)
4085 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4086 if (bflags & BFLAGS_NonPublic)
4091 if (bflags & BFLAGS_NonPublic)
4097 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4098 if (bflags & BFLAGS_Static)
4099 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4102 if (bflags & BFLAGS_Instance)
4107 if (bflags & BFLAGS_Instance)
4113 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, len * 2);
4114 mono_array_memcpy_refs (new_res, 0, res, 0, len);
4118 mono_array_setref (res, i, mono_event_get_object (domain, startklass, event));
4121 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4124 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, i);
4125 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4128 * Better solution for the new GC.
4129 * res->max_length = i;
4135 static MonoReflectionType *
4136 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4144 MONO_ARCH_SAVE_REGS;
4146 domain = ((MonoObject *)type)->vtable->domain;
4147 if (type->type->byref)
4149 klass = mono_class_from_mono_type (type->type);
4150 str = mono_string_to_utf8 (name);
4153 if (klass->exception_type != MONO_EXCEPTION_NONE)
4154 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4157 * If a nested type is generic, return its generic type definition.
4158 * Note that this means that the return value is essentially a
4159 * nested type of the generic type definition of @klass.
4161 * A note in MSDN claims that a generic type definition can have
4162 * nested types that aren't generic. In any case, the container of that
4163 * nested type would be the generic type definition.
4165 if (klass->generic_class)
4166 klass = klass->generic_class->container_class;
4169 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4171 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4172 if (bflags & BFLAGS_Public)
4175 if (bflags & BFLAGS_NonPublic)
4180 if (strcmp (nested->name, str) == 0){
4182 return mono_type_get_object (domain, &nested->byval_arg);
4185 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4192 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4202 MONO_ARCH_SAVE_REGS;
4204 domain = ((MonoObject *)type)->vtable->domain;
4205 if (type->type->byref)
4206 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4207 klass = mono_class_from_mono_type (type->type);
4208 if (klass->exception_type != MONO_EXCEPTION_NONE)
4209 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4212 * If a nested type is generic, return its generic type definition.
4213 * Note that this means that the return value is essentially the set
4214 * of nested types of the generic type definition of @klass.
4216 * A note in MSDN claims that a generic type definition can have
4217 * nested types that aren't generic. In any case, the container of that
4218 * nested type would be the generic type definition.
4220 if (klass->generic_class)
4221 klass = klass->generic_class->container_class;
4225 res = mono_array_new (domain, mono_defaults.monotype_class, len);
4227 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4229 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4230 if (bflags & BFLAGS_Public)
4233 if (bflags & BFLAGS_NonPublic)
4238 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4240 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, len * 2);
4241 mono_array_memcpy_refs (new_res, 0, res, 0, len);
4245 mono_array_setref (res, i, member);
4249 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, i);
4250 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4253 * Better solution for the new GC.
4254 * res->max_length = i;
4260 static MonoReflectionType*
4261 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4264 MonoType *type = NULL;
4265 MonoTypeNameParse info;
4266 gboolean type_resolve;
4268 MONO_ARCH_SAVE_REGS;
4270 /* On MS.NET, this does not fire a TypeResolve event */
4271 type_resolve = TRUE;
4272 str = mono_string_to_utf8 (name);
4273 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4274 if (!mono_reflection_parse_type (str, &info)) {
4276 mono_reflection_free_type_info (&info);
4277 if (throwOnError) /* uhm: this is a parse error, though... */
4278 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4279 /*g_print ("failed parse\n");*/
4283 if (info.assembly.name) {
4285 mono_reflection_free_type_info (&info);
4287 /* 1.0 and 2.0 throw different exceptions */
4288 if (mono_defaults.generic_ilist_class)
4289 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4291 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4296 if (module != NULL) {
4298 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4303 if (assembly->assembly->dynamic) {
4304 /* Enumerate all modules */
4305 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4309 if (abuilder->modules) {
4310 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4311 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4312 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4318 if (!type && abuilder->loaded_modules) {
4319 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4320 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4321 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4328 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4330 mono_reflection_free_type_info (&info);
4332 MonoException *e = NULL;
4335 e = mono_get_exception_type_load (name, NULL);
4337 mono_loader_clear_error ();
4340 mono_raise_exception (e);
4345 if (type->type == MONO_TYPE_CLASS) {
4346 MonoClass *klass = mono_type_get_class (type);
4348 if (mono_is_security_manager_active () && !klass->exception_type)
4349 /* Some security problems are detected during generic vtable construction */
4350 mono_class_setup_vtable (klass);
4351 /* need to report exceptions ? */
4352 if (throwOnError && klass->exception_type) {
4353 /* report SecurityException (or others) that occured when loading the assembly */
4354 MonoException *exc = mono_class_get_exception_for_failure (klass);
4355 mono_loader_clear_error ();
4356 mono_raise_exception (exc);
4357 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4362 /* g_print ("got it\n"); */
4363 return mono_type_get_object (mono_object_domain (assembly), type);
4367 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4369 MonoDomain *domain = mono_object_domain (assembly);
4370 MonoAssembly *mass = assembly->assembly;
4371 MonoString *res = NULL;
4375 gchar *shadow_ini_file;
4379 MONO_ARCH_SAVE_REGS;
4381 if (g_path_is_absolute (mass->image->name)) {
4382 absolute = g_strdup (mass->image->name);
4383 dirname = g_path_get_dirname (absolute);
4385 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4386 dirname = g_strdup (mass->basedir);
4389 /* Check for shadow-copied assembly */
4390 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4391 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4393 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4394 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4400 g_free (shadow_ini_file);
4401 if (content != NULL) {
4411 for (i = strlen (absolute) - 1; i >= 0; i--)
4412 if (absolute [i] == '\\')
4417 uri = g_filename_to_uri (absolute, NULL, NULL);
4419 const char *prepend = "file://";
4421 if (*absolute == '/' && *(absolute + 1) == '/') {
4424 prepend = "file:///";
4427 uri = g_strconcat (prepend, absolute, NULL);
4431 res = mono_string_new (domain, uri);
4439 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4441 MonoAssembly *mass = assembly->assembly;
4443 MONO_ARCH_SAVE_REGS;
4445 return mass->in_gac;
4448 static MonoReflectionAssembly*
4449 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4453 MonoImageOpenStatus status;
4455 MONO_ARCH_SAVE_REGS;
4457 name = mono_string_to_utf8 (mname);
4458 res = mono_assembly_load_with_partial_name (name, &status);
4464 return mono_assembly_get_object (mono_domain_get (), res);
4468 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4470 MonoDomain *domain = mono_object_domain (assembly);
4473 MONO_ARCH_SAVE_REGS;
4475 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4481 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4483 MONO_ARCH_SAVE_REGS;
4485 return assembly->assembly->ref_only;
4489 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4491 MonoDomain *domain = mono_object_domain (assembly);
4493 MONO_ARCH_SAVE_REGS;
4495 return mono_string_new (domain, assembly->assembly->image->version);
4498 static MonoReflectionMethod*
4499 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4501 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4503 MONO_ARCH_SAVE_REGS;
4507 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4510 static MonoReflectionModule*
4511 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4513 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4517 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4519 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4520 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4524 MONO_ARCH_SAVE_REGS;
4526 for (i = 0; i < table->rows; ++i) {
4527 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4528 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4534 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4536 static MonoClass *System_Version = NULL;
4537 static MonoMethod *create_version = NULL;
4541 if (!System_Version) {
4542 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4543 g_assert (System_Version);
4546 if (!create_version) {
4547 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4548 create_version = mono_method_desc_search_in_class (desc, System_Version);
4549 g_assert (create_version);
4550 mono_method_desc_free (desc);
4556 args [3] = &revision;
4557 result = mono_object_new (domain, System_Version);
4558 mono_runtime_invoke (create_version, result, args, NULL);
4564 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4566 static MonoClass *System_Reflection_AssemblyName;
4568 MonoDomain *domain = mono_object_domain (assembly);
4570 static MonoMethod *create_culture = NULL;
4571 MonoImage *image = assembly->assembly->image;
4574 MONO_ARCH_SAVE_REGS;
4576 if (!System_Reflection_AssemblyName)
4577 System_Reflection_AssemblyName = mono_class_from_name (
4578 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4580 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4583 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4586 MonoMethodDesc *desc = mono_method_desc_new (
4587 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4588 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4589 g_assert (create_culture);
4590 mono_method_desc_free (desc);
4593 for (i = 0; i < count; i++) {
4594 MonoReflectionAssemblyName *aname;
4595 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4597 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4599 aname = (MonoReflectionAssemblyName *) mono_object_new (
4600 domain, System_Reflection_AssemblyName);
4602 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4604 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4605 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4606 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4607 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4608 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4609 aname->versioncompat = 1; /* SameMachine (default) */
4610 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4611 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4613 if (create_culture) {
4615 MonoBoolean assembly_ref = 1;
4616 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4617 args [1] = &assembly_ref;
4618 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4621 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4622 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4623 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4625 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4626 /* public key token isn't copied - the class library will
4627 automatically generate it from the public key if required */
4628 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4629 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4631 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4632 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4635 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4638 /* note: this function doesn't return the codebase on purpose (i.e. it can
4639 be used under partial trust as path information isn't present). */
4641 mono_array_setref (result, i, aname);
4652 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4654 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4656 mono_array_setref (info->res, info->idx, name);
4661 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4663 MonoImage *img = assembly->assembly->image;
4667 MONO_ARCH_SAVE_REGS;
4669 if (!img->name_cache)
4670 mono_image_init_name_cache (img);
4672 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4675 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4680 /* move this in some file in mono/util/ */
4682 g_concat_dir_and_file (const char *dir, const char *file)
4684 g_return_val_if_fail (dir != NULL, NULL);
4685 g_return_val_if_fail (file != NULL, NULL);
4688 * If the directory name doesn't have a / on the end, we need
4689 * to add one so we get a proper path to the file
4691 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4692 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4694 return g_strconcat (dir, file, NULL);
4698 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4700 char *n = mono_string_to_utf8 (name);
4701 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4703 guint32 cols [MONO_MANIFEST_SIZE];
4704 guint32 impl, file_idx;
4708 MONO_ARCH_SAVE_REGS;
4710 for (i = 0; i < table->rows; ++i) {
4711 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4712 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4713 if (strcmp (val, n) == 0)
4717 if (i == table->rows)
4720 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4723 * this code should only be called after obtaining the
4724 * ResourceInfo and handling the other cases.
4726 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4727 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4729 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4734 module = assembly->assembly->image;
4736 *ref_module = mono_module_get_object (mono_domain_get (), module);
4738 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4742 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4744 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4746 guint32 cols [MONO_MANIFEST_SIZE];
4747 guint32 file_cols [MONO_FILE_SIZE];
4751 MONO_ARCH_SAVE_REGS;
4753 n = mono_string_to_utf8 (name);
4754 for (i = 0; i < table->rows; ++i) {
4755 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4756 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4757 if (strcmp (val, n) == 0)
4761 if (i == table->rows)
4764 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4765 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4768 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4769 case MONO_IMPLEMENTATION_FILE:
4770 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4771 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4772 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4773 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4774 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4775 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4778 info->location = RESOURCE_LOCATION_EMBEDDED;
4781 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4782 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4783 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4784 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4785 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4786 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4788 mono_raise_exception (ex);
4790 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4792 /* Obtain info recursively */
4793 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4794 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4797 case MONO_IMPLEMENTATION_EXP_TYPE:
4798 g_assert_not_reached ();
4807 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4809 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4810 MonoArray *result = NULL;
4815 MONO_ARCH_SAVE_REGS;
4817 /* check hash if needed */
4819 n = mono_string_to_utf8 (name);
4820 for (i = 0; i < table->rows; ++i) {
4821 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4822 if (strcmp (val, n) == 0) {
4825 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4826 fn = mono_string_new (mono_object_domain (assembly), n);
4828 return (MonoObject*)fn;
4836 for (i = 0; i < table->rows; ++i) {
4837 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4841 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4844 for (i = 0; i < table->rows; ++i) {
4845 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4846 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4847 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4848 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4853 return (MonoObject*)result;
4857 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4859 MonoDomain *domain = mono_domain_get();
4862 int i, j, file_count = 0;
4863 MonoImage **modules;
4864 guint32 module_count, real_module_count;
4865 MonoTableInfo *table;
4866 guint32 cols [MONO_FILE_SIZE];
4867 MonoImage *image = assembly->assembly->image;
4869 g_assert (image != NULL);
4870 g_assert (!assembly->assembly->dynamic);
4872 table = &image->tables [MONO_TABLE_FILE];
4873 file_count = table->rows;
4875 modules = image->modules;
4876 module_count = image->module_count;
4878 real_module_count = 0;
4879 for (i = 0; i < module_count; ++i)
4881 real_module_count ++;
4883 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4884 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4886 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4888 for (i = 0; i < module_count; ++i)
4890 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4894 for (i = 0; i < file_count; ++i, ++j) {
4895 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4896 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4897 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4899 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4901 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4902 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4904 mono_array_setref (res, j, mono_module_get_object (domain, m));
4911 static MonoReflectionMethod*
4912 ves_icall_GetCurrentMethod (void)
4914 MonoMethod *m = mono_method_get_last_managed ();
4916 MONO_ARCH_SAVE_REGS;
4918 return mono_method_get_object (mono_domain_get (), m, NULL);
4923 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4926 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4927 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4928 //method is inflated, we should inflate it on the other class
4929 MonoGenericContext ctx;
4930 ctx.method_inst = inflated->context.method_inst;
4931 ctx.class_inst = inflated->context.class_inst;
4932 if (klass->generic_class)
4933 ctx.class_inst = klass->generic_class->context.class_inst;
4934 else if (klass->generic_container)
4935 ctx.class_inst = klass->generic_container->context.class_inst;
4936 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4939 mono_class_setup_methods (method->klass);
4940 for (i = 0; i < method->klass->method.count; ++i) {
4941 if (method->klass->methods [i] == method) {
4946 mono_class_setup_methods (klass);
4947 g_assert (offset >= 0 && offset < klass->method.count);
4948 return klass->methods [offset];
4951 static MonoReflectionMethod*
4952 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4956 klass = mono_class_from_mono_type (type);
4957 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4959 if (method->klass != klass)
4960 method = mono_method_get_equivalent_method (method, klass);
4962 klass = method->klass;
4963 return mono_method_get_object (mono_domain_get (), method, klass);
4966 static MonoReflectionMethod*
4967 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4969 return mono_method_get_object (mono_domain_get (), method, NULL);
4972 static MonoReflectionMethodBody*
4973 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4975 return mono_method_body_get_object (mono_domain_get (), method);
4978 static MonoReflectionAssembly*
4979 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4981 MonoMethod *dest = NULL;
4983 MONO_ARCH_SAVE_REGS;
4985 mono_stack_walk_no_il (get_executing, &dest);
4986 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4990 static MonoReflectionAssembly*
4991 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4993 MonoDomain* domain = mono_domain_get ();
4995 MONO_ARCH_SAVE_REGS;
4997 if (!domain->entry_assembly)
5000 return mono_assembly_get_object (domain, domain->entry_assembly);
5003 static MonoReflectionAssembly*
5004 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5009 MONO_ARCH_SAVE_REGS;
5012 mono_stack_walk_no_il (get_executing, &dest);
5014 mono_stack_walk_no_il (get_caller, &dest);
5017 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5021 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5022 gboolean assembly_qualified)
5024 MonoDomain *domain = mono_object_domain (object);
5025 MonoTypeNameFormat format;
5029 MONO_ARCH_SAVE_REGS;
5031 format = assembly_qualified ?
5032 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5033 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5035 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5037 name = mono_type_get_name_full (object->type, format);
5041 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5046 res = mono_string_new (domain, name);
5053 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5055 static MonoMethod *create_culture = NULL;
5058 const char *pkey_ptr;
5060 MonoBoolean assembly_ref = 0;
5062 MONO_ARCH_SAVE_REGS;
5064 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5065 aname->major = name->major;
5066 aname->minor = name->minor;
5067 aname->build = name->build;
5068 aname->flags = name->flags;
5069 aname->revision = name->revision;
5070 aname->hashalg = name->hash_alg;
5071 aname->versioncompat = 1; /* SameMachine (default) */
5073 if (by_default_version)
5074 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5077 if (absolute != NULL && *absolute != '\0') {
5078 const gchar *prepend = "file://";
5081 codebase = g_strdup (absolute);
5086 for (i = strlen (codebase) - 1; i >= 0; i--)
5087 if (codebase [i] == '\\')
5090 if (*codebase == '/' && *(codebase + 1) == '/') {
5093 prepend = "file:///";
5097 result = g_strconcat (prepend, codebase, NULL);
5103 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5107 if (!create_culture) {
5108 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5109 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5110 g_assert (create_culture);
5111 mono_method_desc_free (desc);
5114 if (name->culture) {
5115 args [0] = mono_string_new (domain, name->culture);
5116 args [1] = &assembly_ref;
5117 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5120 if (name->public_key) {
5121 pkey_ptr = (char*)name->public_key;
5122 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5124 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5125 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5126 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5127 } else if (default_publickey) {
5128 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5129 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5132 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5133 if (name->public_key_token [0]) {
5137 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5138 p = mono_array_addr (aname->keyToken, char, 0);
5140 for (i = 0, j = 0; i < 8; i++) {
5141 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5142 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5145 } else if (default_token) {
5146 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5151 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5153 MonoDomain *domain = mono_object_domain (assembly);
5154 MonoAssembly *mass = assembly->assembly;
5158 name = g_strdup_printf (
5159 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5161 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5162 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5163 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5164 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5166 res = mono_string_new (domain, name);
5173 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5176 MonoAssembly *mass = assembly->assembly;
5178 MONO_ARCH_SAVE_REGS;
5180 if (g_path_is_absolute (mass->image->name)) {
5181 fill_reflection_assembly_name (mono_object_domain (assembly),
5182 aname, &mass->aname, mass->image->name, TRUE,
5183 TRUE, mono_framework_version () >= 2);
5186 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5188 fill_reflection_assembly_name (mono_object_domain (assembly),
5189 aname, &mass->aname, absolute, TRUE, TRUE,
5190 mono_framework_version () >= 2);
5196 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5199 MonoImageOpenStatus status = MONO_IMAGE_OK;
5202 MonoAssemblyName name;
5204 MONO_ARCH_SAVE_REGS;
5206 filename = mono_string_to_utf8 (fname);
5208 image = mono_image_open (filename, &status);
5214 if (status == MONO_IMAGE_IMAGE_INVALID)
5215 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5217 exc = mono_get_exception_file_not_found2 (NULL, fname);
5218 mono_raise_exception (exc);
5221 res = mono_assembly_fill_assembly_name (image, &name);
5223 mono_image_close (image);
5225 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5228 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5229 TRUE, mono_framework_version () == 1,
5230 mono_framework_version () >= 2);
5233 mono_image_close (image);
5237 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5238 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5240 MonoBoolean result = FALSE;
5241 MonoDeclSecurityEntry entry;
5243 /* SecurityAction.RequestMinimum */
5244 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5245 *minimum = entry.blob;
5246 *minLength = entry.size;
5249 /* SecurityAction.RequestOptional */
5250 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5251 *optional = entry.blob;
5252 *optLength = entry.size;
5255 /* SecurityAction.RequestRefuse */
5256 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5257 *refused = entry.blob;
5258 *refLength = entry.size;
5266 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5270 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5272 guint32 attrs, visibility;
5274 /* we start the count from 1 because we skip the special type <Module> */
5277 for (i = 1; i < tdef->rows; ++i) {
5278 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5279 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5280 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5284 count = tdef->rows - 1;
5286 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5287 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5289 for (i = 1; i < tdef->rows; ++i) {
5290 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5291 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5292 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5293 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5295 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5297 MonoLoaderError *error;
5300 error = mono_loader_get_last_error ();
5301 g_assert (error != NULL);
5303 ex = mono_loader_error_prepare_exception (error);
5304 mono_array_setref (*exceptions, count, ex);
5306 if (mono_loader_get_last_error ())
5307 mono_loader_clear_error ();
5316 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5318 MonoArray *res = NULL;
5319 MonoArray *exceptions = NULL;
5320 MonoImage *image = NULL;
5321 MonoTableInfo *table = NULL;
5324 int i, len, ex_count;
5326 MONO_ARCH_SAVE_REGS;
5328 domain = mono_object_domain (assembly);
5330 g_assert (!assembly->assembly->dynamic);
5331 image = assembly->assembly->image;
5332 table = &image->tables [MONO_TABLE_FILE];
5333 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5335 /* Append data from all modules in the assembly */
5336 for (i = 0; i < table->rows; ++i) {
5337 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5338 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5341 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5342 /* Append the new types to the end of the array */
5343 if (mono_array_length (res2) > 0) {
5345 MonoArray *res3, *ex3;
5347 len1 = mono_array_length (res);
5348 len2 = mono_array_length (res2);
5350 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5351 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5352 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5355 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5356 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5357 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5364 /* the ReflectionTypeLoadException must have all the types (Types property),
5365 * NULL replacing types which throws an exception. The LoaderException must
5366 * contain all exceptions for NULL items.
5369 len = mono_array_length (res);
5372 for (i = 0; i < len; i++) {
5373 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5377 klass = mono_type_get_class (t->type);
5378 if ((klass != NULL) && klass->exception_type) {
5379 /* keep the class in the list */
5380 list = g_list_append (list, klass);
5381 /* and replace Type with NULL */
5382 mono_array_setref (res, i, NULL);
5389 if (list || ex_count) {
5391 MonoException *exc = NULL;
5392 MonoArray *exl = NULL;
5393 int j, length = g_list_length (list) + ex_count;
5395 mono_loader_clear_error ();
5397 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5398 /* Types for which mono_class_get () succeeded */
5399 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5400 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5401 mono_array_setref (exl, i, exc);
5403 /* Types for which it don't */
5404 for (j = 0; j < mono_array_length (exceptions); ++j) {
5405 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5407 g_assert (i < length);
5408 mono_array_setref (exl, i, exc);
5415 exc = mono_get_exception_reflection_type_load (res, exl);
5416 mono_loader_clear_error ();
5417 mono_raise_exception (exc);
5424 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5426 MonoAssemblyName aname;
5427 MonoDomain *domain = mono_object_domain (name);
5429 gboolean is_version_defined;
5430 gboolean is_token_defined;
5432 aname.public_key = NULL;
5433 val = mono_string_to_utf8 (assname);
5434 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5435 g_free ((guint8*) aname.public_key);
5440 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5441 FALSE, is_token_defined);
5443 mono_assembly_name_free (&aname);
5444 g_free ((guint8*) aname.public_key);
5450 static MonoReflectionType*
5451 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5453 MonoDomain *domain = mono_object_domain (module);
5456 MONO_ARCH_SAVE_REGS;
5458 g_assert (module->image);
5460 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5461 /* These images do not have a global type */
5464 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5465 return mono_type_get_object (domain, &klass->byval_arg);
5469 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5471 /*if (module->image)
5472 mono_image_close (module->image);*/
5476 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5478 MonoDomain *domain = mono_object_domain (module);
5480 MONO_ARCH_SAVE_REGS;
5482 g_assert (module->image);
5483 return mono_string_new (domain, module->image->guid);
5487 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5489 #ifdef PLATFORM_WIN32
5490 if (module->image && module->image->is_module_handle)
5491 return module->image->raw_data;
5494 return (gpointer) (-1);
5498 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5500 if (image->dynamic) {
5501 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5502 *pe_kind = dyn->pe_kind;
5503 *machine = dyn->machine;
5506 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5507 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5512 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5514 return (image->md_version_major << 16) | (image->md_version_minor);
5518 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5520 MonoArray *exceptions;
5523 MONO_ARCH_SAVE_REGS;
5526 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5528 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5529 for (i = 0; i < mono_array_length (exceptions); ++i) {
5530 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5532 mono_raise_exception (ex);
5539 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5541 guint32 cols [MONO_MEMBERREF_SIZE];
5543 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5544 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5545 mono_metadata_decode_blob_size (sig, &sig);
5546 return (*sig != 0x6);
5550 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5553 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5554 mono_array_addr (type_args, MonoType*, 0));
5556 context->class_inst = NULL;
5558 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5559 mono_array_addr (method_args, MonoType*, 0));
5561 context->method_inst = NULL;
5565 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5568 int table = mono_metadata_token_table (token);
5569 int index = mono_metadata_token_index (token);
5570 MonoGenericContext context;
5572 *error = ResolveTokenError_Other;
5574 /* Validate token */
5575 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5576 (table != MONO_TABLE_TYPESPEC)) {
5577 *error = ResolveTokenError_BadTable;
5581 if (image->dynamic) {
5582 if (type_args || method_args)
5583 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5584 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5587 return &klass->byval_arg;
5590 if ((index <= 0) || (index > image->tables [table].rows)) {
5591 *error = ResolveTokenError_OutOfRange;
5595 init_generic_context_from_args (&context, type_args, method_args);
5596 klass = mono_class_get_full (image, token, &context);
5598 if (mono_loader_get_last_error ())
5599 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5602 return &klass->byval_arg;
5608 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5610 int table = mono_metadata_token_table (token);
5611 int index = mono_metadata_token_index (token);
5612 MonoGenericContext context;
5615 *error = ResolveTokenError_Other;
5617 /* Validate token */
5618 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5619 (table != MONO_TABLE_MEMBERREF)) {
5620 *error = ResolveTokenError_BadTable;
5624 if (image->dynamic) {
5625 if (type_args || method_args)
5626 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5627 /* FIXME: validate memberref token type */
5628 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5631 if ((index <= 0) || (index > image->tables [table].rows)) {
5632 *error = ResolveTokenError_OutOfRange;
5635 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5636 *error = ResolveTokenError_BadTable;
5640 init_generic_context_from_args (&context, type_args, method_args);
5641 method = mono_get_method_full (image, token, NULL, &context);
5643 if (mono_loader_get_last_error ())
5644 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5650 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5652 int index = mono_metadata_token_index (token);
5654 *error = ResolveTokenError_Other;
5656 /* Validate token */
5657 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5658 *error = ResolveTokenError_BadTable;
5663 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5665 if ((index <= 0) || (index >= image->heap_us.size)) {
5666 *error = ResolveTokenError_OutOfRange;
5670 /* FIXME: What to do if the index points into the middle of a string ? */
5672 return mono_ldstr (mono_domain_get (), image, index);
5675 static MonoClassField*
5676 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5679 int table = mono_metadata_token_table (token);
5680 int index = mono_metadata_token_index (token);
5681 MonoGenericContext context;
5682 MonoClassField *field;
5684 *error = ResolveTokenError_Other;
5686 /* Validate token */
5687 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5688 *error = ResolveTokenError_BadTable;
5692 if (image->dynamic) {
5693 if (type_args || method_args)
5694 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5695 /* FIXME: validate memberref token type */
5696 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5699 if ((index <= 0) || (index > image->tables [table].rows)) {
5700 *error = ResolveTokenError_OutOfRange;
5703 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5704 *error = ResolveTokenError_BadTable;
5708 init_generic_context_from_args (&context, type_args, method_args);
5709 field = mono_field_from_token (image, token, &klass, &context);
5711 if (mono_loader_get_last_error ())
5712 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5719 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5721 int table = mono_metadata_token_table (token);
5723 *error = ResolveTokenError_Other;
5726 case MONO_TABLE_TYPEDEF:
5727 case MONO_TABLE_TYPEREF:
5728 case MONO_TABLE_TYPESPEC: {
5729 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5731 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5735 case MONO_TABLE_METHOD:
5736 case MONO_TABLE_METHODSPEC: {
5737 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5739 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5743 case MONO_TABLE_FIELD: {
5744 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5746 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5750 case MONO_TABLE_MEMBERREF:
5751 if (mono_metadata_memberref_is_method (image, token)) {
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);
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);
5768 *error = ResolveTokenError_BadTable;
5775 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5777 int table = mono_metadata_token_table (token);
5778 int idx = mono_metadata_token_index (token);
5779 MonoTableInfo *tables = image->tables;
5784 *error = ResolveTokenError_OutOfRange;
5786 /* FIXME: Support other tables ? */
5787 if (table != MONO_TABLE_STANDALONESIG)
5793 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5796 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5798 ptr = mono_metadata_blob_heap (image, sig);
5799 len = mono_metadata_decode_blob_size (ptr, &ptr);
5801 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5802 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5806 static MonoReflectionType*
5807 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5810 int isbyref = 0, rank;
5811 char *str = mono_string_to_utf8 (smodifiers);
5814 MONO_ARCH_SAVE_REGS;
5816 klass = mono_class_from_mono_type (tb->type.type);
5818 /* logic taken from mono_reflection_parse_type(): keep in sync */
5822 if (isbyref) { /* only one level allowed by the spec */
5829 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5832 klass = mono_ptr_class_get (&klass->byval_arg);
5833 mono_class_init (klass);
5844 else if (*p != '*') { /* '*' means unknown lower bound */
5855 klass = mono_array_class_get (klass, rank);
5856 mono_class_init (klass);
5863 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5867 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5872 MONO_ARCH_SAVE_REGS;
5875 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5880 static MonoReflectionType *
5881 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5883 MonoClass *klass, *aklass;
5885 MONO_ARCH_SAVE_REGS;
5887 klass = mono_class_from_mono_type (type->type);
5888 aklass = mono_array_class_get (klass, rank);
5890 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5893 static MonoReflectionType *
5894 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5898 MONO_ARCH_SAVE_REGS;
5900 klass = mono_class_from_mono_type (type->type);
5902 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5905 static MonoReflectionType *
5906 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5910 MONO_ARCH_SAVE_REGS;
5912 pklass = mono_ptr_class_get (type->type);
5914 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5918 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5919 MonoReflectionMethod *info)
5921 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5922 MonoObject *delegate;
5924 MonoMethod *method = info->method;
5926 MONO_ARCH_SAVE_REGS;
5928 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5930 /* FIME: We must check if target is visible to the caller under coreclr.
5931 * The check should be disabled otherwise as it shouldn't raise expection under fulltrust.
5934 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5936 if (mono_method_needs_static_rgctx_invoke (method, FALSE)) {
5937 method = mono_marshal_get_static_rgctx_invoke (method);
5938 func = mono_compile_method (method);
5939 } else if (method->dynamic) {
5940 /* Creating a trampoline would leak memory */
5941 func = mono_compile_method (method);
5943 func = mono_create_ftnptr (mono_domain_get (),
5944 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5947 mono_delegate_ctor_with_method (delegate, target, func, method);
5953 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5955 /* Reset the invoke impl to the default one */
5956 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5960 * Magic number to convert a time which is relative to
5961 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5963 #define EPOCH_ADJUST ((guint64)62135596800LL)
5966 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5968 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5970 #ifdef PLATFORM_WIN32
5971 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5973 convert_to_absolute_date(SYSTEMTIME *date)
5975 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5976 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5977 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5978 /* from the calendar FAQ */
5979 int a = (14 - date->wMonth) / 12;
5980 int y = date->wYear - a;
5981 int m = date->wMonth + 12 * a - 2;
5982 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5984 /* d is now the day of the week for the first of the month (0 == Sunday) */
5986 int day_of_week = date->wDayOfWeek;
5988 /* set day_in_month to the first day in the month which falls on day_of_week */
5989 int day_in_month = 1 + (day_of_week - d);
5990 if (day_in_month <= 0)
5993 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5994 date->wDay = day_in_month + (date->wDay - 1) * 7;
5995 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6000 #ifndef PLATFORM_WIN32
6002 * Return's the offset from GMT of a local time.
6004 * tm is a local time
6005 * t is the same local time as seconds.
6008 gmt_offset(struct tm *tm, time_t t)
6010 #if defined (HAVE_TM_GMTOFF)
6011 return tm->tm_gmtoff;
6016 g.tm_isdst = tm->tm_isdst;
6018 return (int)difftime(t, t2);
6023 * This is heavily based on zdump.c from glibc 2.2.
6025 * * data[0]: start of daylight saving time (in DateTime ticks).
6026 * * data[1]: end of daylight saving time (in DateTime ticks).
6027 * * data[2]: utcoffset (in TimeSpan ticks).
6028 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
6029 * * name[0]: name of this timezone when not daylight saving.
6030 * * name[1]: name of this timezone when daylight saving.
6032 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6033 * the class library allows years between 1 and 9999.
6035 * Returns true on success and zero on failure.
6038 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6040 #ifndef PLATFORM_WIN32
6041 MonoDomain *domain = mono_domain_get ();
6042 struct tm start, tt;
6046 int is_daylight = 0, day;
6049 MONO_ARCH_SAVE_REGS;
6051 MONO_CHECK_ARG_NULL (data);
6052 MONO_CHECK_ARG_NULL (names);
6054 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6055 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6058 * no info is better than crashing: we'll need our own tz data
6059 * to make this work properly, anyway. The range is probably
6060 * reduced to 1970 .. 2037 because that is what mktime is
6061 * guaranteed to support (we get into an infinite loop
6065 memset (&start, 0, sizeof (start));
6068 start.tm_year = year-1900;
6070 t = mktime (&start);
6072 if ((year < 1970) || (year > 2037) || (t == -1)) {
6074 tt = *localtime (&t);
6075 strftime (tzone, sizeof (tzone), "%Z", &tt);
6076 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6077 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6081 gmtoff = gmt_offset (&start, t);
6083 /* For each day of the year, calculate the tm_gmtoff. */
6084 for (day = 0; day < 365; day++) {
6087 tt = *localtime (&t);
6089 /* Daylight saving starts or ends here. */
6090 if (gmt_offset (&tt, t) != gmtoff) {
6094 /* Try to find the exact hour when daylight saving starts/ends. */
6098 tt1 = *localtime (&t1);
6099 } while (gmt_offset (&tt1, t1) != gmtoff);
6101 /* Try to find the exact minute when daylight saving starts/ends. */
6104 tt1 = *localtime (&t1);
6105 } while (gmt_offset (&tt1, t1) == gmtoff);
6107 strftime (tzone, sizeof (tzone), "%Z", &tt);
6109 /* Write data, if we're already in daylight saving, we're done. */
6111 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6112 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6115 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6116 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6120 /* This is only set once when we enter daylight saving. */
6121 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6122 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6124 gmtoff = gmt_offset (&tt, t);
6129 strftime (tzone, sizeof (tzone), "%Z", &tt);
6130 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6131 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6132 mono_array_set ((*data), gint64, 0, 0);
6133 mono_array_set ((*data), gint64, 1, 0);
6134 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6135 mono_array_set ((*data), gint64, 3, 0);
6140 MonoDomain *domain = mono_domain_get ();
6141 TIME_ZONE_INFORMATION tz_info;
6146 tz_id = GetTimeZoneInformation (&tz_info);
6147 if (tz_id == TIME_ZONE_ID_INVALID)
6150 MONO_CHECK_ARG_NULL (data);
6151 MONO_CHECK_ARG_NULL (names);
6153 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6154 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6156 for (i = 0; i < 32; ++i)
6157 if (!tz_info.DaylightName [i])
6159 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6160 for (i = 0; i < 32; ++i)
6161 if (!tz_info.StandardName [i])
6163 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6165 if ((year <= 1601) || (year > 30827)) {
6167 * According to MSDN, the MS time functions can't handle dates outside
6173 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6174 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6175 tz_info.StandardDate.wYear = year;
6176 convert_to_absolute_date(&tz_info.StandardDate);
6177 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6182 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6183 tz_info.DaylightDate.wYear = year;
6184 convert_to_absolute_date(&tz_info.DaylightDate);
6185 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6190 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6192 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6193 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6200 ves_icall_System_Object_obj_address (MonoObject *this)
6202 MONO_ARCH_SAVE_REGS;
6209 static inline gint32
6210 mono_array_get_byte_length (MonoArray *array)
6216 klass = array->obj.vtable->klass;
6218 if (array->bounds == NULL)
6219 length = array->max_length;
6222 for (i = 0; i < klass->rank; ++ i)
6223 length *= array->bounds [i].length;
6226 switch (klass->element_class->byval_arg.type) {
6229 case MONO_TYPE_BOOLEAN:
6233 case MONO_TYPE_CHAR:
6241 return length * sizeof (gpointer);
6252 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6254 MONO_ARCH_SAVE_REGS;
6256 return mono_array_get_byte_length (array);
6260 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6262 MONO_ARCH_SAVE_REGS;
6264 return mono_array_get (array, gint8, idx);
6268 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6270 MONO_ARCH_SAVE_REGS;
6272 mono_array_set (array, gint8, idx, value);
6276 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6278 guint8 *src_buf, *dest_buf;
6280 MONO_ARCH_SAVE_REGS;
6282 /* watch out for integer overflow */
6283 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6286 src_buf = (guint8 *)src->vector + src_offset;
6287 dest_buf = (guint8 *)dest->vector + dest_offset;
6290 memcpy (dest_buf, src_buf, count);
6292 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6298 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6300 MonoDomain *domain = mono_object_domain (this);
6302 MonoRealProxy *rp = ((MonoRealProxy *)this);
6303 MonoTransparentProxy *tp;
6307 MONO_ARCH_SAVE_REGS;
6309 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6310 tp = (MonoTransparentProxy*) res;
6312 MONO_OBJECT_SETREF (tp, rp, rp);
6313 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6314 klass = mono_class_from_mono_type (type);
6316 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6317 tp->remote_class = mono_remote_class (domain, class_name, klass);
6319 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6323 static MonoReflectionType *
6324 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6326 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6329 /* System.Environment */
6332 ves_icall_System_Environment_get_MachineName (void)
6334 #if defined (PLATFORM_WIN32)
6339 len = MAX_COMPUTERNAME_LENGTH + 1;
6340 buf = g_new (gunichar2, len);
6343 if (GetComputerName (buf, (PDWORD) &len))
6344 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6352 if (gethostname (buf, sizeof (buf)) == 0)
6353 result = mono_string_new (mono_domain_get (), buf);
6362 ves_icall_System_Environment_get_Platform (void)
6364 #if defined (PLATFORM_WIN32)
6367 #elif defined(__MACH__)
6369 if (mono_framework_version () < 2)
6373 // For compatibility with our client code, this will be 4 for a while.
6374 // We will eventually move to 6 to match .NET, but it requires all client
6375 // code to be updated and the documentation everywhere to be updated
6381 if (mono_framework_version () < 2)
6388 ves_icall_System_Environment_get_NewLine (void)
6390 MONO_ARCH_SAVE_REGS;
6392 #if defined (PLATFORM_WIN32)
6393 return mono_string_new (mono_domain_get (), "\r\n");
6395 return mono_string_new (mono_domain_get (), "\n");
6400 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6405 MONO_ARCH_SAVE_REGS;
6410 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6411 value = g_getenv (utf8_name);
6418 return mono_string_new (mono_domain_get (), value);
6422 * There is no standard way to get at environ.
6425 #ifndef __MINGW32_VERSION
6427 /* Apple defines this in crt_externs.h but doesn't provide that header for
6428 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6429 * in fact exist on all implementations (so far)
6431 gchar ***_NSGetEnviron();
6432 #define environ (*_NSGetEnviron())
6441 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6443 #ifdef PLATFORM_WIN32
6452 env_strings = GetEnvironmentStrings();
6455 env_string = env_strings;
6456 while (*env_string != '\0') {
6457 /* weird case that MS seems to skip */
6458 if (*env_string != '=')
6460 while (*env_string != '\0')
6466 domain = mono_domain_get ();
6467 names = mono_array_new (domain, mono_defaults.string_class, n);
6471 env_string = env_strings;
6472 while (*env_string != '\0') {
6473 /* weird case that MS seems to skip */
6474 if (*env_string != '=') {
6475 equal_str = wcschr(env_string, '=');
6476 g_assert(equal_str);
6477 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6478 mono_array_setref (names, n, str);
6481 while (*env_string != '\0')
6486 FreeEnvironmentStrings (env_strings);
6498 MONO_ARCH_SAVE_REGS;
6501 for (e = environ; *e != 0; ++ e)
6504 domain = mono_domain_get ();
6505 names = mono_array_new (domain, mono_defaults.string_class, n);
6508 for (e = environ; *e != 0; ++ e) {
6509 parts = g_strsplit (*e, "=", 2);
6511 str = mono_string_new (domain, *parts);
6512 mono_array_setref (names, n, str);
6525 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6527 #if !GLIB_CHECK_VERSION(2,4,0)
6528 #define g_setenv(a,b,c) setenv(a,b,c)
6529 #define g_unsetenv(a) unsetenv(a)
6533 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6535 #ifdef PLATFORM_WIN32
6536 gunichar2 *utf16_name, *utf16_value;
6538 gchar *utf8_name, *utf8_value;
6541 MONO_ARCH_SAVE_REGS;
6543 #ifdef PLATFORM_WIN32
6544 utf16_name = mono_string_to_utf16 (name);
6545 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6546 SetEnvironmentVariable (utf16_name, NULL);
6547 g_free (utf16_name);
6551 utf16_value = mono_string_to_utf16 (value);
6553 SetEnvironmentVariable (utf16_name, utf16_value);
6555 g_free (utf16_name);
6556 g_free (utf16_value);
6558 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6560 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6561 g_unsetenv (utf8_name);
6566 utf8_value = mono_string_to_utf8 (value);
6567 g_setenv (utf8_name, utf8_value, TRUE);
6570 g_free (utf8_value);
6575 ves_icall_System_Environment_Exit (int result)
6577 MONO_ARCH_SAVE_REGS;
6579 mono_threads_set_shutting_down ();
6581 mono_runtime_set_shutting_down ();
6583 /* Suspend all managed threads since the runtime is going away */
6584 mono_thread_suspend_all_other_threads ();
6586 mono_runtime_quit ();
6588 /* we may need to do some cleanup here... */
6593 ves_icall_System_Environment_GetGacPath (void)
6595 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6599 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6601 #if defined (PLATFORM_WIN32)
6602 #ifndef CSIDL_FLAG_CREATE
6603 #define CSIDL_FLAG_CREATE 0x8000
6606 WCHAR path [MAX_PATH];
6607 /* Create directory if no existing */
6608 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6612 return mono_string_new_utf16 (mono_domain_get (), path, len);
6615 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6617 return mono_string_new (mono_domain_get (), "");
6621 ves_icall_System_Environment_GetLogicalDrives (void)
6623 gunichar2 buf [128], *ptr, *dname;
6625 guint initial_size = 127, size = 128;
6628 MonoString *drivestr;
6629 MonoDomain *domain = mono_domain_get ();
6632 MONO_ARCH_SAVE_REGS;
6637 while (size > initial_size) {
6638 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6639 if (size > initial_size) {
6642 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6643 initial_size = size;
6657 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6662 while (*u16) { u16++; len ++; }
6663 drivestr = mono_string_new_utf16 (domain, dname, len);
6664 mono_array_setref (result, ndrives++, drivestr);
6675 ves_icall_System_Environment_InternalGetHome (void)
6677 MONO_ARCH_SAVE_REGS;
6679 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6682 static const char *encodings [] = {
6684 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6685 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6686 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6688 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6689 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6690 "x_unicode_2_0_utf_7",
6692 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6693 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6695 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6698 "unicodefffe", "utf_16be",
6705 * Returns the internal codepage, if the value of "int_code_page" is
6706 * 1 at entry, and we can not compute a suitable code page number,
6707 * returns the code page as a string
6710 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6715 char *codepage = NULL;
6717 int want_name = *int_code_page;
6720 *int_code_page = -1;
6721 MONO_ARCH_SAVE_REGS;
6723 g_get_charset (&cset);
6724 c = codepage = strdup (cset);
6725 for (c = codepage; *c; c++){
6726 if (isascii (*c) && isalpha (*c))
6731 /* g_print ("charset: %s\n", cset); */
6733 /* handle some common aliases */
6736 for (i = 0; p != 0; ){
6737 if ((gssize) p < 7){
6739 p = encodings [++i];
6742 if (strcmp (p, codepage) == 0){
6743 *int_code_page = code;
6746 p = encodings [++i];
6749 if (strstr (codepage, "utf_8") != NULL)
6750 *int_code_page |= 0x10000000;
6753 if (want_name && *int_code_page == -1)
6754 return mono_string_new (mono_domain_get (), cset);
6760 ves_icall_System_Environment_get_HasShutdownStarted (void)
6762 if (mono_runtime_is_shutting_down ())
6765 if (mono_domain_is_unloading (mono_domain_get ()))
6772 ves_icall_System_Environment_BroadcastSettingChange (void)
6774 #ifdef PLATFORM_WIN32
6775 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6780 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6781 MonoReflectionMethod *method,
6782 MonoArray *out_args)
6784 MONO_ARCH_SAVE_REGS;
6786 mono_message_init (mono_object_domain (this), this, method, out_args);
6790 ves_icall_IsTransparentProxy (MonoObject *proxy)
6792 MONO_ARCH_SAVE_REGS;
6797 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6803 static MonoReflectionMethod *
6804 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6805 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6809 MonoMethod **vtable;
6810 MonoMethod *res = NULL;
6812 MONO_CHECK_ARG_NULL (rtype);
6813 MONO_CHECK_ARG_NULL (rmethod);
6815 method = rmethod->method;
6816 klass = mono_class_from_mono_type (rtype->type);
6818 if (MONO_CLASS_IS_INTERFACE (klass))
6821 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6824 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6825 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6831 mono_class_setup_vtable (klass);
6832 vtable = klass->vtable;
6834 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6835 int offs = mono_class_interface_offset (klass, method->klass);
6837 res = vtable [offs + method->slot];
6839 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6842 if (method->slot != -1)
6843 res = vtable [method->slot];
6849 return mono_method_get_object (mono_domain_get (), res, NULL);
6853 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6858 MONO_ARCH_SAVE_REGS;
6860 klass = mono_class_from_mono_type (type->type);
6861 vtable = mono_class_vtable (mono_domain_get (), klass);
6863 if (enable) vtable->remote = 1;
6864 else vtable->remote = 0;
6868 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6873 MONO_ARCH_SAVE_REGS;
6875 domain = mono_object_domain (type);
6876 klass = mono_class_from_mono_type (type->type);
6878 if (klass->rank >= 1) {
6879 g_assert (klass->rank == 1);
6880 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6882 /* Bypass remoting object creation check */
6883 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6888 ves_icall_System_IO_get_temp_path (void)
6890 MONO_ARCH_SAVE_REGS;
6892 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6896 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6897 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6901 ULARGE_INTEGER wapi_free_bytes_avail;
6902 ULARGE_INTEGER wapi_total_number_of_bytes;
6903 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6905 MONO_ARCH_SAVE_REGS;
6907 *error = ERROR_SUCCESS;
6908 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6909 &wapi_total_number_of_free_bytes);
6912 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6913 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6914 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6916 *free_bytes_avail = 0;
6917 *total_number_of_bytes = 0;
6918 *total_number_of_free_bytes = 0;
6919 *error = GetLastError ();
6926 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6928 MONO_ARCH_SAVE_REGS;
6930 return GetDriveType (mono_string_chars (root_path_name));
6934 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6936 MONO_ARCH_SAVE_REGS;
6938 return mono_compile_method (method);
6942 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6947 MONO_ARCH_SAVE_REGS;
6949 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6951 #if defined (PLATFORM_WIN32)
6952 /* Avoid mixing '/' and '\\' */
6955 for (i = strlen (path) - 1; i >= 0; i--)
6956 if (path [i] == '/')
6960 mcpath = mono_string_new (mono_domain_get (), path);
6967 get_bundled_machine_config (void)
6969 const gchar *machine_config;
6971 MONO_ARCH_SAVE_REGS;
6973 machine_config = mono_get_machine_config ();
6975 if (!machine_config)
6978 return mono_string_new (mono_domain_get (), machine_config);
6982 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6987 MONO_ARCH_SAVE_REGS;
6989 path = g_path_get_dirname (mono_get_config_dir ());
6991 #if defined (PLATFORM_WIN32)
6992 /* Avoid mixing '/' and '\\' */
6995 for (i = strlen (path) - 1; i >= 0; i--)
6996 if (path [i] == '/')
7000 ipath = mono_string_new (mono_domain_get (), path);
7007 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7009 return mono_debug_using_mono_debugger ();
7013 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7015 #if defined (PLATFORM_WIN32)
7016 OutputDebugString (mono_string_chars (message));
7018 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7022 /* Only used for value types */
7024 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7029 MONO_ARCH_SAVE_REGS;
7031 domain = mono_object_domain (type);
7032 klass = mono_class_from_mono_type (type->type);
7034 if (mono_class_is_nullable (klass))
7035 /* No arguments -> null */
7038 return mono_object_new (domain, klass);
7041 static MonoReflectionMethod *
7042 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7044 MonoClass *klass, *parent;
7045 MonoMethod *method = m->method;
7046 MonoMethod *result = NULL;
7048 MONO_ARCH_SAVE_REGS;
7050 if (method->klass == NULL)
7053 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7054 MONO_CLASS_IS_INTERFACE (method->klass) ||
7055 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7058 klass = method->klass;
7059 if (klass->generic_class)
7060 klass = klass->generic_class->container_class;
7062 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7063 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7064 mono_class_setup_vtable (parent);
7065 if (parent->vtable_size <= method->slot)
7070 if (klass == method->klass)
7073 result = klass->vtable [method->slot];
7074 if (result == NULL) {
7075 /* It is an abstract method */
7076 gpointer iter = NULL;
7077 while ((result = mono_class_get_methods (klass, &iter)))
7078 if (result->slot == method->slot)
7085 return mono_method_get_object (mono_domain_get (), result, NULL);
7089 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7091 MonoMethod *method = m->method;
7093 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7098 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7100 MONO_ARCH_SAVE_REGS;
7102 iter->sig = *(MonoMethodSignature**)argsp;
7104 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7105 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7108 /* FIXME: it's not documented what start is exactly... */
7112 guint32 i, arg_size;
7114 iter->args = argsp + sizeof (gpointer);
7115 #ifndef MONO_ARCH_REGPARMS
7116 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7117 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7118 iter->args = (char*)iter->args + arg_size;
7122 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7124 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7128 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7130 guint32 i, arg_size;
7133 MONO_ARCH_SAVE_REGS;
7135 i = iter->sig->sentinelpos + iter->next_arg;
7137 g_assert (i < iter->sig->param_count);
7139 res.type = iter->sig->params [i];
7140 res.klass = mono_class_from_mono_type (res.type);
7141 res.value = iter->args;
7142 arg_size = mono_type_stack_size (res.type, &align);
7143 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7144 if (arg_size <= sizeof (gpointer)) {
7146 int padding = arg_size - mono_type_size (res.type, &dummy);
7147 res.value = (guint8*)res.value + padding;
7150 iter->args = (char*)iter->args + arg_size;
7153 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7159 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7161 guint32 i, arg_size;
7164 MONO_ARCH_SAVE_REGS;
7166 i = iter->sig->sentinelpos + iter->next_arg;
7168 g_assert (i < iter->sig->param_count);
7170 while (i < iter->sig->param_count) {
7171 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7173 res.type = iter->sig->params [i];
7174 res.klass = mono_class_from_mono_type (res.type);
7175 /* FIXME: endianess issue... */
7176 res.value = iter->args;
7177 arg_size = mono_type_stack_size (res.type, &align);
7178 iter->args = (char*)iter->args + arg_size;
7180 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7183 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7192 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7195 MONO_ARCH_SAVE_REGS;
7197 i = iter->sig->sentinelpos + iter->next_arg;
7199 g_assert (i < iter->sig->param_count);
7201 return iter->sig->params [i];
7205 mono_TypedReference_ToObject (MonoTypedRef tref)
7207 MONO_ARCH_SAVE_REGS;
7209 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7210 MonoObject** objp = tref.value;
7214 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7218 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7220 MONO_ARCH_SAVE_REGS;
7222 if (MONO_TYPE_IS_REFERENCE (type)) {
7223 MonoObject** objp = value;
7227 return mono_value_box (mono_domain_get (), klass, value);
7231 prelink_method (MonoMethod *method)
7233 const char *exc_class, *exc_arg;
7234 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7236 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7238 mono_raise_exception(
7239 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7241 /* create the wrapper, too? */
7245 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7247 MONO_ARCH_SAVE_REGS;
7248 prelink_method (method->method);
7252 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7254 MonoClass *klass = mono_class_from_mono_type (type->type);
7256 gpointer iter = NULL;
7257 MONO_ARCH_SAVE_REGS;
7259 while ((m = mono_class_get_methods (klass, &iter)))
7263 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7265 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7266 gint32 const **exponents,
7267 gunichar2 const **digitLowerTable,
7268 gunichar2 const **digitUpperTable,
7269 gint64 const **tenPowersList,
7270 gint32 const **decHexDigits)
7272 *mantissas = Formatter_MantissaBitsTable;
7273 *exponents = Formatter_TensExponentTable;
7274 *digitLowerTable = Formatter_DigitLowerTable;
7275 *digitUpperTable = Formatter_DigitUpperTable;
7276 *tenPowersList = Formatter_TenPowersList;
7277 *decHexDigits = Formatter_DecHexDigits;
7280 /* These parameters are "readonly" in corlib/System/Char.cs */
7282 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7283 guint8 const **numeric_data,
7284 gdouble const **numeric_data_values,
7285 guint16 const **to_lower_data_low,
7286 guint16 const **to_lower_data_high,
7287 guint16 const **to_upper_data_low,
7288 guint16 const **to_upper_data_high)
7290 *category_data = CategoryData;
7291 *numeric_data = NumericData;
7292 *numeric_data_values = NumericDataValues;
7293 *to_lower_data_low = ToLowerDataLow;
7294 *to_lower_data_high = ToLowerDataHigh;
7295 *to_upper_data_low = ToUpperDataLow;
7296 *to_upper_data_high = ToUpperDataHigh;
7300 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7302 return method->method->token;
7306 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7307 * and avoid useless allocations.
7310 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7314 for (i = 0; i < type->num_mods; ++i) {
7315 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7320 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7322 for (i = 0; i < type->num_mods; ++i) {
7323 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7324 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7325 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7333 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7335 MonoType *type = param->ClassImpl->type;
7336 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7337 MonoImage *image = method->method->klass->image;
7338 int pos = param->PositionImpl;
7339 MonoMethodSignature *sig = mono_method_signature (method->method);
7343 type = sig->params [pos];
7345 return type_array_from_modifiers (image, type, optional);
7349 get_property_type (MonoProperty *prop)
7351 MonoMethodSignature *sig;
7353 sig = mono_method_signature (prop->get);
7355 } else if (prop->set) {
7356 sig = mono_method_signature (prop->set);
7357 return sig->params [sig->param_count - 1];
7363 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7365 MonoType *type = get_property_type (property->property);
7366 MonoImage *image = property->klass->image;
7370 return type_array_from_modifiers (image, type, optional);
7374 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7376 MonoCustomAttrInfo *cinfo;
7379 cinfo = mono_reflection_get_custom_attrs_info (obj);
7382 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7384 mono_custom_attrs_free (cinfo);
7389 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7391 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7393 if (mono_loader_get_last_error ()) {
7394 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7395 g_assert_not_reached ();
7402 GCHandle_CheckCurrentDomain (guint32 gchandle)
7404 return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
7408 ves_icall_Mono_Runtime_GetDisplayName (void)
7410 static const char display_name_str [] = "Mono " VERSION;
7411 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7412 return display_name;
7416 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7418 MonoString *message;
7422 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7423 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7426 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7428 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7436 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7437 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7438 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7439 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7440 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7441 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7442 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7443 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7447 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7452 gunichar2 last, prev_last, prev2_last;
7460 last = prev_last = 0, prev2_last = 0;
7461 for (i = 0; i < ilength; i++) {
7463 if (c >= sizeof (dbase64)) {
7464 exc = mono_exception_from_name_msg (mono_get_corlib (),
7465 "System", "FormatException",
7466 "Invalid character found.");
7467 mono_raise_exception (exc);
7468 } else if (isspace (c)) {
7471 prev2_last = prev_last;
7477 olength = ilength - ignored;
7479 if (allowWhitespaceOnly && olength == 0) {
7480 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7483 if ((olength & 3) != 0 || olength <= 0) {
7484 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7485 "FormatException", "Invalid length.");
7486 mono_raise_exception (exc);
7489 if (prev2_last == '=') {
7490 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7491 mono_raise_exception (exc);
7494 olength = (olength * 3) / 4;
7498 if (prev_last == '=')
7501 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7502 res_ptr = mono_array_addr (result, guchar, 0);
7503 for (i = 0; i < ilength; ) {
7506 for (k = 0; k < 4 && i < ilength;) {
7512 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7513 exc = mono_exception_from_name_msg (mono_get_corlib (),
7514 "System", "FormatException",
7515 "Invalid character found.");
7516 mono_raise_exception (exc);
7521 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7523 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7525 *res_ptr++ = (b [2] << 6) | b [3];
7527 while (i < ilength && isspace (start [i]))
7535 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7537 MONO_ARCH_SAVE_REGS;
7539 return base64_to_byte_array (mono_string_chars (str),
7540 mono_string_length (str), allowWhitespaceOnly);
7544 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7546 MONO_ARCH_SAVE_REGS;
7548 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7552 #define ICALL_TYPE(id,name,first)
7553 #define ICALL(id,name,func) Icall_ ## id,
7556 #include "metadata/icall-def.h"
7562 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7563 #define ICALL(id,name,func)
7565 #include "metadata/icall-def.h"
7571 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7572 #define ICALL(id,name,func)
7574 guint16 first_icall;
7577 static const IcallTypeDesc
7578 icall_type_descs [] = {
7579 #include "metadata/icall-def.h"
7583 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7586 #define ICALL_TYPE(id,name,first)
7589 #ifdef HAVE_ARRAY_ELEM_INIT
7590 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7591 #define MSGSTRFIELD1(line) str##line
7593 static const struct msgstrtn_t {
7594 #define ICALL(id,name,func)
7596 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7597 #include "metadata/icall-def.h"
7599 } icall_type_names_str = {
7600 #define ICALL_TYPE(id,name,first) (name),
7601 #include "metadata/icall-def.h"
7604 static const guint16 icall_type_names_idx [] = {
7605 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7606 #include "metadata/icall-def.h"
7609 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7611 static const struct msgstr_t {
7613 #define ICALL_TYPE(id,name,first)
7614 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7615 #include "metadata/icall-def.h"
7617 } icall_names_str = {
7618 #define ICALL(id,name,func) (name),
7619 #include "metadata/icall-def.h"
7622 static const guint16 icall_names_idx [] = {
7623 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7624 #include "metadata/icall-def.h"
7627 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7633 #define ICALL_TYPE(id,name,first) name,
7634 #define ICALL(id,name,func)
7635 static const char* const
7636 icall_type_names [] = {
7637 #include "metadata/icall-def.h"
7641 #define icall_type_name_get(id) (icall_type_names [(id)])
7645 #define ICALL_TYPE(id,name,first)
7646 #define ICALL(id,name,func) name,
7647 static const char* const
7649 #include "metadata/icall-def.h"
7652 #define icall_name_get(id) icall_names [(id)]
7654 #endif /* !HAVE_ARRAY_ELEM_INIT */
7658 #define ICALL_TYPE(id,name,first)
7659 #define ICALL(id,name,func) func,
7660 static const gconstpointer
7661 icall_functions [] = {
7662 #include "metadata/icall-def.h"
7666 static GHashTable *icall_hash = NULL;
7667 static GHashTable *jit_icall_hash_name = NULL;
7668 static GHashTable *jit_icall_hash_addr = NULL;
7671 mono_icall_init (void)
7675 /* check that tables are sorted: disable in release */
7678 const char *prev_class = NULL;
7679 const char *prev_method;
7681 for (i = 0; i < Icall_type_num; ++i) {
7682 const IcallTypeDesc *desc;
7685 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7686 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7687 prev_class = icall_type_name_get (i);
7688 desc = &icall_type_descs [i];
7689 num_icalls = icall_desc_num_icalls (desc);
7690 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7691 for (j = 0; j < num_icalls; ++j) {
7692 const char *methodn = icall_name_get (desc->first_icall + j);
7693 if (prev_method && strcmp (prev_method, methodn) >= 0)
7694 g_print ("method %s should come before method %s\n", methodn, prev_method);
7695 prev_method = methodn;
7700 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7704 mono_icall_cleanup (void)
7706 g_hash_table_destroy (icall_hash);
7707 g_hash_table_destroy (jit_icall_hash_name);
7708 g_hash_table_destroy (jit_icall_hash_addr);
7712 mono_add_internal_call (const char *name, gconstpointer method)
7714 mono_loader_lock ();
7716 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7718 mono_loader_unlock ();
7721 #ifdef HAVE_ARRAY_ELEM_INIT
7723 compare_method_imap (const void *key, const void *elem)
7725 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7726 return strcmp (key, method_name);
7730 find_method_icall (const IcallTypeDesc *imap, const char *name)
7732 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7735 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7739 compare_class_imap (const void *key, const void *elem)
7741 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7742 return strcmp (key, class_name);
7745 static const IcallTypeDesc*
7746 find_class_icalls (const char *name)
7748 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7751 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7756 compare_method_imap (const void *key, const void *elem)
7758 const char** method_name = (const char**)elem;
7759 return strcmp (key, *method_name);
7763 find_method_icall (const IcallTypeDesc *imap, const char *name)
7765 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7768 return (gpointer)icall_functions [(nameslot - icall_names)];
7772 compare_class_imap (const void *key, const void *elem)
7774 const char** class_name = (const char**)elem;
7775 return strcmp (key, *class_name);
7778 static const IcallTypeDesc*
7779 find_class_icalls (const char *name)
7781 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7784 return &icall_type_descs [nameslot - icall_type_names];
7790 * we should probably export this as an helper (handle nested types).
7791 * Returns the number of chars written in buf.
7794 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7796 int nspacelen, cnamelen;
7797 nspacelen = strlen (klass->name_space);
7798 cnamelen = strlen (klass->name);
7799 if (nspacelen + cnamelen + 2 > bufsize)
7802 memcpy (buf, klass->name_space, nspacelen);
7803 buf [nspacelen ++] = '.';
7805 memcpy (buf + nspacelen, klass->name, cnamelen);
7806 buf [nspacelen + cnamelen] = 0;
7807 return nspacelen + cnamelen;
7811 mono_lookup_internal_call (MonoMethod *method)
7816 int typelen = 0, mlen, siglen;
7818 const IcallTypeDesc *imap;
7820 g_assert (method != NULL);
7822 if (method->is_inflated)
7823 method = ((MonoMethodInflated *) method)->declaring;
7825 if (method->klass->nested_in) {
7826 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7830 mname [pos++] = '/';
7833 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7839 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7844 imap = find_class_icalls (mname);
7846 mname [typelen] = ':';
7847 mname [typelen + 1] = ':';
7849 mlen = strlen (method->name);
7850 memcpy (mname + typelen + 2, method->name, mlen);
7851 sigstart = mname + typelen + 2 + mlen;
7854 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7855 siglen = strlen (tmpsig);
7856 if (typelen + mlen + siglen + 6 > sizeof (mname))
7859 memcpy (sigstart + 1, tmpsig, siglen);
7860 sigstart [siglen + 1] = ')';
7861 sigstart [siglen + 2] = 0;
7864 mono_loader_lock ();
7866 res = g_hash_table_lookup (icall_hash, mname);
7868 mono_loader_unlock ();
7871 /* try without signature */
7873 res = g_hash_table_lookup (icall_hash, mname);
7875 mono_loader_unlock ();
7879 /* it wasn't found in the static call tables */
7881 mono_loader_unlock ();
7884 res = find_method_icall (imap, sigstart - mlen);
7886 mono_loader_unlock ();
7889 /* try _with_ signature */
7891 res = find_method_icall (imap, sigstart - mlen);
7893 mono_loader_unlock ();
7897 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7898 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7899 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7900 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7901 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");
7902 g_print ("If you see other errors or faults after this message they are probably related\n");
7903 g_print ("and you need to fix your mono install first.\n");
7905 mono_loader_unlock ();
7911 type_from_typename (char *typename)
7913 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7915 if (!strcmp (typename, "int"))
7916 klass = mono_defaults.int_class;
7917 else if (!strcmp (typename, "ptr"))
7918 klass = mono_defaults.int_class;
7919 else if (!strcmp (typename, "void"))
7920 klass = mono_defaults.void_class;
7921 else if (!strcmp (typename, "int32"))
7922 klass = mono_defaults.int32_class;
7923 else if (!strcmp (typename, "uint32"))
7924 klass = mono_defaults.uint32_class;
7925 else if (!strcmp (typename, "int8"))
7926 klass = mono_defaults.sbyte_class;
7927 else if (!strcmp (typename, "uint8"))
7928 klass = mono_defaults.byte_class;
7929 else if (!strcmp (typename, "int16"))
7930 klass = mono_defaults.int16_class;
7931 else if (!strcmp (typename, "uint16"))
7932 klass = mono_defaults.uint16_class;
7933 else if (!strcmp (typename, "long"))
7934 klass = mono_defaults.int64_class;
7935 else if (!strcmp (typename, "ulong"))
7936 klass = mono_defaults.uint64_class;
7937 else if (!strcmp (typename, "float"))
7938 klass = mono_defaults.single_class;
7939 else if (!strcmp (typename, "double"))
7940 klass = mono_defaults.double_class;
7941 else if (!strcmp (typename, "object"))
7942 klass = mono_defaults.object_class;
7943 else if (!strcmp (typename, "obj"))
7944 klass = mono_defaults.object_class;
7945 else if (!strcmp (typename, "string"))
7946 klass = mono_defaults.string_class;
7947 else if (!strcmp (typename, "bool"))
7948 klass = mono_defaults.boolean_class;
7949 else if (!strcmp (typename, "boolean"))
7950 klass = mono_defaults.boolean_class;
7953 g_assert_not_reached ();
7955 return &klass->byval_arg;
7958 MonoMethodSignature*
7959 mono_create_icall_signature (const char *sigstr)
7964 MonoMethodSignature *res;
7966 mono_loader_lock ();
7967 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7969 mono_loader_unlock ();
7973 parts = g_strsplit (sigstr, " ", 256);
7982 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7985 #ifdef PLATFORM_WIN32
7987 * Under windows, the default pinvoke calling convention is STDCALL but
7990 res->call_convention = MONO_CALL_C;
7993 res->ret = type_from_typename (parts [0]);
7994 for (i = 1; i < len; ++i) {
7995 res->params [i - 1] = type_from_typename (parts [i]);
8000 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8002 mono_loader_unlock ();
8008 mono_find_jit_icall_by_name (const char *name)
8010 MonoJitICallInfo *info;
8011 g_assert (jit_icall_hash_name);
8013 mono_loader_lock ();
8014 info = g_hash_table_lookup (jit_icall_hash_name, name);
8015 mono_loader_unlock ();
8020 mono_find_jit_icall_by_addr (gconstpointer addr)
8022 MonoJitICallInfo *info;
8023 g_assert (jit_icall_hash_addr);
8025 mono_loader_lock ();
8026 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8027 mono_loader_unlock ();
8033 * mono_get_jit_icall_info:
8035 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8036 * caller should access it while holding the loader lock.
8039 mono_get_jit_icall_info (void)
8041 return jit_icall_hash_name;
8045 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8047 mono_loader_lock ();
8048 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8049 mono_loader_unlock ();
8053 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8055 MonoJitICallInfo *info;
8060 mono_loader_lock ();
8062 if (!jit_icall_hash_name) {
8063 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8064 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8067 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8068 g_warning ("jit icall already defined \"%s\"\n", name);
8069 g_assert_not_reached ();
8072 info = g_new0 (MonoJitICallInfo, 1);
8079 info->wrapper = func;
8081 info->wrapper = NULL;
8084 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8085 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8087 mono_loader_unlock ();