5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
22 #ifdef HAVE_SYS_TIME_H
28 #if defined (HOST_WIN32)
31 #if defined (HAVE_WCHAR_H)
35 #include "mono/utils/mono-membar.h"
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/threads.h>
38 #include <mono/metadata/threads-types.h>
39 #include <mono/metadata/threadpool.h>
40 #include <mono/metadata/monitor.h>
41 #include <mono/metadata/reflection.h>
42 #include <mono/metadata/assembly.h>
43 #include <mono/metadata/tabledefs.h>
44 #include <mono/metadata/exception.h>
45 #include <mono/metadata/file-io.h>
46 #include <mono/metadata/console-io.h>
47 #include <mono/metadata/socket-io.h>
48 #include <mono/metadata/mono-endian.h>
49 #include <mono/metadata/tokentype.h>
50 #include <mono/metadata/domain-internals.h>
51 #include <mono/metadata/metadata-internals.h>
52 #include <mono/metadata/class-internals.h>
53 #include <mono/metadata/marshal.h>
54 #include <mono/metadata/gc-internal.h>
55 #include <mono/metadata/mono-gc.h>
56 #include <mono/metadata/rand.h>
57 #include <mono/metadata/sysmath.h>
58 #include <mono/metadata/string-icalls.h>
59 #include <mono/metadata/debug-helpers.h>
60 #include <mono/metadata/process.h>
61 #include <mono/metadata/environment.h>
62 #include <mono/metadata/profiler-private.h>
63 #include <mono/metadata/locales.h>
64 #include <mono/metadata/filewatcher.h>
65 #include <mono/metadata/char-conversions.h>
66 #include <mono/metadata/security.h>
67 #include <mono/metadata/mono-config.h>
68 #include <mono/metadata/cil-coff.h>
69 #include <mono/metadata/number-formatter.h>
70 #include <mono/metadata/security-manager.h>
71 #include <mono/metadata/security-core-clr.h>
72 #include <mono/metadata/mono-perfcounters.h>
73 #include <mono/metadata/mono-debug.h>
74 #include <mono/metadata/mono-ptr-array.h>
75 #include <mono/metadata/verify-internals.h>
76 #include <mono/metadata/runtime.h>
77 #include <mono/io-layer/io-layer.h>
78 #include <mono/utils/strtod.h>
79 #include <mono/utils/monobitset.h>
80 #include <mono/utils/mono-time.h>
81 #include <mono/utils/mono-proclib.h>
82 #include <mono/utils/mono-string.h>
83 #include <mono/utils/mono-error-internals.h>
84 #include <mono/utils/mono-mmap.h>
85 #include <mono/utils/mono-io-portability.h>
86 #include <mono/utils/mono-digest.h>
88 #if defined (HOST_WIN32)
94 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
96 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
99 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
101 static inline MonoBoolean
102 is_generic_parameter (MonoType *type)
104 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
108 mono_class_init_or_throw (MonoClass *klass)
110 if (!mono_class_init (klass))
111 mono_raise_exception (mono_class_get_exception_for_failure (klass));
115 * We expect a pointer to a char, not a string
117 ICALL_EXPORT gboolean
118 mono_double_ParseImpl (char *ptr, double *result)
120 gchar *endptr = NULL;
127 *result = strtod (ptr, &endptr);
130 /* mono_strtod () is not thread-safe */
131 EnterCriticalSection (&mono_strtod_mutex);
132 *result = mono_strtod (ptr, &endptr);
133 LeaveCriticalSection (&mono_strtod_mutex);
137 if (!*ptr || (endptr && *endptr))
143 ICALL_EXPORT MonoObject *
144 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
153 ao = (MonoArray *)this;
154 ac = (MonoClass *)ao->obj.vtable->klass;
156 esize = mono_array_element_size (ac);
157 ea = (gpointer*)((char*)ao->vector + (pos * esize));
159 if (ac->element_class->valuetype)
160 return mono_value_box (this->vtable->domain, ac->element_class, ea);
165 ICALL_EXPORT MonoObject *
166 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
174 MONO_CHECK_ARG_NULL (idxs);
176 io = (MonoArray *)idxs;
177 ic = (MonoClass *)io->obj.vtable->klass;
179 ao = (MonoArray *)this;
180 ac = (MonoClass *)ao->obj.vtable->klass;
182 g_assert (ic->rank == 1);
183 if (io->bounds != NULL || io->max_length != ac->rank)
184 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
186 ind = (gint32 *)io->vector;
188 if (ao->bounds == NULL) {
189 if (*ind < 0 || *ind >= ao->max_length)
190 mono_raise_exception (mono_get_exception_index_out_of_range ());
192 return ves_icall_System_Array_GetValueImpl (this, *ind);
195 for (i = 0; i < ac->rank; i++)
196 if ((ind [i] < ao->bounds [i].lower_bound) ||
197 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
198 mono_raise_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - ao->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos*ao->bounds [i].length + ind [i] -
203 ao->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (this, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
211 MonoClass *ac, *vc, *ec;
223 vc = value->vtable->klass;
227 ac = this->obj.vtable->klass;
228 ec = ac->element_class;
230 esize = mono_array_element_size (ac);
231 ea = (gpointer*)((char*)this->vector + (pos * esize));
232 va = (gpointer*)((char*)value + sizeof (MonoObject));
234 if (mono_class_is_nullable (ec)) {
235 mono_nullable_init ((guint8*)ea, value, ec);
240 mono_gc_bzero (ea, esize);
244 #define NO_WIDENING_CONVERSION G_STMT_START{\
245 mono_raise_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
249 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
250 if (esize < vsize + (extra)) \
251 mono_raise_exception (mono_get_exception_argument ( \
252 "value", "not a widening conversion")); \
255 #define INVALID_CAST G_STMT_START{ \
256 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
257 mono_raise_exception (mono_get_exception_invalid_cast ()); \
260 /* Check element (destination) type. */
261 switch (ec->byval_arg.type) {
262 case MONO_TYPE_STRING:
263 switch (vc->byval_arg.type) {
264 case MONO_TYPE_STRING:
270 case MONO_TYPE_BOOLEAN:
271 switch (vc->byval_arg.type) {
272 case MONO_TYPE_BOOLEAN:
285 NO_WIDENING_CONVERSION;
292 if (!ec->valuetype) {
293 if (!mono_object_isinst (value, ec))
295 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
299 if (mono_object_isinst (value, ec)) {
300 if (ec->has_references)
301 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
303 mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
310 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
312 et = ec->byval_arg.type;
313 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
314 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
316 vt = vc->byval_arg.type;
317 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
318 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
320 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
326 case MONO_TYPE_CHAR: \
327 CHECK_WIDENING_CONVERSION(0); \
328 *(etype *) ea = (etype) u64; \
330 /* You can't assign a signed value to an unsigned array. */ \
335 /* You can't assign a floating point number to an integer array. */ \
338 NO_WIDENING_CONVERSION; \
342 #define ASSIGN_SIGNED(etype) G_STMT_START{\
348 CHECK_WIDENING_CONVERSION(0); \
349 *(etype *) ea = (etype) i64; \
351 /* You can assign an unsigned value to a signed array if the array's */ \
352 /* element size is larger than the value size. */ \
357 case MONO_TYPE_CHAR: \
358 CHECK_WIDENING_CONVERSION(1); \
359 *(etype *) ea = (etype) u64; \
361 /* You can't assign a floating point number to an integer array. */ \
364 NO_WIDENING_CONVERSION; \
368 #define ASSIGN_REAL(etype) G_STMT_START{\
372 CHECK_WIDENING_CONVERSION(0); \
373 *(etype *) ea = (etype) r64; \
375 /* All integer values fit into a floating point array, so we don't */ \
376 /* need to CHECK_WIDENING_CONVERSION here. */ \
381 *(etype *) ea = (etype) i64; \
387 case MONO_TYPE_CHAR: \
388 *(etype *) ea = (etype) u64; \
395 u64 = *(guint8 *) va;
398 u64 = *(guint16 *) va;
401 u64 = *(guint32 *) va;
404 u64 = *(guint64 *) va;
410 i64 = *(gint16 *) va;
413 i64 = *(gint32 *) va;
416 i64 = *(gint64 *) va;
419 r64 = *(gfloat *) va;
422 r64 = *(gdouble *) va;
425 u64 = *(guint16 *) va;
427 case MONO_TYPE_BOOLEAN:
428 /* Boolean is only compatible with itself. */
441 NO_WIDENING_CONVERSION;
448 /* If we can't do a direct copy, let's try a widening conversion. */
451 ASSIGN_UNSIGNED (guint16);
453 ASSIGN_UNSIGNED (guint8);
455 ASSIGN_UNSIGNED (guint16);
457 ASSIGN_UNSIGNED (guint32);
459 ASSIGN_UNSIGNED (guint64);
461 ASSIGN_SIGNED (gint8);
463 ASSIGN_SIGNED (gint16);
465 ASSIGN_SIGNED (gint32);
467 ASSIGN_SIGNED (gint64);
469 ASSIGN_REAL (gfloat);
471 ASSIGN_REAL (gdouble);
475 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
479 #undef NO_WIDENING_CONVERSION
480 #undef CHECK_WIDENING_CONVERSION
481 #undef ASSIGN_UNSIGNED
487 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
495 MONO_CHECK_ARG_NULL (idxs);
497 ic = idxs->obj.vtable->klass;
498 ac = this->obj.vtable->klass;
500 g_assert (ic->rank == 1);
501 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
502 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
504 ind = (gint32 *)idxs->vector;
506 if (this->bounds == NULL) {
507 if (*ind < 0 || *ind >= this->max_length)
508 mono_raise_exception (mono_get_exception_index_out_of_range ());
510 ves_icall_System_Array_SetValueImpl (this, value, *ind);
514 for (i = 0; i < ac->rank; i++)
515 if ((ind [i] < this->bounds [i].lower_bound) ||
516 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
517 mono_raise_exception (mono_get_exception_index_out_of_range ());
519 pos = ind [0] - this->bounds [0].lower_bound;
520 for (i = 1; i < ac->rank; i++)
521 pos = pos * this->bounds [i].length + ind [i] -
522 this->bounds [i].lower_bound;
524 ves_icall_System_Array_SetValueImpl (this, value, pos);
527 ICALL_EXPORT MonoArray *
528 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
530 MonoClass *aklass, *klass;
533 gboolean bounded = FALSE;
537 MONO_CHECK_ARG_NULL (type);
538 MONO_CHECK_ARG_NULL (lengths);
540 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
542 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
544 for (i = 0; i < mono_array_length (lengths); i++)
545 if (mono_array_get (lengths, gint32, i) < 0)
546 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
548 klass = mono_class_from_mono_type (type->type);
549 mono_class_init_or_throw (klass);
551 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
552 /* vectors are not the same as one dimensional arrays with no-zero bounds */
557 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
559 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
560 for (i = 0; i < aklass->rank; ++i) {
561 sizes [i] = mono_array_get (lengths, guint32, i);
563 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
565 sizes [i + aklass->rank] = 0;
568 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
573 ICALL_EXPORT MonoArray *
574 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
576 MonoClass *aklass, *klass;
579 gboolean bounded = FALSE;
583 MONO_CHECK_ARG_NULL (type);
584 MONO_CHECK_ARG_NULL (lengths);
586 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
588 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
590 for (i = 0; i < mono_array_length (lengths); i++)
591 if ((mono_array_get (lengths, gint64, i) < 0) ||
592 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
593 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
595 klass = mono_class_from_mono_type (type->type);
596 mono_class_init_or_throw (klass);
598 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
599 /* vectors are not the same as one dimensional arrays with no-zero bounds */
604 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
606 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
607 for (i = 0; i < aklass->rank; ++i) {
608 sizes [i] = mono_array_get (lengths, guint64, i);
610 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
612 sizes [i + aklass->rank] = 0;
615 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
621 ves_icall_System_Array_GetRank (MonoObject *this)
625 return this->vtable->klass->rank;
629 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
631 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
636 if ((dimension < 0) || (dimension >= rank))
637 mono_raise_exception (mono_get_exception_index_out_of_range ());
639 if (this->bounds == NULL)
640 length = this->max_length;
642 length = this->bounds [dimension].length;
644 #ifdef MONO_BIG_ARRAYS
645 if (length > G_MAXINT32)
646 mono_raise_exception (mono_get_exception_overflow ());
652 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
654 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank))
659 mono_raise_exception (mono_get_exception_index_out_of_range ());
661 if (this->bounds == NULL)
662 return this->max_length;
664 return this->bounds [dimension].length;
668 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
670 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
674 if ((dimension < 0) || (dimension >= rank))
675 mono_raise_exception (mono_get_exception_index_out_of_range ());
677 if (this->bounds == NULL)
680 return this->bounds [dimension].lower_bound;
684 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
686 int sz = mono_array_element_size (mono_object_class (arr));
687 mono_gc_bzero (mono_array_addr_with_size (arr, sz, idx), length * sz);
690 ICALL_EXPORT gboolean
691 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
696 MonoClass *src_class;
697 MonoClass *dest_class;
701 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
704 if (source->bounds || dest->bounds)
707 /* there's no integer overflow since mono_array_length returns an unsigned integer */
708 if ((dest_idx + length > mono_array_length (dest)) ||
709 (source_idx + length > mono_array_length (source)))
712 src_class = source->obj.vtable->klass->element_class;
713 dest_class = dest->obj.vtable->klass->element_class;
716 * Handle common cases.
719 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
720 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
721 // FIXME: This is racy
725 int has_refs = dest_class->has_references;
726 for (i = source_idx; i < source_idx + length; ++i) {
727 MonoObject *elem = mono_array_get (source, MonoObject*, i);
728 if (elem && !mono_object_isinst (elem, dest_class))
732 element_size = mono_array_element_size (dest->obj.vtable->klass);
733 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
734 for (i = 0; i < length; ++i) {
735 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
736 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
740 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
742 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
748 /* Check if we're copying a char[] <==> (u)short[] */
749 if (src_class != dest_class) {
750 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
753 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
755 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
756 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
757 // FIXME: This is racy
761 for (i = source_idx; i < source_idx + length; ++i) {
762 MonoObject *elem = mono_array_get (source, MonoObject*, i);
763 if (elem && !mono_object_isinst (elem, dest_class))
771 if (dest_class->valuetype) {
772 element_size = mono_array_element_size (source->obj.vtable->klass);
773 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
774 if (dest_class->has_references) {
775 mono_value_copy_array (dest, dest_idx, source_addr, length);
777 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
778 mono_gc_memmove (dest_addr, source_addr, element_size * length);
781 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
788 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
797 ao = (MonoArray *)this;
798 ac = (MonoClass *)ao->obj.vtable->klass;
800 esize = mono_array_element_size (ac);
801 ea = (gpointer*)((char*)ao->vector + (pos * esize));
803 mono_gc_memmove (value, ea, esize);
807 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
816 ao = (MonoArray *)this;
817 ac = (MonoClass *)ao->obj.vtable->klass;
818 ec = ac->element_class;
820 esize = mono_array_element_size (ac);
821 ea = (gpointer*)((char*)ao->vector + (pos * esize));
823 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
824 g_assert (esize == sizeof (gpointer));
825 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
827 g_assert (ec->inited);
828 g_assert (esize == mono_class_value_size (ec, NULL));
829 if (ec->has_references)
830 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
832 mono_gc_memmove (ea, value, esize);
837 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
839 MonoClass *klass = array->obj.vtable->klass;
840 guint32 size = mono_array_element_size (klass);
841 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
843 const char *field_data;
845 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
846 MonoException *exc = mono_get_exception_argument("array",
847 "Cannot initialize array of non-primitive type.");
848 mono_raise_exception (exc);
851 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
852 MonoException *exc = mono_get_exception_argument("field_handle",
853 "Field doesn't have an RVA");
854 mono_raise_exception (exc);
857 size *= array->max_length;
858 field_data = mono_field_get_data (field_handle);
860 if (size > mono_type_size (field_handle->type, &align)) {
861 MonoException *exc = mono_get_exception_argument("field_handle",
862 "Field not large enough to fill array");
863 mono_raise_exception (exc);
866 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
868 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
869 guint ## n *src = (guint ## n *) field_data; \
870 guint ## n *end = (guint ## n *)((char*)src + size); \
872 for (; src < end; data++, src++) { \
873 *data = read ## n (src); \
877 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
879 switch (type->type) {
896 memcpy (mono_array_addr (array, char, 0), field_data, size);
900 memcpy (mono_array_addr (array, char, 0), field_data, size);
902 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
905 double *data = (double*)mono_array_addr (array, double, 0);
907 for (i = 0; i < size; i++, data++) {
917 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
921 return offsetof (MonoString, chars);
924 ICALL_EXPORT MonoObject *
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
929 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
932 return mono_object_clone (obj);
936 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
941 MONO_CHECK_ARG_NULL (handle);
943 klass = mono_class_from_mono_type (handle);
944 MONO_CHECK_ARG (handle, klass);
946 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
948 /* This will call the type constructor */
949 mono_runtime_class_init (vtable);
953 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
957 mono_image_check_for_module_cctor (image);
958 if (image->has_module_cctor) {
959 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
960 /*It's fine to raise the exception here*/
961 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
965 ICALL_EXPORT MonoBoolean
966 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
971 /* later make this configurable and per-arch */
972 int min_size = 4096 * 4 * sizeof (void*);
973 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
974 /* if we have no info we are optimistic and assume there is enough room */
977 current = (guint8 *)&stack_addr;
978 if (current > stack_addr) {
979 if ((current - stack_addr) < min_size)
982 if (current - (stack_addr - stack_size) < min_size)
988 ICALL_EXPORT MonoObject *
989 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
993 return mono_object_clone (this);
997 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
1000 MonoObject **values = NULL;
1004 MonoClassField* field;
1007 MONO_ARCH_SAVE_REGS;
1009 klass = mono_object_class (this);
1011 if (mono_class_num_fields (klass) == 0)
1012 return mono_object_hash (this);
1015 * Compute the starting value of the hashcode for fields of primitive
1016 * types, and return the remaining fields in an array to the managed side.
1017 * This way, we can avoid costly reflection operations in managed code.
1020 while ((field = mono_class_get_fields (klass, &iter))) {
1021 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1023 if (mono_field_is_deleted (field))
1025 /* FIXME: Add more types */
1026 switch (field->type->type) {
1028 result ^= *(gint32*)((guint8*)this + field->offset);
1030 case MONO_TYPE_STRING: {
1032 s = *(MonoString**)((guint8*)this + field->offset);
1034 result ^= mono_string_hash (s);
1039 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1040 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1041 values [count++] = o;
1047 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1048 for (i = 0; i < count; ++i)
1049 mono_array_setref (*fields, i, values [i]);
1056 ICALL_EXPORT MonoBoolean
1057 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1060 MonoObject **values = NULL;
1062 MonoClassField* field;
1066 MONO_ARCH_SAVE_REGS;
1068 MONO_CHECK_ARG_NULL (that);
1070 if (this->vtable != that->vtable)
1073 klass = mono_object_class (this);
1075 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1076 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1079 * Do the comparison for fields of primitive type and return a result if
1080 * possible. Otherwise, return the remaining fields in an array to the
1081 * managed side. This way, we can avoid costly reflection operations in
1086 while ((field = mono_class_get_fields (klass, &iter))) {
1087 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1089 if (mono_field_is_deleted (field))
1091 /* FIXME: Add more types */
1092 switch (field->type->type) {
1095 case MONO_TYPE_BOOLEAN:
1096 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1101 case MONO_TYPE_CHAR:
1102 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1107 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1112 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1116 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1120 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1125 case MONO_TYPE_STRING: {
1126 MonoString *s1, *s2;
1127 guint32 s1len, s2len;
1128 s1 = *(MonoString**)((guint8*)this + field->offset);
1129 s2 = *(MonoString**)((guint8*)that + field->offset);
1132 if ((s1 == NULL) || (s2 == NULL))
1134 s1len = mono_string_length (s1);
1135 s2len = mono_string_length (s2);
1139 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1145 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1146 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1147 values [count++] = o;
1148 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1149 values [count++] = o;
1152 if (klass->enumtype)
1153 /* enums only have one non-static field */
1159 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1160 for (i = 0; i < count; ++i)
1161 mono_array_setref (*fields, i, values [i]);
1168 ICALL_EXPORT MonoReflectionType *
1169 ves_icall_System_Object_GetType (MonoObject *obj)
1171 MONO_ARCH_SAVE_REGS;
1173 #ifndef DISABLE_REMOTING
1174 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1175 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1178 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1182 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1184 MONO_ARCH_SAVE_REGS;
1186 mtype->type = &obj->vtable->klass->byval_arg;
1187 g_assert (mtype->type->type);
1191 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1193 MONO_ARCH_SAVE_REGS;
1195 MONO_CHECK_ARG_NULL (obj);
1197 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1201 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1202 MonoReflectionMethod *method,
1203 MonoArray *opt_param_types)
1205 MONO_ARCH_SAVE_REGS;
1207 MONO_CHECK_ARG_NULL (method);
1209 return mono_image_create_method_token (
1210 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1214 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1216 MONO_ARCH_SAVE_REGS;
1218 mono_image_create_pefile (mb, file);
1222 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1224 MONO_ARCH_SAVE_REGS;
1226 mono_image_build_metadata (mb);
1230 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1232 MONO_ARCH_SAVE_REGS;
1234 mono_image_register_token (mb->dynamic_image, token, obj);
1238 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1240 MonoMethod **dest = data;
1242 /* skip unmanaged frames */
1258 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1260 MonoMethod **dest = data;
1262 /* skip unmanaged frames */
1267 if (!strcmp (m->klass->name_space, "System.Reflection"))
1276 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1278 MonoMethod **dest = data;
1280 /* skip unmanaged frames */
1284 if (m->wrapper_type != MONO_WRAPPER_NONE)
1287 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1301 static MonoReflectionType *
1302 type_from_name (const char *str, MonoBoolean ignoreCase)
1304 MonoType *type = NULL;
1305 MonoAssembly *assembly = NULL;
1306 MonoTypeNameParse info;
1307 char *temp_str = g_strdup (str);
1308 gboolean type_resolve = FALSE;
1310 MONO_ARCH_SAVE_REGS;
1312 /* mono_reflection_parse_type() mangles the string */
1313 if (!mono_reflection_parse_type (temp_str, &info)) {
1314 mono_reflection_free_type_info (&info);
1319 if (info.assembly.name) {
1320 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1322 MonoMethod *m = mono_method_get_last_managed ();
1323 MonoMethod *dest = m;
1325 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1330 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1331 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1332 * to crash. This only seems to happen in some strange remoting
1333 * scenarios and I was unable to figure out what's happening there.
1334 * Dec 10, 2005 - Martin.
1338 assembly = dest->klass->image->assembly;
1339 type_resolve = TRUE;
1341 g_warning (G_STRLOC);
1346 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1347 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1350 if (!info.assembly.name && !type) /* try mscorlib */
1351 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1353 if (assembly && !type && type_resolve) {
1354 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1355 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1358 mono_reflection_free_type_info (&info);
1364 return mono_type_get_object (mono_domain_get (), type);
1368 MonoReflectionType *
1369 mono_type_get (const char *str)
1371 char *copy = g_strdup (str);
1372 MonoReflectionType *type = type_from_name (copy, FALSE);
1379 ICALL_EXPORT MonoReflectionType*
1380 ves_icall_type_from_name (MonoString *name,
1381 MonoBoolean throwOnError,
1382 MonoBoolean ignoreCase)
1384 char *str = mono_string_to_utf8 (name);
1385 MonoReflectionType *type;
1387 type = type_from_name (str, ignoreCase);
1390 MonoException *e = NULL;
1393 e = mono_get_exception_type_load (name, NULL);
1395 mono_loader_clear_error ();
1397 mono_raise_exception (e);
1404 ICALL_EXPORT MonoReflectionType*
1405 ves_icall_type_from_handle (MonoType *handle)
1407 MonoDomain *domain = mono_domain_get ();
1409 MONO_ARCH_SAVE_REGS;
1411 return mono_type_get_object (domain, handle);
1414 ICALL_EXPORT MonoBoolean
1415 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1417 MONO_ARCH_SAVE_REGS;
1419 if (c && type->type && c->type)
1420 return mono_metadata_type_equal (type->type, c->type);
1422 return (type == c) ? TRUE : FALSE;
1425 /* System.TypeCode */
1444 TYPECODE_STRING = 18
1447 ICALL_EXPORT guint32
1448 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1450 int t = type->type->type;
1452 MONO_ARCH_SAVE_REGS;
1454 if (type->type->byref)
1455 return TYPECODE_OBJECT;
1459 case MONO_TYPE_VOID:
1460 return TYPECODE_OBJECT;
1461 case MONO_TYPE_BOOLEAN:
1462 return TYPECODE_BOOLEAN;
1464 return TYPECODE_BYTE;
1466 return TYPECODE_SBYTE;
1468 return TYPECODE_UINT16;
1470 return TYPECODE_INT16;
1471 case MONO_TYPE_CHAR:
1472 return TYPECODE_CHAR;
1476 return TYPECODE_OBJECT;
1478 return TYPECODE_UINT32;
1480 return TYPECODE_INT32;
1482 return TYPECODE_UINT64;
1484 return TYPECODE_INT64;
1486 return TYPECODE_SINGLE;
1488 return TYPECODE_DOUBLE;
1489 case MONO_TYPE_VALUETYPE: {
1490 MonoClass *klass = type->type->data.klass;
1492 if (klass->enumtype) {
1493 t = mono_class_enum_basetype (klass)->type;
1495 } else if (mono_is_corlib_image (klass->image)) {
1496 if (strcmp (klass->name_space, "System") == 0) {
1497 if (strcmp (klass->name, "Decimal") == 0)
1498 return TYPECODE_DECIMAL;
1499 else if (strcmp (klass->name, "DateTime") == 0)
1500 return TYPECODE_DATETIME;
1503 return TYPECODE_OBJECT;
1505 case MONO_TYPE_STRING:
1506 return TYPECODE_STRING;
1507 case MONO_TYPE_SZARRAY:
1508 case MONO_TYPE_ARRAY:
1509 case MONO_TYPE_OBJECT:
1511 case MONO_TYPE_MVAR:
1512 case MONO_TYPE_TYPEDBYREF:
1513 return TYPECODE_OBJECT;
1514 case MONO_TYPE_CLASS:
1516 MonoClass *klass = type->type->data.klass;
1517 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1518 if (strcmp (klass->name, "DBNull") == 0)
1519 return TYPECODE_DBNULL;
1522 return TYPECODE_OBJECT;
1523 case MONO_TYPE_GENERICINST:
1524 return TYPECODE_OBJECT;
1526 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1531 ICALL_EXPORT guint32
1532 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1538 MONO_ARCH_SAVE_REGS;
1540 g_assert (type != NULL);
1542 domain = ((MonoObject *)type)->vtable->domain;
1544 if (!c) /* FIXME: dont know what do do here */
1547 klass = mono_class_from_mono_type (type->type);
1548 klassc = mono_class_from_mono_type (c->type);
1550 /* Interface check requires a more complex setup so we
1551 * only do for them. Otherwise we simply avoid mono_class_init.
1553 if (check_interfaces) {
1554 mono_class_init_or_throw (klass);
1555 mono_class_init_or_throw (klassc);
1556 } else if (!klass->supertypes || !klassc->supertypes) {
1557 mono_loader_lock ();
1558 mono_class_setup_supertypes (klass);
1559 mono_class_setup_supertypes (klassc);
1560 mono_loader_unlock ();
1563 if (type->type->byref)
1564 return klassc == mono_defaults.object_class;
1566 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1570 mono_type_is_primitive (MonoType *type)
1572 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1573 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1577 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1579 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1580 return mono_class_enum_basetype (type->data.klass);
1581 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1582 return mono_class_enum_basetype (type->data.generic_class->container_class);
1586 ICALL_EXPORT guint32
1587 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1593 MONO_ARCH_SAVE_REGS;
1595 g_assert (type != NULL);
1597 domain = ((MonoObject *)type)->vtable->domain;
1599 klass = mono_class_from_mono_type (type->type);
1600 klassc = mono_class_from_mono_type (c->type);
1602 mono_class_init_or_throw (klass);
1603 mono_class_init_or_throw (klassc);
1605 if (type->type->byref ^ c->type->byref)
1608 if (type->type->byref) {
1609 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1610 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1612 klass = mono_class_from_mono_type (t);
1613 klassc = mono_class_from_mono_type (ot);
1615 if (mono_type_is_primitive (t)) {
1616 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1617 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1618 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1619 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1620 return t->type == ot->type;
1622 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1625 if (klass->valuetype)
1626 return klass == klassc;
1627 return klass->valuetype == klassc->valuetype;
1630 return mono_class_is_assignable_from (klass, klassc);
1633 ICALL_EXPORT guint32
1634 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1636 MonoClass *klass = mono_class_from_mono_type (type->type);
1637 mono_class_init_or_throw (klass);
1638 return mono_object_isinst (obj, klass) != NULL;
1641 ICALL_EXPORT guint32
1642 ves_icall_get_attributes (MonoReflectionType *type)
1644 MonoClass *klass = mono_class_from_mono_type (type->type);
1645 return klass->flags;
1648 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1649 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1651 MonoClass *klass = field->field->parent;
1652 MonoMarshalType *info;
1655 if (klass->generic_container ||
1656 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1659 info = mono_marshal_load_type_info (klass);
1661 for (i = 0; i < info->num_fields; ++i) {
1662 if (info->fields [i].field == field->field) {
1663 if (!info->fields [i].mspec)
1666 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1673 ICALL_EXPORT MonoReflectionField*
1674 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1676 gboolean found = FALSE;
1683 klass = handle->parent;
1685 klass = mono_class_from_mono_type (type);
1687 /* Check that the field belongs to the class */
1688 for (k = klass; k; k = k->parent) {
1689 if (k == handle->parent) {
1696 /* The managed code will throw the exception */
1700 return mono_field_get_object (mono_domain_get (), klass, handle);
1703 ICALL_EXPORT MonoArray*
1704 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1707 MonoType *type = mono_field_get_type_checked (field->field, &error);
1708 if (!mono_error_ok (&error))
1709 mono_error_raise_exception (&error);
1711 return type_array_from_modifiers (field->field->parent->image, type, optional);
1715 vell_icall_get_method_attributes (MonoMethod *method)
1717 return method->flags;
1721 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1724 MonoDomain *domain = mono_domain_get ();
1725 MonoMethodSignature* sig;
1726 MONO_ARCH_SAVE_REGS;
1728 sig = mono_method_signature_checked (method, &error);
1729 if (!mono_error_ok (&error))
1730 mono_error_raise_exception (&error);
1733 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1734 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1735 info->attrs = method->flags;
1736 info->implattrs = method->iflags;
1737 if (sig->call_convention == MONO_CALL_DEFAULT)
1738 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1740 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1745 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1748 ICALL_EXPORT MonoArray*
1749 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1751 MonoDomain *domain = mono_domain_get ();
1753 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1756 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1757 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1759 MonoDomain *domain = mono_domain_get ();
1760 MonoReflectionMarshalAsAttribute* res = NULL;
1761 MonoMarshalSpec **mspecs;
1764 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1765 mono_method_get_marshal_info (method, mspecs);
1768 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1770 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1772 mono_metadata_free_marshal_spec (mspecs [i]);
1779 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1781 MonoClass *parent = field->field->parent;
1782 if (!parent->size_inited)
1783 mono_class_init (parent);
1785 return field->field->offset - sizeof (MonoObject);
1788 ICALL_EXPORT MonoReflectionType*
1789 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1792 MONO_ARCH_SAVE_REGS;
1794 parent = declaring? field->field->parent: field->klass;
1796 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1799 ICALL_EXPORT MonoObject *
1800 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1802 MonoClass *fklass = field->klass;
1803 MonoClassField *cf = field->field;
1804 MonoDomain *domain = mono_object_domain (field);
1806 if (fklass->image->assembly->ref_only)
1807 mono_raise_exception (mono_get_exception_invalid_operation (
1808 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1810 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1811 mono_security_core_clr_ensure_reflection_access_field (cf);
1813 return mono_field_get_value_object (domain, cf, obj);
1817 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1820 MonoClassField *cf = field->field;
1824 MONO_ARCH_SAVE_REGS;
1826 if (field->klass->image->assembly->ref_only)
1827 mono_raise_exception (mono_get_exception_invalid_operation (
1828 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1830 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1831 mono_security_core_clr_ensure_reflection_access_field (cf);
1833 type = mono_field_get_type_checked (cf, &error);
1834 if (!mono_error_ok (&error))
1835 mono_error_raise_exception (&error);
1837 v = (gchar *) value;
1839 switch (type->type) {
1842 case MONO_TYPE_BOOLEAN:
1845 case MONO_TYPE_CHAR:
1854 case MONO_TYPE_VALUETYPE:
1857 v += sizeof (MonoObject);
1859 case MONO_TYPE_STRING:
1860 case MONO_TYPE_OBJECT:
1861 case MONO_TYPE_CLASS:
1862 case MONO_TYPE_ARRAY:
1863 case MONO_TYPE_SZARRAY:
1866 case MONO_TYPE_GENERICINST: {
1867 MonoGenericClass *gclass = type->data.generic_class;
1868 g_assert (!gclass->context.class_inst->is_open);
1870 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1871 MonoClass *nklass = mono_class_from_mono_type (type);
1872 MonoObject *nullable;
1875 * Convert the boxed vtype into a Nullable structure.
1876 * This is complicated by the fact that Nullables have
1877 * a variable structure.
1879 nullable = mono_object_new (mono_domain_get (), nklass);
1881 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1883 v = mono_object_unbox (nullable);
1886 if (gclass->container_class->valuetype && (v != NULL))
1887 v += sizeof (MonoObject);
1891 g_error ("type 0x%x not handled in "
1892 "ves_icall_FieldInfo_SetValueInternal", type->type);
1897 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1898 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1899 if (!vtable->initialized)
1900 mono_runtime_class_init (vtable);
1901 mono_field_static_set_value (vtable, cf, v);
1903 mono_field_set_value (obj, cf, v);
1907 ICALL_EXPORT MonoObject *
1908 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1910 MonoObject *o = NULL;
1911 MonoClassField *field = this->field;
1913 MonoDomain *domain = mono_object_domain (this);
1915 MonoTypeEnum def_type;
1916 const char *def_value;
1920 MONO_ARCH_SAVE_REGS;
1922 mono_class_init (field->parent);
1924 t = mono_field_get_type_checked (field, &error);
1925 if (!mono_error_ok (&error))
1926 mono_error_raise_exception (&error);
1928 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1929 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1931 if (field->parent->image->dynamic) {
1933 g_assert_not_reached ();
1936 def_value = mono_class_get_field_default_value (field, &def_type);
1937 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1938 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1940 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1944 case MONO_TYPE_BOOLEAN:
1947 case MONO_TYPE_CHAR:
1955 case MONO_TYPE_R8: {
1958 /* boxed value type */
1959 t = g_new0 (MonoType, 1);
1961 klass = mono_class_from_mono_type (t);
1963 o = mono_object_new (domain, klass);
1964 v = ((gchar *) o) + sizeof (MonoObject);
1965 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1968 case MONO_TYPE_STRING:
1969 case MONO_TYPE_CLASS:
1970 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1973 g_assert_not_reached ();
1979 ICALL_EXPORT MonoReflectionType*
1980 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1983 MonoClassField *field = ref_field->field;
1984 MonoType *type = mono_field_get_type_checked (field, &error);
1985 if (!mono_error_ok (&error))
1986 mono_error_raise_exception (&error);
1987 return mono_type_get_object (mono_object_domain (ref_field), type);
1990 ICALL_EXPORT MonoReflectionType*
1991 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1993 MonoMethod *method = rmethod->method.method;
1995 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1998 /* From MonoProperty.cs */
2000 PInfo_Attributes = 1,
2001 PInfo_GetMethod = 1 << 1,
2002 PInfo_SetMethod = 1 << 2,
2003 PInfo_ReflectedType = 1 << 3,
2004 PInfo_DeclaringType = 1 << 4,
2009 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2011 MonoDomain *domain = mono_object_domain (property);
2013 MONO_ARCH_SAVE_REGS;
2015 if ((req_info & PInfo_ReflectedType) != 0)
2016 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2017 if ((req_info & PInfo_DeclaringType) != 0)
2018 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2020 if ((req_info & PInfo_Name) != 0)
2021 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2023 if ((req_info & PInfo_Attributes) != 0)
2024 info->attrs = property->property->attrs;
2026 if ((req_info & PInfo_GetMethod) != 0)
2027 MONO_STRUCT_SETREF (info, get, property->property->get ?
2028 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2030 if ((req_info & PInfo_SetMethod) != 0)
2031 MONO_STRUCT_SETREF (info, set, property->property->set ?
2032 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2034 * There may be other methods defined for properties, though, it seems they are not exposed
2035 * in the reflection API
2040 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2042 MonoDomain *domain = mono_object_domain (event);
2044 MONO_ARCH_SAVE_REGS;
2046 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2047 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2049 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2050 info->attrs = event->event->attrs;
2051 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2052 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2053 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2055 #ifndef MONO_SMALL_CONFIG
2056 if (event->event->other) {
2058 while (event->event->other [n])
2060 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2062 for (i = 0; i < n; i++)
2063 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2069 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2074 mono_class_setup_interfaces (klass, error);
2075 if (!mono_error_ok (error))
2078 for (i = 0; i < klass->interface_count; i++) {
2079 ic = klass->interfaces [i];
2080 g_hash_table_insert (ifaces, ic, ic);
2082 collect_interfaces (ic, ifaces, error);
2083 if (!mono_error_ok (error))
2089 MonoArray *iface_array;
2090 MonoGenericContext *context;
2094 } FillIfaceArrayData;
2097 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2099 FillIfaceArrayData *data = user_data;
2100 MonoClass *ic = key;
2101 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2103 if (!mono_error_ok (data->error))
2106 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2107 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2108 if (!mono_error_ok (data->error))
2112 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2115 mono_metadata_free_type (inflated);
2118 ICALL_EXPORT MonoArray*
2119 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2122 MonoClass *class = mono_class_from_mono_type (type->type);
2124 FillIfaceArrayData data = { 0 };
2127 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2129 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2130 data.context = mono_class_get_context (class);
2131 class = class->generic_class->container_class;
2134 for (parent = class; parent; parent = parent->parent) {
2135 mono_class_setup_interfaces (parent, &error);
2136 if (!mono_error_ok (&error))
2138 collect_interfaces (parent, iface_hash, &error);
2139 if (!mono_error_ok (&error))
2143 data.error = &error;
2144 data.domain = mono_object_domain (type);
2146 len = g_hash_table_size (iface_hash);
2148 g_hash_table_destroy (iface_hash);
2149 if (!data.domain->empty_types)
2150 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2151 return data.domain->empty_types;
2154 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2155 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2156 if (!mono_error_ok (&error))
2159 g_hash_table_destroy (iface_hash);
2160 return data.iface_array;
2163 g_hash_table_destroy (iface_hash);
2164 mono_error_raise_exception (&error);
2169 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2171 gboolean variance_used;
2172 MonoClass *class = mono_class_from_mono_type (type->type);
2173 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2174 MonoReflectionMethod *member;
2177 int i = 0, len, ioffset;
2180 MONO_ARCH_SAVE_REGS;
2181 mono_class_init_or_throw (class);
2182 mono_class_init_or_throw (iclass);
2184 mono_class_setup_vtable (class);
2186 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2190 len = mono_class_num_methods (iclass);
2191 domain = mono_object_domain (type);
2192 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2193 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2195 while ((method = mono_class_get_methods (iclass, &iter))) {
2196 member = mono_method_get_object (domain, method, iclass);
2197 mono_array_setref (*methods, i, member);
2198 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2199 mono_array_setref (*targets, i, member);
2206 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2208 MonoClass *klass = mono_class_from_mono_type (type->type);
2209 mono_class_init_or_throw (klass);
2211 if (klass->image->dynamic) {
2212 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2213 *packing = tb->packing_size;
2214 *size = tb->class_size;
2216 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2220 ICALL_EXPORT MonoReflectionType*
2221 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2225 MONO_ARCH_SAVE_REGS;
2227 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2228 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2230 class = mono_class_from_mono_type (type->type);
2231 mono_class_init_or_throw (class);
2233 // GetElementType should only return a type for:
2234 // Array Pointer PassedByRef
2235 if (type->type->byref)
2236 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2237 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2238 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2239 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2240 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2245 ICALL_EXPORT MonoReflectionType*
2246 ves_icall_get_type_parent (MonoReflectionType *type)
2248 MonoClass *class = mono_class_from_mono_type (type->type);
2249 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2252 ICALL_EXPORT MonoBoolean
2253 ves_icall_type_ispointer (MonoReflectionType *type)
2255 MONO_ARCH_SAVE_REGS;
2257 return type->type->type == MONO_TYPE_PTR;
2260 ICALL_EXPORT MonoBoolean
2261 ves_icall_type_isprimitive (MonoReflectionType *type)
2263 MONO_ARCH_SAVE_REGS;
2265 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)));
2268 ICALL_EXPORT MonoBoolean
2269 ves_icall_type_isbyref (MonoReflectionType *type)
2271 MONO_ARCH_SAVE_REGS;
2273 return type->type->byref;
2276 ICALL_EXPORT MonoBoolean
2277 ves_icall_type_iscomobject (MonoReflectionType *type)
2279 MonoClass *klass = mono_class_from_mono_type (type->type);
2280 mono_class_init_or_throw (klass);
2282 return mono_class_is_com_object (klass);
2285 ICALL_EXPORT MonoReflectionModule*
2286 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2288 MonoClass *class = mono_class_from_mono_type (type->type);
2289 return mono_module_get_object (mono_object_domain (type), class->image);
2292 ICALL_EXPORT MonoReflectionAssembly*
2293 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2295 MonoDomain *domain = mono_domain_get ();
2296 MonoClass *class = mono_class_from_mono_type (type->type);
2297 return mono_assembly_get_object (domain, class->image->assembly);
2300 ICALL_EXPORT MonoReflectionType*
2301 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2303 MonoDomain *domain = mono_domain_get ();
2306 MONO_ARCH_SAVE_REGS;
2308 if (type->type->byref)
2310 if (type->type->type == MONO_TYPE_VAR)
2311 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2312 else if (type->type->type == MONO_TYPE_MVAR)
2313 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2315 class = mono_class_from_mono_type (type->type)->nested_in;
2317 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2320 ICALL_EXPORT MonoString*
2321 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2323 MonoDomain *domain = mono_domain_get ();
2324 MonoClass *class = mono_class_from_mono_type (type->type);
2326 if (type->type->byref) {
2327 char *n = g_strdup_printf ("%s&", class->name);
2328 MonoString *res = mono_string_new (domain, n);
2334 return mono_string_new (domain, class->name);
2338 ICALL_EXPORT MonoString*
2339 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2341 MonoDomain *domain = mono_domain_get ();
2342 MonoClass *class = mono_class_from_mono_type (type->type);
2344 while (class->nested_in)
2345 class = class->nested_in;
2347 if (class->name_space [0] == '\0')
2350 return mono_string_new (domain, class->name_space);
2354 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2358 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2359 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2361 class = mono_class_from_mono_type (type->type);
2366 ICALL_EXPORT MonoArray*
2367 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2370 MonoClass *klass, *pklass;
2371 MonoDomain *domain = mono_object_domain (type);
2372 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2374 MONO_ARCH_SAVE_REGS;
2376 klass = mono_class_from_mono_type (type->type);
2378 if (klass->generic_container) {
2379 MonoGenericContainer *container = klass->generic_container;
2380 res = mono_array_new_specific (array_vtable, container->type_argc);
2381 for (i = 0; i < container->type_argc; ++i) {
2382 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2383 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2385 } else if (klass->generic_class) {
2386 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2387 res = mono_array_new_specific (array_vtable, inst->type_argc);
2388 for (i = 0; i < inst->type_argc; ++i)
2389 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2391 res = mono_array_new_specific (array_vtable, 0);
2396 ICALL_EXPORT gboolean
2397 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2400 MONO_ARCH_SAVE_REGS;
2402 if (!IS_MONOTYPE (type))
2405 if (type->type->byref)
2408 klass = mono_class_from_mono_type (type->type);
2409 return klass->generic_container != NULL;
2412 ICALL_EXPORT MonoReflectionType*
2413 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2416 MONO_ARCH_SAVE_REGS;
2418 if (type->type->byref)
2421 klass = mono_class_from_mono_type (type->type);
2423 if (klass->generic_container) {
2424 return type; /* check this one */
2426 if (klass->generic_class) {
2427 MonoClass *generic_class = klass->generic_class->container_class;
2430 tb = mono_class_get_ref_info (generic_class);
2432 if (generic_class->wastypebuilder && tb)
2435 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2440 ICALL_EXPORT MonoReflectionType*
2441 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2444 MonoType *geninst, **types;
2447 g_assert (IS_MONOTYPE (type));
2448 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2450 count = mono_array_length (type_array);
2451 types = g_new0 (MonoType *, count);
2453 for (i = 0; i < count; i++) {
2454 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2455 types [i] = t->type;
2458 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2463 class = mono_class_from_mono_type (geninst);
2465 /*we might inflate to the GTD*/
2466 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2467 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2469 return mono_type_get_object (mono_object_domain (type), geninst);
2472 ICALL_EXPORT gboolean
2473 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2476 MONO_ARCH_SAVE_REGS;
2478 if (type->type->byref)
2481 klass = mono_class_from_mono_type (type->type);
2483 return klass->generic_class != NULL;
2486 ICALL_EXPORT gboolean
2487 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2490 MONO_ARCH_SAVE_REGS;
2492 if (!IS_MONOTYPE (type))
2495 if (type->type->byref)
2498 klass = mono_class_from_mono_type (type->type);
2499 return klass->generic_class != NULL || klass->generic_container != NULL;
2503 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2505 MONO_ARCH_SAVE_REGS;
2507 if (!IS_MONOTYPE (type))
2510 if (is_generic_parameter (type->type))
2511 return mono_type_get_generic_param_num (type->type);
2515 ICALL_EXPORT GenericParameterAttributes
2516 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2518 MONO_ARCH_SAVE_REGS;
2520 g_assert (IS_MONOTYPE (type));
2521 g_assert (is_generic_parameter (type->type));
2522 return mono_generic_param_info (type->type->data.generic_param)->flags;
2525 ICALL_EXPORT MonoArray *
2526 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2528 MonoGenericParamInfo *param_info;
2534 MONO_ARCH_SAVE_REGS;
2536 g_assert (IS_MONOTYPE (type));
2538 domain = mono_object_domain (type);
2539 param_info = mono_generic_param_info (type->type->data.generic_param);
2540 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2543 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2544 for (i = 0; i < count; i++)
2545 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2551 ICALL_EXPORT MonoBoolean
2552 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2554 MONO_ARCH_SAVE_REGS;
2555 return is_generic_parameter (type->type);
2558 ICALL_EXPORT MonoBoolean
2559 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2561 MONO_ARCH_SAVE_REGS;
2562 return is_generic_parameter (tb->type.type);
2566 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2567 MonoReflectionType *t)
2569 enumtype->type = t->type;
2572 ICALL_EXPORT MonoReflectionMethod*
2573 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2574 MonoReflectionMethod* generic)
2581 MONO_ARCH_SAVE_REGS;
2583 domain = ((MonoObject *)type)->vtable->domain;
2585 klass = mono_class_from_mono_type (type->type);
2586 mono_class_init_or_throw (klass);
2589 while ((method = mono_class_get_methods (klass, &iter))) {
2590 if (method->token == generic->method->token)
2591 return mono_method_get_object (domain, method, klass);
2599 ICALL_EXPORT MonoReflectionMethod *
2600 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2603 MonoType *type = ref_type->type;
2605 MONO_ARCH_SAVE_REGS;
2607 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2608 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2609 if (type->type == MONO_TYPE_VAR)
2612 method = mono_type_get_generic_param_owner (type)->owner.method;
2614 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2617 ICALL_EXPORT MonoReflectionDllImportAttribute*
2618 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2620 static MonoClass *DllImportAttributeClass = NULL;
2621 MonoDomain *domain = mono_domain_get ();
2622 MonoReflectionDllImportAttribute *attr;
2623 MonoImage *image = method->klass->image;
2624 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2625 MonoTableInfo *tables = image->tables;
2626 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2627 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2628 guint32 im_cols [MONO_IMPLMAP_SIZE];
2629 guint32 scope_token;
2630 const char *import = NULL;
2631 const char *scope = NULL;
2634 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2637 if (!DllImportAttributeClass) {
2638 DllImportAttributeClass =
2639 mono_class_from_name (mono_defaults.corlib,
2640 "System.Runtime.InteropServices", "DllImportAttribute");
2641 g_assert (DllImportAttributeClass);
2644 if (method->klass->image->dynamic) {
2645 MonoReflectionMethodAux *method_aux =
2646 g_hash_table_lookup (
2647 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2649 import = method_aux->dllentry;
2650 scope = method_aux->dll;
2653 if (!import || !scope) {
2654 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2659 if (piinfo->implmap_idx) {
2660 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2662 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2663 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2664 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2665 scope = mono_metadata_string_heap (image, scope_token);
2668 flags = piinfo->piflags;
2670 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2672 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2673 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2674 attr->call_conv = (flags & 0x700) >> 8;
2675 attr->charset = ((flags & 0x6) >> 1) + 1;
2676 if (attr->charset == 1)
2678 attr->exact_spelling = (flags & 0x1) != 0;
2679 attr->set_last_error = (flags & 0x40) != 0;
2680 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2681 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2682 attr->preserve_sig = FALSE;
2687 ICALL_EXPORT MonoReflectionMethod *
2688 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2690 MonoMethodInflated *imethod;
2693 MONO_ARCH_SAVE_REGS;
2695 if (method->method->is_generic)
2698 if (!method->method->is_inflated)
2701 imethod = (MonoMethodInflated *) method->method;
2703 result = imethod->declaring;
2704 /* Not a generic method. */
2705 if (!result->is_generic)
2708 if (method->method->klass->image->dynamic) {
2709 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2710 MonoReflectionMethod *res;
2713 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2714 * the dynamic case as well ?
2716 mono_loader_lock ();
2717 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2718 mono_loader_unlock ();
2724 if (imethod->context.class_inst) {
2725 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2726 /*Generic methods gets the context of the GTD.*/
2727 if (mono_class_get_context (klass))
2728 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2731 return mono_method_get_object (mono_object_domain (method), result, NULL);
2734 ICALL_EXPORT gboolean
2735 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2737 MONO_ARCH_SAVE_REGS;
2739 return mono_method_signature (method->method)->generic_param_count != 0;
2742 ICALL_EXPORT gboolean
2743 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2745 MONO_ARCH_SAVE_REGS;
2747 return method->method->is_generic;
2750 ICALL_EXPORT MonoArray*
2751 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2756 MONO_ARCH_SAVE_REGS;
2758 domain = mono_object_domain (method);
2760 if (method->method->is_inflated) {
2761 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2764 count = inst->type_argc;
2765 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2767 for (i = 0; i < count; i++)
2768 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2774 count = mono_method_signature (method->method)->generic_param_count;
2775 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2777 for (i = 0; i < count; i++) {
2778 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2779 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2780 MonoClass *pklass = mono_class_from_generic_parameter (
2781 param, method->method->klass->image, TRUE);
2782 mono_array_setref (res, i,
2783 mono_type_get_object (domain, &pklass->byval_arg));
2789 ICALL_EXPORT MonoObject *
2790 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2793 * Invoke from reflection is supposed to always be a virtual call (the API
2794 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2795 * greater flexibility.
2797 MonoMethod *m = method->method;
2798 MonoMethodSignature *sig = mono_method_signature (m);
2802 MONO_ARCH_SAVE_REGS;
2806 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2807 mono_security_core_clr_ensure_reflection_access_method (m);
2809 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2810 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2811 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2816 if (!mono_object_isinst (this, m->klass)) {
2817 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2818 char *target_name = mono_type_get_full_name (m->klass);
2819 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2820 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2822 g_free (target_name);
2826 m = mono_object_get_virtual_method (this, m);
2827 /* must pass the pointer to the value for valuetype methods */
2828 if (m->klass->valuetype)
2829 obj = mono_object_unbox (this);
2830 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2831 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2836 if (sig->ret->byref) {
2837 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
2841 pcount = params? mono_array_length (params): 0;
2842 if (pcount != sig->param_count) {
2843 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2847 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2848 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2852 if (m->klass->image->assembly->ref_only) {
2853 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2857 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2860 intptr_t *lower_bounds;
2861 pcount = mono_array_length (params);
2862 lengths = alloca (sizeof (uintptr_t) * pcount);
2863 /* Note: the synthetized array .ctors have int32 as argument type */
2864 for (i = 0; i < pcount; ++i)
2865 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2867 if (m->klass->rank == pcount) {
2868 /* Only lengths provided. */
2869 lower_bounds = NULL;
2871 g_assert (pcount == (m->klass->rank * 2));
2872 /* lower bounds are first. */
2873 lower_bounds = (intptr_t*)lengths;
2874 lengths += m->klass->rank;
2877 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2879 return mono_runtime_invoke_array (m, obj, params, NULL);
2882 #ifndef DISABLE_REMOTING
2883 ICALL_EXPORT MonoObject *
2884 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2886 MonoDomain *domain = mono_object_domain (method);
2887 MonoMethod *m = method->method;
2888 MonoMethodSignature *sig = mono_method_signature (m);
2889 MonoArray *out_args;
2891 int i, j, outarg_count = 0;
2893 MONO_ARCH_SAVE_REGS;
2895 if (m->klass == mono_defaults.object_class) {
2897 if (!strcmp (m->name, "FieldGetter")) {
2898 MonoClass *k = this->vtable->klass;
2902 /* If this is a proxy, then it must be a CBO */
2903 if (k == mono_defaults.transparent_proxy_class) {
2904 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2905 this = tp->rp->unwrapped_server;
2907 k = this->vtable->klass;
2910 name = mono_array_get (params, MonoString *, 1);
2911 str = mono_string_to_utf8 (name);
2914 MonoClassField* field = mono_class_get_field_from_name (k, str);
2916 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2917 if (field_klass->valuetype)
2918 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2920 result = *((gpointer *)((char *)this + field->offset));
2922 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2923 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2924 mono_array_setref (out_args, 0, result);
2932 g_assert_not_reached ();
2934 } else if (!strcmp (m->name, "FieldSetter")) {
2935 MonoClass *k = this->vtable->klass;
2941 /* If this is a proxy, then it must be a CBO */
2942 if (k == mono_defaults.transparent_proxy_class) {
2943 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2944 this = tp->rp->unwrapped_server;
2946 k = this->vtable->klass;
2949 name = mono_array_get (params, MonoString *, 1);
2950 str = mono_string_to_utf8 (name);
2953 MonoClassField* field = mono_class_get_field_from_name (k, str);
2955 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2956 MonoObject *val = mono_array_get (params, gpointer, 2);
2958 if (field_klass->valuetype) {
2959 size = mono_type_size (field->type, &align);
2960 g_assert (size == mono_class_value_size (field_klass, NULL));
2961 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2963 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2966 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2967 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2977 g_assert_not_reached ();
2982 for (i = 0; i < mono_array_length (params); i++) {
2983 if (sig->params [i]->byref)
2987 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2989 /* handle constructors only for objects already allocated */
2990 if (!strcmp (method->method->name, ".ctor"))
2993 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2994 g_assert (!method->method->klass->valuetype);
2995 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2997 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2998 if (sig->params [i]->byref) {
3000 arg = mono_array_get (params, gpointer, i);
3001 mono_array_setref (out_args, j, arg);
3006 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3013 read_enum_value (char *mem, int type)
3017 return *(guint8*)mem;
3019 return *(gint8*)mem;
3021 return *(guint16*)mem;
3023 return *(gint16*)mem;
3025 return *(guint32*)mem;
3027 return *(gint32*)mem;
3029 return *(guint64*)mem;
3031 return *(gint64*)mem;
3033 g_assert_not_reached ();
3039 write_enum_value (char *mem, int type, guint64 value)
3043 case MONO_TYPE_I1: {
3044 guint8 *p = (guint8*)mem;
3049 case MONO_TYPE_I2: {
3050 guint16 *p = (void*)mem;
3055 case MONO_TYPE_I4: {
3056 guint32 *p = (void*)mem;
3061 case MONO_TYPE_I8: {
3062 guint64 *p = (void*)mem;
3067 g_assert_not_reached ();
3072 ICALL_EXPORT MonoObject *
3073 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3076 MonoClass *enumc, *objc;
3081 MONO_ARCH_SAVE_REGS;
3083 MONO_CHECK_ARG_NULL (enumType);
3084 MONO_CHECK_ARG_NULL (value);
3086 domain = mono_object_domain (enumType);
3087 enumc = mono_class_from_mono_type (enumType->type);
3089 mono_class_init_or_throw (enumc);
3091 objc = value->vtable->klass;
3093 if (!enumc->enumtype)
3094 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3095 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3096 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."));
3098 etype = mono_class_enum_basetype (enumc);
3100 /* MS throws this for typebuilders */
3101 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3103 res = mono_object_new (domain, enumc);
3104 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3105 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3110 ICALL_EXPORT MonoObject *
3111 ves_icall_System_Enum_get_value (MonoObject *this)
3119 MONO_ARCH_SAVE_REGS;
3124 g_assert (this->vtable->klass->enumtype);
3126 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3127 res = mono_object_new (mono_object_domain (this), enumc);
3128 dst = (char *)res + sizeof (MonoObject);
3129 src = (char *)this + sizeof (MonoObject);
3130 size = mono_class_value_size (enumc, NULL);
3132 memcpy (dst, src, size);
3137 ICALL_EXPORT MonoReflectionType *
3138 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3143 MONO_ARCH_SAVE_REGS;
3145 klass = mono_class_from_mono_type (type->type);
3146 mono_class_init_or_throw (klass);
3148 etype = mono_class_enum_basetype (klass);
3150 /* MS throws this for typebuilders */
3151 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3153 return mono_type_get_object (mono_object_domain (type), etype);
3157 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3159 gpointer tdata = (char *)this + sizeof (MonoObject);
3160 gpointer odata = (char *)other + sizeof (MonoObject);
3161 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3162 g_assert (basetype);
3164 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3165 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3166 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3169 return me > other ? 1 : -1; \
3172 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3173 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3174 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3177 return me - other; \
3180 switch (basetype->type) {
3182 COMPARE_ENUM_VALUES (guint8);
3184 COMPARE_ENUM_VALUES (gint8);
3185 case MONO_TYPE_CHAR:
3187 COMPARE_ENUM_VALUES_RANGE (guint16);
3189 COMPARE_ENUM_VALUES (gint16);
3191 COMPARE_ENUM_VALUES (guint32);
3193 COMPARE_ENUM_VALUES (gint32);
3195 COMPARE_ENUM_VALUES (guint64);
3197 COMPARE_ENUM_VALUES (gint64);
3199 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3201 #undef COMPARE_ENUM_VALUES_RANGE
3202 #undef COMPARE_ENUM_VALUES
3207 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3209 gpointer data = (char *)this + sizeof (MonoObject);
3210 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3211 g_assert (basetype);
3213 switch (basetype->type) {
3215 return *((gint8*)data);
3217 return *((guint8*)data);
3218 case MONO_TYPE_CHAR:
3220 return *((guint16*)data);
3223 return *((gint16*)data);
3225 return *((guint32*)data);
3227 return *((gint32*)data);
3229 case MONO_TYPE_I8: {
3230 gint64 value = *((gint64*)data);
3231 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3234 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3240 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3242 MonoDomain *domain = mono_object_domain (type);
3243 MonoClass *enumc = mono_class_from_mono_type (type->type);
3244 guint j = 0, nvalues, crow;
3246 MonoClassField *field;
3248 MONO_ARCH_SAVE_REGS;
3250 mono_class_init_or_throw (enumc);
3252 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3253 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3254 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3255 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3259 while ((field = mono_class_get_fields (enumc, &iter))) {
3262 MonoTypeEnum def_type;
3264 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3266 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3268 if (mono_field_is_deleted (field))
3270 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3272 p = mono_class_get_field_default_value (field, &def_type);
3273 len = mono_metadata_decode_blob_size (p, &p);
3274 switch (mono_class_enum_basetype (enumc)->type) {
3277 mono_array_set (info->values, gchar, j, *p);
3279 case MONO_TYPE_CHAR:
3282 mono_array_set (info->values, gint16, j, read16 (p));
3286 mono_array_set (info->values, gint32, j, read32 (p));
3290 mono_array_set (info->values, gint64, j, read64 (p));
3293 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3300 BFLAGS_IgnoreCase = 1,
3301 BFLAGS_DeclaredOnly = 2,
3302 BFLAGS_Instance = 4,
3304 BFLAGS_Public = 0x10,
3305 BFLAGS_NonPublic = 0x20,
3306 BFLAGS_FlattenHierarchy = 0x40,
3307 BFLAGS_InvokeMethod = 0x100,
3308 BFLAGS_CreateInstance = 0x200,
3309 BFLAGS_GetField = 0x400,
3310 BFLAGS_SetField = 0x800,
3311 BFLAGS_GetProperty = 0x1000,
3312 BFLAGS_SetProperty = 0x2000,
3313 BFLAGS_ExactBinding = 0x10000,
3314 BFLAGS_SuppressChangeType = 0x20000,
3315 BFLAGS_OptionalParamBinding = 0x40000
3318 ICALL_EXPORT MonoReflectionField *
3319 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3322 MonoClass *startklass, *klass;
3324 MonoClassField *field;
3327 int (*compare_func) (const char *s1, const char *s2) = NULL;
3328 domain = ((MonoObject *)type)->vtable->domain;
3329 klass = startklass = mono_class_from_mono_type (type->type);
3332 mono_raise_exception (mono_get_exception_argument_null ("name"));
3333 if (type->type->byref)
3336 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3339 if (klass->exception_type != MONO_EXCEPTION_NONE)
3340 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3343 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3344 guint32 flags = mono_field_get_flags (field);
3347 if (mono_field_is_deleted_with_flags (field, flags))
3349 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3350 if (bflags & BFLAGS_Public)
3352 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3353 if (bflags & BFLAGS_NonPublic) {
3360 if (flags & FIELD_ATTRIBUTE_STATIC) {
3361 if (bflags & BFLAGS_Static)
3362 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3365 if (bflags & BFLAGS_Instance)
3372 utf8_name = mono_string_to_utf8 (name);
3374 if (compare_func (mono_field_get_name (field), utf8_name)) {
3380 return mono_field_get_object (domain, klass, field);
3382 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3388 ICALL_EXPORT MonoArray*
3389 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3392 MonoClass *startklass, *klass, *refklass;
3397 MonoClassField *field;
3398 MonoPtrArray tmp_array;
3400 MONO_ARCH_SAVE_REGS;
3402 domain = ((MonoObject *)type)->vtable->domain;
3403 if (type->type->byref)
3404 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3405 klass = startklass = mono_class_from_mono_type (type->type);
3406 refklass = mono_class_from_mono_type (reftype->type);
3408 mono_ptr_array_init (tmp_array, 2);
3411 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3412 mono_ptr_array_destroy (tmp_array);
3413 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3417 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3418 guint32 flags = mono_field_get_flags (field);
3420 if (mono_field_is_deleted_with_flags (field, flags))
3422 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3423 if (bflags & BFLAGS_Public)
3425 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3426 if (bflags & BFLAGS_NonPublic) {
3433 if (flags & FIELD_ATTRIBUTE_STATIC) {
3434 if (bflags & BFLAGS_Static)
3435 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3438 if (bflags & BFLAGS_Instance)
3444 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3445 mono_ptr_array_append (tmp_array, member);
3447 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3450 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3452 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3453 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3455 mono_ptr_array_destroy (tmp_array);
3461 method_nonpublic (MonoMethod* method, gboolean start_klass)
3463 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3464 case METHOD_ATTRIBUTE_ASSEM:
3465 return (start_klass || mono_defaults.generic_ilist_class);
3466 case METHOD_ATTRIBUTE_PRIVATE:
3468 case METHOD_ATTRIBUTE_PUBLIC:
3476 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3479 MonoClass *startklass;
3482 int len, match, nslots;
3483 /*FIXME, use MonoBitSet*/
3484 guint32 method_slots_default [8];
3485 guint32 *method_slots = NULL;
3486 int (*compare_func) (const char *s1, const char *s2) = NULL;
3488 array = g_ptr_array_new ();
3494 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3496 /* An optimization for calls made from Delegate:CreateDelegate () */
3497 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3498 method = mono_get_delegate_invoke (klass);
3499 if (mono_loader_get_last_error ())
3502 g_ptr_array_add (array, method);
3506 mono_class_setup_vtable (klass);
3507 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3510 if (is_generic_parameter (&klass->byval_arg))
3511 nslots = mono_class_get_vtable_size (klass->parent);
3513 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3514 if (nslots >= sizeof (method_slots_default) * 8) {
3515 method_slots = g_new0 (guint32, nslots / 32 + 1);
3517 method_slots = method_slots_default;
3518 memset (method_slots, 0, sizeof (method_slots_default));
3521 mono_class_setup_vtable (klass);
3522 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3526 while ((method = mono_class_get_methods (klass, &iter))) {
3528 if (method->slot != -1) {
3529 g_assert (method->slot < nslots);
3530 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3532 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3533 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3536 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3538 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3539 if (bflags & BFLAGS_Public)
3541 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3547 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3548 if (bflags & BFLAGS_Static)
3549 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3552 if (bflags & BFLAGS_Instance)
3560 if (compare_func (name, method->name))
3565 g_ptr_array_add (array, method);
3567 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3569 if (method_slots != method_slots_default)
3570 g_free (method_slots);
3575 if (method_slots != method_slots_default)
3576 g_free (method_slots);
3577 g_ptr_array_free (array, TRUE);
3579 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3580 *ex = mono_class_get_exception_for_failure (klass);
3582 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3583 mono_loader_clear_error ();
3588 ICALL_EXPORT MonoArray*
3589 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3591 static MonoClass *MethodInfo_array;
3594 MonoVTable *array_vtable;
3595 MonoException *ex = NULL;
3596 const char *mname = NULL;
3597 GPtrArray *method_array;
3598 MonoClass *klass, *refklass;
3601 if (!MethodInfo_array) {
3602 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3603 mono_memory_barrier ();
3604 MethodInfo_array = klass;
3607 klass = mono_class_from_mono_type (type->type);
3608 refklass = mono_class_from_mono_type (reftype->type);
3609 domain = ((MonoObject *)type)->vtable->domain;
3610 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3611 if (type->type->byref)
3612 return mono_array_new_specific (array_vtable, 0);
3615 mname = mono_string_to_utf8 (name);
3617 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3618 g_free ((char*)mname);
3620 mono_raise_exception (ex);
3622 res = mono_array_new_specific (array_vtable, method_array->len);
3625 for (i = 0; i < method_array->len; ++i) {
3626 MonoMethod *method = g_ptr_array_index (method_array, i);
3627 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3630 g_ptr_array_free (method_array, TRUE);
3634 ICALL_EXPORT MonoArray*
3635 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3638 static MonoClass *System_Reflection_ConstructorInfo;
3639 MonoClass *startklass, *klass, *refklass;
3644 gpointer iter = NULL;
3645 MonoPtrArray tmp_array;
3647 MONO_ARCH_SAVE_REGS;
3649 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3651 domain = ((MonoObject *)type)->vtable->domain;
3652 if (type->type->byref)
3653 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3654 klass = startklass = mono_class_from_mono_type (type->type);
3655 refklass = mono_class_from_mono_type (reftype->type);
3657 if (!System_Reflection_ConstructorInfo)
3658 System_Reflection_ConstructorInfo = mono_class_from_name (
3659 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3662 while ((method = mono_class_get_methods (klass, &iter))) {
3664 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3666 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3667 if (bflags & BFLAGS_Public)
3670 if (bflags & BFLAGS_NonPublic)
3676 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3677 if (bflags & BFLAGS_Static)
3678 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3681 if (bflags & BFLAGS_Instance)
3687 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3689 mono_ptr_array_append (tmp_array, member);
3692 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3694 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3695 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3697 mono_ptr_array_destroy (tmp_array);
3703 property_hash (gconstpointer data)
3705 MonoProperty *prop = (MonoProperty*)data;
3707 return g_str_hash (prop->name);
3711 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3713 // Properties are hide-by-name-and-signature
3714 if (!g_str_equal (prop1->name, prop2->name))
3717 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3719 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3725 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3730 return method_nonpublic (accessor, start_klass);
3733 ICALL_EXPORT MonoArray*
3734 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3738 static MonoClass *System_Reflection_PropertyInfo;
3739 MonoClass *startklass, *klass;
3745 gchar *propname = NULL;
3746 int (*compare_func) (const char *s1, const char *s2) = NULL;
3748 GHashTable *properties = NULL;
3749 MonoPtrArray tmp_array;
3751 MONO_ARCH_SAVE_REGS;
3753 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3755 if (!System_Reflection_PropertyInfo)
3756 System_Reflection_PropertyInfo = mono_class_from_name (
3757 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3759 domain = ((MonoObject *)type)->vtable->domain;
3760 if (type->type->byref)
3761 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3762 klass = startklass = mono_class_from_mono_type (type->type);
3765 propname = mono_string_to_utf8 (name);
3766 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3769 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3771 mono_class_setup_vtable (klass);
3772 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3776 while ((prop = mono_class_get_properties (klass, &iter))) {
3782 flags = method->flags;
3785 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3786 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3787 if (bflags & BFLAGS_Public)
3789 } else if (bflags & BFLAGS_NonPublic) {
3790 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3791 property_accessor_nonpublic(prop->set, startklass == klass)) {
3798 if (flags & METHOD_ATTRIBUTE_STATIC) {
3799 if (bflags & BFLAGS_Static)
3800 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3803 if (bflags & BFLAGS_Instance)
3812 if (compare_func (propname, prop->name))
3816 if (g_hash_table_lookup (properties, prop))
3819 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3821 g_hash_table_insert (properties, prop, prop);
3823 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3826 g_hash_table_destroy (properties);
3829 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3830 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3831 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3833 mono_ptr_array_destroy (tmp_array);
3839 g_hash_table_destroy (properties);
3842 mono_ptr_array_destroy (tmp_array);
3844 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3845 ex = mono_class_get_exception_for_failure (klass);
3847 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3848 mono_loader_clear_error ();
3850 mono_raise_exception (ex);
3854 ICALL_EXPORT MonoReflectionEvent *
3855 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3858 MonoClass *klass, *startklass;
3863 int (*compare_func) (const char *s1, const char *s2);
3865 MONO_ARCH_SAVE_REGS;
3867 event_name = mono_string_to_utf8 (name);
3868 if (type->type->byref)
3870 klass = startklass = mono_class_from_mono_type (type->type);
3871 domain = mono_object_domain (type);
3873 mono_class_init_or_throw (klass);
3875 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3877 if (klass->exception_type != MONO_EXCEPTION_NONE)
3878 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3881 while ((event = mono_class_get_events (klass, &iter))) {
3882 if (compare_func (event->name, event_name))
3885 method = event->add;
3887 method = event->remove;
3889 method = event->raise;
3891 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3892 if (!(bflags & BFLAGS_Public))
3895 if (!(bflags & BFLAGS_NonPublic))
3897 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3901 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3902 if (!(bflags & BFLAGS_Static))
3904 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3907 if (!(bflags & BFLAGS_Instance))
3911 if (!(bflags & BFLAGS_NonPublic))
3914 g_free (event_name);
3915 return mono_event_get_object (domain, startklass, event);
3918 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3921 g_free (event_name);
3925 ICALL_EXPORT MonoArray*
3926 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3930 static MonoClass *System_Reflection_EventInfo;
3931 MonoClass *startklass, *klass;
3938 MonoPtrArray tmp_array;
3940 MONO_ARCH_SAVE_REGS;
3942 mono_ptr_array_init (tmp_array, 4);
3944 if (!System_Reflection_EventInfo)
3945 System_Reflection_EventInfo = mono_class_from_name (
3946 mono_defaults.corlib, "System.Reflection", "EventInfo");
3948 domain = mono_object_domain (type);
3949 if (type->type->byref)
3950 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3951 klass = startklass = mono_class_from_mono_type (type->type);
3954 mono_class_setup_vtable (klass);
3955 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3959 while ((event = mono_class_get_events (klass, &iter))) {
3961 method = event->add;
3963 method = event->remove;
3965 method = event->raise;
3967 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3968 if (bflags & BFLAGS_Public)
3970 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3971 if (bflags & BFLAGS_NonPublic)
3976 if (bflags & BFLAGS_NonPublic)
3982 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3983 if (bflags & BFLAGS_Static)
3984 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3987 if (bflags & BFLAGS_Instance)
3992 if (bflags & BFLAGS_Instance)
3996 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3998 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4001 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4003 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4004 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4006 mono_ptr_array_destroy (tmp_array);
4011 mono_ptr_array_destroy (tmp_array);
4012 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4013 ex = mono_class_get_exception_for_failure (klass);
4015 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4016 mono_loader_clear_error ();
4018 mono_raise_exception (ex);
4022 ICALL_EXPORT MonoReflectionType *
4023 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4031 MONO_ARCH_SAVE_REGS;
4034 mono_raise_exception (mono_get_exception_argument_null ("name"));
4036 domain = ((MonoObject *)type)->vtable->domain;
4037 if (type->type->byref)
4039 klass = mono_class_from_mono_type (type->type);
4041 str = mono_string_to_utf8 (name);
4044 if (klass->exception_type != MONO_EXCEPTION_NONE)
4045 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4048 * If a nested type is generic, return its generic type definition.
4049 * Note that this means that the return value is essentially a
4050 * nested type of the generic type definition of @klass.
4052 * A note in MSDN claims that a generic type definition can have
4053 * nested types that aren't generic. In any case, the container of that
4054 * nested type would be the generic type definition.
4056 if (klass->generic_class)
4057 klass = klass->generic_class->container_class;
4060 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4062 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4063 if (bflags & BFLAGS_Public)
4066 if (bflags & BFLAGS_NonPublic)
4071 if (strcmp (nested->name, str) == 0){
4073 return mono_type_get_object (domain, &nested->byval_arg);
4076 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4082 ICALL_EXPORT MonoArray*
4083 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4092 MonoPtrArray tmp_array;
4094 MONO_ARCH_SAVE_REGS;
4096 domain = ((MonoObject *)type)->vtable->domain;
4097 if (type->type->byref)
4098 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4099 klass = mono_class_from_mono_type (type->type);
4102 * If a nested type is generic, return its generic type definition.
4103 * Note that this means that the return value is essentially the set
4104 * of nested types of the generic type definition of @klass.
4106 * A note in MSDN claims that a generic type definition can have
4107 * nested types that aren't generic. In any case, the container of that
4108 * nested type would be the generic type definition.
4110 if (klass->generic_class)
4111 klass = klass->generic_class->container_class;
4113 mono_ptr_array_init (tmp_array, 1);
4115 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4117 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4118 if (bflags & BFLAGS_Public)
4121 if (bflags & BFLAGS_NonPublic)
4126 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4127 mono_ptr_array_append (tmp_array, member);
4130 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4132 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4133 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4135 mono_ptr_array_destroy (tmp_array);
4140 ICALL_EXPORT MonoReflectionType*
4141 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4144 MonoType *type = NULL;
4145 MonoTypeNameParse info;
4146 gboolean type_resolve;
4148 MONO_ARCH_SAVE_REGS;
4150 /* On MS.NET, this does not fire a TypeResolve event */
4151 type_resolve = TRUE;
4152 str = mono_string_to_utf8 (name);
4153 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4154 if (!mono_reflection_parse_type (str, &info)) {
4156 mono_reflection_free_type_info (&info);
4157 if (throwOnError) /* uhm: this is a parse error, though... */
4158 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4159 /*g_print ("failed parse\n");*/
4163 if (info.assembly.name) {
4165 mono_reflection_free_type_info (&info);
4167 /* 1.0 and 2.0 throw different exceptions */
4168 if (mono_defaults.generic_ilist_class)
4169 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4171 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4176 if (module != NULL) {
4178 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4183 if (assembly->assembly->dynamic) {
4184 /* Enumerate all modules */
4185 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4189 if (abuilder->modules) {
4190 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4191 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4192 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4198 if (!type && abuilder->loaded_modules) {
4199 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4200 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4201 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4208 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4210 mono_reflection_free_type_info (&info);
4212 MonoException *e = NULL;
4215 e = mono_get_exception_type_load (name, NULL);
4217 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4218 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4220 mono_loader_clear_error ();
4223 mono_raise_exception (e);
4226 } else if (mono_loader_get_last_error ()) {
4228 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4229 mono_loader_clear_error ();
4232 if (type->type == MONO_TYPE_CLASS) {
4233 MonoClass *klass = mono_type_get_class (type);
4235 if (mono_is_security_manager_active () && !klass->exception_type)
4236 /* Some security problems are detected during generic vtable construction */
4237 mono_class_setup_vtable (klass);
4238 /* need to report exceptions ? */
4239 if (throwOnError && klass->exception_type) {
4240 /* report SecurityException (or others) that occured when loading the assembly */
4241 MonoException *exc = mono_class_get_exception_for_failure (klass);
4242 mono_loader_clear_error ();
4243 mono_raise_exception (exc);
4244 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4249 /* g_print ("got it\n"); */
4250 return mono_type_get_object (mono_object_domain (assembly), type);
4254 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4257 gchar *shadow_ini_file;
4260 /* Check for shadow-copied assembly */
4261 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4262 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4264 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4265 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4271 g_free (shadow_ini_file);
4272 if (content != NULL) {
4275 *filename = content;
4282 ICALL_EXPORT MonoString *
4283 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4285 MonoDomain *domain = mono_object_domain (assembly);
4286 MonoAssembly *mass = assembly->assembly;
4287 MonoString *res = NULL;
4292 MONO_ARCH_SAVE_REGS;
4294 if (g_path_is_absolute (mass->image->name)) {
4295 absolute = g_strdup (mass->image->name);
4296 dirname = g_path_get_dirname (absolute);
4298 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4299 dirname = g_strdup (mass->basedir);
4302 replace_shadow_path (domain, dirname, &absolute);
4307 for (i = strlen (absolute) - 1; i >= 0; i--)
4308 if (absolute [i] == '\\')
4313 uri = g_filename_to_uri (absolute, NULL, NULL);
4315 const char *prepend = "file://";
4317 if (*absolute == '/' && *(absolute + 1) == '/') {
4320 prepend = "file:///";
4323 uri = g_strconcat (prepend, absolute, NULL);
4327 res = mono_string_new (domain, uri);
4334 ICALL_EXPORT MonoBoolean
4335 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4337 MonoAssembly *mass = assembly->assembly;
4339 MONO_ARCH_SAVE_REGS;
4341 return mass->in_gac;
4344 ICALL_EXPORT MonoReflectionAssembly*
4345 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4349 MonoImageOpenStatus status;
4351 MONO_ARCH_SAVE_REGS;
4353 name = mono_string_to_utf8 (mname);
4354 res = mono_assembly_load_with_partial_name (name, &status);
4360 return mono_assembly_get_object (mono_domain_get (), res);
4363 ICALL_EXPORT MonoString *
4364 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4366 MonoDomain *domain = mono_object_domain (assembly);
4369 MONO_ARCH_SAVE_REGS;
4371 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4376 ICALL_EXPORT MonoBoolean
4377 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4379 MONO_ARCH_SAVE_REGS;
4381 return assembly->assembly->ref_only;
4384 ICALL_EXPORT MonoString *
4385 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4387 MonoDomain *domain = mono_object_domain (assembly);
4389 MONO_ARCH_SAVE_REGS;
4391 return mono_string_new (domain, assembly->assembly->image->version);
4394 ICALL_EXPORT MonoReflectionMethod*
4395 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4397 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4399 MONO_ARCH_SAVE_REGS;
4403 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4406 ICALL_EXPORT MonoReflectionModule*
4407 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4409 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4412 ICALL_EXPORT MonoArray*
4413 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4415 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4416 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4420 MONO_ARCH_SAVE_REGS;
4422 for (i = 0; i < table->rows; ++i) {
4423 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4424 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4430 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4432 static MonoClass *System_Version = NULL;
4433 static MonoMethod *create_version = NULL;
4437 if (!System_Version) {
4438 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4439 g_assert (System_Version);
4442 if (!create_version) {
4443 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4444 create_version = mono_method_desc_search_in_class (desc, System_Version);
4445 g_assert (create_version);
4446 mono_method_desc_free (desc);
4452 args [3] = &revision;
4453 result = mono_object_new (domain, System_Version);
4454 mono_runtime_invoke (create_version, result, args, NULL);
4459 ICALL_EXPORT MonoArray*
4460 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4462 static MonoClass *System_Reflection_AssemblyName;
4464 MonoDomain *domain = mono_object_domain (assembly);
4466 static MonoMethod *create_culture = NULL;
4467 MonoImage *image = assembly->assembly->image;
4470 MONO_ARCH_SAVE_REGS;
4472 if (!System_Reflection_AssemblyName)
4473 System_Reflection_AssemblyName = mono_class_from_name (
4474 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4476 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4479 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4481 if (count > 0 && !create_culture) {
4482 MonoMethodDesc *desc = mono_method_desc_new (
4483 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4484 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4485 g_assert (create_culture);
4486 mono_method_desc_free (desc);
4489 for (i = 0; i < count; i++) {
4490 MonoReflectionAssemblyName *aname;
4491 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4493 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4495 aname = (MonoReflectionAssemblyName *) mono_object_new (
4496 domain, System_Reflection_AssemblyName);
4498 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4500 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4501 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4502 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4503 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4504 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4505 aname->versioncompat = 1; /* SameMachine (default) */
4506 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4507 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4509 if (create_culture) {
4511 MonoBoolean assembly_ref = 1;
4512 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4513 args [1] = &assembly_ref;
4514 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4517 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4518 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4519 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4521 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4522 /* public key token isn't copied - the class library will
4523 automatically generate it from the public key if required */
4524 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4525 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4527 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4528 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4531 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4534 /* note: this function doesn't return the codebase on purpose (i.e. it can
4535 be used under partial trust as path information isn't present). */
4537 mono_array_setref (result, i, aname);
4542 /* move this in some file in mono/util/ */
4544 g_concat_dir_and_file (const char *dir, const char *file)
4546 g_return_val_if_fail (dir != NULL, NULL);
4547 g_return_val_if_fail (file != NULL, NULL);
4550 * If the directory name doesn't have a / on the end, we need
4551 * to add one so we get a proper path to the file
4553 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4554 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4556 return g_strconcat (dir, file, NULL);
4560 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4562 char *n = mono_string_to_utf8 (name);
4563 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4565 guint32 cols [MONO_MANIFEST_SIZE];
4566 guint32 impl, file_idx;
4570 MONO_ARCH_SAVE_REGS;
4572 for (i = 0; i < table->rows; ++i) {
4573 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4574 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4575 if (strcmp (val, n) == 0)
4579 if (i == table->rows)
4582 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4585 * this code should only be called after obtaining the
4586 * ResourceInfo and handling the other cases.
4588 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4589 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4591 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4596 module = assembly->assembly->image;
4598 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4600 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4603 ICALL_EXPORT gboolean
4604 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4606 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4608 guint32 cols [MONO_MANIFEST_SIZE];
4609 guint32 file_cols [MONO_FILE_SIZE];
4613 MONO_ARCH_SAVE_REGS;
4615 n = mono_string_to_utf8 (name);
4616 for (i = 0; i < table->rows; ++i) {
4617 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4618 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4619 if (strcmp (val, n) == 0)
4623 if (i == table->rows)
4626 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4627 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4630 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4631 case MONO_IMPLEMENTATION_FILE:
4632 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4633 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4634 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4635 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4636 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4637 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4640 info->location = RESOURCE_LOCATION_EMBEDDED;
4643 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4644 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4645 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4646 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4647 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4648 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4650 mono_raise_exception (ex);
4652 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4654 /* Obtain info recursively */
4655 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4656 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4659 case MONO_IMPLEMENTATION_EXP_TYPE:
4660 g_assert_not_reached ();
4668 ICALL_EXPORT MonoObject*
4669 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4671 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4672 MonoArray *result = NULL;
4677 MONO_ARCH_SAVE_REGS;
4679 /* check hash if needed */
4681 n = mono_string_to_utf8 (name);
4682 for (i = 0; i < table->rows; ++i) {
4683 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4684 if (strcmp (val, n) == 0) {
4687 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4688 fn = mono_string_new (mono_object_domain (assembly), n);
4690 return (MonoObject*)fn;
4698 for (i = 0; i < table->rows; ++i) {
4699 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4703 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4706 for (i = 0; i < table->rows; ++i) {
4707 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4708 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4709 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4710 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4715 return (MonoObject*)result;
4718 ICALL_EXPORT MonoArray*
4719 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4721 MonoDomain *domain = mono_domain_get();
4724 int i, j, file_count = 0;
4725 MonoImage **modules;
4726 guint32 module_count, real_module_count;
4727 MonoTableInfo *table;
4728 guint32 cols [MONO_FILE_SIZE];
4729 MonoImage *image = assembly->assembly->image;
4731 g_assert (image != NULL);
4732 g_assert (!assembly->assembly->dynamic);
4734 table = &image->tables [MONO_TABLE_FILE];
4735 file_count = table->rows;
4737 modules = image->modules;
4738 module_count = image->module_count;
4740 real_module_count = 0;
4741 for (i = 0; i < module_count; ++i)
4743 real_module_count ++;
4745 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4746 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4748 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4750 for (i = 0; i < module_count; ++i)
4752 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4756 for (i = 0; i < file_count; ++i, ++j) {
4757 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4758 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4759 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4761 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4763 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4764 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4766 mono_array_setref (res, j, mono_module_get_object (domain, m));
4773 ICALL_EXPORT MonoReflectionMethod*
4774 ves_icall_GetCurrentMethod (void)
4776 MonoMethod *m = mono_method_get_last_managed ();
4778 while (m->is_inflated)
4779 m = ((MonoMethodInflated*)m)->declaring;
4781 return mono_method_get_object (mono_domain_get (), m, NULL);
4786 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4789 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4790 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4791 //method is inflated, we should inflate it on the other class
4792 MonoGenericContext ctx;
4793 ctx.method_inst = inflated->context.method_inst;
4794 ctx.class_inst = inflated->context.class_inst;
4795 if (klass->generic_class)
4796 ctx.class_inst = klass->generic_class->context.class_inst;
4797 else if (klass->generic_container)
4798 ctx.class_inst = klass->generic_container->context.class_inst;
4799 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4802 mono_class_setup_methods (method->klass);
4803 if (method->klass->exception_type)
4805 for (i = 0; i < method->klass->method.count; ++i) {
4806 if (method->klass->methods [i] == method) {
4811 mono_class_setup_methods (klass);
4812 if (klass->exception_type)
4814 g_assert (offset >= 0 && offset < klass->method.count);
4815 return klass->methods [offset];
4818 ICALL_EXPORT MonoReflectionMethod*
4819 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4823 klass = mono_class_from_mono_type (type);
4824 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4826 if (method->klass != klass) {
4827 method = mono_method_get_equivalent_method (method, klass);
4832 klass = method->klass;
4833 return mono_method_get_object (mono_domain_get (), method, klass);
4836 ICALL_EXPORT MonoReflectionMethod*
4837 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4839 return mono_method_get_object (mono_domain_get (), method, NULL);
4842 ICALL_EXPORT MonoReflectionMethodBody*
4843 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4845 return mono_method_body_get_object (mono_domain_get (), method);
4848 ICALL_EXPORT MonoReflectionAssembly*
4849 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4851 MonoMethod *dest = NULL;
4853 MONO_ARCH_SAVE_REGS;
4855 mono_stack_walk_no_il (get_executing, &dest);
4857 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4861 ICALL_EXPORT MonoReflectionAssembly*
4862 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4864 MonoDomain* domain = mono_domain_get ();
4866 MONO_ARCH_SAVE_REGS;
4868 if (!domain->entry_assembly)
4871 return mono_assembly_get_object (domain, domain->entry_assembly);
4874 ICALL_EXPORT MonoReflectionAssembly*
4875 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4880 MONO_ARCH_SAVE_REGS;
4883 mono_stack_walk_no_il (get_executing, &dest);
4885 mono_stack_walk_no_il (get_caller, &dest);
4888 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4891 ICALL_EXPORT MonoString *
4892 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4893 gboolean assembly_qualified)
4895 MonoDomain *domain = mono_object_domain (object);
4896 MonoTypeNameFormat format;
4901 format = assembly_qualified ?
4902 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4903 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4905 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4907 name = mono_type_get_name_full (object->type, format);
4911 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4916 res = mono_string_new (domain, name);
4923 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4925 MonoClass *klass = mono_class_from_mono_type (this->type);
4926 mono_class_init_or_throw (klass);
4927 return mono_security_core_clr_class_level (klass);
4931 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4933 static MonoMethod *create_culture = NULL;
4936 const char *pkey_ptr;
4938 MonoBoolean assembly_ref = 0;
4940 MONO_ARCH_SAVE_REGS;
4942 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4943 aname->major = name->major;
4944 aname->minor = name->minor;
4945 aname->build = name->build;
4946 aname->flags = name->flags;
4947 aname->revision = name->revision;
4948 aname->hashalg = name->hash_alg;
4949 aname->versioncompat = 1; /* SameMachine (default) */
4950 aname->processor_architecture = name->arch;
4952 if (by_default_version)
4953 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4956 if (absolute != NULL && *absolute != '\0') {
4957 const gchar *prepend = "file://";
4960 codebase = g_strdup (absolute);
4965 for (i = strlen (codebase) - 1; i >= 0; i--)
4966 if (codebase [i] == '\\')
4969 if (*codebase == '/' && *(codebase + 1) == '/') {
4972 prepend = "file:///";
4976 result = g_strconcat (prepend, codebase, NULL);
4982 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4986 if (!create_culture) {
4987 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4988 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4989 g_assert (create_culture);
4990 mono_method_desc_free (desc);
4993 if (name->culture) {
4994 args [0] = mono_string_new (domain, name->culture);
4995 args [1] = &assembly_ref;
4996 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4999 if (name->public_key) {
5000 pkey_ptr = (char*)name->public_key;
5001 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5003 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5004 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5005 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5006 } else if (default_publickey) {
5007 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5008 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5011 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5012 if (name->public_key_token [0]) {
5016 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5017 p = mono_array_addr (aname->keyToken, char, 0);
5019 for (i = 0, j = 0; i < 8; i++) {
5020 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5021 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5024 } else if (default_token) {
5025 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5029 ICALL_EXPORT MonoString *
5030 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5032 MonoDomain *domain = mono_object_domain (assembly);
5033 MonoAssembly *mass = assembly->assembly;
5037 name = mono_stringify_assembly_name (&mass->aname);
5038 res = mono_string_new (domain, name);
5045 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5048 MonoAssembly *mass = assembly->assembly;
5050 MONO_ARCH_SAVE_REGS;
5052 if (g_path_is_absolute (mass->image->name)) {
5053 fill_reflection_assembly_name (mono_object_domain (assembly),
5054 aname, &mass->aname, mass->image->name, TRUE,
5058 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5060 fill_reflection_assembly_name (mono_object_domain (assembly),
5061 aname, &mass->aname, absolute, TRUE, TRUE,
5068 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5071 MonoImageOpenStatus status = MONO_IMAGE_OK;
5074 MonoAssemblyName name;
5077 MONO_ARCH_SAVE_REGS;
5079 filename = mono_string_to_utf8 (fname);
5081 dirname = g_path_get_dirname (filename);
5082 replace_shadow_path (mono_domain_get (), dirname, &filename);
5085 image = mono_image_open (filename, &status);
5091 if (status == MONO_IMAGE_IMAGE_INVALID)
5092 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5094 exc = mono_get_exception_file_not_found2 (NULL, fname);
5095 mono_raise_exception (exc);
5098 res = mono_assembly_fill_assembly_name (image, &name);
5100 mono_image_close (image);
5102 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5105 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5109 mono_image_close (image);
5112 ICALL_EXPORT MonoBoolean
5113 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5114 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5116 MonoBoolean result = FALSE;
5117 MonoDeclSecurityEntry entry;
5119 /* SecurityAction.RequestMinimum */
5120 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5121 *minimum = entry.blob;
5122 *minLength = entry.size;
5125 /* SecurityAction.RequestOptional */
5126 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5127 *optional = entry.blob;
5128 *optLength = entry.size;
5131 /* SecurityAction.RequestRefuse */
5132 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5133 *refused = entry.blob;
5134 *refLength = entry.size;
5142 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5146 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5148 guint32 attrs, visibility;
5150 /* we start the count from 1 because we skip the special type <Module> */
5153 for (i = 1; i < tdef->rows; ++i) {
5154 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5155 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5156 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5160 count = tdef->rows - 1;
5162 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5163 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5165 for (i = 1; i < tdef->rows; ++i) {
5166 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5167 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5168 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5169 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5171 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5173 MonoLoaderError *error;
5176 error = mono_loader_get_last_error ();
5177 g_assert (error != NULL);
5179 ex = mono_loader_error_prepare_exception (error);
5180 mono_array_setref (*exceptions, count, ex);
5182 if (mono_loader_get_last_error ())
5183 mono_loader_clear_error ();
5191 ICALL_EXPORT MonoArray*
5192 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5194 MonoArray *res = NULL;
5195 MonoArray *exceptions = NULL;
5196 MonoImage *image = NULL;
5197 MonoTableInfo *table = NULL;
5200 int i, len, ex_count;
5202 MONO_ARCH_SAVE_REGS;
5204 domain = mono_object_domain (assembly);
5206 g_assert (!assembly->assembly->dynamic);
5207 image = assembly->assembly->image;
5208 table = &image->tables [MONO_TABLE_FILE];
5209 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5211 /* Append data from all modules in the assembly */
5212 for (i = 0; i < table->rows; ++i) {
5213 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5214 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5217 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5218 /* Append the new types to the end of the array */
5219 if (mono_array_length (res2) > 0) {
5221 MonoArray *res3, *ex3;
5223 len1 = mono_array_length (res);
5224 len2 = mono_array_length (res2);
5226 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5227 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5228 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5231 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5232 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5233 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5240 /* the ReflectionTypeLoadException must have all the types (Types property),
5241 * NULL replacing types which throws an exception. The LoaderException must
5242 * contain all exceptions for NULL items.
5245 len = mono_array_length (res);
5248 for (i = 0; i < len; i++) {
5249 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5253 klass = mono_type_get_class (t->type);
5254 if ((klass != NULL) && klass->exception_type) {
5255 /* keep the class in the list */
5256 list = g_list_append (list, klass);
5257 /* and replace Type with NULL */
5258 mono_array_setref (res, i, NULL);
5265 if (list || ex_count) {
5267 MonoException *exc = NULL;
5268 MonoArray *exl = NULL;
5269 int j, length = g_list_length (list) + ex_count;
5271 mono_loader_clear_error ();
5273 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5274 /* Types for which mono_class_get () succeeded */
5275 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5276 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5277 mono_array_setref (exl, i, exc);
5279 /* Types for which it don't */
5280 for (j = 0; j < mono_array_length (exceptions); ++j) {
5281 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5283 g_assert (i < length);
5284 mono_array_setref (exl, i, exc);
5291 exc = mono_get_exception_reflection_type_load (res, exl);
5292 mono_loader_clear_error ();
5293 mono_raise_exception (exc);
5299 ICALL_EXPORT gboolean
5300 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5302 MonoAssemblyName aname;
5303 MonoDomain *domain = mono_object_domain (name);
5305 gboolean is_version_defined;
5306 gboolean is_token_defined;
5308 aname.public_key = NULL;
5309 val = mono_string_to_utf8 (assname);
5310 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5311 g_free ((guint8*) aname.public_key);
5316 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5317 FALSE, is_token_defined);
5319 mono_assembly_name_free (&aname);
5320 g_free ((guint8*) aname.public_key);
5326 ICALL_EXPORT MonoReflectionType*
5327 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5329 MonoDomain *domain = mono_object_domain (module);
5332 MONO_ARCH_SAVE_REGS;
5334 g_assert (module->image);
5336 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5337 /* These images do not have a global type */
5340 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5341 return mono_type_get_object (domain, &klass->byval_arg);
5345 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5347 /*if (module->image)
5348 mono_image_close (module->image);*/
5351 ICALL_EXPORT MonoString*
5352 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5354 MonoDomain *domain = mono_object_domain (module);
5356 MONO_ARCH_SAVE_REGS;
5358 g_assert (module->image);
5359 return mono_string_new (domain, module->image->guid);
5362 ICALL_EXPORT gpointer
5363 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5366 if (module->image && module->image->is_module_handle)
5367 return module->image->raw_data;
5370 return (gpointer) (-1);
5374 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5376 if (image->dynamic) {
5377 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5378 *pe_kind = dyn->pe_kind;
5379 *machine = dyn->machine;
5382 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5383 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5388 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5390 return (image->md_version_major << 16) | (image->md_version_minor);
5393 ICALL_EXPORT MonoArray*
5394 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5396 MonoArray *exceptions;
5399 MONO_ARCH_SAVE_REGS;
5402 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5404 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5405 for (i = 0; i < mono_array_length (exceptions); ++i) {
5406 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5408 mono_raise_exception (ex);
5415 mono_memberref_is_method (MonoImage *image, guint32 token)
5417 if (!image->dynamic) {
5418 guint32 cols [MONO_MEMBERREF_SIZE];
5420 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5421 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5422 mono_metadata_decode_blob_size (sig, &sig);
5423 return (*sig != 0x6);
5425 MonoClass *handle_class;
5427 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5430 return mono_defaults.methodhandle_class == handle_class;
5435 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5438 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5439 mono_array_addr (type_args, MonoType*, 0));
5441 context->class_inst = NULL;
5443 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5444 mono_array_addr (method_args, MonoType*, 0));
5446 context->method_inst = NULL;
5449 ICALL_EXPORT MonoType*
5450 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5453 int table = mono_metadata_token_table (token);
5454 int index = mono_metadata_token_index (token);
5455 MonoGenericContext context;
5457 *error = ResolveTokenError_Other;
5459 /* Validate token */
5460 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5461 (table != MONO_TABLE_TYPESPEC)) {
5462 *error = ResolveTokenError_BadTable;
5466 if (image->dynamic) {
5467 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5468 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5469 return klass ? &klass->byval_arg : NULL;
5472 init_generic_context_from_args (&context, type_args, method_args);
5473 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5474 return klass ? &klass->byval_arg : NULL;
5477 if ((index <= 0) || (index > image->tables [table].rows)) {
5478 *error = ResolveTokenError_OutOfRange;
5482 init_generic_context_from_args (&context, type_args, method_args);
5483 klass = mono_class_get_full (image, token, &context);
5485 if (mono_loader_get_last_error ())
5486 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5489 return &klass->byval_arg;
5494 ICALL_EXPORT MonoMethod*
5495 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5497 int table = mono_metadata_token_table (token);
5498 int index = mono_metadata_token_index (token);
5499 MonoGenericContext context;
5502 *error = ResolveTokenError_Other;
5504 /* Validate token */
5505 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5506 (table != MONO_TABLE_MEMBERREF)) {
5507 *error = ResolveTokenError_BadTable;
5511 if (image->dynamic) {
5512 if (table == MONO_TABLE_METHOD)
5513 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5515 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5516 *error = ResolveTokenError_BadTable;
5520 init_generic_context_from_args (&context, type_args, method_args);
5521 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5524 if ((index <= 0) || (index > image->tables [table].rows)) {
5525 *error = ResolveTokenError_OutOfRange;
5528 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5529 *error = ResolveTokenError_BadTable;
5533 init_generic_context_from_args (&context, type_args, method_args);
5534 method = mono_get_method_full (image, token, NULL, &context);
5536 if (mono_loader_get_last_error ())
5537 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5542 ICALL_EXPORT MonoString*
5543 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5545 int index = mono_metadata_token_index (token);
5547 *error = ResolveTokenError_Other;
5549 /* Validate token */
5550 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5551 *error = ResolveTokenError_BadTable;
5556 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5558 if ((index <= 0) || (index >= image->heap_us.size)) {
5559 *error = ResolveTokenError_OutOfRange;
5563 /* FIXME: What to do if the index points into the middle of a string ? */
5565 return mono_ldstr (mono_domain_get (), image, index);
5568 ICALL_EXPORT MonoClassField*
5569 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5572 int table = mono_metadata_token_table (token);
5573 int index = mono_metadata_token_index (token);
5574 MonoGenericContext context;
5575 MonoClassField *field;
5577 *error = ResolveTokenError_Other;
5579 /* Validate token */
5580 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5581 *error = ResolveTokenError_BadTable;
5585 if (image->dynamic) {
5586 if (table == MONO_TABLE_FIELD)
5587 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5589 if (mono_memberref_is_method (image, token)) {
5590 *error = ResolveTokenError_BadTable;
5594 init_generic_context_from_args (&context, type_args, method_args);
5595 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5598 if ((index <= 0) || (index > image->tables [table].rows)) {
5599 *error = ResolveTokenError_OutOfRange;
5602 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5603 *error = ResolveTokenError_BadTable;
5607 init_generic_context_from_args (&context, type_args, method_args);
5608 field = mono_field_from_token (image, token, &klass, &context);
5610 if (mono_loader_get_last_error ())
5611 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5617 ICALL_EXPORT MonoObject*
5618 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5620 int table = mono_metadata_token_table (token);
5622 *error = ResolveTokenError_Other;
5625 case MONO_TABLE_TYPEDEF:
5626 case MONO_TABLE_TYPEREF:
5627 case MONO_TABLE_TYPESPEC: {
5628 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5630 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5634 case MONO_TABLE_METHOD:
5635 case MONO_TABLE_METHODSPEC: {
5636 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5638 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5642 case MONO_TABLE_FIELD: {
5643 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5645 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5649 case MONO_TABLE_MEMBERREF:
5650 if (mono_memberref_is_method (image, token)) {
5651 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5653 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5658 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5660 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5667 *error = ResolveTokenError_BadTable;
5673 ICALL_EXPORT MonoArray*
5674 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5676 int table = mono_metadata_token_table (token);
5677 int idx = mono_metadata_token_index (token);
5678 MonoTableInfo *tables = image->tables;
5683 *error = ResolveTokenError_OutOfRange;
5685 /* FIXME: Support other tables ? */
5686 if (table != MONO_TABLE_STANDALONESIG)
5692 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5695 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5697 ptr = mono_metadata_blob_heap (image, sig);
5698 len = mono_metadata_decode_blob_size (ptr, &ptr);
5700 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5701 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5705 ICALL_EXPORT MonoReflectionType*
5706 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5709 int isbyref = 0, rank;
5710 char *str = mono_string_to_utf8 (smodifiers);
5713 MONO_ARCH_SAVE_REGS;
5715 klass = mono_class_from_mono_type (tb->type.type);
5717 /* logic taken from mono_reflection_parse_type(): keep in sync */
5721 if (isbyref) { /* only one level allowed by the spec */
5728 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5731 klass = mono_ptr_class_get (&klass->byval_arg);
5732 mono_class_init (klass);
5743 else if (*p != '*') { /* '*' means unknown lower bound */
5754 klass = mono_array_class_get (klass, rank);
5755 mono_class_init (klass);
5762 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5765 ICALL_EXPORT MonoBoolean
5766 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5771 MONO_ARCH_SAVE_REGS;
5774 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5780 check_for_invalid_type (MonoClass *klass)
5784 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5787 name = mono_type_get_full_name (klass);
5788 str = mono_string_new (mono_domain_get (), name);
5790 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5793 ICALL_EXPORT MonoReflectionType *
5794 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5796 MonoClass *klass, *aklass;
5798 MONO_ARCH_SAVE_REGS;
5800 klass = mono_class_from_mono_type (type->type);
5801 check_for_invalid_type (klass);
5803 if (rank == 0) //single dimentional array
5804 aklass = mono_array_class_get (klass, 1);
5806 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5808 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5811 ICALL_EXPORT MonoReflectionType *
5812 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5816 MONO_ARCH_SAVE_REGS;
5818 klass = mono_class_from_mono_type (type->type);
5819 mono_class_init_or_throw (klass);
5820 check_for_invalid_type (klass);
5822 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5825 ICALL_EXPORT MonoReflectionType *
5826 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5828 MonoClass *klass, *pklass;
5830 klass = mono_class_from_mono_type (type->type);
5831 mono_class_init_or_throw (klass);
5832 check_for_invalid_type (klass);
5834 pklass = mono_ptr_class_get (type->type);
5836 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5839 ICALL_EXPORT MonoObject *
5840 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5841 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5843 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5844 MonoObject *delegate;
5846 MonoMethod *method = info->method;
5848 MONO_ARCH_SAVE_REGS;
5850 mono_class_init_or_throw (delegate_class);
5852 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5854 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5855 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5859 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5861 if (method->dynamic) {
5862 /* Creating a trampoline would leak memory */
5863 func = mono_compile_method (method);
5865 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5866 method = mono_object_get_virtual_method (target, method);
5867 func = mono_create_ftnptr (mono_domain_get (),
5868 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5871 mono_delegate_ctor_with_method (delegate, target, func, method);
5877 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5879 /* Reset the invoke impl to the default one */
5880 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5884 * Magic number to convert a time which is relative to
5885 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5887 #define EPOCH_ADJUST ((guint64)62135596800LL)
5890 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5892 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5895 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5897 convert_to_absolute_date(SYSTEMTIME *date)
5899 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5900 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5901 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5902 /* from the calendar FAQ */
5903 int a = (14 - date->wMonth) / 12;
5904 int y = date->wYear - a;
5905 int m = date->wMonth + 12 * a - 2;
5906 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5908 /* d is now the day of the week for the first of the month (0 == Sunday) */
5910 int day_of_week = date->wDayOfWeek;
5912 /* set day_in_month to the first day in the month which falls on day_of_week */
5913 int day_in_month = 1 + (day_of_week - d);
5914 if (day_in_month <= 0)
5917 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5918 date->wDay = day_in_month + (date->wDay - 1) * 7;
5919 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5926 * Return's the offset from GMT of a local time.
5928 * tm is a local time
5929 * t is the same local time as seconds.
5932 gmt_offset(struct tm *tm, time_t t)
5934 #if defined (HAVE_TM_GMTOFF)
5935 return tm->tm_gmtoff;
5940 g.tm_isdst = tm->tm_isdst;
5942 return (int)difftime(t, t2);
5947 * This is heavily based on zdump.c from glibc 2.2.
5949 * * data[0]: start of daylight saving time (in DateTime ticks).
5950 * * data[1]: end of daylight saving time (in DateTime ticks).
5951 * * data[2]: utcoffset (in TimeSpan ticks).
5952 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5953 * * name[0]: name of this timezone when not daylight saving.
5954 * * name[1]: name of this timezone when daylight saving.
5956 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5957 * the class library allows years between 1 and 9999.
5959 * Returns true on success and zero on failure.
5961 ICALL_EXPORT guint32
5962 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5965 MonoDomain *domain = mono_domain_get ();
5966 struct tm start, tt;
5970 int is_daylight = 0, day;
5973 MONO_ARCH_SAVE_REGS;
5975 MONO_CHECK_ARG_NULL (data);
5976 MONO_CHECK_ARG_NULL (names);
5978 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5979 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5982 * no info is better than crashing: we'll need our own tz data
5983 * to make this work properly, anyway. The range is probably
5984 * reduced to 1970 .. 2037 because that is what mktime is
5985 * guaranteed to support (we get into an infinite loop
5989 memset (&start, 0, sizeof (start));
5992 start.tm_year = year-1900;
5994 t = mktime (&start);
5996 if ((year < 1970) || (year > 2037) || (t == -1)) {
5998 tt = *localtime (&t);
5999 strftime (tzone, sizeof (tzone), "%Z", &tt);
6000 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6001 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6005 gmtoff = gmt_offset (&start, t);
6007 /* For each day of the year, calculate the tm_gmtoff. */
6008 for (day = 0; day < 365; day++) {
6011 tt = *localtime (&t);
6013 /* Daylight saving starts or ends here. */
6014 if (gmt_offset (&tt, t) != gmtoff) {
6018 /* Try to find the exact hour when daylight saving starts/ends. */
6022 tt1 = *localtime (&t1);
6023 } while (gmt_offset (&tt1, t1) != gmtoff);
6025 /* Try to find the exact minute when daylight saving starts/ends. */
6028 tt1 = *localtime (&t1);
6029 } while (gmt_offset (&tt1, t1) == gmtoff);
6031 strftime (tzone, sizeof (tzone), "%Z", &tt);
6033 /* Write data, if we're already in daylight saving, we're done. */
6035 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6036 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6042 memset (&end, 0, sizeof (end));
6043 end.tm_year = year-1900 + 1;
6048 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6049 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6050 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6051 mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
6055 /* This is only set once when we enter daylight saving. */
6056 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6057 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6059 gmtoff = gmt_offset (&tt, t);
6064 strftime (tzone, sizeof (tzone), "%Z", &tt);
6065 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6066 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6067 mono_array_set ((*data), gint64, 0, 0);
6068 mono_array_set ((*data), gint64, 1, 0);
6069 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6070 mono_array_set ((*data), gint64, 3, 0);
6075 MonoDomain *domain = mono_domain_get ();
6076 TIME_ZONE_INFORMATION tz_info;
6081 tz_id = GetTimeZoneInformation (&tz_info);
6082 if (tz_id == TIME_ZONE_ID_INVALID)
6085 MONO_CHECK_ARG_NULL (data);
6086 MONO_CHECK_ARG_NULL (names);
6088 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6089 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6091 for (i = 0; i < 32; ++i)
6092 if (!tz_info.DaylightName [i])
6094 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6095 for (i = 0; i < 32; ++i)
6096 if (!tz_info.StandardName [i])
6098 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6100 if ((year <= 1601) || (year > 30827)) {
6102 * According to MSDN, the MS time functions can't handle dates outside
6108 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6109 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6110 tz_info.StandardDate.wYear = year;
6111 convert_to_absolute_date(&tz_info.StandardDate);
6112 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6117 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6118 tz_info.DaylightDate.wYear = year;
6119 convert_to_absolute_date(&tz_info.DaylightDate);
6120 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6125 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6127 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6128 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6134 ICALL_EXPORT gpointer
6135 ves_icall_System_Object_obj_address (MonoObject *this)
6137 MONO_ARCH_SAVE_REGS;
6144 static inline gint32
6145 mono_array_get_byte_length (MonoArray *array)
6151 klass = array->obj.vtable->klass;
6153 if (array->bounds == NULL)
6154 length = array->max_length;
6157 for (i = 0; i < klass->rank; ++ i)
6158 length *= array->bounds [i].length;
6161 switch (klass->element_class->byval_arg.type) {
6164 case MONO_TYPE_BOOLEAN:
6168 case MONO_TYPE_CHAR:
6176 return length * sizeof (gpointer);
6187 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6189 MONO_ARCH_SAVE_REGS;
6191 return mono_array_get_byte_length (array);
6195 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6197 MONO_ARCH_SAVE_REGS;
6199 return mono_array_get (array, gint8, idx);
6203 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6205 MONO_ARCH_SAVE_REGS;
6207 mono_array_set (array, gint8, idx, value);
6210 ICALL_EXPORT MonoBoolean
6211 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6213 guint8 *src_buf, *dest_buf;
6215 MONO_ARCH_SAVE_REGS;
6217 /* This is called directly from the class libraries without going through the managed wrapper */
6218 MONO_CHECK_ARG_NULL (src);
6219 MONO_CHECK_ARG_NULL (dest);
6221 /* watch out for integer overflow */
6222 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6225 src_buf = (guint8 *)src->vector + src_offset;
6226 dest_buf = (guint8 *)dest->vector + dest_offset;
6229 memcpy (dest_buf, src_buf, count);
6231 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6236 #ifndef DISABLE_REMOTING
6237 ICALL_EXPORT MonoObject *
6238 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6240 MonoDomain *domain = mono_object_domain (this);
6242 MonoRealProxy *rp = ((MonoRealProxy *)this);
6243 MonoTransparentProxy *tp;
6247 MONO_ARCH_SAVE_REGS;
6249 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6250 tp = (MonoTransparentProxy*) res;
6252 MONO_OBJECT_SETREF (tp, rp, rp);
6253 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6254 klass = mono_class_from_mono_type (type);
6256 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6257 tp->remote_class = mono_remote_class (domain, class_name, klass);
6259 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6263 ICALL_EXPORT MonoReflectionType *
6264 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6266 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6270 /* System.Environment */
6273 ves_icall_System_Environment_get_UserName (void)
6275 MONO_ARCH_SAVE_REGS;
6277 /* using glib is more portable */
6278 return mono_string_new (mono_domain_get (), g_get_user_name ());
6282 ICALL_EXPORT MonoString *
6283 ves_icall_System_Environment_get_MachineName (void)
6285 #if defined (HOST_WIN32)
6290 len = MAX_COMPUTERNAME_LENGTH + 1;
6291 buf = g_new (gunichar2, len);
6294 if (GetComputerName (buf, (PDWORD) &len))
6295 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6299 #elif !defined(DISABLE_SOCKETS)
6303 if (gethostname (buf, sizeof (buf)) == 0)
6304 result = mono_string_new (mono_domain_get (), buf);
6310 return mono_string_new (mono_domain_get (), "mono");
6315 ves_icall_System_Environment_get_Platform (void)
6317 #if defined (TARGET_WIN32)
6320 #elif defined(__MACH__)
6323 // Notice that the value is hidden from user code, and only exposed
6324 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6325 // define and making assumptions based on Unix/128/4 values before there
6326 // was a MacOS define. Lots of code would assume that not-Unix meant
6327 // Windows, but in this case, it would be OSX.
6336 ICALL_EXPORT MonoString *
6337 ves_icall_System_Environment_get_NewLine (void)
6339 MONO_ARCH_SAVE_REGS;
6341 #if defined (HOST_WIN32)
6342 return mono_string_new (mono_domain_get (), "\r\n");
6344 return mono_string_new (mono_domain_get (), "\n");
6348 ICALL_EXPORT MonoString *
6349 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6354 MONO_ARCH_SAVE_REGS;
6359 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6360 value = g_getenv (utf8_name);
6367 return mono_string_new (mono_domain_get (), value);
6371 * There is no standard way to get at environ.
6374 #ifndef __MINGW32_VERSION
6375 #if defined(__APPLE__) && !defined (__arm__)
6376 /* Apple defines this in crt_externs.h but doesn't provide that header for
6377 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6378 * in fact exist on all implementations (so far)
6380 gchar ***_NSGetEnviron(void);
6381 #define environ (*_NSGetEnviron())
6389 ICALL_EXPORT MonoArray *
6390 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6401 env_strings = GetEnvironmentStrings();
6404 env_string = env_strings;
6405 while (*env_string != '\0') {
6406 /* weird case that MS seems to skip */
6407 if (*env_string != '=')
6409 while (*env_string != '\0')
6415 domain = mono_domain_get ();
6416 names = mono_array_new (domain, mono_defaults.string_class, n);
6420 env_string = env_strings;
6421 while (*env_string != '\0') {
6422 /* weird case that MS seems to skip */
6423 if (*env_string != '=') {
6424 equal_str = wcschr(env_string, '=');
6425 g_assert(equal_str);
6426 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6427 mono_array_setref (names, n, str);
6430 while (*env_string != '\0')
6435 FreeEnvironmentStrings (env_strings);
6447 MONO_ARCH_SAVE_REGS;
6450 for (e = environ; *e != 0; ++ e)
6453 domain = mono_domain_get ();
6454 names = mono_array_new (domain, mono_defaults.string_class, n);
6457 for (e = environ; *e != 0; ++ e) {
6458 parts = g_strsplit (*e, "=", 2);
6460 str = mono_string_new (domain, *parts);
6461 mono_array_setref (names, n, str);
6474 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6476 #if !GLIB_CHECK_VERSION(2,4,0)
6477 #define g_setenv(a,b,c) setenv(a,b,c)
6478 #define g_unsetenv(a) unsetenv(a)
6482 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6487 gunichar2 *utf16_name, *utf16_value;
6489 gchar *utf8_name, *utf8_value;
6492 MONO_ARCH_SAVE_REGS;
6495 utf16_name = mono_string_to_utf16 (name);
6496 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6497 SetEnvironmentVariable (utf16_name, NULL);
6498 g_free (utf16_name);
6502 utf16_value = mono_string_to_utf16 (value);
6504 SetEnvironmentVariable (utf16_name, utf16_value);
6506 g_free (utf16_name);
6507 g_free (utf16_value);
6509 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6511 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6512 g_unsetenv (utf8_name);
6517 utf8_value = mono_string_to_utf8_checked (value, &error);
6518 if (!mono_error_ok (&error)) {
6520 mono_error_raise_exception (&error);
6522 g_setenv (utf8_name, utf8_value, TRUE);
6525 g_free (utf8_value);
6530 ves_icall_System_Environment_Exit (int result)
6532 MONO_ARCH_SAVE_REGS;
6534 /* FIXME: There are some cleanup hangs that should be worked out, but
6535 * if the program is going to exit, everything will be cleaned up when
6536 * NaCl exits anyway.
6538 #ifndef __native_client__
6539 mono_runtime_shutdown ();
6541 /* This will kill the tp threads which cannot be suspended */
6542 mono_thread_pool_cleanup ();
6544 /* Suspend all managed threads since the runtime is going away */
6545 mono_thread_suspend_all_other_threads ();
6547 mono_runtime_quit ();
6550 /* we may need to do some cleanup here... */
6554 ICALL_EXPORT MonoString*
6555 ves_icall_System_Environment_GetGacPath (void)
6557 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6560 ICALL_EXPORT MonoString*
6561 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6563 #if defined (HOST_WIN32)
6564 #ifndef CSIDL_FLAG_CREATE
6565 #define CSIDL_FLAG_CREATE 0x8000
6568 WCHAR path [MAX_PATH];
6569 /* Create directory if no existing */
6570 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6574 return mono_string_new_utf16 (mono_domain_get (), path, len);
6577 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6579 return mono_string_new (mono_domain_get (), "");
6582 ICALL_EXPORT MonoArray *
6583 ves_icall_System_Environment_GetLogicalDrives (void)
6585 gunichar2 buf [256], *ptr, *dname;
6587 guint initial_size = 127, size = 128;
6590 MonoString *drivestr;
6591 MonoDomain *domain = mono_domain_get ();
6594 MONO_ARCH_SAVE_REGS;
6599 while (size > initial_size) {
6600 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6601 if (size > initial_size) {
6604 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6605 initial_size = size;
6619 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6624 while (*u16) { u16++; len ++; }
6625 drivestr = mono_string_new_utf16 (domain, dname, len);
6626 mono_array_setref (result, ndrives++, drivestr);
6636 ICALL_EXPORT MonoString *
6637 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6639 gunichar2 volume_name [MAX_PATH + 1];
6641 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6643 return mono_string_from_utf16 (volume_name);
6646 ICALL_EXPORT MonoString *
6647 ves_icall_System_Environment_InternalGetHome (void)
6649 MONO_ARCH_SAVE_REGS;
6651 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6654 static const char *encodings [] = {
6656 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6657 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6658 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6660 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6661 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6662 "x_unicode_2_0_utf_7",
6664 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6665 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6667 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6670 "unicodefffe", "utf_16be",
6677 * Returns the internal codepage, if the value of "int_code_page" is
6678 * 1 at entry, and we can not compute a suitable code page number,
6679 * returns the code page as a string
6681 ICALL_EXPORT MonoString*
6682 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6687 char *codepage = NULL;
6689 int want_name = *int_code_page;
6692 *int_code_page = -1;
6693 MONO_ARCH_SAVE_REGS;
6695 g_get_charset (&cset);
6696 c = codepage = strdup (cset);
6697 for (c = codepage; *c; c++){
6698 if (isascii (*c) && isalpha (*c))
6703 /* g_print ("charset: %s\n", cset); */
6705 /* handle some common aliases */
6708 for (i = 0; p != 0; ){
6709 if ((gssize) p < 7){
6711 p = encodings [++i];
6714 if (strcmp (p, codepage) == 0){
6715 *int_code_page = code;
6718 p = encodings [++i];
6721 if (strstr (codepage, "utf_8") != NULL)
6722 *int_code_page |= 0x10000000;
6725 if (want_name && *int_code_page == -1)
6726 return mono_string_new (mono_domain_get (), cset);
6731 ICALL_EXPORT MonoBoolean
6732 ves_icall_System_Environment_get_HasShutdownStarted (void)
6734 if (mono_runtime_is_shutting_down ())
6737 if (mono_domain_is_unloading (mono_domain_get ()))
6744 ves_icall_System_Environment_BroadcastSettingChange (void)
6747 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6752 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6753 MonoReflectionMethod *method,
6754 MonoArray *out_args)
6756 MONO_ARCH_SAVE_REGS;
6758 mono_message_init (mono_object_domain (this), this, method, out_args);
6761 #ifndef DISABLE_REMOTING
6762 ICALL_EXPORT MonoBoolean
6763 ves_icall_IsTransparentProxy (MonoObject *proxy)
6765 MONO_ARCH_SAVE_REGS;
6770 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6776 ICALL_EXPORT MonoReflectionMethod *
6777 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6778 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6782 MonoMethod **vtable;
6783 MonoMethod *res = NULL;
6785 MONO_CHECK_ARG_NULL (rtype);
6786 MONO_CHECK_ARG_NULL (rmethod);
6788 method = rmethod->method;
6789 klass = mono_class_from_mono_type (rtype->type);
6790 mono_class_init_or_throw (klass);
6792 if (MONO_CLASS_IS_INTERFACE (klass))
6795 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6798 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6799 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6805 mono_class_setup_vtable (klass);
6806 vtable = klass->vtable;
6808 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6809 gboolean variance_used = FALSE;
6810 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6811 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6813 res = vtable [offs + method->slot];
6815 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6818 if (method->slot != -1)
6819 res = vtable [method->slot];
6825 return mono_method_get_object (mono_domain_get (), res, NULL);
6829 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6834 MONO_ARCH_SAVE_REGS;
6836 klass = mono_class_from_mono_type (type->type);
6837 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6839 mono_vtable_set_is_remote (vtable, enable);
6843 ICALL_EXPORT MonoObject *
6844 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6849 MONO_ARCH_SAVE_REGS;
6851 domain = mono_object_domain (type);
6852 klass = mono_class_from_mono_type (type->type);
6853 mono_class_init_or_throw (klass);
6855 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6856 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6858 if (klass->rank >= 1) {
6859 g_assert (klass->rank == 1);
6860 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6862 /* Bypass remoting object creation check */
6863 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6867 ICALL_EXPORT MonoString *
6868 ves_icall_System_IO_get_temp_path (void)
6870 MONO_ARCH_SAVE_REGS;
6872 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6875 #ifndef PLATFORM_NO_DRIVEINFO
6876 ICALL_EXPORT MonoBoolean
6877 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6878 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6882 ULARGE_INTEGER wapi_free_bytes_avail;
6883 ULARGE_INTEGER wapi_total_number_of_bytes;
6884 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6886 MONO_ARCH_SAVE_REGS;
6888 *error = ERROR_SUCCESS;
6889 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6890 &wapi_total_number_of_free_bytes);
6893 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6894 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6895 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6897 *free_bytes_avail = 0;
6898 *total_number_of_bytes = 0;
6899 *total_number_of_free_bytes = 0;
6900 *error = GetLastError ();
6906 ICALL_EXPORT guint32
6907 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6909 MONO_ARCH_SAVE_REGS;
6911 return GetDriveType (mono_string_chars (root_path_name));
6915 ICALL_EXPORT gpointer
6916 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6918 MONO_ARCH_SAVE_REGS;
6920 return mono_compile_method (method);
6923 ICALL_EXPORT MonoString *
6924 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6929 MONO_ARCH_SAVE_REGS;
6931 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6933 #if defined (HOST_WIN32)
6934 /* Avoid mixing '/' and '\\' */
6937 for (i = strlen (path) - 1; i >= 0; i--)
6938 if (path [i] == '/')
6942 mcpath = mono_string_new (mono_domain_get (), path);
6949 get_bundled_app_config (void)
6951 const gchar *app_config;
6954 gchar *config_file_name, *config_file_path;
6958 MONO_ARCH_SAVE_REGS;
6960 domain = mono_domain_get ();
6961 file = domain->setup->configuration_file;
6965 // Retrieve config file and remove the extension
6966 config_file_name = mono_string_to_utf8 (file);
6967 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6968 if (!config_file_path)
6969 config_file_path = config_file_name;
6970 len = strlen (config_file_path) - strlen (".config");
6971 module = g_malloc0 (len + 1);
6972 memcpy (module, config_file_path, len);
6973 // Get the config file from the module name
6974 app_config = mono_config_string_for_assembly_file (module);
6977 if (config_file_name != config_file_path)
6978 g_free (config_file_name);
6979 g_free (config_file_path);
6984 return mono_string_new (mono_domain_get (), app_config);
6988 get_bundled_machine_config (void)
6990 const gchar *machine_config;
6992 MONO_ARCH_SAVE_REGS;
6994 machine_config = mono_get_machine_config ();
6996 if (!machine_config)
6999 return mono_string_new (mono_domain_get (), machine_config);
7002 ICALL_EXPORT MonoString *
7003 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7008 MONO_ARCH_SAVE_REGS;
7010 path = g_path_get_dirname (mono_get_config_dir ());
7012 #if defined (HOST_WIN32)
7013 /* Avoid mixing '/' and '\\' */
7016 for (i = strlen (path) - 1; i >= 0; i--)
7017 if (path [i] == '/')
7021 ipath = mono_string_new (mono_domain_get (), path);
7027 ICALL_EXPORT gboolean
7028 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7030 MonoPEResourceDataEntry *entry;
7033 MONO_ARCH_SAVE_REGS;
7035 if (!assembly || !result || !size)
7040 image = assembly->assembly->image;
7041 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7045 *result = mono_image_rva_map (image, entry->rde_data_offset);
7050 *size = entry->rde_size;
7055 ICALL_EXPORT MonoBoolean
7056 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7058 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7061 ICALL_EXPORT MonoBoolean
7062 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7064 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7065 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7071 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7073 if (mono_get_runtime_callbacks ()->debug_log)
7074 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7078 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7080 #if defined (HOST_WIN32)
7081 OutputDebugString (mono_string_chars (message));
7083 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7087 /* Only used for value types */
7088 ICALL_EXPORT MonoObject *
7089 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7094 MONO_ARCH_SAVE_REGS;
7096 domain = mono_object_domain (type);
7097 klass = mono_class_from_mono_type (type->type);
7098 mono_class_init_or_throw (klass);
7100 if (mono_class_is_nullable (klass))
7101 /* No arguments -> null */
7104 return mono_object_new (domain, klass);
7107 ICALL_EXPORT MonoReflectionMethod *
7108 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7110 MonoClass *klass, *parent;
7111 MonoMethod *method = m->method;
7112 MonoMethod *result = NULL;
7115 MONO_ARCH_SAVE_REGS;
7117 if (method->klass == NULL)
7120 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7121 MONO_CLASS_IS_INTERFACE (method->klass) ||
7122 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7125 slot = mono_method_get_vtable_slot (method);
7129 klass = method->klass;
7130 if (klass->generic_class)
7131 klass = klass->generic_class->container_class;
7134 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7135 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7136 mono_class_setup_vtable (parent);
7137 if (parent->vtable_size <= slot)
7142 klass = klass->parent;
7147 if (klass == method->klass)
7150 /*This is possible if definition == FALSE.
7151 * Do it here to be really sure we don't read invalid memory.
7153 if (slot >= klass->vtable_size)
7156 mono_class_setup_vtable (klass);
7158 result = klass->vtable [slot];
7159 if (result == NULL) {
7160 /* It is an abstract method */
7161 gpointer iter = NULL;
7162 while ((result = mono_class_get_methods (klass, &iter)))
7163 if (result->slot == slot)
7170 return mono_method_get_object (mono_domain_get (), result, NULL);
7173 ICALL_EXPORT MonoString*
7174 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7176 MonoMethod *method = m->method;
7178 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7183 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7185 MONO_ARCH_SAVE_REGS;
7187 iter->sig = *(MonoMethodSignature**)argsp;
7189 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7190 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7193 /* FIXME: it's not documented what start is exactly... */
7197 iter->args = argsp + sizeof (gpointer);
7199 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7201 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7204 ICALL_EXPORT MonoTypedRef
7205 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7207 guint32 i, arg_size;
7210 MONO_ARCH_SAVE_REGS;
7212 i = iter->sig->sentinelpos + iter->next_arg;
7214 g_assert (i < iter->sig->param_count);
7216 res.type = iter->sig->params [i];
7217 res.klass = mono_class_from_mono_type (res.type);
7218 arg_size = mono_type_stack_size (res.type, &align);
7219 #if defined(__arm__) || defined(__mips__)
7220 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7222 res.value = iter->args;
7223 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7224 /* Values are stored as 8 byte register sized objects, but 'value'
7225 * is dereferenced as a pointer in other routines.
7227 res.value = (char*)res.value + 4;
7229 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7230 if (arg_size <= sizeof (gpointer)) {
7232 int padding = arg_size - mono_type_size (res.type, &dummy);
7233 res.value = (guint8*)res.value + padding;
7236 iter->args = (char*)iter->args + arg_size;
7239 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7244 ICALL_EXPORT MonoTypedRef
7245 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7247 guint32 i, arg_size;
7250 MONO_ARCH_SAVE_REGS;
7252 i = iter->sig->sentinelpos + iter->next_arg;
7254 g_assert (i < iter->sig->param_count);
7256 while (i < iter->sig->param_count) {
7257 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7259 res.type = iter->sig->params [i];
7260 res.klass = mono_class_from_mono_type (res.type);
7261 /* FIXME: endianess issue... */
7262 arg_size = mono_type_stack_size (res.type, &align);
7263 #if defined(__arm__) || defined(__mips__)
7264 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7266 res.value = iter->args;
7267 iter->args = (char*)iter->args + arg_size;
7269 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7272 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7280 ICALL_EXPORT MonoType*
7281 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7284 MONO_ARCH_SAVE_REGS;
7286 i = iter->sig->sentinelpos + iter->next_arg;
7288 g_assert (i < iter->sig->param_count);
7290 return iter->sig->params [i];
7293 ICALL_EXPORT MonoObject*
7294 mono_TypedReference_ToObject (MonoTypedRef tref)
7296 MONO_ARCH_SAVE_REGS;
7298 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7299 MonoObject** objp = tref.value;
7303 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7306 ICALL_EXPORT MonoObject*
7307 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7309 MONO_ARCH_SAVE_REGS;
7311 if (MONO_TYPE_IS_REFERENCE (type)) {
7312 MonoObject** objp = value;
7316 return mono_value_box (mono_domain_get (), klass, value);
7320 prelink_method (MonoMethod *method)
7322 const char *exc_class, *exc_arg;
7323 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7325 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7327 mono_raise_exception(
7328 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7330 /* create the wrapper, too? */
7334 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7336 MONO_ARCH_SAVE_REGS;
7337 prelink_method (method->method);
7341 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7343 MonoClass *klass = mono_class_from_mono_type (type->type);
7345 gpointer iter = NULL;
7346 MONO_ARCH_SAVE_REGS;
7348 mono_class_init_or_throw (klass);
7350 while ((m = mono_class_get_methods (klass, &iter)))
7354 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7356 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7357 gint32 const **exponents,
7358 gunichar2 const **digitLowerTable,
7359 gunichar2 const **digitUpperTable,
7360 gint64 const **tenPowersList,
7361 gint32 const **decHexDigits)
7363 *mantissas = Formatter_MantissaBitsTable;
7364 *exponents = Formatter_TensExponentTable;
7365 *digitLowerTable = Formatter_DigitLowerTable;
7366 *digitUpperTable = Formatter_DigitUpperTable;
7367 *tenPowersList = Formatter_TenPowersList;
7368 *decHexDigits = Formatter_DecHexDigits;
7372 get_category_data (int version,
7373 guint8 const **category_data,
7374 guint16 const **category_astral_index)
7376 *category_astral_index = NULL;
7378 #ifndef DISABLE_NET_4_0
7380 *category_data = CategoryData_v4;
7381 #ifndef DISABLE_ASTRAL
7382 *category_astral_index = CategoryData_v4_astral_index;
7388 *category_data = CategoryData_v2;
7389 #ifndef DISABLE_ASTRAL
7390 *category_astral_index = CategoryData_v2_astral_index;
7394 /* These parameters are "readonly" in corlib/System/Char.cs */
7396 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7397 guint8 const **category_data,
7398 guint16 const **category_astral_index,
7399 guint8 const **numeric_data,
7400 gdouble const **numeric_data_values,
7401 guint16 const **to_lower_data_low,
7402 guint16 const **to_lower_data_high,
7403 guint16 const **to_upper_data_low,
7404 guint16 const **to_upper_data_high)
7406 get_category_data (category_data_version, category_data, category_astral_index);
7407 *numeric_data = NumericData;
7408 *numeric_data_values = NumericDataValues;
7409 *to_lower_data_low = ToLowerDataLow;
7410 *to_lower_data_high = ToLowerDataHigh;
7411 *to_upper_data_low = ToUpperDataLow;
7412 *to_upper_data_high = ToUpperDataHigh;
7416 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7418 return method->method->token;
7422 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7423 * and avoid useless allocations.
7426 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7430 for (i = 0; i < type->num_mods; ++i) {
7431 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7436 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7438 for (i = 0; i < type->num_mods; ++i) {
7439 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7440 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7441 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7448 ICALL_EXPORT MonoArray*
7449 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7451 MonoType *type = param->ClassImpl->type;
7452 MonoClass *member_class = mono_object_class (param->MemberImpl);
7453 MonoMethod *method = NULL;
7456 MonoMethodSignature *sig;
7458 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7459 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7460 method = rmethod->method;
7461 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7462 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7463 if (!(method = prop->property->get))
7464 method = prop->property->set;
7467 char *type_name = mono_type_get_full_name (member_class);
7468 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7469 MonoException *ex = mono_get_exception_not_supported (msg);
7472 mono_raise_exception (ex);
7475 image = method->klass->image;
7476 pos = param->PositionImpl;
7477 sig = mono_method_signature (method);
7481 type = sig->params [pos];
7483 return type_array_from_modifiers (image, type, optional);
7487 get_property_type (MonoProperty *prop)
7489 MonoMethodSignature *sig;
7491 sig = mono_method_signature (prop->get);
7493 } else if (prop->set) {
7494 sig = mono_method_signature (prop->set);
7495 return sig->params [sig->param_count - 1];
7500 ICALL_EXPORT MonoArray*
7501 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7503 MonoType *type = get_property_type (property->property);
7504 MonoImage *image = property->klass->image;
7508 return type_array_from_modifiers (image, type, optional);
7512 *Construct a MonoType suited to be used to decode a constant blob object.
7514 * @type is the target type which will be constructed
7515 * @blob_type is the blob type, for example, that comes from the constant table
7516 * @real_type is the expected constructed type.
7519 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7521 type->type = blob_type;
7522 type->data.klass = NULL;
7523 if (blob_type == MONO_TYPE_CLASS)
7524 type->data.klass = mono_defaults.object_class;
7525 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7526 /* For enums, we need to use the base type */
7527 type->type = MONO_TYPE_VALUETYPE;
7528 type->data.klass = mono_class_from_mono_type (real_type);
7530 type->data.klass = mono_class_from_mono_type (real_type);
7533 ICALL_EXPORT MonoObject*
7534 property_info_get_default_value (MonoReflectionProperty *property)
7537 MonoProperty *prop = property->property;
7538 MonoType *type = get_property_type (prop);
7539 MonoDomain *domain = mono_object_domain (property);
7540 MonoTypeEnum def_type;
7541 const char *def_value;
7544 mono_class_init (prop->parent);
7546 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7547 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7549 def_value = mono_class_get_property_default_value (prop, &def_type);
7551 mono_type_from_blob_type (&blob_type, def_type, type);
7552 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7557 ICALL_EXPORT MonoBoolean
7558 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7560 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7561 MonoCustomAttrInfo *cinfo;
7564 mono_class_init_or_throw (attr_class);
7566 cinfo = mono_reflection_get_custom_attrs_info (obj);
7569 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7571 mono_custom_attrs_free (cinfo);
7575 ICALL_EXPORT MonoArray*
7576 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7578 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7583 mono_class_init_or_throw (attr_class);
7585 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7586 if (!mono_error_ok (&error))
7587 mono_error_raise_exception (&error);
7588 if (mono_loader_get_last_error ()) {
7589 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7590 g_assert_not_reached ();
7598 ICALL_EXPORT MonoString*
7599 ves_icall_Mono_Runtime_GetDisplayName (void)
7602 MonoString *display_name;
7604 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7605 display_name = mono_string_new (mono_domain_get (), info);
7607 return display_name;
7610 ICALL_EXPORT MonoString*
7611 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7613 MonoString *message;
7617 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7618 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7621 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7623 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7631 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7632 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7633 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7634 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7635 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7636 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7637 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7638 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7642 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7647 gunichar2 last, prev_last, prev2_last;
7654 int havePadding = 0;
7656 last = prev_last = 0, prev2_last = 0;
7657 for (i = 0; i < ilength; i++) {
7659 if (c >= sizeof (dbase64)) {
7660 exc = mono_exception_from_name_msg (mono_get_corlib (),
7661 "System", "FormatException",
7662 "Invalid character found.");
7663 mono_raise_exception (exc);
7664 } else if (isspace (c)) {
7666 } else if (havePadding && c != '=') {
7667 exc = mono_exception_from_name_msg (mono_get_corlib (),
7668 "System", "FormatException",
7669 "Invalid character found.");
7670 mono_raise_exception (exc);
7672 if (c == '=') havePadding = 1;
7673 prev2_last = prev_last;
7679 olength = ilength - ignored;
7681 if (allowWhitespaceOnly && olength == 0) {
7682 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7685 if ((olength & 3) != 0 || olength <= 0) {
7686 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7687 "FormatException", "Invalid length.");
7688 mono_raise_exception (exc);
7691 if (prev2_last == '=') {
7692 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7693 mono_raise_exception (exc);
7696 olength = (olength * 3) / 4;
7700 if (prev_last == '=')
7703 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7704 res_ptr = mono_array_addr (result, guchar, 0);
7705 for (i = 0; i < ilength; ) {
7708 for (k = 0; k < 4 && i < ilength;) {
7714 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7715 exc = mono_exception_from_name_msg (mono_get_corlib (),
7716 "System", "FormatException",
7717 "Invalid character found.");
7718 mono_raise_exception (exc);
7723 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7725 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7727 *res_ptr++ = (b [2] << 6) | b [3];
7729 while (i < ilength && isspace (start [i]))
7736 ICALL_EXPORT MonoArray *
7737 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7739 MONO_ARCH_SAVE_REGS;
7741 return base64_to_byte_array (mono_string_chars (str),
7742 mono_string_length (str), allowWhitespaceOnly);
7745 ICALL_EXPORT MonoArray *
7746 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7748 MONO_ARCH_SAVE_REGS;
7750 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7754 #ifndef DISABLE_ICALL_TABLES
7756 #define ICALL_TYPE(id,name,first)
7757 #define ICALL(id,name,func) Icall_ ## id,
7760 #include "metadata/icall-def.h"
7766 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7767 #define ICALL(id,name,func)
7769 #include "metadata/icall-def.h"
7775 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7776 #define ICALL(id,name,func)
7778 guint16 first_icall;
7781 static const IcallTypeDesc
7782 icall_type_descs [] = {
7783 #include "metadata/icall-def.h"
7787 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7790 #define ICALL_TYPE(id,name,first)
7793 #ifdef HAVE_ARRAY_ELEM_INIT
7794 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7795 #define MSGSTRFIELD1(line) str##line
7797 static const struct msgstrtn_t {
7798 #define ICALL(id,name,func)
7800 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7801 #include "metadata/icall-def.h"
7803 } icall_type_names_str = {
7804 #define ICALL_TYPE(id,name,first) (name),
7805 #include "metadata/icall-def.h"
7808 static const guint16 icall_type_names_idx [] = {
7809 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7810 #include "metadata/icall-def.h"
7813 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7815 static const struct msgstr_t {
7817 #define ICALL_TYPE(id,name,first)
7818 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7819 #include "metadata/icall-def.h"
7821 } icall_names_str = {
7822 #define ICALL(id,name,func) (name),
7823 #include "metadata/icall-def.h"
7826 static const guint16 icall_names_idx [] = {
7827 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7828 #include "metadata/icall-def.h"
7831 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7837 #define ICALL_TYPE(id,name,first) name,
7838 #define ICALL(id,name,func)
7839 static const char* const
7840 icall_type_names [] = {
7841 #include "metadata/icall-def.h"
7845 #define icall_type_name_get(id) (icall_type_names [(id)])
7849 #define ICALL_TYPE(id,name,first)
7850 #define ICALL(id,name,func) name,
7851 static const char* const
7853 #include "metadata/icall-def.h"
7856 #define icall_name_get(id) icall_names [(id)]
7858 #endif /* !HAVE_ARRAY_ELEM_INIT */
7862 #define ICALL_TYPE(id,name,first)
7863 #define ICALL(id,name,func) func,
7864 static const gconstpointer
7865 icall_functions [] = {
7866 #include "metadata/icall-def.h"
7870 #ifdef ENABLE_ICALL_SYMBOL_MAP
7873 #define ICALL_TYPE(id,name,first)
7874 #define ICALL(id,name,func) #func,
7875 static const gconstpointer
7876 icall_symbols [] = {
7877 #include "metadata/icall-def.h"
7882 #endif /* DISABLE_ICALL_TABLES */
7884 static GHashTable *icall_hash = NULL;
7885 static GHashTable *jit_icall_hash_name = NULL;
7886 static GHashTable *jit_icall_hash_addr = NULL;
7889 mono_icall_init (void)
7891 #ifndef DISABLE_ICALL_TABLES
7894 /* check that tables are sorted: disable in release */
7897 const char *prev_class = NULL;
7898 const char *prev_method;
7900 for (i = 0; i < Icall_type_num; ++i) {
7901 const IcallTypeDesc *desc;
7904 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7905 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7906 prev_class = icall_type_name_get (i);
7907 desc = &icall_type_descs [i];
7908 num_icalls = icall_desc_num_icalls (desc);
7909 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7910 for (j = 0; j < num_icalls; ++j) {
7911 const char *methodn = icall_name_get (desc->first_icall + j);
7912 if (prev_method && strcmp (prev_method, methodn) >= 0)
7913 g_print ("method %s should come before method %s\n", methodn, prev_method);
7914 prev_method = methodn;
7920 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7924 mono_icall_cleanup (void)
7926 g_hash_table_destroy (icall_hash);
7927 g_hash_table_destroy (jit_icall_hash_name);
7928 g_hash_table_destroy (jit_icall_hash_addr);
7932 mono_add_internal_call (const char *name, gconstpointer method)
7934 mono_loader_lock ();
7936 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7938 mono_loader_unlock ();
7941 #ifndef DISABLE_ICALL_TABLES
7943 #ifdef HAVE_ARRAY_ELEM_INIT
7945 compare_method_imap (const void *key, const void *elem)
7947 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7948 return strcmp (key, method_name);
7952 find_method_icall (const IcallTypeDesc *imap, const char *name)
7954 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7957 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7961 compare_class_imap (const void *key, const void *elem)
7963 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7964 return strcmp (key, class_name);
7967 static const IcallTypeDesc*
7968 find_class_icalls (const char *name)
7970 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7973 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7976 #else /* HAVE_ARRAY_ELEM_INIT */
7979 compare_method_imap (const void *key, const void *elem)
7981 const char** method_name = (const char**)elem;
7982 return strcmp (key, *method_name);
7986 find_method_icall (const IcallTypeDesc *imap, const char *name)
7988 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7991 return (gpointer)icall_functions [(nameslot - icall_names)];
7995 compare_class_imap (const void *key, const void *elem)
7997 const char** class_name = (const char**)elem;
7998 return strcmp (key, *class_name);
8001 static const IcallTypeDesc*
8002 find_class_icalls (const char *name)
8004 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8007 return &icall_type_descs [nameslot - icall_type_names];
8010 #endif /* HAVE_ARRAY_ELEM_INIT */
8012 #endif /* DISABLE_ICALL_TABLES */
8015 * we should probably export this as an helper (handle nested types).
8016 * Returns the number of chars written in buf.
8019 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8021 int nspacelen, cnamelen;
8022 nspacelen = strlen (klass->name_space);
8023 cnamelen = strlen (klass->name);
8024 if (nspacelen + cnamelen + 2 > bufsize)
8027 memcpy (buf, klass->name_space, nspacelen);
8028 buf [nspacelen ++] = '.';
8030 memcpy (buf + nspacelen, klass->name, cnamelen);
8031 buf [nspacelen + cnamelen] = 0;
8032 return nspacelen + cnamelen;
8035 #ifdef DISABLE_ICALL_TABLES
8037 no_icall_table (void)
8039 g_assert_not_reached ();
8044 mono_lookup_internal_call (MonoMethod *method)
8049 int typelen = 0, mlen, siglen;
8051 #ifndef DISABLE_ICALL_TABLES
8052 const IcallTypeDesc *imap = NULL;
8055 g_assert (method != NULL);
8057 if (method->is_inflated)
8058 method = ((MonoMethodInflated *) method)->declaring;
8060 if (method->klass->nested_in) {
8061 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8065 mname [pos++] = '/';
8068 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8074 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8079 #ifndef DISABLE_ICALL_TABLES
8080 imap = find_class_icalls (mname);
8083 mname [typelen] = ':';
8084 mname [typelen + 1] = ':';
8086 mlen = strlen (method->name);
8087 memcpy (mname + typelen + 2, method->name, mlen);
8088 sigstart = mname + typelen + 2 + mlen;
8091 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8092 siglen = strlen (tmpsig);
8093 if (typelen + mlen + siglen + 6 > sizeof (mname))
8096 memcpy (sigstart + 1, tmpsig, siglen);
8097 sigstart [siglen + 1] = ')';
8098 sigstart [siglen + 2] = 0;
8101 mono_loader_lock ();
8103 res = g_hash_table_lookup (icall_hash, mname);
8105 mono_loader_unlock ();
8108 /* try without signature */
8110 res = g_hash_table_lookup (icall_hash, mname);
8112 mono_loader_unlock ();
8116 #ifdef DISABLE_ICALL_TABLES
8117 mono_loader_unlock ();
8118 /* Fail only when the result is actually used */
8119 /* mono_marshal_get_native_wrapper () depends on this */
8120 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8121 return ves_icall_System_String_ctor_RedirectToCreateString;
8123 return no_icall_table;
8125 /* it wasn't found in the static call tables */
8127 mono_loader_unlock ();
8130 res = find_method_icall (imap, sigstart - mlen);
8132 mono_loader_unlock ();
8135 /* try _with_ signature */
8137 res = find_method_icall (imap, sigstart - mlen);
8139 mono_loader_unlock ();
8143 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8144 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8145 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8146 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8147 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");
8148 g_print ("If you see other errors or faults after this message they are probably related\n");
8149 g_print ("and you need to fix your mono install first.\n");
8151 mono_loader_unlock ();
8157 #ifdef ENABLE_ICALL_SYMBOL_MAP
8159 func_cmp (gconstpointer key, gconstpointer p)
8161 return (gsize)key - (gsize)*(gsize*)p;
8166 * mono_lookup_icall_symbol:
8168 * Given the icall METHOD, returns its C symbol.
8171 mono_lookup_icall_symbol (MonoMethod *m)
8173 #ifdef DISABLE_ICALL_TABLES
8174 g_assert_not_reached ();
8177 #ifdef ENABLE_ICALL_SYMBOL_MAP
8181 static gconstpointer *functions_sorted;
8182 static const char**symbols_sorted;
8183 static gboolean inited;
8188 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8189 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8190 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8191 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8192 /* Bubble sort the two arrays */
8196 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8197 if (functions_sorted [i] > functions_sorted [i + 1]) {
8200 tmp = functions_sorted [i];
8201 functions_sorted [i] = functions_sorted [i + 1];
8202 functions_sorted [i + 1] = tmp;
8203 tmp = symbols_sorted [i];
8204 symbols_sorted [i] = symbols_sorted [i + 1];
8205 symbols_sorted [i + 1] = tmp;
8212 func = mono_lookup_internal_call (m);
8215 slot = bsearch (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8219 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8221 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8222 g_assert_not_reached ();
8229 type_from_typename (char *typename)
8231 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8233 if (!strcmp (typename, "int"))
8234 klass = mono_defaults.int_class;
8235 else if (!strcmp (typename, "ptr"))
8236 klass = mono_defaults.int_class;
8237 else if (!strcmp (typename, "void"))
8238 klass = mono_defaults.void_class;
8239 else if (!strcmp (typename, "int32"))
8240 klass = mono_defaults.int32_class;
8241 else if (!strcmp (typename, "uint32"))
8242 klass = mono_defaults.uint32_class;
8243 else if (!strcmp (typename, "int8"))
8244 klass = mono_defaults.sbyte_class;
8245 else if (!strcmp (typename, "uint8"))
8246 klass = mono_defaults.byte_class;
8247 else if (!strcmp (typename, "int16"))
8248 klass = mono_defaults.int16_class;
8249 else if (!strcmp (typename, "uint16"))
8250 klass = mono_defaults.uint16_class;
8251 else if (!strcmp (typename, "long"))
8252 klass = mono_defaults.int64_class;
8253 else if (!strcmp (typename, "ulong"))
8254 klass = mono_defaults.uint64_class;
8255 else if (!strcmp (typename, "float"))
8256 klass = mono_defaults.single_class;
8257 else if (!strcmp (typename, "double"))
8258 klass = mono_defaults.double_class;
8259 else if (!strcmp (typename, "object"))
8260 klass = mono_defaults.object_class;
8261 else if (!strcmp (typename, "obj"))
8262 klass = mono_defaults.object_class;
8263 else if (!strcmp (typename, "string"))
8264 klass = mono_defaults.string_class;
8265 else if (!strcmp (typename, "bool"))
8266 klass = mono_defaults.boolean_class;
8267 else if (!strcmp (typename, "boolean"))
8268 klass = mono_defaults.boolean_class;
8270 g_error ("%s", typename);
8271 g_assert_not_reached ();
8273 return &klass->byval_arg;
8276 MonoMethodSignature*
8277 mono_create_icall_signature (const char *sigstr)
8282 MonoMethodSignature *res;
8284 mono_loader_lock ();
8285 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8287 mono_loader_unlock ();
8291 parts = g_strsplit (sigstr, " ", 256);
8300 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8305 * Under windows, the default pinvoke calling convention is STDCALL but
8308 res->call_convention = MONO_CALL_C;
8311 res->ret = type_from_typename (parts [0]);
8312 for (i = 1; i < len; ++i) {
8313 res->params [i - 1] = type_from_typename (parts [i]);
8318 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8320 mono_loader_unlock ();
8326 mono_find_jit_icall_by_name (const char *name)
8328 MonoJitICallInfo *info;
8329 g_assert (jit_icall_hash_name);
8331 mono_loader_lock ();
8332 info = g_hash_table_lookup (jit_icall_hash_name, name);
8333 mono_loader_unlock ();
8338 mono_find_jit_icall_by_addr (gconstpointer addr)
8340 MonoJitICallInfo *info;
8341 g_assert (jit_icall_hash_addr);
8343 mono_loader_lock ();
8344 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8345 mono_loader_unlock ();
8351 * mono_get_jit_icall_info:
8353 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8354 * caller should access it while holding the loader lock.
8357 mono_get_jit_icall_info (void)
8359 return jit_icall_hash_name;
8363 * mono_lookup_jit_icall_symbol:
8365 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8368 mono_lookup_jit_icall_symbol (const char *name)
8370 MonoJitICallInfo *info;
8371 const char *res = NULL;
8373 mono_loader_lock ();
8374 info = g_hash_table_lookup (jit_icall_hash_name, name);
8376 res = info->c_symbol;
8377 mono_loader_unlock ();
8382 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8384 mono_loader_lock ();
8385 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8386 mono_loader_unlock ();
8390 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8392 MonoJitICallInfo *info;
8397 mono_loader_lock ();
8399 if (!jit_icall_hash_name) {
8400 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8401 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8404 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8405 g_warning ("jit icall already defined \"%s\"\n", name);
8406 g_assert_not_reached ();
8409 info = g_new0 (MonoJitICallInfo, 1);
8414 info->c_symbol = c_symbol;
8417 info->wrapper = func;
8419 info->wrapper = NULL;
8422 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8423 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8425 mono_loader_unlock ();
8430 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8432 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);