5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * (C) 2001 Ximian, Inc.
19 #if defined (PLATFORM_WIN32)
23 #include <mono/metadata/object.h>
24 #include <mono/metadata/threads.h>
25 #include <mono/metadata/threads-types.h>
26 #include <mono/metadata/threadpool.h>
27 #include <mono/metadata/monitor.h>
28 #include <mono/metadata/reflection.h>
29 #include <mono/metadata/assembly.h>
30 #include <mono/metadata/tabledefs.h>
31 #include <mono/metadata/exception.h>
32 #include <mono/metadata/file-io.h>
33 #include <mono/metadata/console-io.h>
34 #include <mono/metadata/socket-io.h>
35 #include <mono/metadata/mono-endian.h>
36 #include <mono/metadata/tokentype.h>
37 #include <mono/metadata/domain-internals.h>
38 #include <mono/metadata/metadata-internals.h>
39 #include <mono/metadata/class-internals.h>
40 #include <mono/metadata/marshal.h>
41 #include <mono/metadata/gc-internal.h>
42 #include <mono/metadata/rand.h>
43 #include <mono/metadata/sysmath.h>
44 #include <mono/metadata/string-icalls.h>
45 #include <mono/metadata/debug-helpers.h>
46 #include <mono/metadata/process.h>
47 #include <mono/metadata/environment.h>
48 #include <mono/metadata/profiler-private.h>
49 #include <mono/metadata/locales.h>
50 #include <mono/metadata/filewatcher.h>
51 #include <mono/metadata/char-conversions.h>
52 #include <mono/metadata/security.h>
53 #include <mono/metadata/mono-config.h>
54 #include <mono/metadata/cil-coff.h>
55 #include <mono/metadata/security-manager.h>
56 #include <mono/io-layer/io-layer.h>
57 #include <mono/utils/strtod.h>
58 #include <mono/utils/monobitset.h>
60 #if defined (PLATFORM_WIN32)
66 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
69 static inline MonoBoolean
70 is_generic_parameter (MonoType *type)
72 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
76 * We expect a pointer to a char, not a string
79 mono_double_ParseImpl (char *ptr, double *result)
88 *result = strtod (ptr, &endptr);
91 *result = bsd_strtod (ptr, &endptr);
94 if (!*ptr || (endptr && *endptr))
101 mono_class_get_throw (MonoImage *image, guint32 type_token)
103 MonoClass *class = mono_class_get (image, type_token);
104 MonoLoaderError *error;
110 error = mono_loader_get_last_error ();
111 g_assert (error != NULL);
113 ex = mono_loader_error_prepare_exception (error);
114 mono_raise_exception (ex);
119 ves_icall_System_Double_AssertEndianity (double *value)
123 MONO_DOUBLE_ASSERT_ENDIANITY (value);
127 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
136 ao = (MonoArray *)this;
137 ac = (MonoClass *)ao->obj.vtable->klass;
139 esize = mono_array_element_size (ac);
140 ea = (gpointer*)((char*)ao->vector + (pos * esize));
142 if (ac->element_class->valuetype)
143 return mono_value_box (this->vtable->domain, ac->element_class, ea);
149 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
157 MONO_CHECK_ARG_NULL (idxs);
159 io = (MonoArray *)idxs;
160 ic = (MonoClass *)io->obj.vtable->klass;
162 ao = (MonoArray *)this;
163 ac = (MonoClass *)ao->obj.vtable->klass;
165 g_assert (ic->rank == 1);
166 if (io->bounds != NULL || io->max_length != ac->rank)
167 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
169 ind = (gint32 *)io->vector;
171 if (ao->bounds == NULL) {
172 if (*ind < 0 || *ind >= ao->max_length)
173 mono_raise_exception (mono_get_exception_index_out_of_range ());
175 return ves_icall_System_Array_GetValueImpl (this, *ind);
178 for (i = 0; i < ac->rank; i++)
179 if ((ind [i] < ao->bounds [i].lower_bound) ||
180 (ind [i] >= ao->bounds [i].length + ao->bounds [i].lower_bound))
181 mono_raise_exception (mono_get_exception_index_out_of_range ());
183 pos = ind [0] - ao->bounds [0].lower_bound;
184 for (i = 1; i < ac->rank; i++)
185 pos = pos*ao->bounds [i].length + ind [i] -
186 ao->bounds [i].lower_bound;
188 return ves_icall_System_Array_GetValueImpl (this, pos);
192 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
194 MonoClass *ac, *vc, *ec;
205 vc = value->vtable->klass;
209 ac = this->obj.vtable->klass;
210 ec = ac->element_class;
212 esize = mono_array_element_size (ac);
213 ea = (gpointer*)((char*)this->vector + (pos * esize));
214 va = (gpointer*)((char*)value + sizeof (MonoObject));
217 memset (ea, 0, esize);
221 #define NO_WIDENING_CONVERSION G_STMT_START{\
222 mono_raise_exception (mono_get_exception_argument ( \
223 "value", "not a widening conversion")); \
226 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
227 if (esize < vsize + (extra)) \
228 mono_raise_exception (mono_get_exception_argument ( \
229 "value", "not a widening conversion")); \
232 #define INVALID_CAST G_STMT_START{\
233 mono_raise_exception (mono_get_exception_invalid_cast ()); \
236 /* Check element (destination) type. */
237 switch (ec->byval_arg.type) {
238 case MONO_TYPE_STRING:
239 switch (vc->byval_arg.type) {
240 case MONO_TYPE_STRING:
246 case MONO_TYPE_BOOLEAN:
247 switch (vc->byval_arg.type) {
248 case MONO_TYPE_BOOLEAN:
261 NO_WIDENING_CONVERSION;
268 if (!ec->valuetype) {
269 if (!mono_object_isinst (value, ec))
271 *ea = (gpointer)value;
275 if (mono_object_isinst (value, ec)) {
276 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
283 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
285 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
286 switch (vc->byval_arg.type) { \
291 case MONO_TYPE_CHAR: \
292 CHECK_WIDENING_CONVERSION(0); \
293 *(etype *) ea = (etype) u64; \
295 /* You can't assign a signed value to an unsigned array. */ \
300 /* You can't assign a floating point number to an integer array. */ \
303 NO_WIDENING_CONVERSION; \
307 #define ASSIGN_SIGNED(etype) G_STMT_START{\
308 switch (vc->byval_arg.type) { \
313 CHECK_WIDENING_CONVERSION(0); \
314 *(etype *) ea = (etype) i64; \
316 /* You can assign an unsigned value to a signed array if the array's */ \
317 /* element size is larger than the value size. */ \
322 case MONO_TYPE_CHAR: \
323 CHECK_WIDENING_CONVERSION(1); \
324 *(etype *) ea = (etype) u64; \
326 /* You can't assign a floating point number to an integer array. */ \
329 NO_WIDENING_CONVERSION; \
333 #define ASSIGN_REAL(etype) G_STMT_START{\
334 switch (vc->byval_arg.type) { \
337 CHECK_WIDENING_CONVERSION(0); \
338 *(etype *) ea = (etype) r64; \
340 /* All integer values fit into a floating point array, so we don't */ \
341 /* need to CHECK_WIDENING_CONVERSION here. */ \
346 *(etype *) ea = (etype) i64; \
352 case MONO_TYPE_CHAR: \
353 *(etype *) ea = (etype) u64; \
358 switch (vc->byval_arg.type) {
360 u64 = *(guint8 *) va;
363 u64 = *(guint16 *) va;
366 u64 = *(guint32 *) va;
369 u64 = *(guint64 *) va;
375 i64 = *(gint16 *) va;
378 i64 = *(gint32 *) va;
381 i64 = *(gint64 *) va;
384 r64 = *(gfloat *) va;
387 r64 = *(gdouble *) va;
390 u64 = *(guint16 *) va;
392 case MONO_TYPE_BOOLEAN:
393 /* Boolean is only compatible with itself. */
394 switch (ec->byval_arg.type) {
406 NO_WIDENING_CONVERSION;
413 /* If we can't do a direct copy, let's try a widening conversion. */
414 switch (ec->byval_arg.type) {
416 ASSIGN_UNSIGNED (guint16);
418 ASSIGN_UNSIGNED (guint8);
420 ASSIGN_UNSIGNED (guint16);
422 ASSIGN_UNSIGNED (guint32);
424 ASSIGN_UNSIGNED (guint64);
426 ASSIGN_SIGNED (gint8);
428 ASSIGN_SIGNED (gint16);
430 ASSIGN_SIGNED (gint32);
432 ASSIGN_SIGNED (gint64);
434 ASSIGN_REAL (gfloat);
436 ASSIGN_REAL (gdouble);
440 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
444 #undef NO_WIDENING_CONVERSION
445 #undef CHECK_WIDENING_CONVERSION
446 #undef ASSIGN_UNSIGNED
452 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
460 MONO_CHECK_ARG_NULL (idxs);
462 ic = idxs->obj.vtable->klass;
463 ac = this->obj.vtable->klass;
465 g_assert (ic->rank == 1);
466 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
467 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
469 ind = (gint32 *)idxs->vector;
471 if (this->bounds == NULL) {
472 if (*ind < 0 || *ind >= this->max_length)
473 mono_raise_exception (mono_get_exception_index_out_of_range ());
475 ves_icall_System_Array_SetValueImpl (this, value, *ind);
479 for (i = 0; i < ac->rank; i++)
480 if ((ind [i] < this->bounds [i].lower_bound) ||
481 (ind [i] >= this->bounds [i].length + this->bounds [i].lower_bound))
482 mono_raise_exception (mono_get_exception_index_out_of_range ());
484 pos = ind [0] - this->bounds [0].lower_bound;
485 for (i = 1; i < ac->rank; i++)
486 pos = pos * this->bounds [i].length + ind [i] -
487 this->bounds [i].lower_bound;
489 ves_icall_System_Array_SetValueImpl (this, value, pos);
493 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
498 gboolean bounded = FALSE;
502 MONO_CHECK_ARG_NULL (type);
503 MONO_CHECK_ARG_NULL (lengths);
505 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
507 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
509 for (i = 0; i < mono_array_length (lengths); i++)
510 if (mono_array_get (lengths, gint32, i) < 0)
511 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
513 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
514 /* vectors are not the same as one dimensional arrays with no-zero bounds */
519 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
521 sizes = alloca (aklass->rank * sizeof(guint32) * 2);
522 for (i = 0; i < aklass->rank; ++i) {
523 sizes [i] = mono_array_get (lengths, guint32, i);
525 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
527 sizes [i + aklass->rank] = 0;
530 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
536 ves_icall_System_Array_GetRank (MonoObject *this)
540 return this->vtable->klass->rank;
544 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
546 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
550 if ((dimension < 0) || (dimension >= rank))
551 mono_raise_exception (mono_get_exception_index_out_of_range ());
553 if (this->bounds == NULL)
554 return this->max_length;
556 return this->bounds [dimension].length;
560 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
562 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
566 if ((dimension < 0) || (dimension >= rank))
567 mono_raise_exception (mono_get_exception_index_out_of_range ());
569 if (this->bounds == NULL)
572 return this->bounds [dimension].lower_bound;
576 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
578 int sz = mono_array_element_size (mono_object_class (arr));
579 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
583 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
588 MonoClass *src_class;
589 MonoClass *dest_class;
594 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
597 if (source->bounds || dest->bounds)
600 if ((dest_idx + length > mono_array_length (dest)) ||
601 (source_idx + length > mono_array_length (source)))
604 src_class = source->obj.vtable->klass->element_class;
605 dest_class = dest->obj.vtable->klass->element_class;
608 * Handle common cases.
611 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
612 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
613 int has_refs = dest_class->has_references;
614 for (i = source_idx; i < source_idx + length; ++i) {
615 MonoObject *elem = mono_array_get (source, MonoObject*, i);
616 if (elem && !mono_object_isinst (elem, dest_class))
620 element_size = mono_array_element_size (dest->obj.vtable->klass);
621 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
622 for (i = 0; i < length; ++i) {
623 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
624 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
628 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
630 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
635 /* Check if we're copying a char[] <==> (u)short[] */
636 if (src_class != dest_class) {
637 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
640 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
642 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
643 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
644 for (i = source_idx; i < source_idx + length; ++i) {
645 MonoObject *elem = mono_array_get (source, MonoObject*, i);
646 if (elem && !mono_object_isinst (elem, dest_class))
653 if (dest_class->valuetype) {
654 element_size = mono_array_element_size (source->obj.vtable->klass);
655 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
656 if (dest_class->has_references) {
657 mono_value_copy_array (dest, dest_idx, source_addr, length);
659 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
660 memmove (dest_addr, source_addr, element_size * length);
663 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
670 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
679 ao = (MonoArray *)this;
680 ac = (MonoClass *)ao->obj.vtable->klass;
682 esize = mono_array_element_size (ac);
683 ea = (gpointer*)((char*)ao->vector + (pos * esize));
685 memcpy (value, ea, esize);
689 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
691 MonoClass *klass = array->obj.vtable->klass;
692 guint32 size = mono_array_element_size (klass);
697 if (array->bounds == NULL)
698 size *= array->max_length;
700 for (i = 0; i < klass->rank; ++i)
701 size *= array->bounds [i].length;
703 memcpy (mono_array_addr (array, char, 0), field_handle->data, size);
705 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
709 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
711 for (i = 0; i < size; i += n/8, data++) { \
712 tmp = read ## n (data); \
717 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
719 switch (mono_type_get_underlying_type (&klass->element_class->byval_arg)->type) {
739 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
743 return offsetof (MonoString, chars);
747 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
751 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
754 return mono_object_clone (obj);
758 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
764 MONO_CHECK_ARG_NULL (handle);
766 klass = mono_class_from_mono_type (handle);
767 MONO_CHECK_ARG (handle, klass);
769 /* This will call the type constructor */
770 if (! (klass->flags & TYPE_ATTRIBUTE_INTERFACE))
771 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
775 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
779 return mono_object_clone (this);
783 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
786 MonoObject **values = NULL;
790 MonoClassField* field;
795 klass = mono_object_class (this);
797 if (mono_class_num_fields (klass) == 0)
798 return mono_object_hash (this);
801 * Compute the starting value of the hashcode for fields of primitive
802 * types, and return the remaining fields in an array to the managed side.
803 * This way, we can avoid costly reflection operations in managed code.
806 while ((field = mono_class_get_fields (klass, &iter))) {
807 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
809 if (mono_field_is_deleted (field))
811 /* FIXME: Add more types */
812 switch (field->type->type) {
814 result ^= *(gint32*)((guint8*)this + field->offset);
816 case MONO_TYPE_STRING: {
818 s = *(MonoString**)((guint8*)this + field->offset);
820 result ^= mono_string_hash (s);
825 values = g_newa (MonoObject*, mono_class_num_fields (klass));
826 o = mono_field_get_value_object (mono_object_domain (this), field, this);
827 values [count++] = o;
833 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
834 for (i = 0; i < count; ++i)
835 mono_array_setref (*fields, i, values [i]);
843 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
846 MonoObject **values = NULL;
848 MonoClassField* field;
854 MONO_CHECK_ARG_NULL (that);
856 if (this->vtable != that->vtable)
859 klass = mono_object_class (this);
862 * Do the comparison for fields of primitive type and return a result if
863 * possible. Otherwise, return the remaining fields in an array to the
864 * managed side. This way, we can avoid costly reflection operations in
869 while ((field = mono_class_get_fields (klass, &iter))) {
870 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
872 if (mono_field_is_deleted (field))
874 /* FIXME: Add more types */
875 switch (field->type->type) {
877 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
880 case MONO_TYPE_STRING: {
882 guint32 s1len, s2len;
883 s1 = *(MonoString**)((guint8*)this + field->offset);
884 s2 = *(MonoString**)((guint8*)that + field->offset);
887 if ((s1 == NULL) || (s2 == NULL))
889 s1len = mono_string_length (s1);
890 s2len = mono_string_length (s2);
894 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
900 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
901 o = mono_field_get_value_object (mono_object_domain (this), field, this);
902 values [count++] = o;
903 o = mono_field_get_value_object (mono_object_domain (this), field, that);
904 values [count++] = o;
910 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
911 for (i = 0; i < count; ++i)
912 mono_array_setref (*fields, i, values [i]);
919 static MonoReflectionType *
920 ves_icall_System_Object_GetType (MonoObject *obj)
924 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
925 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
927 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
931 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
935 mtype->type = &obj->vtable->klass->byval_arg;
936 g_assert (mtype->type->type);
940 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
944 MONO_CHECK_ARG_NULL (obj);
946 return mono_image_create_token (mb->dynamic_image, obj, TRUE);
950 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
951 MonoReflectionMethod *method,
952 MonoArray *opt_param_types)
956 MONO_CHECK_ARG_NULL (method);
958 return mono_image_create_method_token (
959 mb->dynamic_image, (MonoObject *) method, opt_param_types);
963 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
967 mono_image_create_pefile (mb, file);
971 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
975 mono_image_build_metadata (mb);
979 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
981 MonoMethod **dest = data;
983 /* skip unmanaged frames */
998 static MonoReflectionType *
999 type_from_name (const char *str, MonoBoolean ignoreCase)
1001 MonoType *type = NULL;
1002 MonoAssembly *assembly = NULL;
1003 MonoTypeNameParse info;
1004 char *temp_str = g_strdup (str);
1005 gboolean type_resolve = FALSE;
1007 MONO_ARCH_SAVE_REGS;
1009 /* mono_reflection_parse_type() mangles the string */
1010 if (!mono_reflection_parse_type (temp_str, &info)) {
1011 g_list_free (info.modifiers);
1012 g_list_free (info.nested);
1017 if (info.assembly.name) {
1018 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1020 MonoMethod *m = mono_method_get_last_managed ();
1021 MonoMethod *dest = m;
1023 mono_stack_walk_no_il (get_caller, &dest);
1028 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1029 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1030 * to crash. This only seems to happen in some strange remoting
1031 * scenarios and I was unable to figure out what's happening there.
1032 * Dec 10, 2005 - Martin.
1036 assembly = dest->klass->image->assembly;
1038 g_warning (G_STRLOC);
1043 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1045 if (!info.assembly.name && !type) /* try mscorlib */
1046 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1048 g_list_free (info.modifiers);
1049 g_list_free (info.nested);
1055 return mono_type_get_object (mono_domain_get (), type);
1059 MonoReflectionType *
1060 mono_type_get (const char *str)
1062 char *copy = g_strdup (str);
1063 MonoReflectionType *type = type_from_name (copy, FALSE);
1070 static MonoReflectionType*
1071 ves_icall_type_from_name (MonoString *name,
1072 MonoBoolean throwOnError,
1073 MonoBoolean ignoreCase)
1075 char *str = mono_string_to_utf8 (name);
1076 MonoReflectionType *type;
1078 type = type_from_name (str, ignoreCase);
1082 mono_raise_exception (mono_get_exception_type_load (name, NULL));
1089 static MonoReflectionType*
1090 ves_icall_type_from_handle (MonoType *handle)
1092 MonoDomain *domain = mono_domain_get ();
1093 MonoClass *klass = mono_class_from_mono_type (handle);
1095 MONO_ARCH_SAVE_REGS;
1097 mono_class_init (klass);
1098 return mono_type_get_object (domain, handle);
1102 ves_icall_type_Equals (MonoReflectionType *type, MonoReflectionType *c)
1104 MONO_ARCH_SAVE_REGS;
1106 if (c && type->type && c->type)
1107 return mono_metadata_type_equal (type->type, c->type);
1112 /* System.TypeCode */
1131 TYPECODE_STRING = 18
1135 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1137 int t = type->type->type;
1139 MONO_ARCH_SAVE_REGS;
1141 if (type->type->byref)
1142 return TYPECODE_OBJECT;
1146 case MONO_TYPE_VOID:
1147 return TYPECODE_OBJECT;
1148 case MONO_TYPE_BOOLEAN:
1149 return TYPECODE_BOOLEAN;
1151 return TYPECODE_BYTE;
1153 return TYPECODE_SBYTE;
1155 return TYPECODE_UINT16;
1157 return TYPECODE_INT16;
1158 case MONO_TYPE_CHAR:
1159 return TYPECODE_CHAR;
1163 return TYPECODE_OBJECT;
1165 return TYPECODE_UINT32;
1167 return TYPECODE_INT32;
1169 return TYPECODE_UINT64;
1171 return TYPECODE_INT64;
1173 return TYPECODE_SINGLE;
1175 return TYPECODE_DOUBLE;
1176 case MONO_TYPE_VALUETYPE:
1177 if (type->type->data.klass->enumtype) {
1178 t = type->type->data.klass->enum_basetype->type;
1181 MonoClass *k = type->type->data.klass;
1182 if (strcmp (k->name_space, "System") == 0) {
1183 if (strcmp (k->name, "Decimal") == 0)
1184 return TYPECODE_DECIMAL;
1185 else if (strcmp (k->name, "DateTime") == 0)
1186 return TYPECODE_DATETIME;
1189 return TYPECODE_OBJECT;
1190 case MONO_TYPE_STRING:
1191 return TYPECODE_STRING;
1192 case MONO_TYPE_SZARRAY:
1193 case MONO_TYPE_ARRAY:
1194 case MONO_TYPE_OBJECT:
1196 case MONO_TYPE_MVAR:
1197 case MONO_TYPE_TYPEDBYREF:
1198 return TYPECODE_OBJECT;
1199 case MONO_TYPE_CLASS:
1201 MonoClass *k = type->type->data.klass;
1202 if (strcmp (k->name_space, "System") == 0) {
1203 if (strcmp (k->name, "DBNull") == 0)
1204 return TYPECODE_DBNULL;
1207 return TYPECODE_OBJECT;
1208 case MONO_TYPE_GENERICINST:
1209 return TYPECODE_OBJECT;
1211 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1217 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1223 MONO_ARCH_SAVE_REGS;
1225 g_assert (type != NULL);
1227 domain = ((MonoObject *)type)->vtable->domain;
1229 if (!c) /* FIXME: dont know what do do here */
1232 klass = mono_class_from_mono_type (type->type);
1233 klassc = mono_class_from_mono_type (c->type);
1235 if (type->type->byref)
1236 return klassc == mono_defaults.object_class;
1238 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1242 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1248 MONO_ARCH_SAVE_REGS;
1250 g_assert (type != NULL);
1252 domain = ((MonoObject *)type)->vtable->domain;
1254 klass = mono_class_from_mono_type (type->type);
1255 klassc = mono_class_from_mono_type (c->type);
1257 if (type->type->byref && !c->type->byref)
1260 return mono_class_is_assignable_from (klass, klassc);
1264 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1266 MonoClass *klass = mono_class_from_mono_type (type->type);
1267 return mono_object_isinst (obj, klass) != NULL;
1271 ves_icall_get_attributes (MonoReflectionType *type)
1273 MonoClass *klass = mono_class_from_mono_type (type->type);
1275 MONO_ARCH_SAVE_REGS;
1277 return klass->flags;
1280 static MonoReflectionMarshal*
1281 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1283 MonoClass *klass = field->field->parent;
1284 MonoMarshalType *info;
1287 if (klass->generic_container ||
1288 (klass->generic_class && klass->generic_class->inst->is_open))
1291 info = mono_marshal_load_type_info (klass);
1293 for (i = 0; i < info->num_fields; ++i) {
1294 if (info->fields [i].field == field->field) {
1295 if (!info->fields [i].mspec)
1298 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1305 static MonoReflectionField*
1306 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1308 MONO_ARCH_SAVE_REGS;
1312 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1316 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1318 MonoDomain *domain = mono_domain_get ();
1319 MonoMethodSignature* sig;
1320 MONO_ARCH_SAVE_REGS;
1322 if (method->is_inflated)
1323 method = mono_get_inflated_method (method);
1325 sig = mono_method_signature (method);
1327 info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
1328 info->ret = mono_type_get_object (domain, sig->ret);
1329 info->attrs = method->flags;
1330 info->implattrs = method->iflags;
1331 if (sig->call_convention == MONO_CALL_DEFAULT)
1334 if (sig->call_convention == MONO_CALL_VARARG)
1339 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1343 ves_icall_get_parameter_info (MonoMethod *method)
1345 MonoDomain *domain = mono_domain_get ();
1347 MONO_ARCH_SAVE_REGS;
1349 if (method->is_inflated)
1350 method = mono_get_inflated_method (method);
1352 return mono_param_get_objects (domain, method);
1355 static MonoReflectionMarshal*
1356 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1358 MonoDomain *domain = mono_domain_get ();
1359 MonoReflectionMarshal* res = NULL;
1360 MonoMarshalSpec **mspecs;
1363 MONO_ARCH_SAVE_REGS;
1365 if (method->is_inflated)
1366 method = mono_get_inflated_method (method);
1368 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1369 mono_method_get_marshal_info (method, mspecs);
1372 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1374 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1376 mono_metadata_free_marshal_spec (mspecs [i]);
1383 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1385 return field->field->offset - sizeof (MonoObject);
1388 static MonoReflectionType*
1389 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1392 MONO_ARCH_SAVE_REGS;
1394 parent = declaring? field->field->parent: field->klass;
1396 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1400 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1403 MonoClassField *cf = field->field;
1407 MonoDomain *domain = mono_object_domain (field);
1409 gboolean is_static = FALSE;
1410 gboolean is_ref = FALSE;
1412 MONO_ARCH_SAVE_REGS;
1414 if (field->klass->image->assembly->ref_only)
1415 mono_raise_exception (mono_get_exception_invalid_operation (
1416 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1418 mono_class_init (field->klass);
1420 t = mono_type_get_underlying_type (cf->type);
1422 case MONO_TYPE_STRING:
1423 case MONO_TYPE_OBJECT:
1424 case MONO_TYPE_CLASS:
1425 case MONO_TYPE_ARRAY:
1426 case MONO_TYPE_SZARRAY:
1431 case MONO_TYPE_BOOLEAN:
1434 case MONO_TYPE_CHAR:
1443 case MONO_TYPE_VALUETYPE:
1446 case MONO_TYPE_GENERICINST:
1447 if (mono_type_generic_inst_is_valuetype (t)) {
1454 g_error ("type 0x%x not handled in "
1455 "ves_icall_Monofield_GetValue", t->type);
1460 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1462 vtable = mono_class_vtable (domain, cf->parent);
1463 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1464 mono_runtime_class_init (vtable);
1469 mono_field_static_get_value (vtable, cf, &o);
1471 mono_field_get_value (obj, cf, &o);
1476 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1477 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1480 /* Convert the Nullable structure into a boxed vtype */
1482 buf = (guint8*)vtable->data + cf->offset;
1484 buf = (guint8*)obj + cf->offset;
1486 return mono_nullable_box (buf, nklass);
1489 /* boxed value type */
1490 klass = mono_class_from_mono_type (cf->type);
1491 o = mono_object_new (domain, klass);
1492 v = ((gchar *) o) + sizeof (MonoObject);
1494 mono_field_static_get_value (vtable, cf, v);
1496 mono_field_get_value (obj, cf, v);
1503 ves_icall_FieldInfo_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1505 MonoClassField *cf = field->field;
1508 MONO_ARCH_SAVE_REGS;
1510 if (field->klass->image->assembly->ref_only)
1511 mono_raise_exception (mono_get_exception_invalid_operation (
1512 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1514 v = (gchar *) value;
1515 if (!cf->type->byref) {
1516 switch (cf->type->type) {
1519 case MONO_TYPE_BOOLEAN:
1522 case MONO_TYPE_CHAR:
1531 case MONO_TYPE_VALUETYPE:
1533 v += sizeof (MonoObject);
1535 case MONO_TYPE_STRING:
1536 case MONO_TYPE_OBJECT:
1537 case MONO_TYPE_CLASS:
1538 case MONO_TYPE_ARRAY:
1539 case MONO_TYPE_SZARRAY:
1542 case MONO_TYPE_GENERICINST: {
1543 MonoGenericClass *gclass = cf->type->data.generic_class;
1544 g_assert (!gclass->inst->is_open);
1546 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1547 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1551 * Convert the boxed vtype into a Nullable structure.
1552 * This is complicated by the fact that Nullables have
1553 * a variable structure.
1555 /* Allocate using alloca so it gets GC tracking */
1556 buf = alloca (nklass->instance_size);
1558 mono_nullable_init (buf, value, nklass);
1563 if (gclass->container_class->valuetype && (v != NULL))
1564 v += sizeof (MonoObject);
1568 g_error ("type 0x%x not handled in "
1569 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1574 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1575 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1576 if (!vtable->initialized)
1577 mono_runtime_class_init (vtable);
1578 mono_field_static_set_value (vtable, cf, v);
1580 mono_field_set_value (obj, cf, v);
1584 static MonoReflectionType*
1585 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1587 MonoMethod *method = mono_get_inflated_method (rmethod->method.method);
1589 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1592 /* From MonoProperty.cs */
1594 PInfo_Attributes = 1,
1595 PInfo_GetMethod = 1 << 1,
1596 PInfo_SetMethod = 1 << 2,
1597 PInfo_ReflectedType = 1 << 3,
1598 PInfo_DeclaringType = 1 << 4,
1603 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1605 MonoDomain *domain = mono_object_domain (property);
1607 MONO_ARCH_SAVE_REGS;
1609 if ((req_info & PInfo_ReflectedType) != 0)
1610 info->parent = mono_type_get_object (domain, &property->klass->byval_arg);
1611 else if ((req_info & PInfo_DeclaringType) != 0)
1612 info->parent = mono_type_get_object (domain, &property->property->parent->byval_arg);
1614 if ((req_info & PInfo_Name) != 0)
1615 info->name = mono_string_new (domain, property->property->name);
1617 if ((req_info & PInfo_Attributes) != 0)
1618 info->attrs = property->property->attrs;
1620 if ((req_info & PInfo_GetMethod) != 0)
1621 info->get = property->property->get ?
1622 mono_method_get_object (domain, property->property->get, NULL): NULL;
1624 if ((req_info & PInfo_SetMethod) != 0)
1625 info->set = property->property->set ?
1626 mono_method_get_object (domain, property->property->set, NULL): NULL;
1628 * There may be other methods defined for properties, though, it seems they are not exposed
1629 * in the reflection API
1634 ves_icall_get_event_info (MonoReflectionEvent *event, MonoEventInfo *info)
1636 MonoDomain *domain = mono_object_domain (event);
1638 MONO_ARCH_SAVE_REGS;
1640 info->reflected_type = mono_type_get_object (domain, &event->klass->byval_arg);
1641 info->declaring_type = mono_type_get_object (domain, &event->event->parent->byval_arg);
1643 info->name = mono_string_new (domain, event->event->name);
1644 info->attrs = event->event->attrs;
1645 info->add_method = event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL;
1646 info->remove_method = event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL;
1647 info->raise_method = event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL;
1649 if (event->event->other) {
1651 while (event->event->other [n])
1653 info->other_methods = mono_array_new (domain, mono_defaults.method_info_class, n);
1655 for (i = 0; i < n; i++)
1656 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
1661 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
1663 MonoDomain *domain = mono_object_domain (type);
1665 GPtrArray *ifaces = NULL;
1667 MonoClass *class = mono_class_from_mono_type (type->type);
1670 MonoGenericContext *context = NULL;
1672 MONO_ARCH_SAVE_REGS;
1674 /* open generic-instance classes can share their interface_id */
1675 if (class->generic_class && class->generic_class->inst->is_open) {
1676 context = class->generic_class->context;
1677 class = class->generic_class->container_class;
1680 mono_class_setup_vtable (class);
1682 slots = mono_bitset_new (class->max_interface_id + 1, 0);
1684 for (parent = class; parent; parent = parent->parent) {
1685 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
1687 for (i = 0; i < tmp_ifaces->len; ++i) {
1688 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
1690 if (mono_bitset_test (slots, ic->interface_id))
1693 mono_bitset_set (slots, ic->interface_id);
1695 ifaces = g_ptr_array_new ();
1696 g_ptr_array_add (ifaces, ic);
1698 g_ptr_array_free (tmp_ifaces, TRUE);
1701 mono_bitset_free (slots);
1704 return mono_array_new (domain, mono_defaults.monotype_class, 0);
1706 intf = mono_array_new (domain, mono_defaults.monotype_class, ifaces->len);
1707 for (i = 0; i < ifaces->len; ++i) {
1708 MonoClass *ic = g_ptr_array_index (ifaces, i);
1709 MonoType *ret = &ic->byval_arg;
1710 if (context && ic->generic_class && ic->generic_class->inst->is_open)
1711 ret = mono_class_inflate_generic_type (ret, context);
1713 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
1715 g_ptr_array_free (ifaces, TRUE);
1721 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
1723 MonoClass *class = mono_class_from_mono_type (type->type);
1724 MonoClass *iclass = mono_class_from_mono_type (iface->type);
1725 MonoReflectionMethod *member;
1728 int i = 0, len, ioffset;
1731 MONO_ARCH_SAVE_REGS;
1733 mono_class_setup_vtable (class);
1735 /* type doesn't implement iface: the exception is thrown in managed code */
1736 if ((iclass->interface_id > class->max_interface_id) || !class->interface_offsets [iclass->interface_id])
1739 len = mono_class_num_methods (iclass);
1740 ioffset = class->interface_offsets [iclass->interface_id];
1741 domain = mono_object_domain (type);
1742 *targets = mono_array_new (domain, mono_defaults.method_info_class, len);
1743 *methods = mono_array_new (domain, mono_defaults.method_info_class, len);
1746 while ((method = mono_class_get_methods (iclass, &iter))) {
1747 member = mono_method_get_object (domain, method, iclass);
1748 mono_array_setref (*methods, i, member);
1749 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
1750 mono_array_setref (*targets, i, member);
1757 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
1759 MonoClass *klass = mono_class_from_mono_type (type->type);
1761 g_assert (!klass->image->dynamic);
1763 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
1766 static MonoReflectionType*
1767 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
1769 MonoClass *class = mono_class_from_mono_type (type->type);
1771 MONO_ARCH_SAVE_REGS;
1773 // GelElementType should only return a type for:
1774 // Array Pointer PassedByRef
1775 if (type->type->byref)
1776 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
1777 if (class->enumtype && class->enum_basetype) /* types that are modifierd typebuilkders may not have enum_basetype set */
1778 return mono_type_get_object (mono_object_domain (type), class->enum_basetype);
1779 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
1780 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
1781 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
1782 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
1787 static MonoReflectionType*
1788 ves_icall_get_type_parent (MonoReflectionType *type)
1790 MonoClass *class = mono_class_from_mono_type (type->type);
1792 MONO_ARCH_SAVE_REGS;
1794 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
1798 ves_icall_type_ispointer (MonoReflectionType *type)
1800 MONO_ARCH_SAVE_REGS;
1802 return type->type->type == MONO_TYPE_PTR;
1806 ves_icall_type_isprimitive (MonoReflectionType *type)
1808 MONO_ARCH_SAVE_REGS;
1810 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)));
1814 ves_icall_type_isbyref (MonoReflectionType *type)
1816 MONO_ARCH_SAVE_REGS;
1818 return type->type->byref;
1822 ves_icall_type_iscomobject (MonoReflectionType *type)
1824 MonoClass *klass = mono_class_from_mono_type (type->type);
1825 MONO_ARCH_SAVE_REGS;
1827 return (klass && klass->is_com_object);
1830 static MonoReflectionModule*
1831 ves_icall_MonoType_get_Module (MonoReflectionType *type)
1833 MonoClass *class = mono_class_from_mono_type (type->type);
1835 MONO_ARCH_SAVE_REGS;
1837 return mono_module_get_object (mono_object_domain (type), class->image);
1840 static MonoReflectionAssembly*
1841 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
1843 MonoDomain *domain = mono_domain_get ();
1844 MonoClass *class = mono_class_from_mono_type (type->type);
1846 MONO_ARCH_SAVE_REGS;
1848 return mono_assembly_get_object (domain, class->image->assembly);
1851 static MonoReflectionType*
1852 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
1854 MonoDomain *domain = mono_domain_get ();
1857 MONO_ARCH_SAVE_REGS;
1859 if (type->type->byref)
1861 if (type->type->type == MONO_TYPE_VAR)
1862 class = type->type->data.generic_param->owner->klass;
1863 else if (type->type->type == MONO_TYPE_MVAR)
1864 class = type->type->data.generic_param->method->klass;
1866 class = mono_class_from_mono_type (type->type)->nested_in;
1868 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
1871 static MonoReflectionType*
1872 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
1874 MonoDomain *domain = mono_domain_get ();
1875 MonoClass *class = mono_class_from_mono_type (type->type);
1877 MONO_ARCH_SAVE_REGS;
1879 if (class->enumtype && class->enum_basetype) /* types that are modified typebuilders may not have enum_basetype set */
1880 return mono_type_get_object (domain, class->enum_basetype);
1881 else if (class->element_class)
1882 return mono_type_get_object (domain, &class->element_class->byval_arg);
1888 ves_icall_MonoType_get_Name (MonoReflectionType *type)
1890 MonoDomain *domain = mono_domain_get ();
1891 MonoClass *class = mono_class_from_mono_type (type->type);
1893 MONO_ARCH_SAVE_REGS;
1895 if (type->type->byref) {
1896 char *n = g_strdup_printf ("%s&", class->name);
1897 MonoString *res = mono_string_new (domain, n);
1903 return mono_string_new (domain, class->name);
1908 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
1910 MonoDomain *domain = mono_domain_get ();
1911 MonoClass *class = mono_class_from_mono_type (type->type);
1913 MONO_ARCH_SAVE_REGS;
1915 while (class->nested_in)
1916 class = class->nested_in;
1918 if (class->name_space [0] == '\0')
1921 return mono_string_new (domain, class->name_space);
1925 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
1927 MonoClass *class = mono_class_from_mono_type (type->type);
1929 MONO_ARCH_SAVE_REGS;
1935 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
1938 MonoClass *klass, *pklass;
1940 MONO_ARCH_SAVE_REGS;
1942 klass = mono_class_from_mono_type (type->type);
1944 if (klass->generic_container) {
1945 MonoGenericContainer *container = klass->generic_container;
1946 res = mono_array_new (mono_object_domain (type), mono_defaults.monotype_class, container->type_argc);
1947 for (i = 0; i < container->type_argc; ++i) {
1948 pklass = mono_class_from_generic_parameter (&container->type_params [i], klass->image, FALSE);
1949 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), &pklass->byval_arg));
1951 } else if (klass->generic_class) {
1952 MonoGenericInst *inst = klass->generic_class->inst;
1953 res = mono_array_new (mono_object_domain (type), mono_defaults.monotype_class, inst->type_argc);
1954 for (i = 0; i < inst->type_argc; ++i)
1955 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), inst->type_argv [i]));
1957 res = mono_array_new (mono_object_domain (type), mono_defaults.monotype_class, 0);
1963 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
1966 MONO_ARCH_SAVE_REGS;
1968 if (type->type->byref)
1971 klass = mono_class_from_mono_type (type->type);
1973 return klass->generic_container != NULL;
1976 static MonoReflectionType*
1977 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
1980 MONO_ARCH_SAVE_REGS;
1982 if (type->type->byref)
1985 klass = mono_class_from_mono_type (type->type);
1986 if (klass->generic_container) {
1987 return type; /* check this one */
1989 if (klass->generic_class) {
1990 MonoClass *generic_class = klass->generic_class->container_class;
1992 if (generic_class->wastypebuilder && generic_class->reflection_info)
1993 return generic_class->reflection_info;
1995 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2000 static MonoReflectionType*
2001 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2003 MonoType *geninst, **types;
2006 MONO_ARCH_SAVE_REGS;
2008 count = mono_array_length (type_array);
2009 types = g_new0 (MonoType *, count);
2011 for (i = 0; i < count; i++) {
2012 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2013 types [i] = t->type;
2016 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2020 return mono_type_get_object (mono_object_domain (type), geninst);
2024 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2027 MONO_ARCH_SAVE_REGS;
2029 if (type->type->byref)
2032 klass = mono_class_from_mono_type (type->type);
2033 return klass->generic_class != NULL;
2037 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2040 MONO_ARCH_SAVE_REGS;
2042 if (type->type->byref)
2045 klass = mono_class_from_mono_type (type->type);
2046 return klass->generic_class != NULL || klass->generic_container != NULL;
2050 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2052 MONO_ARCH_SAVE_REGS;
2054 if (is_generic_parameter (type->type))
2055 return type->type->data.generic_param->num;
2059 static GenericParameterAttributes
2060 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2062 MONO_ARCH_SAVE_REGS;
2063 g_assert (is_generic_parameter (type->type));
2064 return type->type->data.generic_param->flags;
2068 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2070 MonoGenericParam *param;
2076 MONO_ARCH_SAVE_REGS;
2078 domain = mono_object_domain (type);
2079 param = type->type->data.generic_param;
2080 for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
2083 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2084 for (i = 0; i < count; i++)
2085 mono_array_setref (res, i, mono_type_get_object (domain, ¶m->constraints [i]->byval_arg));
2092 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2094 MONO_ARCH_SAVE_REGS;
2095 return is_generic_parameter (type->type);
2099 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2101 MONO_ARCH_SAVE_REGS;
2102 return is_generic_parameter (tb->type.type);
2106 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2107 MonoReflectionType *t)
2109 enumtype->type = t->type;
2112 static MonoReflectionType*
2113 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2115 MonoDynamicGenericClass *gclass;
2116 MonoReflectionType *parent = NULL;
2121 MONO_ARCH_SAVE_REGS;
2123 g_assert (type->type.type->data.generic_class->is_dynamic);
2124 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2126 domain = mono_object_domain (type);
2127 klass = mono_class_from_mono_type (type->generic_type->type);
2129 if (!klass->generic_class && !klass->generic_container)
2132 if (!strcmp (type->generic_type->object.vtable->klass->name, "TypeBuilder")) {
2133 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *) type->generic_type;
2134 parent = tb->parent;
2135 } else if (klass->wastypebuilder) {
2136 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *) type->generic_type;
2137 parent = tb->parent;
2139 MonoClass *pklass = klass->parent;
2141 parent = mono_type_get_object (domain, &pklass->byval_arg);
2144 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2147 inflated = mono_class_inflate_generic_type (
2148 parent->type, gclass->generic_class.generic_class.context);
2150 return mono_type_get_object (domain, inflated);
2154 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2156 static MonoClass *System_Reflection_MonoGenericClass;
2157 MonoDynamicGenericClass *gclass;
2158 MonoReflectionTypeBuilder *tb = NULL;
2159 MonoClass *klass = NULL;
2164 MONO_ARCH_SAVE_REGS;
2166 if (!System_Reflection_MonoGenericClass) {
2167 System_Reflection_MonoGenericClass = mono_class_from_name (
2168 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2169 g_assert (System_Reflection_MonoGenericClass);
2172 domain = mono_object_domain (type);
2174 g_assert (type->type.type->data.generic_class->is_dynamic);
2175 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2177 if (!strcmp (type->generic_type->object.vtable->klass->name, "TypeBuilder")) {
2178 tb = (MonoReflectionTypeBuilder *) type->generic_type;
2179 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2181 klass = gclass->generic_class.generic_class.container_class;
2182 mono_class_init (klass);
2183 icount = klass->interface_count;
2186 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2188 for (i = 0; i < icount; i++) {
2189 MonoReflectionType *iface;
2193 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2196 it = &klass->interfaces [i]->byval_arg;
2198 it = mono_class_inflate_generic_type (
2199 it, gclass->generic_class.generic_class.context);
2201 iface = mono_type_get_object (domain, it);
2202 mono_array_setref (res, i, iface);
2208 static MonoReflectionMethod*
2209 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2210 MonoReflectionMethod* generic)
2212 MonoGenericClass *gclass;
2213 MonoDynamicGenericClass *dgclass;
2217 MONO_ARCH_SAVE_REGS;
2219 gclass = type->type.type->data.generic_class;
2220 g_assert (gclass->is_dynamic);
2222 dgclass = (MonoDynamicGenericClass *) gclass;
2224 domain = mono_object_domain (type);
2226 for (i = 0; i < dgclass->count_methods; i++)
2227 if (generic->method->token == dgclass->methods [i]->token)
2228 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2233 static MonoReflectionMethod*
2234 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2235 MonoReflectionMethod* generic)
2237 MonoGenericClass *gclass;
2238 MonoDynamicGenericClass *dgclass;
2242 MONO_ARCH_SAVE_REGS;
2244 gclass = type->type.type->data.generic_class;
2245 g_assert (gclass->is_dynamic);
2247 dgclass = (MonoDynamicGenericClass *) gclass;
2249 domain = mono_object_domain (type);
2251 for (i = 0; i < dgclass->count_ctors; i++)
2252 if (generic->method->token == dgclass->ctors [i]->token)
2253 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2259 static MonoReflectionField*
2260 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2261 MonoString* generic_name)
2263 MonoGenericClass *gclass;
2264 MonoDynamicGenericClass *dgclass;
2266 MonoClass *refclass;
2267 char *utf8_name = mono_string_to_utf8 (generic_name);
2270 MONO_ARCH_SAVE_REGS;
2272 gclass = type->type.type->data.generic_class;
2273 g_assert (gclass->is_dynamic);
2275 dgclass = (MonoDynamicGenericClass *) gclass;
2277 refclass = mono_class_from_mono_type (type->type.type);
2279 domain = mono_object_domain (type);
2281 for (i = 0; i < dgclass->count_fields; i++)
2282 if (strcmp (utf8_name, dgclass->fields [i].name) == 0) {
2284 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2293 static MonoReflectionMethod*
2294 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2295 MonoReflectionMethod* generic)
2302 MONO_ARCH_SAVE_REGS;
2304 domain = ((MonoObject *)type)->vtable->domain;
2306 klass = mono_class_from_mono_type (type->type);
2309 while ((method = mono_class_get_methods (klass, &iter))) {
2310 if (method->token == generic->method->token)
2311 return mono_method_get_object (domain, method, klass);
2318 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2319 MonoReflectionType *reflected_type)
2321 MonoGenericClass *gclass;
2322 MonoDynamicGenericClass *dgclass;
2324 MonoClass *refclass;
2328 MONO_ARCH_SAVE_REGS;
2330 gclass = type->type.type->data.generic_class;
2331 g_assert (gclass->is_dynamic);
2332 dgclass = (MonoDynamicGenericClass *) gclass;
2334 refclass = mono_class_from_mono_type (reflected_type->type);
2336 domain = mono_object_domain (type);
2337 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2339 for (i = 0; i < dgclass->count_methods; i++)
2340 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2346 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2347 MonoReflectionType *reflected_type)
2349 static MonoClass *System_Reflection_ConstructorInfo;
2350 MonoGenericClass *gclass;
2351 MonoDynamicGenericClass *dgclass;
2353 MonoClass *refclass;
2357 MONO_ARCH_SAVE_REGS;
2359 if (!System_Reflection_ConstructorInfo)
2360 System_Reflection_ConstructorInfo = mono_class_from_name (
2361 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2363 gclass = type->type.type->data.generic_class;
2364 g_assert (gclass->is_dynamic);
2365 dgclass = (MonoDynamicGenericClass *) gclass;
2367 refclass = mono_class_from_mono_type (reflected_type->type);
2369 domain = mono_object_domain (type);
2370 res = mono_array_new (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2372 for (i = 0; i < dgclass->count_ctors; i++)
2373 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2379 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2380 MonoReflectionType *reflected_type)
2382 MonoGenericClass *gclass;
2383 MonoDynamicGenericClass *dgclass;
2385 MonoClass *refclass;
2389 MONO_ARCH_SAVE_REGS;
2391 gclass = type->type.type->data.generic_class;
2392 g_assert (gclass->is_dynamic);
2393 dgclass = (MonoDynamicGenericClass *) gclass;
2395 refclass = mono_class_from_mono_type (reflected_type->type);
2397 domain = mono_object_domain (type);
2398 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2400 for (i = 0; i < dgclass->count_fields; i++)
2401 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2407 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2408 MonoReflectionType *reflected_type)
2410 static MonoClass *System_Reflection_PropertyInfo;
2411 MonoGenericClass *gclass;
2412 MonoDynamicGenericClass *dgclass;
2414 MonoClass *refclass;
2418 MONO_ARCH_SAVE_REGS;
2420 if (!System_Reflection_PropertyInfo)
2421 System_Reflection_PropertyInfo = mono_class_from_name (
2422 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2424 gclass = type->type.type->data.generic_class;
2425 g_assert (gclass->is_dynamic);
2426 dgclass = (MonoDynamicGenericClass *) gclass;
2428 refclass = mono_class_from_mono_type (reflected_type->type);
2430 domain = mono_object_domain (type);
2431 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2433 for (i = 0; i < dgclass->count_properties; i++)
2434 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2440 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2441 MonoReflectionType *reflected_type)
2443 static MonoClass *System_Reflection_EventInfo;
2444 MonoGenericClass *gclass;
2445 MonoDynamicGenericClass *dgclass;
2447 MonoClass *refclass;
2451 MONO_ARCH_SAVE_REGS;
2453 if (!System_Reflection_EventInfo)
2454 System_Reflection_EventInfo = mono_class_from_name (
2455 mono_defaults.corlib, "System.Reflection", "EventInfo");
2457 gclass = type->type.type->data.generic_class;
2458 g_assert (gclass->is_dynamic);
2459 dgclass = (MonoDynamicGenericClass *) gclass;
2461 refclass = mono_class_from_mono_type (reflected_type->type);
2463 domain = mono_object_domain (type);
2464 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2466 for (i = 0; i < dgclass->count_events; i++)
2467 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2472 static MonoReflectionMethod *
2473 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2478 MONO_ARCH_SAVE_REGS;
2480 if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2483 method = type->type->data.generic_param->method;
2485 klass = mono_class_from_mono_type (type->type);
2486 return mono_method_get_object (mono_object_domain (type), method, klass);
2489 static MonoReflectionDllImportAttribute*
2490 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2492 static MonoClass *DllImportAttributeClass = NULL;
2493 MonoDomain *domain = mono_domain_get ();
2494 MonoReflectionDllImportAttribute *attr;
2495 MonoImage *image = method->klass->image;
2496 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2497 MonoTableInfo *tables = image->tables;
2498 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2499 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2500 guint32 im_cols [MONO_IMPLMAP_SIZE];
2501 guint32 scope_token;
2502 const char *import = NULL;
2503 const char *scope = NULL;
2506 if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2509 if (!DllImportAttributeClass) {
2510 DllImportAttributeClass =
2511 mono_class_from_name (mono_defaults.corlib,
2512 "System.Runtime.InteropServices", "DllImportAttribute");
2513 g_assert (DllImportAttributeClass);
2516 if (method->klass->image->dynamic) {
2517 MonoReflectionMethodAux *method_aux =
2518 g_hash_table_lookup (
2519 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2521 import = method_aux->dllentry;
2522 scope = method_aux->dll;
2526 if (piinfo->implmap_idx) {
2527 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2529 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2530 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2531 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2532 scope = mono_metadata_string_heap (image, scope_token);
2535 flags = piinfo->piflags;
2537 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2539 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2540 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2541 attr->call_conv = (flags & 0x700) >> 8;
2542 attr->charset = ((flags & 0x6) >> 1) + 1;
2543 if (attr->charset == 1)
2545 attr->exact_spelling = (flags & 0x1) != 0;
2546 attr->set_last_error = (flags & 0x40) != 0;
2547 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2548 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2549 attr->preserve_sig = FALSE;
2554 static MonoReflectionMethod *
2555 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2557 MonoMethodInflated *imethod;
2559 MONO_ARCH_SAVE_REGS;
2561 if (!method->method->is_inflated) {
2562 if (mono_method_signature (method->method)->generic_param_count)
2568 imethod = (MonoMethodInflated *) method->method;
2569 if (imethod->context->gmethod && imethod->context->gmethod->reflection_info)
2570 return imethod->context->gmethod->reflection_info;
2572 return mono_method_get_object (
2573 mono_object_domain (method), imethod->declaring, NULL);
2577 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2579 MONO_ARCH_SAVE_REGS;
2581 return mono_method_signature (method->method)->generic_param_count != 0;
2585 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2587 MONO_ARCH_SAVE_REGS;
2589 return !method->method->is_inflated &&
2590 (mono_method_signature (method->method)->generic_param_count != 0);
2594 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2599 MONO_ARCH_SAVE_REGS;
2601 domain = mono_object_domain (method);
2603 if (method->method->is_inflated) {
2604 MonoMethodInflated *imethod = (MonoMethodInflated *) method->method;
2605 MonoGenericMethod *gmethod = imethod->context->gmethod;
2608 count = gmethod->inst->type_argc;
2609 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2611 for (i = 0; i < count; i++)
2612 mono_array_setref (res, i, mono_type_get_object (domain, gmethod->inst->type_argv [i]));
2618 count = mono_method_signature (method->method)->generic_param_count;
2619 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2621 for (i = 0; i < count; i++) {
2622 MonoGenericParam *param = &method->method->generic_container->type_params [i];
2623 MonoClass *pklass = mono_class_from_generic_parameter (
2624 param, method->method->klass->image, TRUE);
2625 mono_array_setref (res, i,
2626 mono_type_get_object (domain, &pklass->byval_arg));
2633 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params)
2636 * Invoke from reflection is supposed to always be a virtual call (the API
2637 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2638 * greater flexibility.
2640 MonoMethod *m = mono_get_inflated_method (method->method);
2644 MONO_ARCH_SAVE_REGS;
2646 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2648 if (!mono_object_isinst (this, m->klass))
2649 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetException"));
2650 m = mono_object_get_virtual_method (this, m);
2651 /* must pass the pointer to the value for valuetype methods */
2652 if (m->klass->valuetype)
2653 obj = mono_object_unbox (this);
2654 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type)
2655 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetException"));
2658 pcount = params? mono_array_length (params): 0;
2659 if (pcount != mono_method_signature (m)->param_count)
2660 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2662 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor"))
2663 mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", "Cannot invoke constructor of an abstract class."));
2665 if (m->klass->image->assembly->ref_only)
2666 mono_raise_exception (mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2668 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2671 guint32 *lower_bounds;
2672 pcount = mono_array_length (params);
2673 lengths = alloca (sizeof (guint32) * pcount);
2674 for (i = 0; i < pcount; ++i)
2675 lengths [i] = *(gint32*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2677 if (m->klass->rank == pcount) {
2678 /* Only lengths provided. */
2679 lower_bounds = NULL;
2681 g_assert (pcount == (m->klass->rank * 2));
2682 /* lower bounds are first. */
2683 lower_bounds = lengths;
2684 lengths += m->klass->rank;
2687 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2689 return mono_runtime_invoke_array (m, obj, params, NULL);
2693 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2695 MonoDomain *domain = mono_object_domain (method);
2696 MonoMethod *m = method->method;
2697 MonoMethodSignature *sig = mono_method_signature (m);
2698 MonoArray *out_args;
2700 int i, j, outarg_count = 0;
2702 MONO_ARCH_SAVE_REGS;
2704 if (m->klass == mono_defaults.object_class) {
2706 if (!strcmp (m->name, "FieldGetter")) {
2707 MonoClass *k = this->vtable->klass;
2711 /* If this is a proxy, then it must be a CBO */
2712 if (k == mono_defaults.transparent_proxy_class) {
2713 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2714 this = tp->rp->unwrapped_server;
2716 k = this->vtable->klass;
2719 name = mono_array_get (params, MonoString *, 1);
2720 str = mono_string_to_utf8 (name);
2723 MonoClassField* field = mono_class_get_field_from_name (k, str);
2725 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2726 if (field_klass->valuetype)
2727 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2729 result = *((gpointer *)((char *)this + field->offset));
2731 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2732 *outArgs = out_args;
2733 mono_array_setref (out_args, 0, result);
2741 g_assert_not_reached ();
2743 } else if (!strcmp (m->name, "FieldSetter")) {
2744 MonoClass *k = this->vtable->klass;
2749 /* If this is a proxy, then it must be a CBO */
2750 if (k == mono_defaults.transparent_proxy_class) {
2751 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2752 this = tp->rp->unwrapped_server;
2754 k = this->vtable->klass;
2757 name = mono_array_get (params, MonoString *, 1);
2758 str = mono_string_to_utf8 (name);
2761 MonoClassField* field = mono_class_get_field_from_name (k, str);
2763 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2764 MonoObject *val = mono_array_get (params, gpointer, 2);
2766 if (field_klass->valuetype) {
2767 size = mono_type_size (field->type, &align);
2768 memcpy ((char *)this + field->offset,
2769 ((char *)val) + sizeof (MonoObject), size);
2771 *(MonoObject**)((char *)this + field->offset) = val;
2773 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2774 *outArgs = out_args;
2784 g_assert_not_reached ();
2789 for (i = 0; i < mono_array_length (params); i++) {
2790 if (sig->params [i]->byref)
2794 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2796 /* handle constructors only for objects already allocated */
2797 if (!strcmp (method->method->name, ".ctor"))
2800 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2801 g_assert (!method->method->klass->valuetype);
2802 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2804 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2805 if (sig->params [i]->byref) {
2807 arg = mono_array_get (params, gpointer, i);
2808 mono_array_setref (out_args, j, arg);
2813 *outArgs = out_args;
2819 read_enum_value (char *mem, int type)
2823 return *(guint8*)mem;
2825 return *(gint8*)mem;
2827 return *(guint16*)mem;
2829 return *(gint16*)mem;
2831 return *(guint32*)mem;
2833 return *(gint32*)mem;
2835 return *(guint64*)mem;
2837 return *(gint64*)mem;
2839 g_assert_not_reached ();
2845 write_enum_value (char *mem, int type, guint64 value)
2849 case MONO_TYPE_I1: {
2850 guint8 *p = (guint8*)mem;
2855 case MONO_TYPE_I2: {
2856 guint16 *p = (void*)mem;
2861 case MONO_TYPE_I4: {
2862 guint32 *p = (void*)mem;
2867 case MONO_TYPE_I8: {
2868 guint64 *p = (void*)mem;
2873 g_assert_not_reached ();
2879 ves_icall_System_Enum_ToObject (MonoReflectionType *type, MonoObject *obj)
2882 MonoClass *enumc, *objc;
2886 MONO_ARCH_SAVE_REGS;
2888 MONO_CHECK_ARG_NULL (type);
2889 MONO_CHECK_ARG_NULL (obj);
2891 domain = mono_object_domain (type);
2892 enumc = mono_class_from_mono_type (type->type);
2893 objc = obj->vtable->klass;
2895 if (!enumc->enumtype)
2896 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
2897 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
2898 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."));
2900 res = mono_object_new (domain, enumc);
2901 val = read_enum_value ((char *)obj + sizeof (MonoObject), objc->enumtype? objc->enum_basetype->type: objc->byval_arg.type);
2902 write_enum_value ((char *)res + sizeof (MonoObject), enumc->enum_basetype->type, val);
2908 ves_icall_System_Enum_get_value (MonoObject *this)
2916 MONO_ARCH_SAVE_REGS;
2921 g_assert (this->vtable->klass->enumtype);
2923 enumc = mono_class_from_mono_type (this->vtable->klass->enum_basetype);
2924 res = mono_object_new (mono_object_domain (this), enumc);
2925 dst = (char *)res + sizeof (MonoObject);
2926 src = (char *)this + sizeof (MonoObject);
2927 size = mono_class_value_size (enumc, NULL);
2929 memcpy (dst, src, size);
2935 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
2937 MonoDomain *domain = mono_object_domain (type);
2938 MonoClass *enumc = mono_class_from_mono_type (type->type);
2939 guint j = 0, nvalues, crow;
2941 MonoClassField *field;
2943 MONO_ARCH_SAVE_REGS;
2945 info->utype = mono_type_get_object (domain, enumc->enum_basetype);
2946 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
2947 info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
2948 info->values = mono_array_new (domain, enumc, nvalues);
2952 while ((field = mono_class_get_fields (enumc, &iter))) {
2956 if (strcmp ("value__", field->name) == 0)
2958 if (mono_field_is_deleted (field))
2960 mono_array_setref (info->names, j, mono_string_new (domain, field->name));
2963 crow = mono_metadata_get_constant_index (enumc->image, mono_class_get_field_token (field), crow + 1);
2964 field->def_type = mono_metadata_decode_row_col (&enumc->image->tables [MONO_TABLE_CONSTANT], crow-1, MONO_CONSTANT_TYPE);
2965 crow = mono_metadata_decode_row_col (&enumc->image->tables [MONO_TABLE_CONSTANT], crow-1, MONO_CONSTANT_VALUE);
2966 field->data = (gpointer)mono_metadata_blob_heap (enumc->image, crow);
2970 len = mono_metadata_decode_blob_size (p, &p);
2971 switch (enumc->enum_basetype->type) {
2974 mono_array_set (info->values, gchar, j, *p);
2976 case MONO_TYPE_CHAR:
2979 mono_array_set (info->values, gint16, j, read16 (p));
2983 mono_array_set (info->values, gint32, j, read32 (p));
2987 mono_array_set (info->values, gint64, j, read64 (p));
2990 g_error ("Implement type 0x%02x in get_enum_info", enumc->enum_basetype->type);
2997 BFLAGS_IgnoreCase = 1,
2998 BFLAGS_DeclaredOnly = 2,
2999 BFLAGS_Instance = 4,
3001 BFLAGS_Public = 0x10,
3002 BFLAGS_NonPublic = 0x20,
3003 BFLAGS_FlattenHierarchy = 0x40,
3004 BFLAGS_InvokeMethod = 0x100,
3005 BFLAGS_CreateInstance = 0x200,
3006 BFLAGS_GetField = 0x400,
3007 BFLAGS_SetField = 0x800,
3008 BFLAGS_GetProperty = 0x1000,
3009 BFLAGS_SetProperty = 0x2000,
3010 BFLAGS_ExactBinding = 0x10000,
3011 BFLAGS_SuppressChangeType = 0x20000,
3012 BFLAGS_OptionalParamBinding = 0x40000
3015 static MonoReflectionField *
3016 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3019 MonoClass *startklass, *klass;
3021 MonoClassField *field;
3024 int (*compare_func) (const char *s1, const char *s2) = NULL;
3025 domain = ((MonoObject *)type)->vtable->domain;
3026 klass = startklass = mono_class_from_mono_type (type->type);
3028 MONO_ARCH_SAVE_REGS;
3031 mono_raise_exception (mono_get_exception_argument_null ("name"));
3032 if (type->type->byref)
3035 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3039 while ((field = mono_class_get_fields (klass, &iter))) {
3041 if (mono_field_is_deleted (field))
3043 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3044 if (bflags & BFLAGS_Public)
3047 if (bflags & BFLAGS_NonPublic)
3053 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3054 if (bflags & BFLAGS_Static)
3055 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3058 if (bflags & BFLAGS_Instance)
3065 utf8_name = mono_string_to_utf8 (name);
3067 if (compare_func (field->name, utf8_name)) {
3073 return mono_field_get_object (domain, klass, field);
3075 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3082 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3085 MonoClass *startklass, *klass, *refklass;
3090 MonoClassField *field;
3092 MONO_ARCH_SAVE_REGS;
3094 domain = ((MonoObject *)type)->vtable->domain;
3095 if (type->type->byref)
3096 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3097 klass = startklass = mono_class_from_mono_type (type->type);
3098 refklass = mono_class_from_mono_type (reftype->type);
3102 res = mono_array_new (domain, mono_defaults.field_info_class, len);
3105 while ((field = mono_class_get_fields (klass, &iter))) {
3107 if (mono_field_is_deleted (field))
3109 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3110 if (bflags & BFLAGS_Public)
3113 if (bflags & BFLAGS_NonPublic)
3119 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3120 if (bflags & BFLAGS_Static)
3121 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3124 if (bflags & BFLAGS_Instance)
3130 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3132 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, len * 2);
3133 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3137 mono_array_setref (res, i, member);
3140 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3143 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, i);
3144 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3147 * Better solution for the new GC.
3148 * res->max_length = i;
3155 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3158 MonoClass *startklass, *klass, *refklass;
3163 int i, len, match, nslots;
3164 guint32 method_slots_default [8];
3165 guint32 *method_slots;
3166 gchar *mname = NULL;
3167 int (*compare_func) (const char *s1, const char *s2) = NULL;
3169 MONO_ARCH_SAVE_REGS;
3171 domain = ((MonoObject *)type)->vtable->domain;
3172 if (type->type->byref)
3173 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3174 klass = startklass = mono_class_from_mono_type (type->type);
3175 refklass = mono_class_from_mono_type (reftype->type);
3178 mname = mono_string_to_utf8 (name);
3179 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3182 mono_class_setup_vtable (klass);
3184 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3185 if (nslots >= sizeof (method_slots_default) * 8) {
3186 method_slots = g_new0 (guint32, nslots / 32 + 1);
3188 method_slots = method_slots_default;
3189 memset (method_slots, 0, sizeof (method_slots_default));
3193 res = mono_array_new (domain, mono_defaults.method_info_class, len);
3195 mono_class_setup_vtable (klass);
3197 while ((method = mono_class_get_methods (klass, &iter))) {
3199 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3201 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3202 if (bflags & BFLAGS_Public)
3205 if (bflags & BFLAGS_NonPublic)
3211 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3212 if (bflags & BFLAGS_Static)
3213 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3216 if (bflags & BFLAGS_Instance)
3224 if (compare_func (mname, method->name))
3229 if (method->slot != -1) {
3230 g_assert (method->slot < nslots);
3231 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3233 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3236 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3239 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, len * 2);
3240 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3244 mono_array_setref (res, i, member);
3247 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3251 if (method_slots != method_slots_default)
3252 g_free (method_slots);
3254 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, i);
3255 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3258 * Better solution for the new GC.
3259 * res->max_length = i;
3266 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3269 static MonoClass *System_Reflection_ConstructorInfo;
3270 MonoClass *startklass, *klass, *refklass;
3275 gpointer iter = NULL;
3277 MONO_ARCH_SAVE_REGS;
3279 domain = ((MonoObject *)type)->vtable->domain;
3280 if (type->type->byref)
3281 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3282 klass = startklass = mono_class_from_mono_type (type->type);
3283 refklass = mono_class_from_mono_type (reftype->type);
3285 if (!System_Reflection_ConstructorInfo)
3286 System_Reflection_ConstructorInfo = mono_class_from_name (
3287 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3291 res = mono_array_new (domain, System_Reflection_ConstructorInfo, len);
3293 while ((method = mono_class_get_methods (klass, &iter))) {
3295 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3297 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3298 if (bflags & BFLAGS_Public)
3301 if (bflags & BFLAGS_NonPublic)
3307 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3308 if (bflags & BFLAGS_Static)
3309 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3312 if (bflags & BFLAGS_Instance)
3318 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3321 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, len * 2);
3322 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3326 mono_array_setref (res, i, member);
3330 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, i);
3331 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3334 * Better solution for the new GC.
3335 * res->max_length = i;
3342 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3345 static MonoClass *System_Reflection_PropertyInfo;
3346 MonoClass *startklass, *klass;
3350 int i, match, nslots;
3353 guint32 method_slots_default [8];
3354 guint32 *method_slots;
3355 gchar *propname = NULL;
3356 int (*compare_func) (const char *s1, const char *s2) = NULL;
3359 MONO_ARCH_SAVE_REGS;
3361 if (!System_Reflection_PropertyInfo)
3362 System_Reflection_PropertyInfo = mono_class_from_name (
3363 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3365 domain = ((MonoObject *)type)->vtable->domain;
3366 if (type->type->byref)
3367 return mono_array_new (domain, System_Reflection_PropertyInfo, 0);
3368 klass = startklass = mono_class_from_mono_type (type->type);
3370 propname = mono_string_to_utf8 (name);
3371 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3374 mono_class_setup_vtable (klass);
3376 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3377 if (nslots >= sizeof (method_slots_default) * 8) {
3378 method_slots = g_new0 (guint32, nslots / 32 + 1);
3380 method_slots = method_slots_default;
3381 memset (method_slots, 0, sizeof (method_slots_default));
3385 res = mono_array_new (domain, System_Reflection_PropertyInfo, len);
3387 mono_class_setup_vtable (klass);
3389 while ((prop = mono_class_get_properties (klass, &iter))) {
3395 flags = method->flags;
3398 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3399 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3400 if (bflags & BFLAGS_Public)
3403 if (bflags & BFLAGS_NonPublic)
3409 if (flags & METHOD_ATTRIBUTE_STATIC) {
3410 if (bflags & BFLAGS_Static)
3411 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3414 if (bflags & BFLAGS_Instance)
3423 if (compare_func (propname, prop->name))
3427 if (prop->get && prop->get->slot != -1) {
3428 if (method_slots [prop->get->slot >> 5] & (1 << (prop->get->slot & 0x1f)))
3430 method_slots [prop->get->slot >> 5] |= 1 << (prop->get->slot & 0x1f);
3432 if (prop->set && prop->set->slot != -1) {
3433 if (method_slots [prop->set->slot >> 5] & (1 << (prop->set->slot & 0x1f)))
3435 method_slots [prop->set->slot >> 5] |= 1 << (prop->set->slot & 0x1f);
3439 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, len * 2);
3440 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3444 mono_array_setref (res, i, mono_property_get_object (domain, startklass, prop));
3447 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3451 if (method_slots != method_slots_default)
3452 g_free (method_slots);
3454 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, i);
3455 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3458 * Better solution for the new GC.
3459 * res->max_length = i;
3465 static MonoReflectionEvent *
3466 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3469 MonoClass *klass, *startklass;
3475 MONO_ARCH_SAVE_REGS;
3477 event_name = mono_string_to_utf8 (name);
3478 if (type->type->byref)
3480 klass = startklass = mono_class_from_mono_type (type->type);
3481 domain = mono_object_domain (type);
3485 while ((event = mono_class_get_events (klass, &iter))) {
3486 if (strcmp (event->name, event_name))
3489 method = event->add;
3491 method = event->remove;
3493 method = event->raise;
3495 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3496 if (!(bflags & BFLAGS_Public))
3499 if (!(bflags & BFLAGS_NonPublic))
3504 if (!(bflags & BFLAGS_NonPublic))
3507 g_free (event_name);
3508 return mono_event_get_object (domain, startklass, event);
3511 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3514 g_free (event_name);
3519 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3522 static MonoClass *System_Reflection_EventInfo;
3523 MonoClass *startklass, *klass;
3530 MONO_ARCH_SAVE_REGS;
3532 if (!System_Reflection_EventInfo)
3533 System_Reflection_EventInfo = mono_class_from_name (
3534 mono_defaults.corlib, "System.Reflection", "EventInfo");
3536 domain = mono_object_domain (type);
3537 if (type->type->byref)
3538 return mono_array_new (domain, System_Reflection_EventInfo, 0);
3539 klass = startklass = mono_class_from_mono_type (type->type);
3543 res = mono_array_new (domain, System_Reflection_EventInfo, len);
3546 while ((event = mono_class_get_events (klass, &iter))) {
3548 method = event->add;
3550 method = event->remove;
3552 method = event->raise;
3554 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3555 if (bflags & BFLAGS_Public)
3558 if (bflags & BFLAGS_NonPublic)
3563 if (bflags & BFLAGS_NonPublic)
3569 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3570 if (bflags & BFLAGS_Static)
3571 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3574 if (bflags & BFLAGS_Instance)
3579 if (bflags & BFLAGS_Instance)
3585 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, len * 2);
3586 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3590 mono_array_setref (res, i, mono_event_get_object (domain, startklass, event));
3593 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3596 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, i);
3597 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3600 * Better solution for the new GC.
3601 * res->max_length = i;
3607 static MonoReflectionType *
3608 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3611 MonoClass *startklass, *klass;
3616 MONO_ARCH_SAVE_REGS;
3618 domain = ((MonoObject *)type)->vtable->domain;
3619 if (type->type->byref)
3621 klass = startklass = mono_class_from_mono_type (type->type);
3622 str = mono_string_to_utf8 (name);
3625 for (tmpn = klass->nested_classes; tmpn; tmpn = tmpn->next) {
3627 nested = tmpn->data;
3628 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3629 if (bflags & BFLAGS_Public)
3632 if (bflags & BFLAGS_NonPublic)
3637 if (strcmp (nested->name, str) == 0){
3639 return mono_type_get_object (domain, &nested->byval_arg);
3642 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3649 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
3653 MonoClass *startklass, *klass;
3659 MONO_ARCH_SAVE_REGS;
3661 domain = ((MonoObject *)type)->vtable->domain;
3662 if (type->type->byref)
3663 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3664 klass = startklass = mono_class_from_mono_type (type->type);
3668 res = mono_array_new (domain, mono_defaults.monotype_class, len);
3669 for (tmpn = klass->nested_classes; tmpn; tmpn = tmpn->next) {
3671 nested = tmpn->data;
3672 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3673 if (bflags & BFLAGS_Public)
3676 if (bflags & BFLAGS_NonPublic)
3681 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
3683 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, len * 2);
3684 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3688 mono_array_setref (res, i, member);
3692 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, i);
3693 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3696 * Better solution for the new GC.
3697 * res->max_length = i;
3703 static MonoReflectionType*
3704 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
3707 MonoType *type = NULL;
3708 MonoTypeNameParse info;
3709 gboolean type_resolve;
3711 MONO_ARCH_SAVE_REGS;
3713 /* On MS.NET, this does not fire a TypeResolve event */
3714 type_resolve = TRUE;
3715 str = mono_string_to_utf8 (name);
3716 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
3717 if (!mono_reflection_parse_type (str, &info)) {
3719 g_list_free (info.modifiers);
3720 g_list_free (info.nested);
3721 if (throwOnError) /* uhm: this is a parse error, though... */
3722 mono_raise_exception (mono_get_exception_type_load (name, NULL));
3723 /*g_print ("failed parse\n");*/
3727 if (module != NULL) {
3729 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
3734 if (assembly->assembly->dynamic) {
3735 /* Enumerate all modules */
3736 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
3740 if (abuilder->modules) {
3741 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
3742 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
3743 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
3749 if (!type && abuilder->loaded_modules) {
3750 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
3751 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
3752 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
3759 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
3761 g_list_free (info.modifiers);
3762 g_list_free (info.nested);
3765 mono_raise_exception (mono_get_exception_type_load (name, NULL));
3766 /* g_print ("failed find\n"); */
3770 if (type->type == MONO_TYPE_CLASS) {
3771 MonoClass *klass = mono_type_get_class (type);
3772 /* need to report exceptions ? */
3773 if (throwOnError && klass->exception_type) {
3774 /* report SecurityException (or others) that occured when loading the assembly */
3775 MonoException *exc = mono_class_get_exception_for_failure (klass);
3776 mono_raise_exception (exc);
3777 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
3782 /* g_print ("got it\n"); */
3783 return mono_type_get_object (mono_object_domain (assembly), type);
3787 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
3789 MonoDomain *domain = mono_object_domain (assembly);
3790 MonoAssembly *mass = assembly->assembly;
3791 MonoString *res = NULL;
3795 MONO_ARCH_SAVE_REGS;
3797 if (g_path_is_absolute (mass->image->name))
3798 absolute = g_strdup (mass->image->name);
3800 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
3804 for (i = strlen (absolute) - 1; i >= 0; i--)
3805 if (absolute [i] == '\\')
3810 uri = g_filename_to_uri (absolute, NULL, NULL);
3812 uri = g_strconcat ("file://", absolute, NULL);
3816 res = mono_string_new (domain, uri);
3824 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
3826 MonoAssembly *mass = assembly->assembly;
3828 MONO_ARCH_SAVE_REGS;
3830 return mass->in_gac;
3833 static MonoReflectionAssembly*
3834 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
3838 MonoImageOpenStatus status;
3840 MONO_ARCH_SAVE_REGS;
3842 name = mono_string_to_utf8 (mname);
3843 res = mono_assembly_load_with_partial_name (name, &status);
3849 return mono_assembly_get_object (mono_domain_get (), res);
3853 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
3855 MonoDomain *domain = mono_object_domain (assembly);
3858 MONO_ARCH_SAVE_REGS;
3860 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
3866 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
3868 MONO_ARCH_SAVE_REGS;
3870 return assembly->assembly->ref_only;
3874 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
3876 MonoDomain *domain = mono_object_domain (assembly);
3878 MONO_ARCH_SAVE_REGS;
3880 return mono_string_new (domain, assembly->assembly->image->version);
3883 static MonoReflectionMethod*
3884 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
3886 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
3888 MONO_ARCH_SAVE_REGS;
3892 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
3895 static MonoReflectionModule*
3896 ves_icall_System_Reflection_Assembly_get_ManifestModule (MonoReflectionAssembly *assembly)
3898 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
3902 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
3904 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
3905 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
3909 MONO_ARCH_SAVE_REGS;
3911 for (i = 0; i < table->rows; ++i) {
3912 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
3913 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
3919 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
3921 static MonoClass *System_Version = NULL;
3922 static MonoMethod *create_version = NULL;
3926 if (!System_Version) {
3927 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
3928 g_assert (System_Version);
3931 if (!create_version) {
3932 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
3933 create_version = mono_method_desc_search_in_class (desc, System_Version);
3934 g_assert (create_version);
3935 mono_method_desc_free (desc);
3941 args [3] = &revision;
3942 result = mono_object_new (domain, System_Version);
3943 mono_runtime_invoke (create_version, result, args, NULL);
3949 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
3951 static MonoClass *System_Reflection_AssemblyName;
3953 MonoDomain *domain = mono_object_domain (assembly);
3955 static MonoMethod *create_culture = NULL;
3956 MonoImage *image = assembly->assembly->image;
3959 MONO_ARCH_SAVE_REGS;
3961 if (!System_Reflection_AssemblyName)
3962 System_Reflection_AssemblyName = mono_class_from_name (
3963 mono_defaults.corlib, "System.Reflection", "AssemblyName");
3965 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
3968 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
3971 MonoMethodDesc *desc = mono_method_desc_new (
3972 "System.Globalization.CultureInfo:CreateSpecificCulture(string)", TRUE);
3973 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
3974 g_assert (create_culture);
3975 mono_method_desc_free (desc);
3978 for (i = 0; i < count; i++) {
3979 MonoReflectionAssemblyName *aname;
3980 guint32 cols [MONO_ASSEMBLYREF_SIZE];
3982 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
3984 aname = (MonoReflectionAssemblyName *) mono_object_new (
3985 domain, System_Reflection_AssemblyName);
3987 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
3989 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
3990 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
3991 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
3992 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
3993 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
3994 aname->versioncompat = 1; /* SameMachine (default) */
3995 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
3996 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
3998 if (create_culture) {
4000 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4001 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4004 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4005 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4006 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4008 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4009 /* public key token isn't copied - the class library will
4010 automatically generate it from the public key if required */
4011 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4012 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4014 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4015 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4019 /* note: this function doesn't return the codebase on purpose (i.e. it can
4020 be used under partial trust as path information isn't present). */
4022 mono_array_setref (result, i, aname);
4033 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4035 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4037 mono_array_setref (info->res, info->idx, name);
4042 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4044 MonoImage *img = assembly->assembly->image;
4048 MONO_ARCH_SAVE_REGS;
4050 if (!img->name_cache)
4051 mono_image_init_name_cache (img);
4053 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4056 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4061 /* move this in some file in mono/util/ */
4063 g_concat_dir_and_file (const char *dir, const char *file)
4065 g_return_val_if_fail (dir != NULL, NULL);
4066 g_return_val_if_fail (file != NULL, NULL);
4069 * If the directory name doesn't have a / on the end, we need
4070 * to add one so we get a proper path to the file
4072 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4073 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4075 return g_strconcat (dir, file, NULL);
4079 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4081 char *n = mono_string_to_utf8 (name);
4082 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4084 guint32 cols [MONO_MANIFEST_SIZE];
4085 guint32 impl, file_idx;
4089 MONO_ARCH_SAVE_REGS;
4091 for (i = 0; i < table->rows; ++i) {
4092 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4093 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4094 if (strcmp (val, n) == 0)
4098 if (i == table->rows)
4101 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4104 * this code should only be called after obtaining the
4105 * ResourceInfo and handling the other cases.
4107 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4108 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4110 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4115 module = assembly->assembly->image;
4117 *ref_module = mono_module_get_object (mono_domain_get (), module);
4119 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4123 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4125 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4127 guint32 cols [MONO_MANIFEST_SIZE];
4128 guint32 file_cols [MONO_FILE_SIZE];
4132 MONO_ARCH_SAVE_REGS;
4134 n = mono_string_to_utf8 (name);
4135 for (i = 0; i < table->rows; ++i) {
4136 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4137 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4138 if (strcmp (val, n) == 0)
4142 if (i == table->rows)
4145 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4146 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4149 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4150 case MONO_IMPLEMENTATION_FILE:
4151 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4152 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4153 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4154 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4155 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4156 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4159 info->location = RESOURCE_LOCATION_EMBEDDED;
4162 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4163 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4164 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4165 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4166 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4167 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4169 mono_raise_exception (ex);
4171 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4173 /* Obtain info recursively */
4174 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4175 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4178 case MONO_IMPLEMENTATION_EXP_TYPE:
4179 g_assert_not_reached ();
4188 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4190 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4191 MonoArray *result = NULL;
4196 MONO_ARCH_SAVE_REGS;
4198 /* check hash if needed */
4200 n = mono_string_to_utf8 (name);
4201 for (i = 0; i < table->rows; ++i) {
4202 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4203 if (strcmp (val, n) == 0) {
4206 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4207 fn = mono_string_new (mono_object_domain (assembly), n);
4209 return (MonoObject*)fn;
4217 for (i = 0; i < table->rows; ++i) {
4218 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4222 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4225 for (i = 0; i < table->rows; ++i) {
4226 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4227 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4228 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4229 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4234 return (MonoObject*)result;
4238 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4240 MonoDomain *domain = mono_domain_get();
4243 int i, j, file_count = 0;
4244 MonoImage **modules;
4245 guint32 module_count, real_module_count;
4246 MonoTableInfo *table;
4248 g_assert (assembly->assembly->image != NULL);
4250 if (assembly->assembly->dynamic) {
4251 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)assembly;
4253 if (assemblyb->modules)
4254 module_count = mono_array_length (assemblyb->modules);
4257 real_module_count = module_count;
4259 modules = g_new0 (MonoImage*, module_count);
4260 if (assemblyb->modules) {
4261 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4263 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i)->module.image;
4268 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4269 file_count = table->rows;
4271 modules = assembly->assembly->image->modules;
4272 module_count = assembly->assembly->image->module_count;
4274 real_module_count = 0;
4275 for (i = 0; i < module_count; ++i)
4277 real_module_count ++;
4280 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4281 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4283 mono_array_setref (res, 0, mono_module_get_object (domain, assembly->assembly->image));
4285 for (i = 0; i < module_count; ++i)
4287 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4291 for (i = 0; i < file_count; ++i, ++j)
4292 mono_array_setref (res, j, mono_module_file_get_object (domain, assembly->assembly->image, i));
4294 if (assembly->assembly->dynamic)
4300 static MonoReflectionMethod*
4301 ves_icall_GetCurrentMethod (void)
4303 MonoMethod *m = mono_method_get_last_managed ();
4305 MONO_ARCH_SAVE_REGS;
4307 return mono_method_get_object (mono_domain_get (), m, NULL);
4310 static MonoReflectionMethod*
4311 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4313 return mono_method_get_object (mono_domain_get (), method, NULL);
4316 static MonoReflectionMethodBody*
4317 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4319 return mono_method_body_get_object (mono_domain_get (), method);
4322 static MonoReflectionAssembly*
4323 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4325 MonoMethod *m = mono_method_get_last_managed ();
4327 MONO_ARCH_SAVE_REGS;
4329 return mono_assembly_get_object (mono_domain_get (), m->klass->image->assembly);
4333 static MonoReflectionAssembly*
4334 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4336 MonoDomain* domain = mono_domain_get ();
4338 MONO_ARCH_SAVE_REGS;
4340 if (!domain->entry_assembly)
4343 return mono_assembly_get_object (domain, domain->entry_assembly);
4346 static MonoReflectionAssembly*
4347 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4349 MonoMethod *m = mono_method_get_last_managed ();
4350 MonoMethod *dest = m;
4352 MONO_ARCH_SAVE_REGS;
4354 mono_stack_walk_no_il (get_caller, &dest);
4357 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4361 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4362 gboolean assembly_qualified)
4364 MonoDomain *domain = mono_object_domain (object);
4365 MonoTypeNameFormat format;
4369 MONO_ARCH_SAVE_REGS;
4371 format = assembly_qualified ?
4372 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4373 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4375 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4377 name = mono_type_get_name_full (object->type, format);
4381 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR))
4384 res = mono_string_new (domain, name);
4391 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version)
4393 static MonoMethod *create_culture = NULL;
4396 const char *pkey_ptr;
4399 MONO_ARCH_SAVE_REGS;
4401 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4402 aname->major = name->major;
4403 aname->minor = name->minor;
4404 aname->build = name->build;
4405 aname->revision = name->revision;
4406 aname->hashalg = name->hash_alg;
4407 if (by_default_version)
4408 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4410 codebase = g_filename_to_uri (absolute, NULL, NULL);
4412 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4416 if (!create_culture) {
4417 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateSpecificCulture(string)", TRUE);
4418 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4419 g_assert (create_culture);
4420 mono_method_desc_free (desc);
4423 if (name->culture) {
4424 args [0] = mono_string_new (domain, name->culture);
4425 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4428 if (name->public_key) {
4429 pkey_ptr = (char*)name->public_key;
4430 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4432 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4433 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4436 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4437 if (name->public_key_token [0]) {
4441 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4442 p = mono_array_addr (aname->keyToken, char, 0);
4444 for (i = 0, j = 0; i < 8; i++) {
4445 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4446 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4453 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4456 MonoAssembly *mass = assembly->assembly;
4458 MONO_ARCH_SAVE_REGS;
4460 if (g_path_is_absolute (mass->image->name)) {
4461 fill_reflection_assembly_name (mono_object_domain (assembly),
4462 aname, &mass->aname, mass->image->name, TRUE);
4465 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4467 fill_reflection_assembly_name (mono_object_domain (assembly),
4468 aname, &mass->aname, absolute, TRUE);
4474 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4477 MonoImageOpenStatus status = MONO_IMAGE_OK;
4480 MonoAssemblyName name;
4482 MONO_ARCH_SAVE_REGS;
4484 filename = mono_string_to_utf8 (fname);
4486 image = mono_image_open (filename, &status);
4492 exc = mono_get_exception_file_not_found (fname);
4493 mono_raise_exception (exc);
4496 res = mono_assembly_fill_assembly_name (image, &name);
4498 mono_image_close (image);
4500 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4503 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE);
4506 mono_image_close (image);
4510 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
4511 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
4513 MonoBoolean result = FALSE;
4514 MonoDeclSecurityEntry entry;
4516 /* SecurityAction.RequestMinimum */
4517 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
4518 *minimum = entry.blob;
4519 *minLength = entry.size;
4522 /* SecurityAction.RequestOptional */
4523 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
4524 *optional = entry.blob;
4525 *optLength = entry.size;
4528 /* SecurityAction.RequestRefuse */
4529 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
4530 *refused = entry.blob;
4531 *refLength = entry.size;
4539 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoBoolean exportedOnly)
4543 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
4545 guint32 attrs, visibility;
4547 /* we start the count from 1 because we skip the special type <Module> */
4550 for (i = 1; i < tdef->rows; ++i) {
4551 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
4552 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4553 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
4557 count = tdef->rows - 1;
4559 res = mono_array_new (domain, mono_defaults.monotype_class, count);
4561 for (i = 1; i < tdef->rows; ++i) {
4562 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
4563 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4564 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
4565 klass = mono_class_get_throw (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
4566 if (mono_loader_get_last_error ())
4567 mono_loader_clear_error ();
4568 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
4577 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
4579 MonoArray *res = NULL;
4580 MonoImage *image = NULL;
4581 MonoTableInfo *table = NULL;
4586 MONO_ARCH_SAVE_REGS;
4588 domain = mono_object_domain (assembly);
4590 if (assembly->assembly->dynamic) {
4591 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4592 if (abuilder->modules) {
4593 for (i = 0; i < mono_array_length(abuilder->modules); i++) {
4594 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4595 MonoArray *append = mb->types;
4596 /* The types array might not be fully filled up */
4597 if (append && mb->num_types > 0) {
4600 len1 = res ? mono_array_length (res) : 0;
4601 len2 = mb->num_types;
4602 new = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
4604 mono_array_memcpy_refs (new, 0, res, 0, len1);
4605 mono_array_memcpy_refs (new, len1, append, 0, len2);
4611 * Replace TypeBuilders with the created types to be compatible
4615 for (i = 0; i < mono_array_length (res); ++i) {
4616 MonoReflectionTypeBuilder *tb = mono_array_get (res, MonoReflectionTypeBuilder*, i);
4618 mono_array_setref (res, i, tb->created);
4623 if (abuilder->loaded_modules)
4624 for (i = 0; i < mono_array_length(abuilder->loaded_modules); i++) {
4625 MonoReflectionModule *rm = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4626 MonoArray *append = mono_module_get_types (domain, rm->image, exportedOnly);
4627 if (append && mono_array_length (append) > 0) {
4630 len1 = res ? mono_array_length (res) : 0;
4631 len2 = mono_array_length (append);
4632 new = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
4634 mono_array_memcpy_refs (new, 0, res, 0, len1);
4635 mono_array_memcpy_refs (new, len1, append, 0, len2);
4642 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4644 image = assembly->assembly->image;
4645 table = &image->tables [MONO_TABLE_FILE];
4646 res = mono_module_get_types (domain, image, exportedOnly);
4648 /* Append data from all modules in the assembly */
4649 for (i = 0; i < table->rows; ++i) {
4650 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4651 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
4653 MonoArray *res2 = mono_module_get_types (domain, loaded_image, exportedOnly);
4654 /* Append the new types to the end of the array */
4655 if (mono_array_length (res2) > 0) {
4659 len1 = mono_array_length (res);
4660 len2 = mono_array_length (res2);
4661 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
4662 mono_array_memcpy_refs (res3, 0, res, 0, len1);
4663 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
4670 /* the ReflectionTypeLoadException must have all the types (Types property),
4671 * NULL replacing types which throws an exception. The LoaderException must
4672 * contain all exceptions for NULL items.
4675 len = mono_array_length (res);
4677 for (i = 0; i < len; i++) {
4678 MonoReflectionType *t = mono_array_get (res, gpointer, i);
4679 MonoClass *klass = mono_type_get_class (t->type);
4680 if ((klass != NULL) && klass->exception_type) {
4681 /* keep the class in the list */
4682 list = g_list_append (list, klass);
4683 /* and replace Type with NULL */
4684 mono_array_setref (res, i, NULL);
4690 MonoException *exc = NULL;
4691 MonoArray *exl = NULL;
4692 int length = g_list_length (list);
4694 mono_loader_clear_error ();
4696 exl = mono_array_new (domain, mono_defaults.exception_class, length);
4697 for (i = 0, tmp = list; i < length; i++, tmp = tmp->next) {
4698 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
4699 mono_array_setref (exl, i, exc);
4704 exc = mono_get_exception_reflection_type_load (res, exl);
4705 mono_raise_exception (exc);
4712 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
4714 MonoAssemblyName aname;
4715 MonoDomain *domain = mono_object_domain (name);
4717 gboolean is_version_defined;
4719 val = mono_string_to_utf8 (assname);
4720 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined))
4723 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined);
4725 mono_assembly_name_free (&aname);
4726 g_free ((guint8*) aname.public_key);
4732 static MonoReflectionType*
4733 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
4735 MonoDomain *domain = mono_object_domain (module);
4738 MONO_ARCH_SAVE_REGS;
4740 g_assert (module->image);
4742 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
4743 /* These images do not have a global type */
4746 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
4747 return mono_type_get_object (domain, &klass->byval_arg);
4751 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
4753 /*if (module->image)
4754 mono_image_close (module->image);*/
4758 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
4760 MonoDomain *domain = mono_object_domain (module);
4762 MONO_ARCH_SAVE_REGS;
4764 g_assert (module->image);
4765 return mono_string_new (domain, module->image->guid);
4769 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
4771 if (image->dynamic) {
4772 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
4773 *pe_kind = dyn->pe_kind;
4774 *machine = dyn->machine;
4777 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
4778 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
4783 ves_icall_System_Reflection_Module_get_MDStreamVersion (MonoReflectionModule *module)
4785 MonoImage *image = module->image;
4788 mono_raise_exception (mono_get_exception_not_supported (""));
4790 return (image->md_version_major << 16) | (image->md_version_minor);
4794 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
4796 MONO_ARCH_SAVE_REGS;
4799 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
4801 return mono_module_get_types (mono_object_domain (module), module->image, FALSE);
4805 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
4807 guint32 cols [MONO_MEMBERREF_SIZE];
4809 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
4810 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
4811 mono_metadata_decode_blob_size (sig, &sig);
4812 return (*sig != 0x6);
4816 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
4819 int table = mono_metadata_token_table (token);
4820 int index = mono_metadata_token_index (token);
4822 *error = ResolveTokenError_Other;
4824 /* Validate token */
4825 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
4826 (table != MONO_TABLE_TYPESPEC)) {
4827 *error = ResolveTokenError_BadTable;
4832 return mono_lookup_dynamic_token (image, token);
4834 if ((index <= 0) || (index > image->tables [table].rows)) {
4835 *error = ResolveTokenError_OutOfRange;
4839 klass = mono_class_get (image, token);
4841 return &klass->byval_arg;
4847 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
4849 int table = mono_metadata_token_table (token);
4850 int index = mono_metadata_token_index (token);
4852 *error = ResolveTokenError_Other;
4854 /* Validate token */
4855 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
4856 (table != MONO_TABLE_MEMBERREF)) {
4857 *error = ResolveTokenError_BadTable;
4862 /* FIXME: validate memberref token type */
4863 return mono_lookup_dynamic_token (image, token);
4865 if ((index <= 0) || (index > image->tables [table].rows)) {
4866 *error = ResolveTokenError_OutOfRange;
4869 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
4870 *error = ResolveTokenError_BadTable;
4874 return mono_get_method (image, token, NULL);
4878 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
4880 int index = mono_metadata_token_index (token);
4882 *error = ResolveTokenError_Other;
4884 /* Validate token */
4885 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
4886 *error = ResolveTokenError_BadTable;
4891 return mono_lookup_dynamic_token (image, token);
4893 if ((index <= 0) || (index >= image->heap_us.size)) {
4894 *error = ResolveTokenError_OutOfRange;
4898 /* FIXME: What to do if the index points into the middle of a string ? */
4900 return mono_ldstr (mono_domain_get (), image, index);
4903 static MonoClassField*
4904 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
4907 int table = mono_metadata_token_table (token);
4908 int index = mono_metadata_token_index (token);
4910 *error = ResolveTokenError_Other;
4912 /* Validate token */
4913 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
4914 *error = ResolveTokenError_BadTable;
4919 /* FIXME: validate memberref token type */
4920 return mono_lookup_dynamic_token (image, token);
4922 if ((index <= 0) || (index > image->tables [table].rows)) {
4923 *error = ResolveTokenError_OutOfRange;
4926 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
4927 *error = ResolveTokenError_BadTable;
4931 return mono_field_from_token (image, token, &klass, NULL);
4936 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
4938 int table = mono_metadata_token_table (token);
4940 *error = ResolveTokenError_Other;
4943 case MONO_TABLE_TYPEDEF:
4944 case MONO_TABLE_TYPEREF:
4945 case MONO_TABLE_TYPESPEC: {
4946 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, error);
4948 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
4952 case MONO_TABLE_METHOD:
4953 case MONO_TABLE_METHODSPEC: {
4954 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, error);
4956 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
4960 case MONO_TABLE_FIELD: {
4961 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, error);
4963 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
4967 case MONO_TABLE_MEMBERREF:
4968 if (mono_metadata_memberref_is_method (image, token)) {
4969 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, error);
4971 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
4976 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, error);
4978 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
4985 *error = ResolveTokenError_BadTable;
4991 static MonoReflectionType*
4992 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
4995 int isbyref = 0, rank;
4996 char *str = mono_string_to_utf8 (smodifiers);
4999 MONO_ARCH_SAVE_REGS;
5001 klass = mono_class_from_mono_type (tb->type.type);
5003 /* logic taken from mono_reflection_parse_type(): keep in sync */
5007 if (isbyref) { /* only one level allowed by the spec */
5014 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5017 klass = mono_ptr_class_get (&klass->byval_arg);
5018 mono_class_init (klass);
5029 else if (*p != '*') { /* '*' means unknown lower bound */
5040 klass = mono_array_class_get (klass, rank);
5041 mono_class_init (klass);
5048 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5052 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5057 MONO_ARCH_SAVE_REGS;
5060 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5065 static MonoReflectionType *
5066 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5068 MonoClass *klass, *aklass;
5070 MONO_ARCH_SAVE_REGS;
5072 klass = mono_class_from_mono_type (type->type);
5073 aklass = mono_array_class_get (klass, rank);
5075 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5078 static MonoReflectionType *
5079 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5083 MONO_ARCH_SAVE_REGS;
5085 klass = mono_class_from_mono_type (type->type);
5087 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5090 static MonoReflectionType *
5091 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5095 MONO_ARCH_SAVE_REGS;
5097 pklass = mono_ptr_class_get (type->type);
5099 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5103 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5104 MonoReflectionMethod *info)
5106 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5107 MonoObject *delegate;
5110 MONO_ARCH_SAVE_REGS;
5112 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5114 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5116 func = mono_compile_method (info->method);
5118 mono_delegate_ctor (delegate, target, func);
5124 ves_icall_System_Delegate_FreeTrampoline (MonoDelegate *this)
5127 Delegates have a finalizer only when needed, now.
5128 mono_delegate_free_ftnptr (this);*/
5132 * Magic number to convert a time which is relative to
5133 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5135 #define EPOCH_ADJUST ((guint64)62135596800LL)
5138 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5140 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5143 * This returns Now in UTC
5146 ves_icall_System_DateTime_GetNow (void)
5148 #ifdef PLATFORM_WIN32
5152 GetSystemTime (&st);
5153 SystemTimeToFileTime (&st, &ft);
5154 return (gint64) FILETIME_ADJUST + ((((gint64)ft.dwHighDateTime)<<32) | ft.dwLowDateTime);
5156 /* FIXME: put this in io-layer and call it GetLocalTime */
5160 MONO_ARCH_SAVE_REGS;
5162 if (gettimeofday (&tv, NULL) == 0) {
5163 res = (((gint64)tv.tv_sec + EPOCH_ADJUST)* 1000000 + tv.tv_usec)*10;
5166 /* fixme: raise exception */
5171 #ifdef PLATFORM_WIN32
5172 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5174 convert_to_absolute_date(SYSTEMTIME *date)
5176 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5177 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5178 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5179 /* from the calendar FAQ */
5180 int a = (14 - date->wMonth) / 12;
5181 int y = date->wYear - a;
5182 int m = date->wMonth + 12 * a - 2;
5183 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5185 /* d is now the day of the week for the first of the month (0 == Sunday) */
5187 int day_of_week = date->wDayOfWeek;
5189 /* set day_in_month to the first day in the month which falls on day_of_week */
5190 int day_in_month = 1 + (day_of_week - d);
5191 if (day_in_month <= 0)
5194 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5195 date->wDay = day_in_month + (date->wDay - 1) * 7;
5196 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5201 #ifndef PLATFORM_WIN32
5203 * Return's the offset from GMT of a local time.
5205 * tm is a local time
5206 * t is the same local time as seconds.
5209 gmt_offset(struct tm *tm, time_t t)
5211 #if defined (HAVE_TM_GMTOFF)
5212 return tm->tm_gmtoff;
5217 g.tm_isdst = tm->tm_isdst;
5219 return (int)difftime(t, t2);
5224 * This is heavily based on zdump.c from glibc 2.2.
5226 * * data[0]: start of daylight saving time (in DateTime ticks).
5227 * * data[1]: end of daylight saving time (in DateTime ticks).
5228 * * data[2]: utcoffset (in TimeSpan ticks).
5229 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5230 * * name[0]: name of this timezone when not daylight saving.
5231 * * name[1]: name of this timezone when daylight saving.
5233 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5234 * the class library allows years between 1 and 9999.
5236 * Returns true on success and zero on failure.
5239 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5241 #ifndef PLATFORM_WIN32
5242 MonoDomain *domain = mono_domain_get ();
5243 struct tm start, tt;
5247 int is_daylight = 0, day;
5250 MONO_ARCH_SAVE_REGS;
5252 MONO_CHECK_ARG_NULL (data);
5253 MONO_CHECK_ARG_NULL (names);
5255 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
5256 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
5259 * no info is better than crashing: we'll need our own tz data
5260 * to make this work properly, anyway. The range is probably
5261 * reduced to 1970 .. 2037 because that is what mktime is
5262 * guaranteed to support (we get into an infinite loop
5266 memset (&start, 0, sizeof (start));
5269 start.tm_year = year-1900;
5271 t = mktime (&start);
5273 if ((year < 1970) || (year > 2037) || (t == -1)) {
5275 tt = *localtime (&t);
5276 strftime (tzone, sizeof (tzone), "%Z", &tt);
5277 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5278 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5282 gmtoff = gmt_offset (&start, t);
5284 /* For each day of the year, calculate the tm_gmtoff. */
5285 for (day = 0; day < 365; day++) {
5288 tt = *localtime (&t);
5290 /* Daylight saving starts or ends here. */
5291 if (gmt_offset (&tt, t) != gmtoff) {
5295 /* Try to find the exact hour when daylight saving starts/ends. */
5299 tt1 = *localtime (&t1);
5300 } while (gmt_offset (&tt1, t1) != gmtoff);
5302 /* Try to find the exact minute when daylight saving starts/ends. */
5305 tt1 = *localtime (&t1);
5306 } while (gmt_offset (&tt1, t1) == gmtoff);
5308 strftime (tzone, sizeof (tzone), "%Z", &tt);
5310 /* Write data, if we're already in daylight saving, we're done. */
5312 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5313 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5316 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5317 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5321 /* This is only set once when we enter daylight saving. */
5322 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5323 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5325 gmtoff = gmt_offset (&tt, t);
5330 strftime (tzone, sizeof (tzone), "%Z", &tt);
5331 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5332 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5333 mono_array_set ((*data), gint64, 0, 0);
5334 mono_array_set ((*data), gint64, 1, 0);
5335 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5336 mono_array_set ((*data), gint64, 3, 0);
5341 MonoDomain *domain = mono_domain_get ();
5342 TIME_ZONE_INFORMATION tz_info;
5347 tz_id = GetTimeZoneInformation (&tz_info);
5348 if (tz_id == TIME_ZONE_ID_INVALID)
5351 MONO_CHECK_ARG_NULL (data);
5352 MONO_CHECK_ARG_NULL (names);
5354 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
5355 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
5357 for (i = 0; i < 32; ++i)
5358 if (!tz_info.DaylightName [i])
5360 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
5361 for (i = 0; i < 32; ++i)
5362 if (!tz_info.StandardName [i])
5364 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
5366 if ((year <= 1601) || (year > 30827)) {
5368 * According to MSDN, the MS time functions can't handle dates outside
5374 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
5375 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
5376 tz_info.StandardDate.wYear = year;
5377 convert_to_absolute_date(&tz_info.StandardDate);
5378 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
5380 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5381 tz_info.DaylightDate.wYear = year;
5382 convert_to_absolute_date(&tz_info.DaylightDate);
5383 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
5385 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5387 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
5388 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
5395 ves_icall_System_Object_obj_address (MonoObject *this)
5397 MONO_ARCH_SAVE_REGS;
5404 static inline gint32
5405 mono_array_get_byte_length (MonoArray *array)
5411 klass = array->obj.vtable->klass;
5413 if (array->bounds == NULL)
5414 length = array->max_length;
5417 for (i = 0; i < klass->rank; ++ i)
5418 length *= array->bounds [i].length;
5421 switch (klass->element_class->byval_arg.type) {
5424 case MONO_TYPE_BOOLEAN:
5428 case MONO_TYPE_CHAR:
5436 return length * sizeof (gpointer);
5447 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
5449 MONO_ARCH_SAVE_REGS;
5451 return mono_array_get_byte_length (array);
5455 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
5457 MONO_ARCH_SAVE_REGS;
5459 return mono_array_get (array, gint8, idx);
5463 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
5465 MONO_ARCH_SAVE_REGS;
5467 mono_array_set (array, gint8, idx, value);
5471 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
5473 guint8 *src_buf, *dest_buf;
5475 MONO_ARCH_SAVE_REGS;
5477 /* watch out for integer overflow */
5478 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
5481 src_buf = (guint8 *)src->vector + src_offset;
5482 dest_buf = (guint8 *)dest->vector + dest_offset;
5485 memcpy (dest_buf, src_buf, count);
5487 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
5493 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
5495 MonoDomain *domain = mono_object_domain (this);
5497 MonoRealProxy *rp = ((MonoRealProxy *)this);
5498 MonoTransparentProxy *tp;
5502 MONO_ARCH_SAVE_REGS;
5504 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
5505 tp = (MonoTransparentProxy*) res;
5507 MONO_OBJECT_SETREF (tp, rp, rp);
5508 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
5509 klass = mono_class_from_mono_type (type);
5511 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
5512 tp->remote_class = mono_remote_class (domain, class_name, klass);
5514 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
5518 static MonoReflectionType *
5519 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
5521 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
5524 /* System.Environment */
5527 ves_icall_System_Environment_get_MachineName (void)
5529 #if defined (PLATFORM_WIN32)
5534 len = MAX_COMPUTERNAME_LENGTH + 1;
5535 buf = g_new (gunichar2, len);
5538 if (GetComputerName (buf, (PDWORD) &len))
5539 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
5547 if (gethostname (buf, sizeof (buf)) == 0)
5548 result = mono_string_new (mono_domain_get (), buf);
5557 ves_icall_System_Environment_get_Platform (void)
5559 MONO_ARCH_SAVE_REGS;
5561 #if defined (PLATFORM_WIN32)
5571 ves_icall_System_Environment_get_NewLine (void)
5573 MONO_ARCH_SAVE_REGS;
5575 #if defined (PLATFORM_WIN32)
5576 return mono_string_new (mono_domain_get (), "\r\n");
5578 return mono_string_new (mono_domain_get (), "\n");
5583 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
5588 MONO_ARCH_SAVE_REGS;
5593 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5594 value = g_getenv (utf8_name);
5601 return mono_string_new (mono_domain_get (), value);
5605 * There is no standard way to get at environ.
5613 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
5621 MONO_ARCH_SAVE_REGS;
5624 for (e = environ; *e != 0; ++ e)
5627 domain = mono_domain_get ();
5628 names = mono_array_new (domain, mono_defaults.string_class, n);
5631 for (e = environ; *e != 0; ++ e) {
5632 parts = g_strsplit (*e, "=", 2);
5634 str = mono_string_new (domain, *parts);
5635 mono_array_setref (names, n, str);
5647 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
5649 #if !GLIB_CHECK_VERSION(2,4,0)
5650 #define g_setenv(a,b,c) setenv(a,b,c)
5651 #define g_unsetenv(a) unsetenv(a)
5655 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
5657 #ifdef PLATFORM_WIN32
5658 gunichar2 *utf16_name, *utf16_value;
5660 gchar *utf8_name, *utf8_value;
5663 MONO_ARCH_SAVE_REGS;
5665 #ifdef PLATFORM_WIN32
5666 utf16_name = mono_string_to_utf16 (name);
5667 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
5668 SetEnvironmentVariable (utf16_name, NULL);
5669 g_free (utf16_name);
5673 utf16_value = mono_string_to_utf16 (value);
5675 SetEnvironmentVariable (utf16_name, utf16_value);
5677 g_free (utf16_name);
5678 g_free (utf16_value);
5680 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5682 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
5683 g_unsetenv (utf8_name);
5688 utf8_value = mono_string_to_utf8 (value);
5689 g_setenv (utf8_name, utf8_value, TRUE);
5692 g_free (utf8_value);
5697 * Returns: the number of milliseconds elapsed since the system started.
5700 ves_icall_System_Environment_get_TickCount (void)
5702 return GetTickCount ();
5707 ves_icall_System_Environment_Exit (int result)
5709 MONO_ARCH_SAVE_REGS;
5711 mono_runtime_set_shutting_down ();
5713 /* Suspend all managed threads since the runtime is going away */
5714 mono_thread_suspend_all_other_threads ();
5716 mono_runtime_quit ();
5718 /* we may need to do some cleanup here... */
5723 ves_icall_System_Environment_GetGacPath (void)
5725 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
5729 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
5731 #if defined (PLATFORM_WIN32)
5732 #ifndef CSIDL_FLAG_CREATE
5733 #define CSIDL_FLAG_CREATE 0x8000
5736 WCHAR path [MAX_PATH];
5737 /* Create directory if no existing */
5738 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
5742 return mono_string_new_utf16 (mono_domain_get (), path, len);
5745 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
5747 return mono_string_new (mono_domain_get (), "");
5751 ves_icall_System_Environment_GetLogicalDrives (void)
5753 gunichar2 buf [128], *ptr, *dname;
5755 gint initial_size = 127, size = 128;
5758 MonoString *drivestr;
5759 MonoDomain *domain = mono_domain_get ();
5762 MONO_ARCH_SAVE_REGS;
5767 while (size > initial_size) {
5768 size = GetLogicalDriveStrings (initial_size, ptr);
5769 if (size > initial_size) {
5772 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
5773 initial_size = size;
5787 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
5792 while (*u16) { u16++; len ++; }
5793 drivestr = mono_string_new_utf16 (domain, dname, len);
5794 mono_array_setref (result, ndrives++, drivestr);
5805 ves_icall_System_Environment_InternalGetHome (void)
5807 MONO_ARCH_SAVE_REGS;
5809 return mono_string_new (mono_domain_get (), g_get_home_dir ());
5812 static const char *encodings [] = {
5814 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
5815 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
5816 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
5818 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
5819 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
5820 "x_unicode_2_0_utf_7",
5822 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
5823 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
5825 "utf_16", "UTF_16LE", "ucs_2", "unicode",
5828 "unicodefffe", "utf_16be",
5835 * Returns the internal codepage, if the value of "int_code_page" is
5836 * 1 at entry, and we can not compute a suitable code page number,
5837 * returns the code page as a string
5840 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
5845 char *codepage = NULL;
5847 int want_name = *int_code_page;
5850 *int_code_page = -1;
5851 MONO_ARCH_SAVE_REGS;
5853 g_get_charset (&cset);
5854 c = codepage = strdup (cset);
5855 for (c = codepage; *c; c++){
5856 if (isascii (*c) && isalpha (*c))
5861 /* g_print ("charset: %s\n", cset); */
5863 /* handle some common aliases */
5866 for (i = 0; p != 0; ){
5867 if ((gssize) p < 7){
5869 p = encodings [++i];
5872 if (strcmp (p, codepage) == 0){
5873 *int_code_page = code;
5876 p = encodings [++i];
5879 if (strstr (codepage, "utf_8") != NULL)
5880 *int_code_page |= 0x10000000;
5883 if (want_name && *int_code_page == -1)
5884 return mono_string_new (mono_domain_get (), cset);
5890 ves_icall_System_Environment_get_HasShutdownStarted (void)
5892 if (mono_runtime_is_shutting_down ())
5895 if (mono_domain_is_unloading (mono_domain_get ()))
5902 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
5903 MonoReflectionMethod *method,
5904 MonoArray *out_args)
5906 MONO_ARCH_SAVE_REGS;
5908 mono_message_init (mono_object_domain (this), this, method, out_args);
5912 ves_icall_IsTransparentProxy (MonoObject *proxy)
5914 MONO_ARCH_SAVE_REGS;
5919 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
5926 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
5931 MONO_ARCH_SAVE_REGS;
5933 klass = mono_class_from_mono_type (type->type);
5934 vtable = mono_class_vtable (mono_domain_get (), klass);
5936 if (enable) vtable->remote = 1;
5937 else vtable->remote = 0;
5941 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
5946 MONO_ARCH_SAVE_REGS;
5948 domain = mono_object_domain (type);
5949 klass = mono_class_from_mono_type (type->type);
5951 if (klass->rank >= 1) {
5952 g_assert (klass->rank == 1);
5953 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
5955 /* Bypass remoting object creation check */
5956 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
5961 ves_icall_System_IO_get_temp_path (void)
5963 MONO_ARCH_SAVE_REGS;
5965 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
5969 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
5971 MONO_ARCH_SAVE_REGS;
5973 return mono_compile_method (method);
5977 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
5982 MONO_ARCH_SAVE_REGS;
5984 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
5986 #if defined (PLATFORM_WIN32)
5987 /* Avoid mixing '/' and '\\' */
5990 for (i = strlen (path) - 1; i >= 0; i--)
5991 if (path [i] == '/')
5995 mcpath = mono_string_new (mono_domain_get (), path);
6002 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6007 MONO_ARCH_SAVE_REGS;
6009 path = g_path_get_dirname (mono_get_config_dir ());
6011 #if defined (PLATFORM_WIN32)
6012 /* Avoid mixing '/' and '\\' */
6015 for (i = strlen (path) - 1; i >= 0; i--)
6016 if (path [i] == '/')
6020 ipath = mono_string_new (mono_domain_get (), path);
6027 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6029 #if defined (PLATFORM_WIN32)
6030 static void (*output_debug) (gunichar2 *);
6031 static gboolean tried_loading = FALSE;
6033 MONO_ARCH_SAVE_REGS;
6035 if (!tried_loading && output_debug == NULL) {
6038 tried_loading = TRUE;
6039 k32 = g_module_open ("kernel32", G_MODULE_BIND_LAZY);
6041 gchar *error = g_strdup (g_module_error ());
6042 g_warning ("Failed to load kernel32.dll: %s\n", error);
6047 g_module_symbol (k32, "OutputDebugStringW", (gpointer *) &output_debug);
6048 if (!output_debug) {
6049 gchar *error = g_strdup (g_module_error ());
6050 g_warning ("Failed to load OutputDebugStringW: %s\n", error);
6056 if (output_debug == NULL)
6059 output_debug (mono_string_chars (message));
6061 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
6065 /* Only used for value types */
6067 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6072 MONO_ARCH_SAVE_REGS;
6074 domain = mono_object_domain (type);
6075 klass = mono_class_from_mono_type (type->type);
6077 if (mono_class_is_nullable (klass))
6078 /* No arguments -> null */
6081 return mono_object_new (domain, klass);
6084 static MonoReflectionMethod *
6085 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
6087 MonoClass *klass, *parent;
6088 MonoMethod *method = m->method;
6089 MonoMethod *result = NULL;
6091 MONO_ARCH_SAVE_REGS;
6093 if (method->klass == NULL)
6096 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6097 MONO_CLASS_IS_INTERFACE (method->klass) ||
6098 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6101 klass = method->klass;
6102 if (klass->generic_class)
6103 klass = klass->generic_class->container_class;
6105 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6106 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6107 mono_class_setup_vtable (parent);
6108 if (parent->vtable_size <= method->slot)
6113 if (klass == method->klass)
6116 result = klass->vtable [method->slot];
6117 if (result == NULL) {
6118 /* It is an abstract method */
6119 gpointer iter = NULL;
6120 while ((result = mono_class_get_methods (klass, &iter)))
6121 if (result->slot == method->slot)
6128 return mono_method_get_object (mono_domain_get (), result, NULL);
6132 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6134 MONO_ARCH_SAVE_REGS;
6136 iter->sig = *(MonoMethodSignature**)argsp;
6138 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6139 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6142 /* FIXME: it's not documented what start is exactly... */
6146 int i, align, arg_size;
6147 iter->args = argsp + sizeof (gpointer);
6148 #ifndef MONO_ARCH_REGPARMS
6149 for (i = 0; i < iter->sig->sentinelpos; ++i) {
6150 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
6151 iter->args = (char*)iter->args + arg_size;
6155 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6157 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6161 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6163 gint i, align, arg_size;
6165 MONO_ARCH_SAVE_REGS;
6167 i = iter->sig->sentinelpos + iter->next_arg;
6169 g_assert (i < iter->sig->param_count);
6171 res.type = iter->sig->params [i];
6172 res.klass = mono_class_from_mono_type (res.type);
6173 /* FIXME: endianess issue... */
6174 res.value = iter->args;
6175 arg_size = mono_type_stack_size (res.type, &align);
6176 iter->args = (char*)iter->args + arg_size;
6179 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6185 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6187 gint i, align, arg_size;
6189 MONO_ARCH_SAVE_REGS;
6191 i = iter->sig->sentinelpos + iter->next_arg;
6193 g_assert (i < iter->sig->param_count);
6195 while (i < iter->sig->param_count) {
6196 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6198 res.type = iter->sig->params [i];
6199 res.klass = mono_class_from_mono_type (res.type);
6200 /* FIXME: endianess issue... */
6201 res.value = iter->args;
6202 arg_size = mono_type_stack_size (res.type, &align);
6203 iter->args = (char*)iter->args + arg_size;
6205 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6208 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
6217 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
6220 MONO_ARCH_SAVE_REGS;
6222 i = iter->sig->sentinelpos + iter->next_arg;
6224 g_assert (i < iter->sig->param_count);
6226 return iter->sig->params [i];
6230 mono_TypedReference_ToObject (MonoTypedRef tref)
6232 MONO_ARCH_SAVE_REGS;
6234 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
6235 MonoObject** objp = tref.value;
6239 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
6243 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
6245 MONO_ARCH_SAVE_REGS;
6247 if (MONO_TYPE_IS_REFERENCE (type)) {
6248 MonoObject** objp = value;
6252 return mono_value_box (mono_domain_get (), klass, value);
6256 prelink_method (MonoMethod *method)
6258 const char *exc_class, *exc_arg;
6259 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
6261 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
6263 mono_raise_exception(
6264 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
6266 /* create the wrapper, too? */
6270 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
6272 MONO_ARCH_SAVE_REGS;
6273 prelink_method (method->method);
6277 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
6279 MonoClass *klass = mono_class_from_mono_type (type->type);
6281 gpointer iter = NULL;
6282 MONO_ARCH_SAVE_REGS;
6284 while ((m = mono_class_get_methods (klass, &iter)))
6288 /* These parameters are "readonly" in corlib/System/Char.cs */
6290 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
6291 guint8 const **numeric_data,
6292 gdouble const **numeric_data_values,
6293 guint16 const **to_lower_data_low,
6294 guint16 const **to_lower_data_high,
6295 guint16 const **to_upper_data_low,
6296 guint16 const **to_upper_data_high)
6298 *category_data = CategoryData;
6299 *numeric_data = NumericData;
6300 *numeric_data_values = NumericDataValues;
6301 *to_lower_data_low = ToLowerDataLow;
6302 *to_lower_data_high = ToLowerDataHigh;
6303 *to_upper_data_low = ToUpperDataLow;
6304 *to_upper_data_high = ToUpperDataHigh;
6308 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
6310 return method->method->token;
6314 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
6316 MonoCustomAttrInfo *cinfo;
6319 cinfo = mono_reflection_get_custom_attrs_info (obj);
6322 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
6324 mono_custom_attrs_free (cinfo);
6329 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
6331 return mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
6335 GCHandle_CheckCurrentDomain (guint32 gchandle)
6337 return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
6341 ves_icall_Mono_Runtime_GetDisplayName (void)
6343 static const char display_name_str [] = "Mono " VERSION;
6344 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
6345 return display_name;
6350 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
6351 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
6352 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
6353 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
6354 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
6355 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
6356 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
6357 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
6361 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
6366 gunichar2 last, prev_last;
6374 last = prev_last = 0;
6375 for (i = 0; i < ilength; i++) {
6377 if (c >= sizeof (dbase64)) {
6378 exc = mono_exception_from_name_msg (mono_get_corlib (),
6379 "System", "FormatException",
6380 "Invalid character found.");
6381 mono_raise_exception (exc);
6382 } else if (isspace (c)) {
6390 olength = ilength - ignored;
6392 if (allowWhitespaceOnly && olength == 0) {
6393 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
6396 if ((olength & 3) != 0 || olength <= 0) {
6397 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
6398 "FormatException", "Invalid length.");
6399 mono_raise_exception (exc);
6402 olength = (olength * 3) / 4;
6406 if (prev_last == '=')
6409 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
6410 res_ptr = mono_array_addr (result, guchar, 0);
6411 for (i = 0; i < ilength; ) {
6414 for (k = 0; k < 4 && i < ilength;) {
6420 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
6421 exc = mono_exception_from_name_msg (mono_get_corlib (),
6422 "System", "FormatException",
6423 "Invalid character found.");
6424 mono_raise_exception (exc);
6429 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
6431 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
6433 *res_ptr++ = (b [2] << 6) | b [3];
6435 while (i < ilength && isspace (start [i]))
6443 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
6445 MONO_ARCH_SAVE_REGS;
6447 return base64_to_byte_array (mono_string_chars (str),
6448 mono_string_length (str), allowWhitespaceOnly);
6452 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
6454 MONO_ARCH_SAVE_REGS;
6456 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
6460 #define ICALL_TYPE(id,name,first)
6461 #define ICALL(id,name,func) Icall_ ## id,
6464 #include "metadata/icall-def.h"
6470 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
6471 #define ICALL(id,name,func)
6473 #include "metadata/icall-def.h"
6479 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
6480 #define ICALL(id,name,func)
6482 guint16 first_icall;
6485 static const IcallTypeDesc
6486 icall_type_descs [] = {
6487 #include "metadata/icall-def.h"
6491 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
6494 #define ICALL_TYPE(id,name,first)
6497 #ifdef HAVE_ARRAY_ELEM_INIT
6498 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
6499 #define MSGSTRFIELD1(line) str##line
6501 static const struct msgstrtn_t {
6502 #define ICALL(id,name,func)
6504 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
6505 #include "metadata/icall-def.h"
6507 } icall_type_names_str = {
6508 #define ICALL_TYPE(id,name,first) (name),
6509 #include "metadata/icall-def.h"
6512 static const guint16 icall_type_names_idx [] = {
6513 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
6514 #include "metadata/icall-def.h"
6517 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
6519 static const struct msgstr_t {
6521 #define ICALL_TYPE(id,name,first)
6522 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
6523 #include "metadata/icall-def.h"
6525 } icall_names_str = {
6526 #define ICALL(id,name,func) (name),
6527 #include "metadata/icall-def.h"
6530 static const guint16 icall_names_idx [] = {
6531 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
6532 #include "metadata/icall-def.h"
6535 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
6541 #define ICALL_TYPE(id,name,first) name,
6542 #define ICALL(id,name,func)
6543 static const char* const
6544 icall_type_names [] = {
6545 #include "metadata/icall-def.h"
6549 #define icall_type_name_get(id) (icall_type_names [(id)])
6552 #define ICALL(id,name,func) name,
6553 static const char* const
6555 #include "metadata/icall-def.h"
6558 #define icall_name_get(id) icall_names [(id)]
6560 #endif /* !HAVE_ARRAY_ELEM_INIT */
6564 #define ICALL_TYPE(id,name,first)
6565 #define ICALL(id,name,func) func,
6566 static const gconstpointer
6567 icall_functions [] = {
6568 #include "metadata/icall-def.h"
6572 static GHashTable *icall_hash = NULL;
6573 static GHashTable *jit_icall_hash_name = NULL;
6574 static GHashTable *jit_icall_hash_addr = NULL;
6577 mono_icall_init (void)
6581 /* check that tables are sorted: disable in release */
6584 const char *prev_class = NULL;
6585 const char *prev_method;
6587 for (i = 0; i < Icall_type_num; ++i) {
6588 const IcallTypeDesc *desc;
6591 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
6592 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
6593 prev_class = icall_type_name_get (i);
6594 desc = &icall_type_descs [i];
6595 num_icalls = icall_desc_num_icalls (desc);
6596 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
6597 for (j = 0; j < num_icalls; ++j) {
6598 const char *methodn = icall_name_get (desc->first_icall + j);
6599 if (prev_method && strcmp (prev_method, methodn) >= 0)
6600 g_print ("method %s should come before method %s\n", methodn, prev_method);
6601 prev_method = methodn;
6606 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
6610 mono_icall_cleanup (void)
6612 g_hash_table_destroy (icall_hash);
6613 g_hash_table_destroy (jit_icall_hash_name);
6614 g_hash_table_destroy (jit_icall_hash_addr);
6618 mono_add_internal_call (const char *name, gconstpointer method)
6620 mono_loader_lock ();
6622 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
6624 mono_loader_unlock ();
6627 #ifdef HAVE_ARRAY_ELEM_INIT
6629 compare_method_imap (const void *key, const void *elem)
6631 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
6632 return strcmp (key, method_name);
6636 find_method_icall (const IcallTypeDesc *imap, const char *name)
6638 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
6641 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
6645 compare_class_imap (const void *key, const void *elem)
6647 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
6648 return strcmp (key, class_name);
6651 static const IcallTypeDesc*
6652 find_class_icalls (const char *name)
6654 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
6657 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
6662 compare_method_imap (const void *key, const void *elem)
6664 const char** method_name = (const char**)elem;
6665 return strcmp (key, *method_name);
6669 find_method_icall (const IcallTypeDesc *imap, const char *name)
6671 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
6674 return (gpointer)icall_functions [(nameslot - icall_names)];
6678 compare_class_imap (const void *key, const void *elem)
6680 const char** class_name = (const char**)elem;
6681 return strcmp (key, *class_name);
6684 static const IcallTypeDesc*
6685 find_class_icalls (const char *name)
6687 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
6690 return &icall_type_descs [nameslot - icall_type_names];
6696 * we should probably export this as an helper (handle nested types).
6697 * Returns the number of chars written in buf.
6700 concat_class_name (char *buf, int bufsize, MonoClass *klass)
6702 int nspacelen, cnamelen;
6703 nspacelen = strlen (klass->name_space);
6704 cnamelen = strlen (klass->name);
6705 if (nspacelen + cnamelen + 2 > bufsize)
6708 memcpy (buf, klass->name_space, nspacelen);
6709 buf [nspacelen ++] = '.';
6711 memcpy (buf + nspacelen, klass->name, cnamelen);
6712 buf [nspacelen + cnamelen] = 0;
6713 return nspacelen + cnamelen;
6717 mono_lookup_internal_call (MonoMethod *method)
6722 int typelen = 0, mlen, siglen;
6724 const IcallTypeDesc *imap;
6726 g_assert (method != NULL);
6728 if (method->is_inflated)
6729 method = ((MonoMethodInflated *) method)->declaring;
6731 if (method->klass->nested_in) {
6732 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
6736 mname [pos++] = '/';
6739 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
6745 typelen = concat_class_name (mname, sizeof (mname), method->klass);
6750 imap = find_class_icalls (mname);
6752 mname [typelen] = ':';
6753 mname [typelen + 1] = ':';
6755 mlen = strlen (method->name);
6756 memcpy (mname + typelen + 2, method->name, mlen);
6757 sigstart = mname + typelen + 2 + mlen;
6760 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
6761 siglen = strlen (tmpsig);
6762 if (typelen + mlen + siglen + 6 > sizeof (mname))
6765 memcpy (sigstart + 1, tmpsig, siglen);
6766 sigstart [siglen + 1] = ')';
6767 sigstart [siglen + 2] = 0;
6770 mono_loader_lock ();
6772 res = g_hash_table_lookup (icall_hash, mname);
6774 mono_loader_unlock ();
6777 /* try without signature */
6779 res = g_hash_table_lookup (icall_hash, mname);
6781 mono_loader_unlock ();
6785 /* it wasn't found in the static call tables */
6787 mono_loader_unlock ();
6790 res = find_method_icall (imap, sigstart - mlen);
6792 mono_loader_unlock ();
6795 /* try _with_ signature */
6797 res = find_method_icall (imap, sigstart - mlen);
6799 mono_loader_unlock ();
6803 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
6804 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
6805 g_print ("The out of sync library is: %s\n", method->klass->image->name);
6806 g_print ("\nWhen you update one from cvs you need to update, compile and install\nthe other too.\n");
6807 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");
6808 g_print ("If you see other errors or faults after this message they are probably related\n");
6809 g_print ("and you need to fix your mono install first.\n");
6811 mono_loader_unlock ();
6817 type_from_typename (char *typename)
6819 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
6821 if (!strcmp (typename, "int"))
6822 klass = mono_defaults.int_class;
6823 else if (!strcmp (typename, "ptr"))
6824 klass = mono_defaults.int_class;
6825 else if (!strcmp (typename, "void"))
6826 klass = mono_defaults.void_class;
6827 else if (!strcmp (typename, "int32"))
6828 klass = mono_defaults.int32_class;
6829 else if (!strcmp (typename, "uint32"))
6830 klass = mono_defaults.uint32_class;
6831 else if (!strcmp (typename, "long"))
6832 klass = mono_defaults.int64_class;
6833 else if (!strcmp (typename, "ulong"))
6834 klass = mono_defaults.uint64_class;
6835 else if (!strcmp (typename, "float"))
6836 klass = mono_defaults.single_class;
6837 else if (!strcmp (typename, "double"))
6838 klass = mono_defaults.double_class;
6839 else if (!strcmp (typename, "object"))
6840 klass = mono_defaults.object_class;
6841 else if (!strcmp (typename, "obj"))
6842 klass = mono_defaults.object_class;
6845 g_assert_not_reached ();
6847 return &klass->byval_arg;
6850 MonoMethodSignature*
6851 mono_create_icall_signature (const char *sigstr)
6856 MonoMethodSignature *res;
6858 mono_loader_lock ();
6859 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
6861 mono_loader_unlock ();
6865 parts = g_strsplit (sigstr, " ", 256);
6874 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
6877 #ifdef PLATFORM_WIN32
6879 * Under windows, the default pinvoke calling convention is STDCALL but
6882 res->call_convention = MONO_CALL_C;
6885 res->ret = type_from_typename (parts [0]);
6886 for (i = 1; i < len; ++i) {
6887 res->params [i - 1] = type_from_typename (parts [i]);
6892 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
6894 mono_loader_unlock ();
6900 mono_find_jit_icall_by_name (const char *name)
6902 MonoJitICallInfo *info;
6903 g_assert (jit_icall_hash_name);
6905 mono_loader_lock ();
6906 info = g_hash_table_lookup (jit_icall_hash_name, name);
6907 mono_loader_unlock ();
6912 mono_find_jit_icall_by_addr (gconstpointer addr)
6914 MonoJitICallInfo *info;
6915 g_assert (jit_icall_hash_addr);
6917 mono_loader_lock ();
6918 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
6919 mono_loader_unlock ();
6925 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
6927 mono_loader_lock ();
6928 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
6929 mono_loader_unlock ();
6933 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
6935 MonoJitICallInfo *info;
6940 mono_loader_lock ();
6942 if (!jit_icall_hash_name) {
6943 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
6944 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
6947 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
6948 g_warning ("jit icall already defined \"%s\"\n", name);
6949 g_assert_not_reached ();
6952 info = g_new0 (MonoJitICallInfo, 1);
6959 info->wrapper = func;
6961 info->wrapper = NULL;
6964 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
6965 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
6967 mono_loader_unlock ();