5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
10 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * Copyright 2011-2014 Xamarin Inc (http://www.xamarin.com).
23 #ifdef HAVE_SYS_TIME_H
29 #if defined (HOST_WIN32)
32 #if defined (HAVE_WCHAR_H)
36 #include "mono/utils/mono-membar.h"
37 #include <mono/metadata/object.h>
38 #include <mono/metadata/threads.h>
39 #include <mono/metadata/threads-types.h>
40 #include <mono/metadata/threadpool.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/assembly.h>
44 #include <mono/metadata/tabledefs.h>
45 #include <mono/metadata/exception.h>
46 #include <mono/metadata/file-io.h>
47 #include <mono/metadata/console-io.h>
48 #include <mono/metadata/socket-io.h>
49 #include <mono/metadata/mono-endian.h>
50 #include <mono/metadata/tokentype.h>
51 #include <mono/metadata/domain-internals.h>
52 #include <mono/metadata/metadata-internals.h>
53 #include <mono/metadata/class-internals.h>
54 #include <mono/metadata/marshal.h>
55 #include <mono/metadata/gc-internal.h>
56 #include <mono/metadata/mono-gc.h>
57 #include <mono/metadata/rand.h>
58 #include <mono/metadata/sysmath.h>
59 #include <mono/metadata/string-icalls.h>
60 #include <mono/metadata/debug-helpers.h>
61 #include <mono/metadata/process.h>
62 #include <mono/metadata/environment.h>
63 #include <mono/metadata/profiler-private.h>
64 #include <mono/metadata/locales.h>
65 #include <mono/metadata/filewatcher.h>
66 #include <mono/metadata/char-conversions.h>
67 #include <mono/metadata/security.h>
68 #include <mono/metadata/mono-config.h>
69 #include <mono/metadata/cil-coff.h>
70 #include <mono/metadata/number-formatter.h>
71 #include <mono/metadata/security-manager.h>
72 #include <mono/metadata/security-core-clr.h>
73 #include <mono/metadata/mono-perfcounters.h>
74 #include <mono/metadata/mono-debug.h>
75 #include <mono/metadata/mono-ptr-array.h>
76 #include <mono/metadata/verify-internals.h>
77 #include <mono/metadata/runtime.h>
78 #include <mono/io-layer/io-layer.h>
79 #include <mono/utils/strtod.h>
80 #include <mono/utils/monobitset.h>
81 #include <mono/utils/mono-time.h>
82 #include <mono/utils/mono-proclib.h>
83 #include <mono/utils/mono-string.h>
84 #include <mono/utils/mono-error-internals.h>
85 #include <mono/utils/mono-mmap.h>
86 #include <mono/utils/mono-io-portability.h>
87 #include <mono/utils/mono-digest.h>
88 #include <mono/utils/bsearch.h>
89 #include <mono/utils/mono-mutex.h>
90 #include <mono/utils/mono-threads.h>
92 #if defined (HOST_WIN32)
98 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
100 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
103 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
105 static inline MonoBoolean
106 is_generic_parameter (MonoType *type)
108 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
112 mono_class_init_or_throw (MonoClass *klass)
114 if (!mono_class_init (klass))
115 mono_raise_exception (mono_class_get_exception_for_failure (klass));
119 * We expect a pointer to a char, not a string
121 ICALL_EXPORT gboolean
122 mono_double_ParseImpl (char *ptr, double *result)
124 gchar *endptr = NULL;
131 *result = strtod (ptr, &endptr);
134 /* mono_strtod () is not thread-safe */
135 EnterCriticalSection (&mono_strtod_mutex);
136 *result = mono_strtod (ptr, &endptr);
137 LeaveCriticalSection (&mono_strtod_mutex);
141 if (!*ptr || (endptr && *endptr))
147 ICALL_EXPORT MonoObject *
148 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
157 ao = (MonoArray *)this;
158 ac = (MonoClass *)ao->obj.vtable->klass;
160 esize = mono_array_element_size (ac);
161 ea = (gpointer*)((char*)ao->vector + (pos * esize));
163 if (ac->element_class->valuetype)
164 return mono_value_box (this->vtable->domain, ac->element_class, ea);
169 ICALL_EXPORT MonoObject *
170 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
178 MONO_CHECK_ARG_NULL (idxs);
180 io = (MonoArray *)idxs;
181 ic = (MonoClass *)io->obj.vtable->klass;
183 ao = (MonoArray *)this;
184 ac = (MonoClass *)ao->obj.vtable->klass;
186 g_assert (ic->rank == 1);
187 if (io->bounds != NULL || io->max_length != ac->rank)
188 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
190 ind = (gint32 *)io->vector;
192 if (ao->bounds == NULL) {
193 if (*ind < 0 || *ind >= ao->max_length)
194 mono_raise_exception (mono_get_exception_index_out_of_range ());
196 return ves_icall_System_Array_GetValueImpl (this, *ind);
199 for (i = 0; i < ac->rank; i++)
200 if ((ind [i] < ao->bounds [i].lower_bound) ||
201 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
202 mono_raise_exception (mono_get_exception_index_out_of_range ());
204 pos = ind [0] - ao->bounds [0].lower_bound;
205 for (i = 1; i < ac->rank; i++)
206 pos = pos*ao->bounds [i].length + ind [i] -
207 ao->bounds [i].lower_bound;
209 return ves_icall_System_Array_GetValueImpl (this, pos);
213 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
215 MonoClass *ac, *vc, *ec;
227 vc = value->vtable->klass;
231 ac = this->obj.vtable->klass;
232 ec = ac->element_class;
234 esize = mono_array_element_size (ac);
235 ea = (gpointer*)((char*)this->vector + (pos * esize));
236 va = (gpointer*)((char*)value + sizeof (MonoObject));
238 if (mono_class_is_nullable (ec)) {
239 mono_nullable_init ((guint8*)ea, value, ec);
244 mono_gc_bzero_atomic (ea, esize);
248 #define NO_WIDENING_CONVERSION G_STMT_START{\
249 mono_raise_exception (mono_get_exception_argument ( \
250 "value", "not a widening conversion")); \
253 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
254 if (esize < vsize + (extra)) \
255 mono_raise_exception (mono_get_exception_argument ( \
256 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_raise_exception (mono_get_exception_invalid_cast ()); \
264 /* Check element (destination) type. */
265 switch (ec->byval_arg.type) {
266 case MONO_TYPE_STRING:
267 switch (vc->byval_arg.type) {
268 case MONO_TYPE_STRING:
274 case MONO_TYPE_BOOLEAN:
275 switch (vc->byval_arg.type) {
276 case MONO_TYPE_BOOLEAN:
289 NO_WIDENING_CONVERSION;
296 if (!ec->valuetype) {
297 if (!mono_object_isinst (value, ec))
299 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
303 if (mono_object_isinst (value, ec)) {
304 if (ec->has_references)
305 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
307 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
314 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
316 et = ec->byval_arg.type;
317 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
318 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
320 vt = vc->byval_arg.type;
321 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
322 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
324 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
330 case MONO_TYPE_CHAR: \
331 CHECK_WIDENING_CONVERSION(0); \
332 *(etype *) ea = (etype) u64; \
334 /* You can't assign a signed value to an unsigned array. */ \
339 /* You can't assign a floating point number to an integer array. */ \
342 NO_WIDENING_CONVERSION; \
346 #define ASSIGN_SIGNED(etype) G_STMT_START{\
352 CHECK_WIDENING_CONVERSION(0); \
353 *(etype *) ea = (etype) i64; \
355 /* You can assign an unsigned value to a signed array if the array's */ \
356 /* element size is larger than the value size. */ \
361 case MONO_TYPE_CHAR: \
362 CHECK_WIDENING_CONVERSION(1); \
363 *(etype *) ea = (etype) u64; \
365 /* You can't assign a floating point number to an integer array. */ \
368 NO_WIDENING_CONVERSION; \
372 #define ASSIGN_REAL(etype) G_STMT_START{\
376 CHECK_WIDENING_CONVERSION(0); \
377 *(etype *) ea = (etype) r64; \
379 /* All integer values fit into a floating point array, so we don't */ \
380 /* need to CHECK_WIDENING_CONVERSION here. */ \
385 *(etype *) ea = (etype) i64; \
391 case MONO_TYPE_CHAR: \
392 *(etype *) ea = (etype) u64; \
399 u64 = *(guint8 *) va;
402 u64 = *(guint16 *) va;
405 u64 = *(guint32 *) va;
408 u64 = *(guint64 *) va;
414 i64 = *(gint16 *) va;
417 i64 = *(gint32 *) va;
420 i64 = *(gint64 *) va;
423 r64 = *(gfloat *) va;
426 r64 = *(gdouble *) va;
429 u64 = *(guint16 *) va;
431 case MONO_TYPE_BOOLEAN:
432 /* Boolean is only compatible with itself. */
445 NO_WIDENING_CONVERSION;
452 /* If we can't do a direct copy, let's try a widening conversion. */
455 ASSIGN_UNSIGNED (guint16);
457 ASSIGN_UNSIGNED (guint8);
459 ASSIGN_UNSIGNED (guint16);
461 ASSIGN_UNSIGNED (guint32);
463 ASSIGN_UNSIGNED (guint64);
465 ASSIGN_SIGNED (gint8);
467 ASSIGN_SIGNED (gint16);
469 ASSIGN_SIGNED (gint32);
471 ASSIGN_SIGNED (gint64);
473 ASSIGN_REAL (gfloat);
475 ASSIGN_REAL (gdouble);
479 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
483 #undef NO_WIDENING_CONVERSION
484 #undef CHECK_WIDENING_CONVERSION
485 #undef ASSIGN_UNSIGNED
491 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
499 MONO_CHECK_ARG_NULL (idxs);
501 ic = idxs->obj.vtable->klass;
502 ac = this->obj.vtable->klass;
504 g_assert (ic->rank == 1);
505 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
506 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
508 ind = (gint32 *)idxs->vector;
510 if (this->bounds == NULL) {
511 if (*ind < 0 || *ind >= this->max_length)
512 mono_raise_exception (mono_get_exception_index_out_of_range ());
514 ves_icall_System_Array_SetValueImpl (this, value, *ind);
518 for (i = 0; i < ac->rank; i++)
519 if ((ind [i] < this->bounds [i].lower_bound) ||
520 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
521 mono_raise_exception (mono_get_exception_index_out_of_range ());
523 pos = ind [0] - this->bounds [0].lower_bound;
524 for (i = 1; i < ac->rank; i++)
525 pos = pos * this->bounds [i].length + ind [i] -
526 this->bounds [i].lower_bound;
528 ves_icall_System_Array_SetValueImpl (this, value, pos);
531 ICALL_EXPORT MonoArray *
532 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
534 MonoClass *aklass, *klass;
537 gboolean bounded = FALSE;
541 MONO_CHECK_ARG_NULL (type);
542 MONO_CHECK_ARG_NULL (lengths);
544 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
546 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
548 for (i = 0; i < mono_array_length (lengths); i++)
549 if (mono_array_get (lengths, gint32, i) < 0)
550 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
552 klass = mono_class_from_mono_type (type->type);
553 mono_class_init_or_throw (klass);
555 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
556 /* vectors are not the same as one dimensional arrays with no-zero bounds */
561 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
563 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
564 for (i = 0; i < aklass->rank; ++i) {
565 sizes [i] = mono_array_get (lengths, guint32, i);
567 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
569 sizes [i + aklass->rank] = 0;
572 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
577 ICALL_EXPORT MonoArray *
578 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
580 MonoClass *aklass, *klass;
583 gboolean bounded = FALSE;
587 MONO_CHECK_ARG_NULL (type);
588 MONO_CHECK_ARG_NULL (lengths);
590 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
592 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
594 for (i = 0; i < mono_array_length (lengths); i++)
595 if ((mono_array_get (lengths, gint64, i) < 0) ||
596 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
597 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
599 klass = mono_class_from_mono_type (type->type);
600 mono_class_init_or_throw (klass);
602 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
603 /* vectors are not the same as one dimensional arrays with no-zero bounds */
608 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
610 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
611 for (i = 0; i < aklass->rank; ++i) {
612 sizes [i] = mono_array_get (lengths, guint64, i);
614 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
616 sizes [i + aklass->rank] = 0;
619 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
625 ves_icall_System_Array_GetRank (MonoObject *this)
629 return this->vtable->klass->rank;
633 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
635 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
640 if ((dimension < 0) || (dimension >= rank))
641 mono_raise_exception (mono_get_exception_index_out_of_range ());
643 if (this->bounds == NULL)
644 length = this->max_length;
646 length = this->bounds [dimension].length;
648 #ifdef MONO_BIG_ARRAYS
649 if (length > G_MAXINT32)
650 mono_raise_exception (mono_get_exception_overflow ());
656 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
658 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
662 if ((dimension < 0) || (dimension >= rank))
663 mono_raise_exception (mono_get_exception_index_out_of_range ());
665 if (this->bounds == NULL)
666 return this->max_length;
668 return this->bounds [dimension].length;
672 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
674 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
678 if ((dimension < 0) || (dimension >= rank))
679 mono_raise_exception (mono_get_exception_index_out_of_range ());
681 if (this->bounds == NULL)
684 return this->bounds [dimension].lower_bound;
688 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
690 int sz = mono_array_element_size (mono_object_class (arr));
691 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
694 ICALL_EXPORT gboolean
695 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
700 MonoVTable *src_vtable;
701 MonoVTable *dest_vtable;
702 MonoClass *src_class;
703 MonoClass *dest_class;
705 src_vtable = source->obj.vtable;
706 dest_vtable = dest->obj.vtable;
708 if (src_vtable->rank != dest_vtable->rank)
711 if (source->bounds || dest->bounds)
714 /* there's no integer overflow since mono_array_length returns an unsigned integer */
715 if ((dest_idx + length > mono_array_length_fast (dest)) ||
716 (source_idx + length > mono_array_length_fast (source)))
719 src_class = src_vtable->klass->element_class;
720 dest_class = dest_vtable->klass->element_class;
723 * Handle common cases.
726 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
727 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
729 if (src_class == mono_defaults.object_class && dest_class->valuetype)
732 /* Check if we're copying a char[] <==> (u)short[] */
733 if (src_class != dest_class) {
734 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
737 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
738 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
742 if (dest_class->valuetype) {
743 element_size = mono_array_element_size (source->obj.vtable->klass);
744 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
745 if (dest_class->has_references) {
746 mono_value_copy_array (dest, dest_idx, source_addr, length);
748 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
749 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
752 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
759 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
768 ao = (MonoArray *)this;
769 ac = (MonoClass *)ao->obj.vtable->klass;
771 esize = mono_array_element_size (ac);
772 ea = (gpointer*)((char*)ao->vector + (pos * esize));
774 mono_gc_memmove_atomic (value, ea, esize);
778 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
787 ao = (MonoArray *)this;
788 ac = (MonoClass *)ao->obj.vtable->klass;
789 ec = ac->element_class;
791 esize = mono_array_element_size (ac);
792 ea = (gpointer*)((char*)ao->vector + (pos * esize));
794 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
795 g_assert (esize == sizeof (gpointer));
796 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
798 g_assert (ec->inited);
799 g_assert (esize == mono_class_value_size (ec, NULL));
800 if (ec->has_references)
801 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
803 mono_gc_memmove_atomic (ea, value, esize);
808 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
810 MonoClass *klass = array->obj.vtable->klass;
811 guint32 size = mono_array_element_size (klass);
812 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
814 const char *field_data;
816 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
817 MonoException *exc = mono_get_exception_argument("array",
818 "Cannot initialize array of non-primitive type.");
819 mono_raise_exception (exc);
822 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
823 MonoException *exc = mono_get_exception_argument("field_handle",
824 "Field doesn't have an RVA");
825 mono_raise_exception (exc);
828 size *= array->max_length;
829 field_data = mono_field_get_data (field_handle);
831 if (size > mono_type_size (field_handle->type, &align)) {
832 MonoException *exc = mono_get_exception_argument("field_handle",
833 "Field not large enough to fill array");
834 mono_raise_exception (exc);
837 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
839 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
840 guint ## n *src = (guint ## n *) field_data; \
841 guint ## n *end = (guint ## n *)((char*)src + size); \
843 for (; src < end; data++, src++) { \
844 *data = read ## n (src); \
848 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
850 switch (type->type) {
867 memcpy (mono_array_addr (array, char, 0), field_data, size);
871 memcpy (mono_array_addr (array, char, 0), field_data, size);
876 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
880 return offsetof (MonoString, chars);
883 ICALL_EXPORT MonoObject *
884 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
888 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
891 return mono_object_clone (obj);
895 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
900 MONO_CHECK_ARG_NULL (handle);
902 klass = mono_class_from_mono_type (handle);
903 MONO_CHECK_ARG (handle, klass);
905 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
907 /* This will call the type constructor */
908 mono_runtime_class_init (vtable);
912 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
916 mono_image_check_for_module_cctor (image);
917 if (image->has_module_cctor) {
918 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
919 /*It's fine to raise the exception here*/
920 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
924 ICALL_EXPORT MonoBoolean
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
930 /* later make this configurable and per-arch */
931 int min_size = 4096 * 4 * sizeof (void*);
932 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
933 /* if we have no info we are optimistic and assume there is enough room */
937 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
941 current = (guint8 *)&stack_addr;
942 if (current > stack_addr) {
943 if ((current - stack_addr) < min_size)
946 if (current - (stack_addr - stack_size) < min_size)
952 ICALL_EXPORT MonoObject *
953 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
957 return mono_object_clone (this);
961 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
964 MonoObject **values = NULL;
967 gint32 result = (int)(gsize)mono_defaults.int32_class;
968 MonoClassField* field;
973 klass = mono_object_class (this);
975 if (mono_class_num_fields (klass) == 0)
979 * Compute the starting value of the hashcode for fields of primitive
980 * types, and return the remaining fields in an array to the managed side.
981 * This way, we can avoid costly reflection operations in managed code.
984 while ((field = mono_class_get_fields (klass, &iter))) {
985 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
987 if (mono_field_is_deleted (field))
989 /* FIXME: Add more types */
990 switch (field->type->type) {
992 result ^= *(gint32*)((guint8*)this + field->offset);
994 case MONO_TYPE_STRING: {
996 s = *(MonoString**)((guint8*)this + field->offset);
998 result ^= mono_string_hash (s);
1003 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1004 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1005 values [count++] = o;
1011 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1012 for (i = 0; i < count; ++i)
1013 mono_array_setref (*fields, i, values [i]);
1020 ICALL_EXPORT MonoBoolean
1021 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1024 MonoObject **values = NULL;
1026 MonoClassField* field;
1030 MONO_ARCH_SAVE_REGS;
1032 MONO_CHECK_ARG_NULL (that);
1034 if (this->vtable != that->vtable)
1037 klass = mono_object_class (this);
1039 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1040 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1043 * Do the comparison for fields of primitive type and return a result if
1044 * possible. Otherwise, return the remaining fields in an array to the
1045 * managed side. This way, we can avoid costly reflection operations in
1050 while ((field = mono_class_get_fields (klass, &iter))) {
1051 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1053 if (mono_field_is_deleted (field))
1055 /* FIXME: Add more types */
1056 switch (field->type->type) {
1059 case MONO_TYPE_BOOLEAN:
1060 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1065 case MONO_TYPE_CHAR:
1066 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1071 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1076 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1080 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1084 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1089 case MONO_TYPE_STRING: {
1090 MonoString *s1, *s2;
1091 guint32 s1len, s2len;
1092 s1 = *(MonoString**)((guint8*)this + field->offset);
1093 s2 = *(MonoString**)((guint8*)that + field->offset);
1096 if ((s1 == NULL) || (s2 == NULL))
1098 s1len = mono_string_length (s1);
1099 s2len = mono_string_length (s2);
1103 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1109 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1110 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1111 values [count++] = o;
1112 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1113 values [count++] = o;
1116 if (klass->enumtype)
1117 /* enums only have one non-static field */
1123 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1124 for (i = 0; i < count; ++i)
1125 mono_array_setref_fast (*fields, i, values [i]);
1132 ICALL_EXPORT MonoReflectionType *
1133 ves_icall_System_Object_GetType (MonoObject *obj)
1135 MONO_ARCH_SAVE_REGS;
1137 #ifndef DISABLE_REMOTING
1138 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1139 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1142 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1146 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1148 MONO_ARCH_SAVE_REGS;
1150 mtype->type = &obj->vtable->klass->byval_arg;
1151 g_assert (mtype->type->type);
1155 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1157 MONO_ARCH_SAVE_REGS;
1159 MONO_CHECK_ARG_NULL (obj);
1161 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1165 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1166 MonoReflectionMethod *method,
1167 MonoArray *opt_param_types)
1169 MONO_ARCH_SAVE_REGS;
1171 MONO_CHECK_ARG_NULL (method);
1173 return mono_image_create_method_token (
1174 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1178 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1180 MONO_ARCH_SAVE_REGS;
1182 mono_image_create_pefile (mb, file);
1186 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1188 MONO_ARCH_SAVE_REGS;
1190 mono_image_build_metadata (mb);
1194 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1196 MONO_ARCH_SAVE_REGS;
1198 mono_image_register_token (mb->dynamic_image, token, obj);
1202 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1204 MonoMethod **dest = data;
1206 /* skip unmanaged frames */
1222 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1224 MonoMethod **dest = data;
1226 /* skip unmanaged frames */
1231 if (!strcmp (m->klass->name_space, "System.Reflection"))
1240 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1242 MonoMethod **dest = data;
1244 /* skip unmanaged frames */
1248 if (m->wrapper_type != MONO_WRAPPER_NONE)
1251 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1265 static MonoReflectionType *
1266 type_from_name (const char *str, MonoBoolean ignoreCase)
1268 MonoType *type = NULL;
1269 MonoAssembly *assembly = NULL;
1270 MonoTypeNameParse info;
1271 char *temp_str = g_strdup (str);
1272 gboolean type_resolve = FALSE;
1274 MONO_ARCH_SAVE_REGS;
1276 /* mono_reflection_parse_type() mangles the string */
1277 if (!mono_reflection_parse_type (temp_str, &info)) {
1278 mono_reflection_free_type_info (&info);
1283 if (info.assembly.name) {
1284 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1286 MonoMethod *m = mono_method_get_last_managed ();
1287 MonoMethod *dest = m;
1289 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1294 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1295 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1296 * to crash. This only seems to happen in some strange remoting
1297 * scenarios and I was unable to figure out what's happening there.
1298 * Dec 10, 2005 - Martin.
1302 assembly = dest->klass->image->assembly;
1303 type_resolve = TRUE;
1305 g_warning (G_STRLOC);
1310 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1311 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1314 if (!info.assembly.name && !type) /* try mscorlib */
1315 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1317 if (assembly && !type && type_resolve) {
1318 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1319 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1322 mono_reflection_free_type_info (&info);
1328 return mono_type_get_object (mono_domain_get (), type);
1332 MonoReflectionType *
1333 mono_type_get (const char *str)
1335 char *copy = g_strdup (str);
1336 MonoReflectionType *type = type_from_name (copy, FALSE);
1343 ICALL_EXPORT MonoReflectionType*
1344 ves_icall_type_from_name (MonoString *name,
1345 MonoBoolean throwOnError,
1346 MonoBoolean ignoreCase)
1348 char *str = mono_string_to_utf8 (name);
1349 MonoReflectionType *type;
1351 type = type_from_name (str, ignoreCase);
1354 MonoException *e = NULL;
1357 e = mono_get_exception_type_load (name, NULL);
1359 mono_loader_clear_error ();
1361 mono_raise_exception (e);
1368 ICALL_EXPORT MonoReflectionType*
1369 ves_icall_type_from_handle (MonoType *handle)
1371 MonoDomain *domain = mono_domain_get ();
1373 MONO_ARCH_SAVE_REGS;
1375 return mono_type_get_object (domain, handle);
1378 ICALL_EXPORT MonoBoolean
1379 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1381 MONO_ARCH_SAVE_REGS;
1383 if (c && type->type && c->type)
1384 return mono_metadata_type_equal (type->type, c->type);
1386 return (type == c) ? TRUE : FALSE;
1389 /* System.TypeCode */
1408 TYPECODE_STRING = 18
1411 ICALL_EXPORT guint32
1412 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1414 int t = type->type->type;
1416 MONO_ARCH_SAVE_REGS;
1418 if (type->type->byref)
1419 return TYPECODE_OBJECT;
1423 case MONO_TYPE_VOID:
1424 return TYPECODE_OBJECT;
1425 case MONO_TYPE_BOOLEAN:
1426 return TYPECODE_BOOLEAN;
1428 return TYPECODE_BYTE;
1430 return TYPECODE_SBYTE;
1432 return TYPECODE_UINT16;
1434 return TYPECODE_INT16;
1435 case MONO_TYPE_CHAR:
1436 return TYPECODE_CHAR;
1440 return TYPECODE_OBJECT;
1442 return TYPECODE_UINT32;
1444 return TYPECODE_INT32;
1446 return TYPECODE_UINT64;
1448 return TYPECODE_INT64;
1450 return TYPECODE_SINGLE;
1452 return TYPECODE_DOUBLE;
1453 case MONO_TYPE_VALUETYPE: {
1454 MonoClass *klass = type->type->data.klass;
1456 if (klass->enumtype) {
1457 t = mono_class_enum_basetype (klass)->type;
1459 } else if (mono_is_corlib_image (klass->image)) {
1460 if (strcmp (klass->name_space, "System") == 0) {
1461 if (strcmp (klass->name, "Decimal") == 0)
1462 return TYPECODE_DECIMAL;
1463 else if (strcmp (klass->name, "DateTime") == 0)
1464 return TYPECODE_DATETIME;
1467 return TYPECODE_OBJECT;
1469 case MONO_TYPE_STRING:
1470 return TYPECODE_STRING;
1471 case MONO_TYPE_SZARRAY:
1472 case MONO_TYPE_ARRAY:
1473 case MONO_TYPE_OBJECT:
1475 case MONO_TYPE_MVAR:
1476 case MONO_TYPE_TYPEDBYREF:
1477 return TYPECODE_OBJECT;
1478 case MONO_TYPE_CLASS:
1480 MonoClass *klass = type->type->data.klass;
1481 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1482 if (strcmp (klass->name, "DBNull") == 0)
1483 return TYPECODE_DBNULL;
1486 return TYPECODE_OBJECT;
1487 case MONO_TYPE_GENERICINST:
1488 return TYPECODE_OBJECT;
1490 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1495 ICALL_EXPORT guint32
1496 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1502 MONO_ARCH_SAVE_REGS;
1504 g_assert (type != NULL);
1506 domain = ((MonoObject *)type)->vtable->domain;
1508 if (!c) /* FIXME: dont know what do do here */
1511 klass = mono_class_from_mono_type (type->type);
1512 klassc = mono_class_from_mono_type (c->type);
1514 /* Interface check requires a more complex setup so we
1515 * only do for them. Otherwise we simply avoid mono_class_init.
1517 if (check_interfaces) {
1518 mono_class_init_or_throw (klass);
1519 mono_class_init_or_throw (klassc);
1520 } else if (!klass->supertypes || !klassc->supertypes) {
1521 mono_class_setup_supertypes (klass);
1522 mono_class_setup_supertypes (klassc);
1525 if (type->type->byref)
1526 return klassc == mono_defaults.object_class;
1528 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1532 mono_type_is_primitive (MonoType *type)
1534 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1535 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1539 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1541 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1542 return mono_class_enum_basetype (type->data.klass);
1543 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1544 return mono_class_enum_basetype (type->data.generic_class->container_class);
1548 ICALL_EXPORT guint32
1549 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1555 MONO_ARCH_SAVE_REGS;
1557 g_assert (type != NULL);
1559 domain = ((MonoObject *)type)->vtable->domain;
1561 klass = mono_class_from_mono_type (type->type);
1562 klassc = mono_class_from_mono_type (c->type);
1564 if (type->type->byref ^ c->type->byref)
1567 if (type->type->byref) {
1568 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1569 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1571 klass = mono_class_from_mono_type (t);
1572 klassc = mono_class_from_mono_type (ot);
1574 if (mono_type_is_primitive (t)) {
1575 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1576 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1577 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1578 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1579 return t->type == ot->type;
1581 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1584 if (klass->valuetype)
1585 return klass == klassc;
1586 return klass->valuetype == klassc->valuetype;
1589 return mono_class_is_assignable_from (klass, klassc);
1592 ICALL_EXPORT guint32
1593 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1595 MonoClass *klass = mono_class_from_mono_type (type->type);
1596 mono_class_init_or_throw (klass);
1597 return mono_object_isinst (obj, klass) != NULL;
1600 ICALL_EXPORT guint32
1601 ves_icall_get_attributes (MonoReflectionType *type)
1603 MonoClass *klass = mono_class_from_mono_type (type->type);
1604 return klass->flags;
1607 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1608 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1610 MonoClass *klass = field->field->parent;
1611 MonoMarshalType *info;
1614 if (klass->generic_container ||
1615 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1618 info = mono_marshal_load_type_info (klass);
1620 for (i = 0; i < info->num_fields; ++i) {
1621 if (info->fields [i].field == field->field) {
1622 if (!info->fields [i].mspec)
1625 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1632 ICALL_EXPORT MonoReflectionField*
1633 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1635 gboolean found = FALSE;
1642 klass = handle->parent;
1644 klass = mono_class_from_mono_type (type);
1646 /* Check that the field belongs to the class */
1647 for (k = klass; k; k = k->parent) {
1648 if (k == handle->parent) {
1655 /* The managed code will throw the exception */
1659 return mono_field_get_object (mono_domain_get (), klass, handle);
1662 ICALL_EXPORT MonoArray*
1663 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1666 MonoType *type = mono_field_get_type_checked (field->field, &error);
1667 if (!mono_error_ok (&error))
1668 mono_error_raise_exception (&error);
1670 return type_array_from_modifiers (field->field->parent->image, type, optional);
1674 vell_icall_get_method_attributes (MonoMethod *method)
1676 return method->flags;
1680 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1683 MonoDomain *domain = mono_domain_get ();
1684 MonoMethodSignature* sig;
1685 MONO_ARCH_SAVE_REGS;
1687 sig = mono_method_signature_checked (method, &error);
1688 if (!mono_error_ok (&error))
1689 mono_error_raise_exception (&error);
1692 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1693 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1694 info->attrs = method->flags;
1695 info->implattrs = method->iflags;
1696 if (sig->call_convention == MONO_CALL_DEFAULT)
1697 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1699 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1704 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1707 ICALL_EXPORT MonoArray*
1708 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1710 MonoDomain *domain = mono_domain_get ();
1712 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1715 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1716 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1718 MonoDomain *domain = mono_domain_get ();
1719 MonoReflectionMarshalAsAttribute* res = NULL;
1720 MonoMarshalSpec **mspecs;
1723 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1724 mono_method_get_marshal_info (method, mspecs);
1727 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1729 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1731 mono_metadata_free_marshal_spec (mspecs [i]);
1738 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1740 MonoClass *parent = field->field->parent;
1741 if (!parent->size_inited)
1742 mono_class_init (parent);
1744 return field->field->offset - sizeof (MonoObject);
1747 ICALL_EXPORT MonoReflectionType*
1748 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1751 MONO_ARCH_SAVE_REGS;
1753 parent = declaring? field->field->parent: field->klass;
1755 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1758 ICALL_EXPORT MonoObject *
1759 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1761 MonoClass *fklass = field->klass;
1762 MonoClassField *cf = field->field;
1763 MonoDomain *domain = mono_object_domain (field);
1765 if (fklass->image->assembly->ref_only)
1766 mono_raise_exception (mono_get_exception_invalid_operation (
1767 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1769 if (mono_security_core_clr_enabled ())
1770 mono_security_core_clr_ensure_reflection_access_field (cf);
1772 return mono_field_get_value_object (domain, cf, obj);
1776 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1779 MonoClassField *cf = field->field;
1783 MONO_ARCH_SAVE_REGS;
1785 if (field->klass->image->assembly->ref_only)
1786 mono_raise_exception (mono_get_exception_invalid_operation (
1787 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1789 if (mono_security_core_clr_enabled ())
1790 mono_security_core_clr_ensure_reflection_access_field (cf);
1792 type = mono_field_get_type_checked (cf, &error);
1793 if (!mono_error_ok (&error))
1794 mono_error_raise_exception (&error);
1796 v = (gchar *) value;
1798 switch (type->type) {
1801 case MONO_TYPE_BOOLEAN:
1804 case MONO_TYPE_CHAR:
1813 case MONO_TYPE_VALUETYPE:
1816 v += sizeof (MonoObject);
1818 case MONO_TYPE_STRING:
1819 case MONO_TYPE_OBJECT:
1820 case MONO_TYPE_CLASS:
1821 case MONO_TYPE_ARRAY:
1822 case MONO_TYPE_SZARRAY:
1825 case MONO_TYPE_GENERICINST: {
1826 MonoGenericClass *gclass = type->data.generic_class;
1827 g_assert (!gclass->context.class_inst->is_open);
1829 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1830 MonoClass *nklass = mono_class_from_mono_type (type);
1831 MonoObject *nullable;
1834 * Convert the boxed vtype into a Nullable structure.
1835 * This is complicated by the fact that Nullables have
1836 * a variable structure.
1838 nullable = mono_object_new (mono_domain_get (), nklass);
1840 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1842 v = mono_object_unbox (nullable);
1845 if (gclass->container_class->valuetype && (v != NULL))
1846 v += sizeof (MonoObject);
1850 g_error ("type 0x%x not handled in "
1851 "ves_icall_FieldInfo_SetValueInternal", type->type);
1856 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1857 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1858 if (!vtable->initialized)
1859 mono_runtime_class_init (vtable);
1860 mono_field_static_set_value (vtable, cf, v);
1862 mono_field_set_value (obj, cf, v);
1866 ICALL_EXPORT MonoObject *
1867 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1869 MonoObject *o = NULL;
1870 MonoClassField *field = this->field;
1872 MonoDomain *domain = mono_object_domain (this);
1874 MonoTypeEnum def_type;
1875 const char *def_value;
1879 MONO_ARCH_SAVE_REGS;
1881 mono_class_init (field->parent);
1883 t = mono_field_get_type_checked (field, &error);
1884 if (!mono_error_ok (&error))
1885 mono_error_raise_exception (&error);
1887 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1888 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1890 if (field->parent->image->dynamic) {
1892 g_assert_not_reached ();
1895 def_value = mono_class_get_field_default_value (field, &def_type);
1896 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1897 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1899 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1903 case MONO_TYPE_BOOLEAN:
1906 case MONO_TYPE_CHAR:
1914 case MONO_TYPE_R8: {
1917 /* boxed value type */
1918 t = g_new0 (MonoType, 1);
1920 klass = mono_class_from_mono_type (t);
1922 o = mono_object_new (domain, klass);
1923 v = ((gchar *) o) + sizeof (MonoObject);
1924 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1927 case MONO_TYPE_STRING:
1928 case MONO_TYPE_CLASS:
1929 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1932 g_assert_not_reached ();
1938 ICALL_EXPORT MonoReflectionType*
1939 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1942 MonoClassField *field = ref_field->field;
1943 MonoType *type = mono_field_get_type_checked (field, &error);
1944 if (!mono_error_ok (&error))
1945 mono_error_raise_exception (&error);
1946 return mono_type_get_object (mono_object_domain (ref_field), type);
1949 ICALL_EXPORT MonoReflectionType*
1950 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1952 MonoMethod *method = rmethod->method.method;
1954 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1957 /* From MonoProperty.cs */
1959 PInfo_Attributes = 1,
1960 PInfo_GetMethod = 1 << 1,
1961 PInfo_SetMethod = 1 << 2,
1962 PInfo_ReflectedType = 1 << 3,
1963 PInfo_DeclaringType = 1 << 4,
1968 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1970 MonoDomain *domain = mono_object_domain (property);
1972 MONO_ARCH_SAVE_REGS;
1974 if ((req_info & PInfo_ReflectedType) != 0)
1975 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1976 if ((req_info & PInfo_DeclaringType) != 0)
1977 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1979 if ((req_info & PInfo_Name) != 0)
1980 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1982 if ((req_info & PInfo_Attributes) != 0)
1983 info->attrs = property->property->attrs;
1985 if ((req_info & PInfo_GetMethod) != 0)
1986 MONO_STRUCT_SETREF (info, get, property->property->get ?
1987 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1989 if ((req_info & PInfo_SetMethod) != 0)
1990 MONO_STRUCT_SETREF (info, set, property->property->set ?
1991 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1993 * There may be other methods defined for properties, though, it seems they are not exposed
1994 * in the reflection API
1999 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2001 MonoDomain *domain = mono_object_domain (event);
2003 MONO_ARCH_SAVE_REGS;
2005 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2006 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2008 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2009 info->attrs = event->event->attrs;
2010 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2011 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2012 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2014 #ifndef MONO_SMALL_CONFIG
2015 if (event->event->other) {
2017 while (event->event->other [n])
2019 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2021 for (i = 0; i < n; i++)
2022 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2028 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2033 mono_class_setup_interfaces (klass, error);
2034 if (!mono_error_ok (error))
2037 for (i = 0; i < klass->interface_count; i++) {
2038 ic = klass->interfaces [i];
2039 g_hash_table_insert (ifaces, ic, ic);
2041 collect_interfaces (ic, ifaces, error);
2042 if (!mono_error_ok (error))
2048 MonoArray *iface_array;
2049 MonoGenericContext *context;
2053 } FillIfaceArrayData;
2056 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2058 FillIfaceArrayData *data = user_data;
2059 MonoClass *ic = key;
2060 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2062 if (!mono_error_ok (data->error))
2065 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2066 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2067 if (!mono_error_ok (data->error))
2071 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2074 mono_metadata_free_type (inflated);
2077 ICALL_EXPORT MonoArray*
2078 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2081 MonoClass *class = mono_class_from_mono_type (type->type);
2083 FillIfaceArrayData data = { 0 };
2086 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2088 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2089 data.context = mono_class_get_context (class);
2090 class = class->generic_class->container_class;
2093 for (parent = class; parent; parent = parent->parent) {
2094 mono_class_setup_interfaces (parent, &error);
2095 if (!mono_error_ok (&error))
2097 collect_interfaces (parent, iface_hash, &error);
2098 if (!mono_error_ok (&error))
2102 data.error = &error;
2103 data.domain = mono_object_domain (type);
2105 len = g_hash_table_size (iface_hash);
2107 g_hash_table_destroy (iface_hash);
2108 if (!data.domain->empty_types)
2109 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2110 return data.domain->empty_types;
2113 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2114 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2115 if (!mono_error_ok (&error))
2118 g_hash_table_destroy (iface_hash);
2119 return data.iface_array;
2122 g_hash_table_destroy (iface_hash);
2123 mono_error_raise_exception (&error);
2128 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2130 gboolean variance_used;
2131 MonoClass *class = mono_class_from_mono_type (type->type);
2132 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2133 MonoReflectionMethod *member;
2136 int i = 0, len, ioffset;
2139 MONO_ARCH_SAVE_REGS;
2140 mono_class_init_or_throw (class);
2141 mono_class_init_or_throw (iclass);
2143 mono_class_setup_vtable (class);
2145 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2149 len = mono_class_num_methods (iclass);
2150 domain = mono_object_domain (type);
2151 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2152 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2154 while ((method = mono_class_get_methods (iclass, &iter))) {
2155 member = mono_method_get_object (domain, method, iclass);
2156 mono_array_setref (*methods, i, member);
2157 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2158 mono_array_setref (*targets, i, member);
2165 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2167 MonoClass *klass = mono_class_from_mono_type (type->type);
2168 mono_class_init_or_throw (klass);
2170 if (klass->image->dynamic) {
2171 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2172 *packing = tb->packing_size;
2173 *size = tb->class_size;
2175 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2179 ICALL_EXPORT MonoReflectionType*
2180 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2184 MONO_ARCH_SAVE_REGS;
2186 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2187 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2189 class = mono_class_from_mono_type (type->type);
2190 mono_class_init_or_throw (class);
2192 // GetElementType should only return a type for:
2193 // Array Pointer PassedByRef
2194 if (type->type->byref)
2195 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2196 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2197 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2198 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2199 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2204 ICALL_EXPORT MonoReflectionType*
2205 ves_icall_get_type_parent (MonoReflectionType *type)
2207 MonoClass *class = mono_class_from_mono_type (type->type);
2208 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2211 ICALL_EXPORT MonoBoolean
2212 ves_icall_type_ispointer (MonoReflectionType *type)
2214 MONO_ARCH_SAVE_REGS;
2216 return type->type->type == MONO_TYPE_PTR;
2219 ICALL_EXPORT MonoBoolean
2220 ves_icall_type_isprimitive (MonoReflectionType *type)
2222 MONO_ARCH_SAVE_REGS;
2224 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)));
2227 ICALL_EXPORT MonoBoolean
2228 ves_icall_type_isbyref (MonoReflectionType *type)
2230 MONO_ARCH_SAVE_REGS;
2232 return type->type->byref;
2235 ICALL_EXPORT MonoBoolean
2236 ves_icall_type_iscomobject (MonoReflectionType *type)
2238 MonoClass *klass = mono_class_from_mono_type (type->type);
2239 mono_class_init_or_throw (klass);
2241 return mono_class_is_com_object (klass);
2244 ICALL_EXPORT MonoReflectionModule*
2245 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2247 MonoClass *class = mono_class_from_mono_type (type->type);
2248 return mono_module_get_object (mono_object_domain (type), class->image);
2251 ICALL_EXPORT MonoReflectionAssembly*
2252 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2254 MonoDomain *domain = mono_domain_get ();
2255 MonoClass *class = mono_class_from_mono_type (type->type);
2256 return mono_assembly_get_object (domain, class->image->assembly);
2259 ICALL_EXPORT MonoReflectionType*
2260 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2262 MonoDomain *domain = mono_domain_get ();
2265 MONO_ARCH_SAVE_REGS;
2267 if (type->type->byref)
2269 if (type->type->type == MONO_TYPE_VAR)
2270 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2271 else if (type->type->type == MONO_TYPE_MVAR)
2272 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2274 class = mono_class_from_mono_type (type->type)->nested_in;
2276 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2279 ICALL_EXPORT MonoString*
2280 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2282 MonoDomain *domain = mono_domain_get ();
2283 MonoClass *class = mono_class_from_mono_type (type->type);
2285 if (type->type->byref) {
2286 char *n = g_strdup_printf ("%s&", class->name);
2287 MonoString *res = mono_string_new (domain, n);
2293 return mono_string_new (domain, class->name);
2297 ICALL_EXPORT MonoString*
2298 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2300 MonoDomain *domain = mono_domain_get ();
2301 MonoClass *class = mono_class_from_mono_type (type->type);
2303 while (class->nested_in)
2304 class = class->nested_in;
2306 if (class->name_space [0] == '\0')
2309 return mono_string_new (domain, class->name_space);
2313 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2317 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2318 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2320 class = mono_class_from_mono_type (type->type);
2325 ICALL_EXPORT MonoArray*
2326 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2329 MonoClass *klass, *pklass;
2330 MonoDomain *domain = mono_object_domain (type);
2331 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2333 MONO_ARCH_SAVE_REGS;
2335 klass = mono_class_from_mono_type (type->type);
2337 if (klass->generic_container) {
2338 MonoGenericContainer *container = klass->generic_container;
2339 res = mono_array_new_specific (array_vtable, container->type_argc);
2340 for (i = 0; i < container->type_argc; ++i) {
2341 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2342 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2344 } else if (klass->generic_class) {
2345 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2346 res = mono_array_new_specific (array_vtable, inst->type_argc);
2347 for (i = 0; i < inst->type_argc; ++i)
2348 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2350 res = mono_array_new_specific (array_vtable, 0);
2355 ICALL_EXPORT gboolean
2356 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2359 MONO_ARCH_SAVE_REGS;
2361 if (!IS_MONOTYPE (type))
2364 if (type->type->byref)
2367 klass = mono_class_from_mono_type (type->type);
2368 return klass->generic_container != NULL;
2371 ICALL_EXPORT MonoReflectionType*
2372 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2375 MONO_ARCH_SAVE_REGS;
2377 if (type->type->byref)
2380 klass = mono_class_from_mono_type (type->type);
2382 if (klass->generic_container) {
2383 return type; /* check this one */
2385 if (klass->generic_class) {
2386 MonoClass *generic_class = klass->generic_class->container_class;
2389 tb = mono_class_get_ref_info (generic_class);
2391 if (generic_class->wastypebuilder && tb)
2394 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2399 ICALL_EXPORT MonoReflectionType*
2400 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2403 MonoType *geninst, **types;
2406 g_assert (IS_MONOTYPE (type));
2407 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2409 count = mono_array_length (type_array);
2410 types = g_new0 (MonoType *, count);
2412 for (i = 0; i < count; i++) {
2413 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2414 types [i] = t->type;
2417 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2422 class = mono_class_from_mono_type (geninst);
2424 /*we might inflate to the GTD*/
2425 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2426 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2428 return mono_type_get_object (mono_object_domain (type), geninst);
2431 ICALL_EXPORT gboolean
2432 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2435 MONO_ARCH_SAVE_REGS;
2437 if (type->type->byref)
2440 klass = mono_class_from_mono_type (type->type);
2442 return klass->generic_class != NULL;
2445 ICALL_EXPORT gboolean
2446 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2449 MONO_ARCH_SAVE_REGS;
2451 if (!IS_MONOTYPE (type))
2454 if (type->type->byref)
2457 klass = mono_class_from_mono_type (type->type);
2458 return klass->generic_class != NULL || klass->generic_container != NULL;
2462 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2464 MONO_ARCH_SAVE_REGS;
2466 if (!IS_MONOTYPE (type))
2469 if (is_generic_parameter (type->type))
2470 return mono_type_get_generic_param_num (type->type);
2474 ICALL_EXPORT GenericParameterAttributes
2475 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2477 MONO_ARCH_SAVE_REGS;
2479 g_assert (IS_MONOTYPE (type));
2480 g_assert (is_generic_parameter (type->type));
2481 return mono_generic_param_info (type->type->data.generic_param)->flags;
2484 ICALL_EXPORT MonoArray *
2485 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2487 MonoGenericParamInfo *param_info;
2493 MONO_ARCH_SAVE_REGS;
2495 g_assert (IS_MONOTYPE (type));
2497 domain = mono_object_domain (type);
2498 param_info = mono_generic_param_info (type->type->data.generic_param);
2499 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2502 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2503 for (i = 0; i < count; i++)
2504 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2510 ICALL_EXPORT MonoBoolean
2511 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2513 MONO_ARCH_SAVE_REGS;
2514 return is_generic_parameter (type->type);
2517 ICALL_EXPORT MonoBoolean
2518 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2520 MONO_ARCH_SAVE_REGS;
2521 return is_generic_parameter (tb->type.type);
2525 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2526 MonoReflectionType *t)
2528 enumtype->type = t->type;
2531 ICALL_EXPORT MonoReflectionMethod*
2532 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2533 MonoReflectionMethod* generic)
2540 MONO_ARCH_SAVE_REGS;
2542 domain = ((MonoObject *)type)->vtable->domain;
2544 klass = mono_class_from_mono_type (type->type);
2545 mono_class_init_or_throw (klass);
2548 while ((method = mono_class_get_methods (klass, &iter))) {
2549 if (method->token == generic->method->token)
2550 return mono_method_get_object (domain, method, klass);
2558 ICALL_EXPORT MonoReflectionMethod *
2559 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2562 MonoType *type = ref_type->type;
2564 MONO_ARCH_SAVE_REGS;
2566 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2567 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2568 if (type->type == MONO_TYPE_VAR)
2571 method = mono_type_get_generic_param_owner (type)->owner.method;
2573 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2576 ICALL_EXPORT MonoReflectionDllImportAttribute*
2577 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2579 static MonoClass *DllImportAttributeClass = NULL;
2580 MonoDomain *domain = mono_domain_get ();
2581 MonoReflectionDllImportAttribute *attr;
2582 MonoImage *image = method->klass->image;
2583 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2584 MonoTableInfo *tables = image->tables;
2585 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2586 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2587 guint32 im_cols [MONO_IMPLMAP_SIZE];
2588 guint32 scope_token;
2589 const char *import = NULL;
2590 const char *scope = NULL;
2593 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2596 if (!DllImportAttributeClass) {
2597 DllImportAttributeClass =
2598 mono_class_from_name (mono_defaults.corlib,
2599 "System.Runtime.InteropServices", "DllImportAttribute");
2600 g_assert (DllImportAttributeClass);
2603 if (method->klass->image->dynamic) {
2604 MonoReflectionMethodAux *method_aux =
2605 g_hash_table_lookup (
2606 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2608 import = method_aux->dllentry;
2609 scope = method_aux->dll;
2612 if (!import || !scope) {
2613 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2618 if (piinfo->implmap_idx) {
2619 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2621 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2622 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2623 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2624 scope = mono_metadata_string_heap (image, scope_token);
2627 flags = piinfo->piflags;
2629 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2631 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2632 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2633 attr->call_conv = (flags & 0x700) >> 8;
2634 attr->charset = ((flags & 0x6) >> 1) + 1;
2635 if (attr->charset == 1)
2637 attr->exact_spelling = (flags & 0x1) != 0;
2638 attr->set_last_error = (flags & 0x40) != 0;
2639 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2640 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2641 attr->preserve_sig = FALSE;
2646 ICALL_EXPORT MonoReflectionMethod *
2647 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2649 MonoMethodInflated *imethod;
2652 MONO_ARCH_SAVE_REGS;
2654 if (method->method->is_generic)
2657 if (!method->method->is_inflated)
2660 imethod = (MonoMethodInflated *) method->method;
2662 result = imethod->declaring;
2663 /* Not a generic method. */
2664 if (!result->is_generic)
2667 if (method->method->klass->image->dynamic) {
2668 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2669 MonoReflectionMethod *res;
2672 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2673 * the dynamic case as well ?
2675 mono_image_lock ((MonoImage*)image);
2676 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2677 mono_image_unlock ((MonoImage*)image);
2683 if (imethod->context.class_inst) {
2684 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2685 /*Generic methods gets the context of the GTD.*/
2686 if (mono_class_get_context (klass))
2687 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2690 return mono_method_get_object (mono_object_domain (method), result, NULL);
2693 ICALL_EXPORT gboolean
2694 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2696 MONO_ARCH_SAVE_REGS;
2698 return mono_method_signature (method->method)->generic_param_count != 0;
2701 ICALL_EXPORT gboolean
2702 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2704 MONO_ARCH_SAVE_REGS;
2706 return method->method->is_generic;
2709 ICALL_EXPORT MonoArray*
2710 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2715 MONO_ARCH_SAVE_REGS;
2717 domain = mono_object_domain (method);
2719 if (method->method->is_inflated) {
2720 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2723 count = inst->type_argc;
2724 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2726 for (i = 0; i < count; i++)
2727 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2733 count = mono_method_signature (method->method)->generic_param_count;
2734 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2736 for (i = 0; i < count; i++) {
2737 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2738 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2739 MonoClass *pklass = mono_class_from_generic_parameter (
2740 param, method->method->klass->image, TRUE);
2741 mono_array_setref (res, i,
2742 mono_type_get_object (domain, &pklass->byval_arg));
2748 ICALL_EXPORT MonoObject *
2749 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2752 * Invoke from reflection is supposed to always be a virtual call (the API
2753 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2754 * greater flexibility.
2756 MonoMethod *m = method->method;
2757 MonoMethodSignature *sig = mono_method_signature (m);
2762 MONO_ARCH_SAVE_REGS;
2766 if (mono_security_core_clr_enabled ())
2767 mono_security_core_clr_ensure_reflection_access_method (m);
2769 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2770 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2771 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2776 if (!mono_object_isinst (this, m->klass)) {
2777 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2778 char *target_name = mono_type_get_full_name (m->klass);
2779 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2780 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2782 g_free (target_name);
2786 m = mono_object_get_virtual_method (this, m);
2787 /* must pass the pointer to the value for valuetype methods */
2788 if (m->klass->valuetype)
2789 obj = mono_object_unbox (this);
2790 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2791 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2796 if (sig->ret->byref) {
2797 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"));
2801 pcount = params? mono_array_length (params): 0;
2802 if (pcount != sig->param_count) {
2803 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2807 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2808 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."));
2812 image = m->klass->image;
2813 if (image->assembly->ref_only) {
2814 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."));
2818 if (image->dynamic && !((MonoDynamicImage*)image)->run) {
2819 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2823 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2826 intptr_t *lower_bounds;
2827 pcount = mono_array_length (params);
2828 lengths = alloca (sizeof (uintptr_t) * pcount);
2829 /* Note: the synthetized array .ctors have int32 as argument type */
2830 for (i = 0; i < pcount; ++i)
2831 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2833 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2834 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2835 MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2837 for (i = 0; i < mono_array_length (arr); ++i) {
2838 MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
2840 mono_array_setref_fast (arr, i, subarray);
2842 return (MonoObject*)arr;
2845 if (m->klass->rank == pcount) {
2846 /* Only lengths provided. */
2847 lower_bounds = NULL;
2849 g_assert (pcount == (m->klass->rank * 2));
2850 /* lower bounds are first. */
2851 lower_bounds = (intptr_t*)lengths;
2852 lengths += m->klass->rank;
2855 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2857 return mono_runtime_invoke_array (m, obj, params, NULL);
2860 #ifndef DISABLE_REMOTING
2861 ICALL_EXPORT MonoObject *
2862 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2864 MonoDomain *domain = mono_object_domain (method);
2865 MonoMethod *m = method->method;
2866 MonoMethodSignature *sig = mono_method_signature (m);
2867 MonoArray *out_args;
2869 int i, j, outarg_count = 0;
2871 MONO_ARCH_SAVE_REGS;
2873 if (m->klass == mono_defaults.object_class) {
2875 if (!strcmp (m->name, "FieldGetter")) {
2876 MonoClass *k = this->vtable->klass;
2880 /* If this is a proxy, then it must be a CBO */
2881 if (k == mono_defaults.transparent_proxy_class) {
2882 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2883 this = tp->rp->unwrapped_server;
2885 k = this->vtable->klass;
2888 name = mono_array_get (params, MonoString *, 1);
2889 str = mono_string_to_utf8 (name);
2892 MonoClassField* field = mono_class_get_field_from_name (k, str);
2894 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2895 if (field_klass->valuetype)
2896 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2898 result = *((gpointer *)((char *)this + field->offset));
2900 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2901 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2902 mono_array_setref (out_args, 0, result);
2910 g_assert_not_reached ();
2912 } else if (!strcmp (m->name, "FieldSetter")) {
2913 MonoClass *k = this->vtable->klass;
2919 /* If this is a proxy, then it must be a CBO */
2920 if (k == mono_defaults.transparent_proxy_class) {
2921 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2922 this = tp->rp->unwrapped_server;
2924 k = this->vtable->klass;
2927 name = mono_array_get (params, MonoString *, 1);
2928 str = mono_string_to_utf8 (name);
2931 MonoClassField* field = mono_class_get_field_from_name (k, str);
2933 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2934 MonoObject *val = mono_array_get (params, gpointer, 2);
2936 if (field_klass->valuetype) {
2937 size = mono_type_size (field->type, &align);
2938 g_assert (size == mono_class_value_size (field_klass, NULL));
2939 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2941 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2944 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2945 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2955 g_assert_not_reached ();
2960 for (i = 0; i < mono_array_length (params); i++) {
2961 if (sig->params [i]->byref)
2965 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2967 /* handle constructors only for objects already allocated */
2968 if (!strcmp (method->method->name, ".ctor"))
2971 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2972 g_assert (!method->method->klass->valuetype);
2973 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2975 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2976 if (sig->params [i]->byref) {
2978 arg = mono_array_get (params, gpointer, i);
2979 mono_array_setref (out_args, j, arg);
2984 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2991 read_enum_value (char *mem, int type)
2995 return *(guint8*)mem;
2997 return *(gint8*)mem;
2999 return *(guint16*)mem;
3001 return *(gint16*)mem;
3003 return *(guint32*)mem;
3005 return *(gint32*)mem;
3007 return *(guint64*)mem;
3009 return *(gint64*)mem;
3011 g_assert_not_reached ();
3017 write_enum_value (char *mem, int type, guint64 value)
3021 case MONO_TYPE_I1: {
3022 guint8 *p = (guint8*)mem;
3027 case MONO_TYPE_I2: {
3028 guint16 *p = (void*)mem;
3033 case MONO_TYPE_I4: {
3034 guint32 *p = (void*)mem;
3039 case MONO_TYPE_I8: {
3040 guint64 *p = (void*)mem;
3045 g_assert_not_reached ();
3050 ICALL_EXPORT MonoObject *
3051 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3054 MonoClass *enumc, *objc;
3059 MONO_ARCH_SAVE_REGS;
3061 MONO_CHECK_ARG_NULL (enumType);
3062 MONO_CHECK_ARG_NULL (value);
3064 domain = mono_object_domain (enumType);
3065 enumc = mono_class_from_mono_type (enumType->type);
3067 mono_class_init_or_throw (enumc);
3069 objc = value->vtable->klass;
3071 if (!enumc->enumtype)
3072 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3073 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3074 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."));
3076 etype = mono_class_enum_basetype (enumc);
3078 /* MS throws this for typebuilders */
3079 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3081 res = mono_object_new (domain, enumc);
3082 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3083 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3088 ICALL_EXPORT MonoObject *
3089 ves_icall_System_Enum_get_value (MonoObject *this)
3097 MONO_ARCH_SAVE_REGS;
3102 g_assert (this->vtable->klass->enumtype);
3104 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3105 res = mono_object_new (mono_object_domain (this), enumc);
3106 dst = (char *)res + sizeof (MonoObject);
3107 src = (char *)this + sizeof (MonoObject);
3108 size = mono_class_value_size (enumc, NULL);
3110 memcpy (dst, src, size);
3115 ICALL_EXPORT MonoReflectionType *
3116 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3121 MONO_ARCH_SAVE_REGS;
3123 klass = mono_class_from_mono_type (type->type);
3124 mono_class_init_or_throw (klass);
3126 etype = mono_class_enum_basetype (klass);
3128 /* MS throws this for typebuilders */
3129 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3131 return mono_type_get_object (mono_object_domain (type), etype);
3135 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3137 gpointer tdata = (char *)this + sizeof (MonoObject);
3138 gpointer odata = (char *)other + sizeof (MonoObject);
3139 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3140 g_assert (basetype);
3142 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3143 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3144 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3147 return me > other ? 1 : -1; \
3150 switch (basetype->type) {
3152 COMPARE_ENUM_VALUES (guint8);
3154 COMPARE_ENUM_VALUES (gint8);
3155 case MONO_TYPE_CHAR:
3157 COMPARE_ENUM_VALUES (guint16);
3159 COMPARE_ENUM_VALUES (gint16);
3161 COMPARE_ENUM_VALUES (guint32);
3163 COMPARE_ENUM_VALUES (gint32);
3165 COMPARE_ENUM_VALUES (guint64);
3167 COMPARE_ENUM_VALUES (gint64);
3169 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3171 #undef COMPARE_ENUM_VALUES
3176 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3178 gpointer data = (char *)this + sizeof (MonoObject);
3179 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3180 g_assert (basetype);
3182 switch (basetype->type) {
3184 return *((gint8*)data);
3186 return *((guint8*)data);
3187 case MONO_TYPE_CHAR:
3189 return *((guint16*)data);
3192 return *((gint16*)data);
3194 return *((guint32*)data);
3196 return *((gint32*)data);
3198 case MONO_TYPE_I8: {
3199 gint64 value = *((gint64*)data);
3200 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3203 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3209 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3211 MonoDomain *domain = mono_object_domain (type);
3212 MonoClass *enumc = mono_class_from_mono_type (type->type);
3213 guint j = 0, nvalues, crow;
3215 MonoClassField *field;
3217 MONO_ARCH_SAVE_REGS;
3219 mono_class_init_or_throw (enumc);
3221 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3222 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3223 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3224 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3228 while ((field = mono_class_get_fields (enumc, &iter))) {
3231 MonoTypeEnum def_type;
3233 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3235 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3237 if (mono_field_is_deleted (field))
3239 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3241 p = mono_class_get_field_default_value (field, &def_type);
3242 len = mono_metadata_decode_blob_size (p, &p);
3243 switch (mono_class_enum_basetype (enumc)->type) {
3246 mono_array_set (info->values, gchar, j, *p);
3248 case MONO_TYPE_CHAR:
3251 mono_array_set (info->values, gint16, j, read16 (p));
3255 mono_array_set (info->values, gint32, j, read32 (p));
3259 mono_array_set (info->values, gint64, j, read64 (p));
3262 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3269 BFLAGS_IgnoreCase = 1,
3270 BFLAGS_DeclaredOnly = 2,
3271 BFLAGS_Instance = 4,
3273 BFLAGS_Public = 0x10,
3274 BFLAGS_NonPublic = 0x20,
3275 BFLAGS_FlattenHierarchy = 0x40,
3276 BFLAGS_InvokeMethod = 0x100,
3277 BFLAGS_CreateInstance = 0x200,
3278 BFLAGS_GetField = 0x400,
3279 BFLAGS_SetField = 0x800,
3280 BFLAGS_GetProperty = 0x1000,
3281 BFLAGS_SetProperty = 0x2000,
3282 BFLAGS_ExactBinding = 0x10000,
3283 BFLAGS_SuppressChangeType = 0x20000,
3284 BFLAGS_OptionalParamBinding = 0x40000
3287 ICALL_EXPORT MonoReflectionField *
3288 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3291 MonoClass *startklass, *klass;
3293 MonoClassField *field;
3296 int (*compare_func) (const char *s1, const char *s2) = NULL;
3297 domain = ((MonoObject *)type)->vtable->domain;
3298 klass = startklass = mono_class_from_mono_type (type->type);
3301 mono_raise_exception (mono_get_exception_argument_null ("name"));
3302 if (type->type->byref)
3305 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3308 if (klass->exception_type != MONO_EXCEPTION_NONE)
3309 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3312 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3313 guint32 flags = mono_field_get_flags (field);
3316 if (mono_field_is_deleted_with_flags (field, flags))
3318 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3319 if (bflags & BFLAGS_Public)
3321 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3322 if (bflags & BFLAGS_NonPublic) {
3329 if (flags & FIELD_ATTRIBUTE_STATIC) {
3330 if (bflags & BFLAGS_Static)
3331 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3334 if (bflags & BFLAGS_Instance)
3341 utf8_name = mono_string_to_utf8 (name);
3343 if (compare_func (mono_field_get_name (field), utf8_name)) {
3349 return mono_field_get_object (domain, klass, field);
3351 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3357 ICALL_EXPORT MonoArray*
3358 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3361 MonoClass *startklass, *klass, *refklass;
3366 MonoClassField *field;
3367 MonoPtrArray tmp_array;
3369 MONO_ARCH_SAVE_REGS;
3371 domain = ((MonoObject *)type)->vtable->domain;
3372 if (type->type->byref)
3373 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3374 klass = startklass = mono_class_from_mono_type (type->type);
3375 refklass = mono_class_from_mono_type (reftype->type);
3377 mono_ptr_array_init (tmp_array, 2);
3380 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3381 mono_ptr_array_destroy (tmp_array);
3382 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3386 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3387 guint32 flags = mono_field_get_flags (field);
3389 if (mono_field_is_deleted_with_flags (field, flags))
3391 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3392 if (bflags & BFLAGS_Public)
3394 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3395 if (bflags & BFLAGS_NonPublic) {
3402 if (flags & FIELD_ATTRIBUTE_STATIC) {
3403 if (bflags & BFLAGS_Static)
3404 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3407 if (bflags & BFLAGS_Instance)
3413 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3414 mono_ptr_array_append (tmp_array, member);
3416 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3419 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3421 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3422 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3424 mono_ptr_array_destroy (tmp_array);
3430 method_nonpublic (MonoMethod* method, gboolean start_klass)
3432 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3433 case METHOD_ATTRIBUTE_ASSEM:
3434 return (start_klass || mono_defaults.generic_ilist_class);
3435 case METHOD_ATTRIBUTE_PRIVATE:
3437 case METHOD_ATTRIBUTE_PUBLIC:
3445 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3448 MonoClass *startklass;
3451 int len, match, nslots;
3452 /*FIXME, use MonoBitSet*/
3453 guint32 method_slots_default [8];
3454 guint32 *method_slots = NULL;
3455 int (*compare_func) (const char *s1, const char *s2) = NULL;
3457 array = g_ptr_array_new ();
3463 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3465 /* An optimization for calls made from Delegate:CreateDelegate () */
3466 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3467 method = mono_get_delegate_invoke (klass);
3468 if (mono_loader_get_last_error ())
3471 g_ptr_array_add (array, method);
3475 mono_class_setup_vtable (klass);
3476 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3479 if (is_generic_parameter (&klass->byval_arg))
3480 nslots = mono_class_get_vtable_size (klass->parent);
3482 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3483 if (nslots >= sizeof (method_slots_default) * 8) {
3484 method_slots = g_new0 (guint32, nslots / 32 + 1);
3486 method_slots = method_slots_default;
3487 memset (method_slots, 0, sizeof (method_slots_default));
3490 mono_class_setup_vtable (klass);
3491 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3495 while ((method = mono_class_get_methods (klass, &iter))) {
3497 if (method->slot != -1) {
3498 g_assert (method->slot < nslots);
3499 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3501 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3502 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3505 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3507 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3508 if (bflags & BFLAGS_Public)
3510 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3516 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3517 if (bflags & BFLAGS_Static)
3518 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3521 if (bflags & BFLAGS_Instance)
3529 if (compare_func (name, method->name))
3534 g_ptr_array_add (array, method);
3536 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3538 if (method_slots != method_slots_default)
3539 g_free (method_slots);
3544 if (method_slots != method_slots_default)
3545 g_free (method_slots);
3546 g_ptr_array_free (array, TRUE);
3548 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3549 *ex = mono_class_get_exception_for_failure (klass);
3551 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3552 mono_loader_clear_error ();
3557 ICALL_EXPORT MonoArray*
3558 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3560 static MonoClass *MethodInfo_array;
3563 MonoVTable *array_vtable;
3564 MonoException *ex = NULL;
3565 const char *mname = NULL;
3566 GPtrArray *method_array;
3567 MonoClass *klass, *refklass;
3570 if (!MethodInfo_array) {
3571 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3572 mono_memory_barrier ();
3573 MethodInfo_array = klass;
3576 klass = mono_class_from_mono_type (type->type);
3577 refklass = mono_class_from_mono_type (reftype->type);
3578 domain = ((MonoObject *)type)->vtable->domain;
3579 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3580 if (type->type->byref)
3581 return mono_array_new_specific (array_vtable, 0);
3584 mname = mono_string_to_utf8 (name);
3586 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3587 g_free ((char*)mname);
3589 mono_raise_exception (ex);
3591 res = mono_array_new_specific (array_vtable, method_array->len);
3594 for (i = 0; i < method_array->len; ++i) {
3595 MonoMethod *method = g_ptr_array_index (method_array, i);
3596 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3599 g_ptr_array_free (method_array, TRUE);
3603 ICALL_EXPORT MonoArray*
3604 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3607 static MonoClass *System_Reflection_ConstructorInfo;
3608 MonoClass *startklass, *klass, *refklass;
3613 gpointer iter = NULL;
3614 MonoPtrArray tmp_array;
3616 MONO_ARCH_SAVE_REGS;
3618 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3620 domain = ((MonoObject *)type)->vtable->domain;
3621 if (type->type->byref)
3622 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3623 klass = startklass = mono_class_from_mono_type (type->type);
3624 refklass = mono_class_from_mono_type (reftype->type);
3626 if (!System_Reflection_ConstructorInfo)
3627 System_Reflection_ConstructorInfo = mono_class_from_name (
3628 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3631 while ((method = mono_class_get_methods (klass, &iter))) {
3633 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3635 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3636 if (bflags & BFLAGS_Public)
3639 if (bflags & BFLAGS_NonPublic)
3645 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3646 if (bflags & BFLAGS_Static)
3647 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3650 if (bflags & BFLAGS_Instance)
3656 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3658 mono_ptr_array_append (tmp_array, member);
3661 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3663 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3664 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3666 mono_ptr_array_destroy (tmp_array);
3672 property_hash (gconstpointer data)
3674 MonoProperty *prop = (MonoProperty*)data;
3676 return g_str_hash (prop->name);
3680 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3682 // Properties are hide-by-name-and-signature
3683 if (!g_str_equal (prop1->name, prop2->name))
3686 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3688 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3694 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3699 return method_nonpublic (accessor, start_klass);
3702 ICALL_EXPORT MonoArray*
3703 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3707 static MonoClass *System_Reflection_PropertyInfo;
3708 MonoClass *startklass, *klass;
3714 gchar *propname = NULL;
3715 int (*compare_func) (const char *s1, const char *s2) = NULL;
3717 GHashTable *properties = NULL;
3718 MonoPtrArray tmp_array;
3720 MONO_ARCH_SAVE_REGS;
3722 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3724 if (!System_Reflection_PropertyInfo)
3725 System_Reflection_PropertyInfo = mono_class_from_name (
3726 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3728 domain = ((MonoObject *)type)->vtable->domain;
3729 if (type->type->byref)
3730 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3731 klass = startklass = mono_class_from_mono_type (type->type);
3734 propname = mono_string_to_utf8 (name);
3735 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3738 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3740 mono_class_setup_vtable (klass);
3741 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3745 while ((prop = mono_class_get_properties (klass, &iter))) {
3751 flags = method->flags;
3754 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3755 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3756 if (bflags & BFLAGS_Public)
3758 } else if (bflags & BFLAGS_NonPublic) {
3759 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3760 property_accessor_nonpublic(prop->set, startklass == klass)) {
3767 if (flags & METHOD_ATTRIBUTE_STATIC) {
3768 if (bflags & BFLAGS_Static)
3769 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3772 if (bflags & BFLAGS_Instance)
3781 if (compare_func (propname, prop->name))
3785 if (g_hash_table_lookup (properties, prop))
3788 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3790 g_hash_table_insert (properties, prop, prop);
3792 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3795 g_hash_table_destroy (properties);
3798 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3799 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3800 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3802 mono_ptr_array_destroy (tmp_array);
3808 g_hash_table_destroy (properties);
3811 mono_ptr_array_destroy (tmp_array);
3813 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3814 ex = mono_class_get_exception_for_failure (klass);
3816 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3817 mono_loader_clear_error ();
3819 mono_raise_exception (ex);
3823 ICALL_EXPORT MonoReflectionEvent *
3824 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3827 MonoClass *klass, *startklass;
3832 int (*compare_func) (const char *s1, const char *s2);
3834 MONO_ARCH_SAVE_REGS;
3836 event_name = mono_string_to_utf8 (name);
3837 if (type->type->byref)
3839 klass = startklass = mono_class_from_mono_type (type->type);
3840 domain = mono_object_domain (type);
3842 mono_class_init_or_throw (klass);
3844 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3846 if (klass->exception_type != MONO_EXCEPTION_NONE)
3847 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3850 while ((event = mono_class_get_events (klass, &iter))) {
3851 if (compare_func (event->name, event_name))
3854 method = event->add;
3856 method = event->remove;
3858 method = event->raise;
3860 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3861 if (!(bflags & BFLAGS_Public))
3864 if (!(bflags & BFLAGS_NonPublic))
3866 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3870 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3871 if (!(bflags & BFLAGS_Static))
3873 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3876 if (!(bflags & BFLAGS_Instance))
3880 if (!(bflags & BFLAGS_NonPublic))
3883 g_free (event_name);
3884 return mono_event_get_object (domain, startklass, event);
3887 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3890 g_free (event_name);
3895 event_hash (gconstpointer data)
3897 MonoEvent *event = (MonoEvent*)data;
3899 return g_str_hash (event->name);
3903 event_equal (MonoEvent *event1, MonoEvent *event2)
3905 // Events are hide-by-name
3906 return g_str_equal (event1->name, event2->name);
3909 ICALL_EXPORT MonoArray*
3910 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3914 static MonoClass *System_Reflection_EventInfo;
3915 MonoClass *startklass, *klass;
3921 GHashTable *events = NULL;
3922 MonoPtrArray tmp_array;
3924 MONO_ARCH_SAVE_REGS;
3926 mono_ptr_array_init (tmp_array, 4);
3928 if (!System_Reflection_EventInfo)
3929 System_Reflection_EventInfo = mono_class_from_name (
3930 mono_defaults.corlib, "System.Reflection", "EventInfo");
3932 domain = mono_object_domain (type);
3933 if (type->type->byref)
3934 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3935 klass = startklass = mono_class_from_mono_type (type->type);
3937 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3939 mono_class_setup_vtable (klass);
3940 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3944 while ((event = mono_class_get_events (klass, &iter))) {
3946 method = event->add;
3948 method = event->remove;
3950 method = event->raise;
3952 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3953 if (bflags & BFLAGS_Public)
3955 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3956 if (bflags & BFLAGS_NonPublic)
3961 if (bflags & BFLAGS_NonPublic)
3967 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3968 if (bflags & BFLAGS_Static)
3969 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3972 if (bflags & BFLAGS_Instance)
3977 if (bflags & BFLAGS_Instance)
3982 if (g_hash_table_lookup (events, event))
3985 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3987 g_hash_table_insert (events, event, event);
3989 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3992 g_hash_table_destroy (events);
3994 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3996 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3997 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3999 mono_ptr_array_destroy (tmp_array);
4004 mono_ptr_array_destroy (tmp_array);
4005 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4006 ex = mono_class_get_exception_for_failure (klass);
4008 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4009 mono_loader_clear_error ();
4011 mono_raise_exception (ex);
4015 ICALL_EXPORT MonoReflectionType *
4016 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4024 MONO_ARCH_SAVE_REGS;
4027 mono_raise_exception (mono_get_exception_argument_null ("name"));
4029 domain = ((MonoObject *)type)->vtable->domain;
4030 if (type->type->byref)
4032 klass = mono_class_from_mono_type (type->type);
4034 str = mono_string_to_utf8 (name);
4037 if (klass->exception_type != MONO_EXCEPTION_NONE)
4038 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4041 * If a nested type is generic, return its generic type definition.
4042 * Note that this means that the return value is essentially a
4043 * nested type of the generic type definition of @klass.
4045 * A note in MSDN claims that a generic type definition can have
4046 * nested types that aren't generic. In any case, the container of that
4047 * nested type would be the generic type definition.
4049 if (klass->generic_class)
4050 klass = klass->generic_class->container_class;
4053 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4055 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4056 if (bflags & BFLAGS_Public)
4059 if (bflags & BFLAGS_NonPublic)
4064 if (strcmp (nested->name, str) == 0){
4066 return mono_type_get_object (domain, &nested->byval_arg);
4069 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4075 ICALL_EXPORT MonoArray*
4076 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4085 MonoPtrArray tmp_array;
4087 MONO_ARCH_SAVE_REGS;
4089 domain = ((MonoObject *)type)->vtable->domain;
4090 if (type->type->byref)
4091 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4092 klass = mono_class_from_mono_type (type->type);
4095 * If a nested type is generic, return its generic type definition.
4096 * Note that this means that the return value is essentially the set
4097 * of nested types of the generic type definition of @klass.
4099 * A note in MSDN claims that a generic type definition can have
4100 * nested types that aren't generic. In any case, the container of that
4101 * nested type would be the generic type definition.
4103 if (klass->generic_class)
4104 klass = klass->generic_class->container_class;
4106 mono_ptr_array_init (tmp_array, 1);
4108 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4110 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4111 if (bflags & BFLAGS_Public)
4114 if (bflags & BFLAGS_NonPublic)
4119 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4120 mono_ptr_array_append (tmp_array, member);
4123 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4125 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4126 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4128 mono_ptr_array_destroy (tmp_array);
4133 ICALL_EXPORT MonoReflectionType*
4134 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4137 MonoType *type = NULL;
4138 MonoTypeNameParse info;
4139 gboolean type_resolve;
4141 MONO_ARCH_SAVE_REGS;
4143 /* On MS.NET, this does not fire a TypeResolve event */
4144 type_resolve = TRUE;
4145 str = mono_string_to_utf8 (name);
4146 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4147 if (!mono_reflection_parse_type (str, &info)) {
4149 mono_reflection_free_type_info (&info);
4150 if (throwOnError) /* uhm: this is a parse error, though... */
4151 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4152 /*g_print ("failed parse\n");*/
4156 if (info.assembly.name) {
4158 mono_reflection_free_type_info (&info);
4160 /* 1.0 and 2.0 throw different exceptions */
4161 if (mono_defaults.generic_ilist_class)
4162 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4164 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4169 if (module != NULL) {
4171 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4176 if (assembly->assembly->dynamic) {
4177 /* Enumerate all modules */
4178 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4182 if (abuilder->modules) {
4183 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4184 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4185 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4191 if (!type && abuilder->loaded_modules) {
4192 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4193 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4194 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4201 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4203 mono_reflection_free_type_info (&info);
4205 MonoException *e = NULL;
4208 e = mono_get_exception_type_load (name, NULL);
4210 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4211 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4213 mono_loader_clear_error ();
4216 mono_raise_exception (e);
4219 } else if (mono_loader_get_last_error ()) {
4221 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4222 mono_loader_clear_error ();
4225 if (type->type == MONO_TYPE_CLASS) {
4226 MonoClass *klass = mono_type_get_class (type);
4228 if (mono_security_enabled () && !klass->exception_type)
4229 /* Some security problems are detected during generic vtable construction */
4230 mono_class_setup_vtable (klass);
4232 /* need to report exceptions ? */
4233 if (throwOnError && klass->exception_type) {
4234 /* report SecurityException (or others) that occured when loading the assembly */
4235 MonoException *exc = mono_class_get_exception_for_failure (klass);
4236 mono_loader_clear_error ();
4237 mono_raise_exception (exc);
4238 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4243 /* g_print ("got it\n"); */
4244 return mono_type_get_object (mono_object_domain (assembly), type);
4248 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4251 gchar *shadow_ini_file;
4254 /* Check for shadow-copied assembly */
4255 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4256 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4258 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4259 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4265 g_free (shadow_ini_file);
4266 if (content != NULL) {
4269 *filename = content;
4276 ICALL_EXPORT MonoString *
4277 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4279 MonoDomain *domain = mono_object_domain (assembly);
4280 MonoAssembly *mass = assembly->assembly;
4281 MonoString *res = NULL;
4286 MONO_ARCH_SAVE_REGS;
4288 if (g_path_is_absolute (mass->image->name)) {
4289 absolute = g_strdup (mass->image->name);
4290 dirname = g_path_get_dirname (absolute);
4292 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4293 dirname = g_strdup (mass->basedir);
4296 replace_shadow_path (domain, dirname, &absolute);
4301 for (i = strlen (absolute) - 1; i >= 0; i--)
4302 if (absolute [i] == '\\')
4307 uri = g_filename_to_uri (absolute, NULL, NULL);
4309 const char *prepend = "file://";
4311 if (*absolute == '/' && *(absolute + 1) == '/') {
4314 prepend = "file:///";
4317 uri = g_strconcat (prepend, absolute, NULL);
4321 res = mono_string_new (domain, uri);
4328 ICALL_EXPORT MonoBoolean
4329 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4331 MonoAssembly *mass = assembly->assembly;
4333 MONO_ARCH_SAVE_REGS;
4335 return mass->in_gac;
4338 ICALL_EXPORT MonoReflectionAssembly*
4339 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4343 MonoImageOpenStatus status;
4345 MONO_ARCH_SAVE_REGS;
4347 name = mono_string_to_utf8 (mname);
4348 res = mono_assembly_load_with_partial_name (name, &status);
4354 return mono_assembly_get_object (mono_domain_get (), res);
4357 ICALL_EXPORT MonoString *
4358 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4360 MonoDomain *domain = mono_object_domain (assembly);
4363 MONO_ARCH_SAVE_REGS;
4365 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4370 ICALL_EXPORT MonoBoolean
4371 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4373 MONO_ARCH_SAVE_REGS;
4375 return assembly->assembly->ref_only;
4378 ICALL_EXPORT MonoString *
4379 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4381 MonoDomain *domain = mono_object_domain (assembly);
4383 MONO_ARCH_SAVE_REGS;
4385 return mono_string_new (domain, assembly->assembly->image->version);
4388 ICALL_EXPORT MonoReflectionMethod*
4389 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4391 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4393 MONO_ARCH_SAVE_REGS;
4397 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4400 ICALL_EXPORT MonoReflectionModule*
4401 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4403 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4406 ICALL_EXPORT MonoArray*
4407 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4409 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4410 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4414 MONO_ARCH_SAVE_REGS;
4416 for (i = 0; i < table->rows; ++i) {
4417 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4418 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4424 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4426 static MonoClass *System_Version = NULL;
4427 static MonoMethod *create_version = NULL;
4431 if (!System_Version) {
4432 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4433 g_assert (System_Version);
4436 if (!create_version) {
4437 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4438 create_version = mono_method_desc_search_in_class (desc, System_Version);
4439 g_assert (create_version);
4440 mono_method_desc_free (desc);
4446 args [3] = &revision;
4447 result = mono_object_new (domain, System_Version);
4448 mono_runtime_invoke (create_version, result, args, NULL);
4453 ICALL_EXPORT MonoArray*
4454 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4456 static MonoClass *System_Reflection_AssemblyName;
4458 MonoDomain *domain = mono_object_domain (assembly);
4460 static MonoMethod *create_culture = NULL;
4461 MonoImage *image = assembly->assembly->image;
4464 MONO_ARCH_SAVE_REGS;
4466 if (!System_Reflection_AssemblyName)
4467 System_Reflection_AssemblyName = mono_class_from_name (
4468 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4470 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4473 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4475 if (count > 0 && !create_culture) {
4476 MonoMethodDesc *desc = mono_method_desc_new (
4477 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4478 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4479 g_assert (create_culture);
4480 mono_method_desc_free (desc);
4483 for (i = 0; i < count; i++) {
4484 MonoReflectionAssemblyName *aname;
4485 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4487 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4489 aname = (MonoReflectionAssemblyName *) mono_object_new (
4490 domain, System_Reflection_AssemblyName);
4492 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4494 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4495 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4496 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4497 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4498 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4499 aname->versioncompat = 1; /* SameMachine (default) */
4500 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4501 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4503 if (create_culture) {
4505 MonoBoolean assembly_ref = 1;
4506 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4507 args [1] = &assembly_ref;
4508 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4511 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4512 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4513 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4515 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4516 /* public key token isn't copied - the class library will
4517 automatically generate it from the public key if required */
4518 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4519 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4521 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4522 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4525 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4528 /* note: this function doesn't return the codebase on purpose (i.e. it can
4529 be used under partial trust as path information isn't present). */
4531 mono_array_setref (result, i, aname);
4536 /* move this in some file in mono/util/ */
4538 g_concat_dir_and_file (const char *dir, const char *file)
4540 g_return_val_if_fail (dir != NULL, NULL);
4541 g_return_val_if_fail (file != NULL, NULL);
4544 * If the directory name doesn't have a / on the end, we need
4545 * to add one so we get a proper path to the file
4547 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4548 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4550 return g_strconcat (dir, file, NULL);
4554 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4556 char *n = mono_string_to_utf8 (name);
4557 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4559 guint32 cols [MONO_MANIFEST_SIZE];
4560 guint32 impl, file_idx;
4564 MONO_ARCH_SAVE_REGS;
4566 for (i = 0; i < table->rows; ++i) {
4567 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4568 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4569 if (strcmp (val, n) == 0)
4573 if (i == table->rows)
4576 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4579 * this code should only be called after obtaining the
4580 * ResourceInfo and handling the other cases.
4582 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4583 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4585 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4590 module = assembly->assembly->image;
4592 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4594 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4597 ICALL_EXPORT gboolean
4598 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4600 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4602 guint32 cols [MONO_MANIFEST_SIZE];
4603 guint32 file_cols [MONO_FILE_SIZE];
4607 MONO_ARCH_SAVE_REGS;
4609 n = mono_string_to_utf8 (name);
4610 for (i = 0; i < table->rows; ++i) {
4611 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4612 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4613 if (strcmp (val, n) == 0)
4617 if (i == table->rows)
4620 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4621 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4624 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4625 case MONO_IMPLEMENTATION_FILE:
4626 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4627 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4628 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4629 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4630 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4631 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4634 info->location = RESOURCE_LOCATION_EMBEDDED;
4637 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4638 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4639 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4640 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4641 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4642 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4644 mono_raise_exception (ex);
4646 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4648 /* Obtain info recursively */
4649 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4650 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4653 case MONO_IMPLEMENTATION_EXP_TYPE:
4654 g_assert_not_reached ();
4662 ICALL_EXPORT MonoObject*
4663 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4665 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4666 MonoArray *result = NULL;
4671 MONO_ARCH_SAVE_REGS;
4673 /* check hash if needed */
4675 n = mono_string_to_utf8 (name);
4676 for (i = 0; i < table->rows; ++i) {
4677 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4678 if (strcmp (val, n) == 0) {
4681 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4682 fn = mono_string_new (mono_object_domain (assembly), n);
4684 return (MonoObject*)fn;
4692 for (i = 0; i < table->rows; ++i) {
4693 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4697 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4700 for (i = 0; i < table->rows; ++i) {
4701 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4702 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4703 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4704 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4709 return (MonoObject*)result;
4712 ICALL_EXPORT MonoArray*
4713 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4715 MonoDomain *domain = mono_domain_get();
4718 int i, j, file_count = 0;
4719 MonoImage **modules;
4720 guint32 module_count, real_module_count;
4721 MonoTableInfo *table;
4722 guint32 cols [MONO_FILE_SIZE];
4723 MonoImage *image = assembly->assembly->image;
4725 g_assert (image != NULL);
4726 g_assert (!assembly->assembly->dynamic);
4728 table = &image->tables [MONO_TABLE_FILE];
4729 file_count = table->rows;
4731 modules = image->modules;
4732 module_count = image->module_count;
4734 real_module_count = 0;
4735 for (i = 0; i < module_count; ++i)
4737 real_module_count ++;
4739 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4740 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4742 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4744 for (i = 0; i < module_count; ++i)
4746 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4750 for (i = 0; i < file_count; ++i, ++j) {
4751 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4752 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4753 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4755 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4757 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4758 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4760 mono_array_setref (res, j, mono_module_get_object (domain, m));
4767 ICALL_EXPORT MonoReflectionMethod*
4768 ves_icall_GetCurrentMethod (void)
4770 MonoMethod *m = mono_method_get_last_managed ();
4772 while (m->is_inflated)
4773 m = ((MonoMethodInflated*)m)->declaring;
4775 return mono_method_get_object (mono_domain_get (), m, NULL);
4780 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4783 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4784 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4785 //method is inflated, we should inflate it on the other class
4786 MonoGenericContext ctx;
4787 ctx.method_inst = inflated->context.method_inst;
4788 ctx.class_inst = inflated->context.class_inst;
4789 if (klass->generic_class)
4790 ctx.class_inst = klass->generic_class->context.class_inst;
4791 else if (klass->generic_container)
4792 ctx.class_inst = klass->generic_container->context.class_inst;
4793 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4796 mono_class_setup_methods (method->klass);
4797 if (method->klass->exception_type)
4799 for (i = 0; i < method->klass->method.count; ++i) {
4800 if (method->klass->methods [i] == method) {
4805 mono_class_setup_methods (klass);
4806 if (klass->exception_type)
4808 g_assert (offset >= 0 && offset < klass->method.count);
4809 return klass->methods [offset];
4812 ICALL_EXPORT MonoReflectionMethod*
4813 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4817 klass = mono_class_from_mono_type (type);
4818 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4820 if (method->klass != klass) {
4821 method = mono_method_get_equivalent_method (method, klass);
4826 klass = method->klass;
4827 return mono_method_get_object (mono_domain_get (), method, klass);
4830 ICALL_EXPORT MonoReflectionMethod*
4831 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4833 return mono_method_get_object (mono_domain_get (), method, NULL);
4836 ICALL_EXPORT MonoReflectionMethodBody*
4837 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4839 return mono_method_body_get_object (mono_domain_get (), method);
4842 ICALL_EXPORT MonoReflectionAssembly*
4843 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4845 MonoMethod *dest = NULL;
4847 MONO_ARCH_SAVE_REGS;
4849 mono_stack_walk_no_il (get_executing, &dest);
4851 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4855 ICALL_EXPORT MonoReflectionAssembly*
4856 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4858 MonoDomain* domain = mono_domain_get ();
4860 MONO_ARCH_SAVE_REGS;
4862 if (!domain->entry_assembly)
4865 return mono_assembly_get_object (domain, domain->entry_assembly);
4868 ICALL_EXPORT MonoReflectionAssembly*
4869 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4874 MONO_ARCH_SAVE_REGS;
4877 mono_stack_walk_no_il (get_executing, &dest);
4879 mono_stack_walk_no_il (get_caller, &dest);
4882 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4885 ICALL_EXPORT MonoString *
4886 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4887 gboolean assembly_qualified)
4889 MonoDomain *domain = mono_object_domain (object);
4890 MonoTypeNameFormat format;
4895 format = assembly_qualified ?
4896 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4897 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4899 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4901 name = mono_type_get_name_full (object->type, format);
4905 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4910 res = mono_string_new (domain, name);
4917 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4919 MonoClass *klass = mono_class_from_mono_type (this->type);
4920 mono_class_init_or_throw (klass);
4921 return mono_security_core_clr_class_level (klass);
4925 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4927 static MonoMethod *create_culture = NULL;
4930 const char *pkey_ptr;
4932 MonoBoolean assembly_ref = 0;
4934 MONO_ARCH_SAVE_REGS;
4936 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4937 aname->major = name->major;
4938 aname->minor = name->minor;
4939 aname->build = name->build;
4940 aname->flags = name->flags;
4941 aname->revision = name->revision;
4942 aname->hashalg = name->hash_alg;
4943 aname->versioncompat = 1; /* SameMachine (default) */
4944 aname->processor_architecture = name->arch;
4946 if (by_default_version)
4947 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4950 if (absolute != NULL && *absolute != '\0') {
4951 const gchar *prepend = "file://";
4954 codebase = g_strdup (absolute);
4959 for (i = strlen (codebase) - 1; i >= 0; i--)
4960 if (codebase [i] == '\\')
4963 if (*codebase == '/' && *(codebase + 1) == '/') {
4966 prepend = "file:///";
4970 result = g_strconcat (prepend, codebase, NULL);
4976 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4980 if (!create_culture) {
4981 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4982 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4983 g_assert (create_culture);
4984 mono_method_desc_free (desc);
4987 if (name->culture) {
4988 args [0] = mono_string_new (domain, name->culture);
4989 args [1] = &assembly_ref;
4990 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4993 if (name->public_key) {
4994 pkey_ptr = (char*)name->public_key;
4995 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4997 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4998 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4999 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5000 } else if (default_publickey) {
5001 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5002 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5005 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5006 if (name->public_key_token [0]) {
5010 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5011 p = mono_array_addr (aname->keyToken, char, 0);
5013 for (i = 0, j = 0; i < 8; i++) {
5014 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5015 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5018 } else if (default_token) {
5019 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5023 ICALL_EXPORT MonoString *
5024 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5026 MonoDomain *domain = mono_object_domain (assembly);
5027 MonoAssembly *mass = assembly->assembly;
5031 name = mono_stringify_assembly_name (&mass->aname);
5032 res = mono_string_new (domain, name);
5039 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5042 MonoAssembly *mass = assembly->assembly;
5044 MONO_ARCH_SAVE_REGS;
5046 if (g_path_is_absolute (mass->image->name)) {
5047 fill_reflection_assembly_name (mono_object_domain (assembly),
5048 aname, &mass->aname, mass->image->name, TRUE,
5052 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5054 fill_reflection_assembly_name (mono_object_domain (assembly),
5055 aname, &mass->aname, absolute, TRUE, TRUE,
5062 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5065 MonoImageOpenStatus status = MONO_IMAGE_OK;
5068 MonoAssemblyName name;
5071 MONO_ARCH_SAVE_REGS;
5073 filename = mono_string_to_utf8 (fname);
5075 dirname = g_path_get_dirname (filename);
5076 replace_shadow_path (mono_domain_get (), dirname, &filename);
5079 image = mono_image_open (filename, &status);
5085 if (status == MONO_IMAGE_IMAGE_INVALID)
5086 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5088 exc = mono_get_exception_file_not_found2 (NULL, fname);
5089 mono_raise_exception (exc);
5092 res = mono_assembly_fill_assembly_name (image, &name);
5094 mono_image_close (image);
5096 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5099 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5103 mono_image_close (image);
5106 ICALL_EXPORT MonoBoolean
5107 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5108 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5110 MonoBoolean result = FALSE;
5111 MonoDeclSecurityEntry entry;
5113 /* SecurityAction.RequestMinimum */
5114 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5115 *minimum = entry.blob;
5116 *minLength = entry.size;
5119 /* SecurityAction.RequestOptional */
5120 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5121 *optional = entry.blob;
5122 *optLength = entry.size;
5125 /* SecurityAction.RequestRefuse */
5126 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5127 *refused = entry.blob;
5128 *refLength = entry.size;
5136 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5140 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5142 guint32 attrs, visibility;
5144 /* we start the count from 1 because we skip the special type <Module> */
5147 for (i = 1; i < tdef->rows; ++i) {
5148 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5149 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5150 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5154 count = tdef->rows - 1;
5156 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5157 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5159 for (i = 1; i < tdef->rows; ++i) {
5160 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5161 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5162 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5163 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5165 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5167 MonoLoaderError *error;
5170 error = mono_loader_get_last_error ();
5171 g_assert (error != NULL);
5173 ex = mono_loader_error_prepare_exception (error);
5174 mono_array_setref (*exceptions, count, ex);
5176 if (mono_loader_get_last_error ())
5177 mono_loader_clear_error ();
5185 ICALL_EXPORT MonoArray*
5186 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5188 MonoArray *res = NULL;
5189 MonoArray *exceptions = NULL;
5190 MonoImage *image = NULL;
5191 MonoTableInfo *table = NULL;
5194 int i, len, ex_count;
5196 MONO_ARCH_SAVE_REGS;
5198 domain = mono_object_domain (assembly);
5200 g_assert (!assembly->assembly->dynamic);
5201 image = assembly->assembly->image;
5202 table = &image->tables [MONO_TABLE_FILE];
5203 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5205 /* Append data from all modules in the assembly */
5206 for (i = 0; i < table->rows; ++i) {
5207 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5208 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5211 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5212 /* Append the new types to the end of the array */
5213 if (mono_array_length (res2) > 0) {
5215 MonoArray *res3, *ex3;
5217 len1 = mono_array_length (res);
5218 len2 = mono_array_length (res2);
5220 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5221 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5222 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5225 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5226 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5227 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5234 /* the ReflectionTypeLoadException must have all the types (Types property),
5235 * NULL replacing types which throws an exception. The LoaderException must
5236 * contain all exceptions for NULL items.
5239 len = mono_array_length (res);
5242 for (i = 0; i < len; i++) {
5243 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5247 klass = mono_type_get_class (t->type);
5248 if ((klass != NULL) && klass->exception_type) {
5249 /* keep the class in the list */
5250 list = g_list_append (list, klass);
5251 /* and replace Type with NULL */
5252 mono_array_setref (res, i, NULL);
5259 if (list || ex_count) {
5261 MonoException *exc = NULL;
5262 MonoArray *exl = NULL;
5263 int j, length = g_list_length (list) + ex_count;
5265 mono_loader_clear_error ();
5267 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5268 /* Types for which mono_class_get () succeeded */
5269 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5270 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5271 mono_array_setref (exl, i, exc);
5273 /* Types for which it don't */
5274 for (j = 0; j < mono_array_length (exceptions); ++j) {
5275 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5277 g_assert (i < length);
5278 mono_array_setref (exl, i, exc);
5285 exc = mono_get_exception_reflection_type_load (res, exl);
5286 mono_loader_clear_error ();
5287 mono_raise_exception (exc);
5293 ICALL_EXPORT gboolean
5294 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5296 MonoAssemblyName aname;
5297 MonoDomain *domain = mono_object_domain (name);
5299 gboolean is_version_defined;
5300 gboolean is_token_defined;
5302 aname.public_key = NULL;
5303 val = mono_string_to_utf8 (assname);
5304 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5305 g_free ((guint8*) aname.public_key);
5310 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5311 FALSE, is_token_defined);
5313 mono_assembly_name_free (&aname);
5314 g_free ((guint8*) aname.public_key);
5320 ICALL_EXPORT MonoReflectionType*
5321 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5323 MonoDomain *domain = mono_object_domain (module);
5326 MONO_ARCH_SAVE_REGS;
5328 g_assert (module->image);
5330 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5331 /* These images do not have a global type */
5334 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5335 return mono_type_get_object (domain, &klass->byval_arg);
5339 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5341 /*if (module->image)
5342 mono_image_close (module->image);*/
5345 ICALL_EXPORT MonoString*
5346 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5348 MonoDomain *domain = mono_object_domain (module);
5350 MONO_ARCH_SAVE_REGS;
5352 g_assert (module->image);
5353 return mono_string_new (domain, module->image->guid);
5356 ICALL_EXPORT gpointer
5357 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5360 if (module->image && module->image->is_module_handle)
5361 return module->image->raw_data;
5364 return (gpointer) (-1);
5368 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5370 if (image->dynamic) {
5371 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5372 *pe_kind = dyn->pe_kind;
5373 *machine = dyn->machine;
5376 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5377 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5382 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5384 return (image->md_version_major << 16) | (image->md_version_minor);
5387 ICALL_EXPORT MonoArray*
5388 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5390 MonoArray *exceptions;
5393 MONO_ARCH_SAVE_REGS;
5396 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5398 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5399 for (i = 0; i < mono_array_length (exceptions); ++i) {
5400 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5402 mono_raise_exception (ex);
5409 mono_memberref_is_method (MonoImage *image, guint32 token)
5411 if (!image->dynamic) {
5412 guint32 cols [MONO_MEMBERREF_SIZE];
5414 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5415 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5416 mono_metadata_decode_blob_size (sig, &sig);
5417 return (*sig != 0x6);
5419 MonoClass *handle_class;
5421 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5424 return mono_defaults.methodhandle_class == handle_class;
5429 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5432 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5433 mono_array_addr (type_args, MonoType*, 0));
5435 context->class_inst = NULL;
5437 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5438 mono_array_addr (method_args, MonoType*, 0));
5440 context->method_inst = NULL;
5443 ICALL_EXPORT MonoType*
5444 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5447 int table = mono_metadata_token_table (token);
5448 int index = mono_metadata_token_index (token);
5449 MonoGenericContext context;
5451 *error = ResolveTokenError_Other;
5453 /* Validate token */
5454 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5455 (table != MONO_TABLE_TYPESPEC)) {
5456 *error = ResolveTokenError_BadTable;
5460 if (image->dynamic) {
5461 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5462 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5463 return klass ? &klass->byval_arg : NULL;
5466 init_generic_context_from_args (&context, type_args, method_args);
5467 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5468 return klass ? &klass->byval_arg : NULL;
5471 if ((index <= 0) || (index > image->tables [table].rows)) {
5472 *error = ResolveTokenError_OutOfRange;
5476 init_generic_context_from_args (&context, type_args, method_args);
5477 klass = mono_class_get_full (image, token, &context);
5479 if (mono_loader_get_last_error ())
5480 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5483 return &klass->byval_arg;
5488 ICALL_EXPORT MonoMethod*
5489 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5491 int table = mono_metadata_token_table (token);
5492 int index = mono_metadata_token_index (token);
5493 MonoGenericContext context;
5496 *error = ResolveTokenError_Other;
5498 /* Validate token */
5499 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5500 (table != MONO_TABLE_MEMBERREF)) {
5501 *error = ResolveTokenError_BadTable;
5505 if (image->dynamic) {
5506 if (table == MONO_TABLE_METHOD)
5507 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5509 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5510 *error = ResolveTokenError_BadTable;
5514 init_generic_context_from_args (&context, type_args, method_args);
5515 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5518 if ((index <= 0) || (index > image->tables [table].rows)) {
5519 *error = ResolveTokenError_OutOfRange;
5522 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5523 *error = ResolveTokenError_BadTable;
5527 init_generic_context_from_args (&context, type_args, method_args);
5528 method = mono_get_method_full (image, token, NULL, &context);
5530 if (mono_loader_get_last_error ())
5531 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5536 ICALL_EXPORT MonoString*
5537 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5539 int index = mono_metadata_token_index (token);
5541 *error = ResolveTokenError_Other;
5543 /* Validate token */
5544 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5545 *error = ResolveTokenError_BadTable;
5550 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5552 if ((index <= 0) || (index >= image->heap_us.size)) {
5553 *error = ResolveTokenError_OutOfRange;
5557 /* FIXME: What to do if the index points into the middle of a string ? */
5559 return mono_ldstr (mono_domain_get (), image, index);
5562 ICALL_EXPORT MonoClassField*
5563 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5566 int table = mono_metadata_token_table (token);
5567 int index = mono_metadata_token_index (token);
5568 MonoGenericContext context;
5569 MonoClassField *field;
5571 *error = ResolveTokenError_Other;
5573 /* Validate token */
5574 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5575 *error = ResolveTokenError_BadTable;
5579 if (image->dynamic) {
5580 if (table == MONO_TABLE_FIELD)
5581 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5583 if (mono_memberref_is_method (image, token)) {
5584 *error = ResolveTokenError_BadTable;
5588 init_generic_context_from_args (&context, type_args, method_args);
5589 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5592 if ((index <= 0) || (index > image->tables [table].rows)) {
5593 *error = ResolveTokenError_OutOfRange;
5596 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5597 *error = ResolveTokenError_BadTable;
5601 init_generic_context_from_args (&context, type_args, method_args);
5602 field = mono_field_from_token (image, token, &klass, &context);
5604 if (mono_loader_get_last_error ())
5605 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5611 ICALL_EXPORT MonoObject*
5612 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5614 int table = mono_metadata_token_table (token);
5616 *error = ResolveTokenError_Other;
5619 case MONO_TABLE_TYPEDEF:
5620 case MONO_TABLE_TYPEREF:
5621 case MONO_TABLE_TYPESPEC: {
5622 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5624 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5628 case MONO_TABLE_METHOD:
5629 case MONO_TABLE_METHODSPEC: {
5630 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5632 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5636 case MONO_TABLE_FIELD: {
5637 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5639 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5643 case MONO_TABLE_MEMBERREF:
5644 if (mono_memberref_is_method (image, token)) {
5645 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5647 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5652 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5654 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5661 *error = ResolveTokenError_BadTable;
5667 ICALL_EXPORT MonoArray*
5668 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5670 int table = mono_metadata_token_table (token);
5671 int idx = mono_metadata_token_index (token);
5672 MonoTableInfo *tables = image->tables;
5677 *error = ResolveTokenError_OutOfRange;
5679 /* FIXME: Support other tables ? */
5680 if (table != MONO_TABLE_STANDALONESIG)
5686 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5689 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5691 ptr = mono_metadata_blob_heap (image, sig);
5692 len = mono_metadata_decode_blob_size (ptr, &ptr);
5694 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5695 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5699 ICALL_EXPORT MonoReflectionType*
5700 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5703 int isbyref = 0, rank;
5704 char *str = mono_string_to_utf8 (smodifiers);
5707 MONO_ARCH_SAVE_REGS;
5709 klass = mono_class_from_mono_type (tb->type.type);
5711 /* logic taken from mono_reflection_parse_type(): keep in sync */
5715 if (isbyref) { /* only one level allowed by the spec */
5722 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5725 klass = mono_ptr_class_get (&klass->byval_arg);
5726 mono_class_init (klass);
5737 else if (*p != '*') { /* '*' means unknown lower bound */
5748 klass = mono_array_class_get (klass, rank);
5749 mono_class_init (klass);
5756 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5759 ICALL_EXPORT MonoBoolean
5760 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5765 MONO_ARCH_SAVE_REGS;
5768 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5774 check_for_invalid_type (MonoClass *klass)
5778 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5781 name = mono_type_get_full_name (klass);
5782 str = mono_string_new (mono_domain_get (), name);
5784 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5787 ICALL_EXPORT MonoReflectionType *
5788 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5790 MonoClass *klass, *aklass;
5792 MONO_ARCH_SAVE_REGS;
5794 klass = mono_class_from_mono_type (type->type);
5795 check_for_invalid_type (klass);
5797 if (rank == 0) //single dimentional array
5798 aklass = mono_array_class_get (klass, 1);
5800 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5802 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5805 ICALL_EXPORT MonoReflectionType *
5806 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5810 MONO_ARCH_SAVE_REGS;
5812 klass = mono_class_from_mono_type (type->type);
5813 mono_class_init_or_throw (klass);
5814 check_for_invalid_type (klass);
5816 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5819 ICALL_EXPORT MonoReflectionType *
5820 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5822 MonoClass *klass, *pklass;
5824 klass = mono_class_from_mono_type (type->type);
5825 mono_class_init_or_throw (klass);
5826 check_for_invalid_type (klass);
5828 pklass = mono_ptr_class_get (type->type);
5830 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5833 ICALL_EXPORT MonoObject *
5834 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5835 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5837 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5838 MonoObject *delegate;
5840 MonoMethod *method = info->method;
5842 MONO_ARCH_SAVE_REGS;
5844 mono_class_init_or_throw (delegate_class);
5846 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5848 if (mono_security_core_clr_enabled ()) {
5849 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5853 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5855 if (method->dynamic) {
5856 /* Creating a trampoline would leak memory */
5857 func = mono_compile_method (method);
5859 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5860 method = mono_object_get_virtual_method (target, method);
5861 func = mono_create_ftnptr (mono_domain_get (),
5862 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5865 mono_delegate_ctor_with_method (delegate, target, func, method);
5871 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5873 /* Reset the invoke impl to the default one */
5874 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5878 * Magic number to convert a time which is relative to
5879 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5881 #define EPOCH_ADJUST ((guint64)62135596800LL)
5884 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5886 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5889 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5891 convert_to_absolute_date(SYSTEMTIME *date)
5893 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5894 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5895 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5896 /* from the calendar FAQ */
5897 int a = (14 - date->wMonth) / 12;
5898 int y = date->wYear - a;
5899 int m = date->wMonth + 12 * a - 2;
5900 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5902 /* d is now the day of the week for the first of the month (0 == Sunday) */
5904 int day_of_week = date->wDayOfWeek;
5906 /* set day_in_month to the first day in the month which falls on day_of_week */
5907 int day_in_month = 1 + (day_of_week - d);
5908 if (day_in_month <= 0)
5911 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5912 date->wDay = day_in_month + (date->wDay - 1) * 7;
5913 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5920 * Return's the offset from GMT of a local time.
5922 * tm is a local time
5923 * t is the same local time as seconds.
5926 gmt_offset(struct tm *tm, time_t t)
5928 #if defined (HAVE_TM_GMTOFF)
5929 return tm->tm_gmtoff;
5934 g.tm_isdst = tm->tm_isdst;
5936 return (int)difftime(t, t2);
5941 * This is heavily based on zdump.c from glibc 2.2.
5943 * * data[0]: start of daylight saving time (in DateTime ticks).
5944 * * data[1]: end of daylight saving time (in DateTime ticks).
5945 * * data[2]: utcoffset (in TimeSpan ticks).
5946 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5947 * * name[0]: name of this timezone when not daylight saving.
5948 * * name[1]: name of this timezone when daylight saving.
5950 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5951 * the class library allows years between 1 and 9999.
5953 * Returns true on success and zero on failure.
5955 ICALL_EXPORT guint32
5956 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5959 MonoDomain *domain = mono_domain_get ();
5960 struct tm start, tt;
5963 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5964 int day, transitioned;
5967 gmtoff_st = gmtoff_ds = transitioned = 0;
5969 MONO_ARCH_SAVE_REGS;
5971 MONO_CHECK_ARG_NULL (data);
5972 MONO_CHECK_ARG_NULL (names);
5974 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5975 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5978 * no info is better than crashing: we'll need our own tz data
5979 * to make this work properly, anyway. The range is probably
5980 * reduced to 1970 .. 2037 because that is what mktime is
5981 * guaranteed to support (we get into an infinite loop
5985 memset (&start, 0, sizeof (start));
5988 start.tm_year = year-1900;
5990 t = mktime (&start);
5992 if ((year < 1970) || (year > 2037) || (t == -1)) {
5994 tt = *localtime (&t);
5995 strftime (tzone, sizeof (tzone), "%Z", &tt);
5996 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5997 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6001 gmtoff = gmt_offset (&start, t);
6003 /* For each day of the year, calculate the tm_gmtoff. */
6004 for (day = 0; day < 365 && transitioned < 2; day++) {
6007 tt = *localtime (&t);
6009 gmtoff_after = gmt_offset(&tt, t);
6011 /* Daylight saving starts or ends here. */
6012 if (gmtoff_after != gmtoff) {
6016 /* Try to find the exact hour when daylight saving starts/ends. */
6020 tt1 = *localtime (&t1);
6021 } while (gmt_offset (&tt1, t1) != gmtoff);
6023 /* Try to find the exact minute when daylight saving starts/ends. */
6026 tt1 = *localtime (&t1);
6027 } while (gmt_offset (&tt1, t1) == gmtoff);
6029 strftime (tzone, sizeof (tzone), "%Z", &tt);
6031 /* Write data, if we're already in daylight saving, we're done. */
6033 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6034 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6035 if (gmtoff_ds == 0) {
6037 gmtoff_ds = gmtoff_after;
6044 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6045 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6046 if (gmtoff_ds == 0) {
6047 gmtoff_st = gmtoff_after;
6053 /* This is only set once when we enter daylight saving. */
6055 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6056 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6058 gmtoff = gmt_offset (&tt, t);
6062 if (transitioned < 2) {
6063 strftime (tzone, sizeof (tzone), "%Z", &tt);
6064 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6065 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6066 mono_array_set ((*data), gint64, 0, 0);
6067 mono_array_set ((*data), gint64, 1, 0);
6068 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6069 mono_array_set ((*data), gint64, 3, 0);
6074 MonoDomain *domain = mono_domain_get ();
6075 TIME_ZONE_INFORMATION tz_info;
6080 tz_id = GetTimeZoneInformation (&tz_info);
6081 if (tz_id == TIME_ZONE_ID_INVALID)
6084 MONO_CHECK_ARG_NULL (data);
6085 MONO_CHECK_ARG_NULL (names);
6087 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6088 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6090 for (i = 0; i < 32; ++i)
6091 if (!tz_info.DaylightName [i])
6093 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6094 for (i = 0; i < 32; ++i)
6095 if (!tz_info.StandardName [i])
6097 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6099 if ((year <= 1601) || (year > 30827)) {
6101 * According to MSDN, the MS time functions can't handle dates outside
6107 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6108 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6109 tz_info.StandardDate.wYear = year;
6110 convert_to_absolute_date(&tz_info.StandardDate);
6111 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6116 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6117 tz_info.DaylightDate.wYear = year;
6118 convert_to_absolute_date(&tz_info.DaylightDate);
6119 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6124 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6126 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6127 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6135 static inline gint32
6136 mono_array_get_byte_length (MonoArray *array)
6142 klass = array->obj.vtable->klass;
6144 if (array->bounds == NULL)
6145 length = array->max_length;
6148 for (i = 0; i < klass->rank; ++ i)
6149 length *= array->bounds [i].length;
6152 switch (klass->element_class->byval_arg.type) {
6155 case MONO_TYPE_BOOLEAN:
6159 case MONO_TYPE_CHAR:
6167 return length * sizeof (gpointer);
6178 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6180 MONO_ARCH_SAVE_REGS;
6182 return mono_array_get_byte_length (array);
6186 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6188 MONO_ARCH_SAVE_REGS;
6190 return mono_array_get (array, gint8, idx);
6194 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6196 MONO_ARCH_SAVE_REGS;
6198 mono_array_set (array, gint8, idx, value);
6201 ICALL_EXPORT MonoBoolean
6202 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6204 guint8 *src_buf, *dest_buf;
6206 MONO_ARCH_SAVE_REGS;
6208 /* This is called directly from the class libraries without going through the managed wrapper */
6209 MONO_CHECK_ARG_NULL (src);
6210 MONO_CHECK_ARG_NULL (dest);
6212 /* watch out for integer overflow */
6213 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6216 src_buf = (guint8 *)src->vector + src_offset;
6217 dest_buf = (guint8 *)dest->vector + dest_offset;
6220 memcpy (dest_buf, src_buf, count);
6222 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6227 #ifndef DISABLE_REMOTING
6228 ICALL_EXPORT MonoObject *
6229 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6231 MonoDomain *domain = mono_object_domain (this);
6233 MonoRealProxy *rp = ((MonoRealProxy *)this);
6234 MonoTransparentProxy *tp;
6238 MONO_ARCH_SAVE_REGS;
6240 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6241 tp = (MonoTransparentProxy*) res;
6243 MONO_OBJECT_SETREF (tp, rp, rp);
6244 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6245 klass = mono_class_from_mono_type (type);
6247 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6248 tp->remote_class = mono_remote_class (domain, class_name, klass);
6250 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6254 ICALL_EXPORT MonoReflectionType *
6255 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6257 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6261 /* System.Environment */
6264 ves_icall_System_Environment_get_UserName (void)
6266 MONO_ARCH_SAVE_REGS;
6268 /* using glib is more portable */
6269 return mono_string_new (mono_domain_get (), g_get_user_name ());
6273 ICALL_EXPORT MonoString *
6274 ves_icall_System_Environment_get_MachineName (void)
6276 #if defined (HOST_WIN32)
6281 len = MAX_COMPUTERNAME_LENGTH + 1;
6282 buf = g_new (gunichar2, len);
6285 if (GetComputerName (buf, (PDWORD) &len))
6286 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6290 #elif !defined(DISABLE_SOCKETS)
6294 if (gethostname (buf, sizeof (buf)) == 0)
6295 result = mono_string_new (mono_domain_get (), buf);
6301 return mono_string_new (mono_domain_get (), "mono");
6306 ves_icall_System_Environment_get_Platform (void)
6308 #if defined (TARGET_WIN32)
6311 #elif defined(__MACH__)
6314 // Notice that the value is hidden from user code, and only exposed
6315 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6316 // define and making assumptions based on Unix/128/4 values before there
6317 // was a MacOS define. Lots of code would assume that not-Unix meant
6318 // Windows, but in this case, it would be OSX.
6327 ICALL_EXPORT MonoString *
6328 ves_icall_System_Environment_get_NewLine (void)
6330 MONO_ARCH_SAVE_REGS;
6332 #if defined (HOST_WIN32)
6333 return mono_string_new (mono_domain_get (), "\r\n");
6335 return mono_string_new (mono_domain_get (), "\n");
6339 ICALL_EXPORT MonoString *
6340 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6345 MONO_ARCH_SAVE_REGS;
6350 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6351 value = g_getenv (utf8_name);
6358 return mono_string_new (mono_domain_get (), value);
6362 * There is no standard way to get at environ.
6365 #ifndef __MINGW32_VERSION
6366 #if defined(__APPLE__) && !defined (__arm__)
6367 /* Apple defines this in crt_externs.h but doesn't provide that header for
6368 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6369 * in fact exist on all implementations (so far)
6371 gchar ***_NSGetEnviron(void);
6372 #define environ (*_NSGetEnviron())
6380 ICALL_EXPORT MonoArray *
6381 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6392 env_strings = GetEnvironmentStrings();
6395 env_string = env_strings;
6396 while (*env_string != '\0') {
6397 /* weird case that MS seems to skip */
6398 if (*env_string != '=')
6400 while (*env_string != '\0')
6406 domain = mono_domain_get ();
6407 names = mono_array_new (domain, mono_defaults.string_class, n);
6411 env_string = env_strings;
6412 while (*env_string != '\0') {
6413 /* weird case that MS seems to skip */
6414 if (*env_string != '=') {
6415 equal_str = wcschr(env_string, '=');
6416 g_assert(equal_str);
6417 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6418 mono_array_setref (names, n, str);
6421 while (*env_string != '\0')
6426 FreeEnvironmentStrings (env_strings);
6438 MONO_ARCH_SAVE_REGS;
6441 for (e = environ; *e != 0; ++ e)
6444 domain = mono_domain_get ();
6445 names = mono_array_new (domain, mono_defaults.string_class, n);
6448 for (e = environ; *e != 0; ++ e) {
6449 parts = g_strsplit (*e, "=", 2);
6451 str = mono_string_new (domain, *parts);
6452 mono_array_setref (names, n, str);
6465 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6467 #if !GLIB_CHECK_VERSION(2,4,0)
6468 #define g_setenv(a,b,c) setenv(a,b,c)
6469 #define g_unsetenv(a) unsetenv(a)
6473 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6478 gunichar2 *utf16_name, *utf16_value;
6480 gchar *utf8_name, *utf8_value;
6483 MONO_ARCH_SAVE_REGS;
6486 utf16_name = mono_string_to_utf16 (name);
6487 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6488 SetEnvironmentVariable (utf16_name, NULL);
6489 g_free (utf16_name);
6493 utf16_value = mono_string_to_utf16 (value);
6495 SetEnvironmentVariable (utf16_name, utf16_value);
6497 g_free (utf16_name);
6498 g_free (utf16_value);
6500 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6502 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6503 g_unsetenv (utf8_name);
6508 utf8_value = mono_string_to_utf8_checked (value, &error);
6509 if (!mono_error_ok (&error)) {
6511 mono_error_raise_exception (&error);
6513 g_setenv (utf8_name, utf8_value, TRUE);
6516 g_free (utf8_value);
6521 ves_icall_System_Environment_Exit (int result)
6523 MONO_ARCH_SAVE_REGS;
6525 mono_environment_exitcode_set (result);
6527 /* FIXME: There are some cleanup hangs that should be worked out, but
6528 * if the program is going to exit, everything will be cleaned up when
6529 * NaCl exits anyway.
6531 #ifndef __native_client__
6532 if (!mono_runtime_try_shutdown ())
6533 mono_thread_exit ();
6535 /* Suspend all managed threads since the runtime is going away */
6536 mono_thread_suspend_all_other_threads ();
6538 mono_runtime_quit ();
6541 /* we may need to do some cleanup here... */
6545 ICALL_EXPORT MonoString*
6546 ves_icall_System_Environment_GetGacPath (void)
6548 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6551 ICALL_EXPORT MonoString*
6552 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6554 #if defined (HOST_WIN32)
6555 #ifndef CSIDL_FLAG_CREATE
6556 #define CSIDL_FLAG_CREATE 0x8000
6559 WCHAR path [MAX_PATH];
6560 /* Create directory if no existing */
6561 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6565 return mono_string_new_utf16 (mono_domain_get (), path, len);
6568 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6570 return mono_string_new (mono_domain_get (), "");
6573 ICALL_EXPORT MonoArray *
6574 ves_icall_System_Environment_GetLogicalDrives (void)
6576 gunichar2 buf [256], *ptr, *dname;
6578 guint initial_size = 127, size = 128;
6581 MonoString *drivestr;
6582 MonoDomain *domain = mono_domain_get ();
6585 MONO_ARCH_SAVE_REGS;
6590 while (size > initial_size) {
6591 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6592 if (size > initial_size) {
6595 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6596 initial_size = size;
6610 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6615 while (*u16) { u16++; len ++; }
6616 drivestr = mono_string_new_utf16 (domain, dname, len);
6617 mono_array_setref (result, ndrives++, drivestr);
6627 ICALL_EXPORT MonoString *
6628 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6630 gunichar2 volume_name [MAX_PATH + 1];
6632 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6634 return mono_string_from_utf16 (volume_name);
6637 ICALL_EXPORT MonoString *
6638 ves_icall_System_Environment_InternalGetHome (void)
6640 MONO_ARCH_SAVE_REGS;
6642 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6645 static const char *encodings [] = {
6647 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6648 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6649 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6651 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6652 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6653 "x_unicode_2_0_utf_7",
6655 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6656 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6658 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6661 "unicodefffe", "utf_16be",
6668 * Returns the internal codepage, if the value of "int_code_page" is
6669 * 1 at entry, and we can not compute a suitable code page number,
6670 * returns the code page as a string
6672 ICALL_EXPORT MonoString*
6673 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6678 char *codepage = NULL;
6680 int want_name = *int_code_page;
6683 *int_code_page = -1;
6684 MONO_ARCH_SAVE_REGS;
6686 g_get_charset (&cset);
6687 c = codepage = strdup (cset);
6688 for (c = codepage; *c; c++){
6689 if (isascii (*c) && isalpha (*c))
6694 /* g_print ("charset: %s\n", cset); */
6696 /* handle some common aliases */
6699 for (i = 0; p != 0; ){
6700 if ((gssize) p < 7){
6702 p = encodings [++i];
6705 if (strcmp (p, codepage) == 0){
6706 *int_code_page = code;
6709 p = encodings [++i];
6712 if (strstr (codepage, "utf_8") != NULL)
6713 *int_code_page |= 0x10000000;
6716 if (want_name && *int_code_page == -1)
6717 return mono_string_new (mono_domain_get (), cset);
6722 ICALL_EXPORT MonoBoolean
6723 ves_icall_System_Environment_get_HasShutdownStarted (void)
6725 if (mono_runtime_is_shutting_down ())
6728 if (mono_domain_is_unloading (mono_domain_get ()))
6735 ves_icall_System_Environment_BroadcastSettingChange (void)
6738 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6743 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6744 MonoReflectionMethod *method,
6745 MonoArray *out_args)
6747 MONO_ARCH_SAVE_REGS;
6749 mono_message_init (mono_object_domain (this), this, method, out_args);
6752 #ifndef DISABLE_REMOTING
6753 ICALL_EXPORT MonoBoolean
6754 ves_icall_IsTransparentProxy (MonoObject *proxy)
6756 MONO_ARCH_SAVE_REGS;
6761 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6767 ICALL_EXPORT MonoReflectionMethod *
6768 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6769 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6773 MonoMethod **vtable;
6774 MonoMethod *res = NULL;
6776 MONO_CHECK_ARG_NULL (rtype);
6777 MONO_CHECK_ARG_NULL (rmethod);
6779 method = rmethod->method;
6780 klass = mono_class_from_mono_type (rtype->type);
6781 mono_class_init_or_throw (klass);
6783 if (MONO_CLASS_IS_INTERFACE (klass))
6786 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6789 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6790 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6796 mono_class_setup_vtable (klass);
6797 vtable = klass->vtable;
6799 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6800 gboolean variance_used = FALSE;
6801 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6802 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6804 res = vtable [offs + method->slot];
6806 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6809 if (method->slot != -1)
6810 res = vtable [method->slot];
6816 return mono_method_get_object (mono_domain_get (), res, NULL);
6820 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6825 MONO_ARCH_SAVE_REGS;
6827 klass = mono_class_from_mono_type (type->type);
6828 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6830 mono_vtable_set_is_remote (vtable, enable);
6833 #else /* DISABLE_REMOTING */
6836 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6838 g_assert_not_reached ();
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_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 mono_mutex_t icall_mutex;
7885 static GHashTable *icall_hash = NULL;
7886 static GHashTable *jit_icall_hash_name = NULL;
7887 static GHashTable *jit_icall_hash_addr = NULL;
7890 mono_icall_init (void)
7892 #ifndef DISABLE_ICALL_TABLES
7895 /* check that tables are sorted: disable in release */
7898 const char *prev_class = NULL;
7899 const char *prev_method;
7901 for (i = 0; i < Icall_type_num; ++i) {
7902 const IcallTypeDesc *desc;
7905 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7906 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7907 prev_class = icall_type_name_get (i);
7908 desc = &icall_type_descs [i];
7909 num_icalls = icall_desc_num_icalls (desc);
7910 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7911 for (j = 0; j < num_icalls; ++j) {
7912 const char *methodn = icall_name_get (desc->first_icall + j);
7913 if (prev_method && strcmp (prev_method, methodn) >= 0)
7914 g_print ("method %s should come before method %s\n", methodn, prev_method);
7915 prev_method = methodn;
7921 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7922 mono_mutex_init (&icall_mutex);
7926 mono_icall_lock (void)
7928 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7932 mono_icall_unlock (void)
7934 mono_locks_mutex_release (&icall_mutex, IcallLock);
7938 mono_icall_cleanup (void)
7940 g_hash_table_destroy (icall_hash);
7941 g_hash_table_destroy (jit_icall_hash_name);
7942 g_hash_table_destroy (jit_icall_hash_addr);
7943 mono_mutex_destroy (&icall_mutex);
7947 mono_add_internal_call (const char *name, gconstpointer method)
7951 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7953 mono_icall_unlock ();
7956 #ifndef DISABLE_ICALL_TABLES
7958 #ifdef HAVE_ARRAY_ELEM_INIT
7960 compare_method_imap (const void *key, const void *elem)
7962 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7963 return strcmp (key, method_name);
7967 find_method_icall (const IcallTypeDesc *imap, const char *name)
7969 const guint16 *nameslot = mono_binary_search (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7972 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7976 compare_class_imap (const void *key, const void *elem)
7978 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7979 return strcmp (key, class_name);
7982 static const IcallTypeDesc*
7983 find_class_icalls (const char *name)
7985 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7988 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7991 #else /* HAVE_ARRAY_ELEM_INIT */
7994 compare_method_imap (const void *key, const void *elem)
7996 const char** method_name = (const char**)elem;
7997 return strcmp (key, *method_name);
8001 find_method_icall (const IcallTypeDesc *imap, const char *name)
8003 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8006 return (gpointer)icall_functions [(nameslot - icall_names)];
8010 compare_class_imap (const void *key, const void *elem)
8012 const char** class_name = (const char**)elem;
8013 return strcmp (key, *class_name);
8016 static const IcallTypeDesc*
8017 find_class_icalls (const char *name)
8019 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8022 return &icall_type_descs [nameslot - icall_type_names];
8025 #endif /* HAVE_ARRAY_ELEM_INIT */
8027 #endif /* DISABLE_ICALL_TABLES */
8030 * we should probably export this as an helper (handle nested types).
8031 * Returns the number of chars written in buf.
8034 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8036 int nspacelen, cnamelen;
8037 nspacelen = strlen (klass->name_space);
8038 cnamelen = strlen (klass->name);
8039 if (nspacelen + cnamelen + 2 > bufsize)
8042 memcpy (buf, klass->name_space, nspacelen);
8043 buf [nspacelen ++] = '.';
8045 memcpy (buf + nspacelen, klass->name, cnamelen);
8046 buf [nspacelen + cnamelen] = 0;
8047 return nspacelen + cnamelen;
8050 #ifdef DISABLE_ICALL_TABLES
8052 no_icall_table (void)
8054 g_assert_not_reached ();
8059 mono_lookup_internal_call (MonoMethod *method)
8064 int typelen = 0, mlen, siglen;
8066 #ifndef DISABLE_ICALL_TABLES
8067 const IcallTypeDesc *imap = NULL;
8070 g_assert (method != NULL);
8072 if (method->is_inflated)
8073 method = ((MonoMethodInflated *) method)->declaring;
8075 if (method->klass->nested_in) {
8076 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8080 mname [pos++] = '/';
8083 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8089 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8094 #ifndef DISABLE_ICALL_TABLES
8095 imap = find_class_icalls (mname);
8098 mname [typelen] = ':';
8099 mname [typelen + 1] = ':';
8101 mlen = strlen (method->name);
8102 memcpy (mname + typelen + 2, method->name, mlen);
8103 sigstart = mname + typelen + 2 + mlen;
8106 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8107 siglen = strlen (tmpsig);
8108 if (typelen + mlen + siglen + 6 > sizeof (mname))
8111 memcpy (sigstart + 1, tmpsig, siglen);
8112 sigstart [siglen + 1] = ')';
8113 sigstart [siglen + 2] = 0;
8118 res = g_hash_table_lookup (icall_hash, mname);
8120 mono_icall_unlock ();;
8123 /* try without signature */
8125 res = g_hash_table_lookup (icall_hash, mname);
8127 mono_icall_unlock ();
8131 #ifdef DISABLE_ICALL_TABLES
8132 mono_icall_unlock ();
8133 /* Fail only when the result is actually used */
8134 /* mono_marshal_get_native_wrapper () depends on this */
8135 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8136 return ves_icall_System_String_ctor_RedirectToCreateString;
8138 return no_icall_table;
8140 /* it wasn't found in the static call tables */
8142 mono_icall_unlock ();
8145 res = find_method_icall (imap, sigstart - mlen);
8147 mono_icall_unlock ();
8150 /* try _with_ signature */
8152 res = find_method_icall (imap, sigstart - mlen);
8154 mono_icall_unlock ();
8158 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8159 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8160 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8161 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8162 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");
8163 g_print ("If you see other errors or faults after this message they are probably related\n");
8164 g_print ("and you need to fix your mono install first.\n");
8166 mono_icall_unlock ();
8172 #ifdef ENABLE_ICALL_SYMBOL_MAP
8174 func_cmp (gconstpointer key, gconstpointer p)
8176 return (gsize)key - (gsize)*(gsize*)p;
8181 * mono_lookup_icall_symbol:
8183 * Given the icall METHOD, returns its C symbol.
8186 mono_lookup_icall_symbol (MonoMethod *m)
8188 #ifdef DISABLE_ICALL_TABLES
8189 g_assert_not_reached ();
8192 #ifdef ENABLE_ICALL_SYMBOL_MAP
8196 static gconstpointer *functions_sorted;
8197 static const char**symbols_sorted;
8198 static gboolean inited;
8203 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8204 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8205 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8206 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8207 /* Bubble sort the two arrays */
8211 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8212 if (functions_sorted [i] > functions_sorted [i + 1]) {
8215 tmp = functions_sorted [i];
8216 functions_sorted [i] = functions_sorted [i + 1];
8217 functions_sorted [i + 1] = tmp;
8218 tmp = symbols_sorted [i];
8219 symbols_sorted [i] = symbols_sorted [i + 1];
8220 symbols_sorted [i + 1] = tmp;
8227 func = mono_lookup_internal_call (m);
8230 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8234 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8236 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8237 g_assert_not_reached ();
8244 type_from_typename (char *typename)
8246 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8248 if (!strcmp (typename, "int"))
8249 klass = mono_defaults.int_class;
8250 else if (!strcmp (typename, "ptr"))
8251 klass = mono_defaults.int_class;
8252 else if (!strcmp (typename, "void"))
8253 klass = mono_defaults.void_class;
8254 else if (!strcmp (typename, "int32"))
8255 klass = mono_defaults.int32_class;
8256 else if (!strcmp (typename, "uint32"))
8257 klass = mono_defaults.uint32_class;
8258 else if (!strcmp (typename, "int8"))
8259 klass = mono_defaults.sbyte_class;
8260 else if (!strcmp (typename, "uint8"))
8261 klass = mono_defaults.byte_class;
8262 else if (!strcmp (typename, "int16"))
8263 klass = mono_defaults.int16_class;
8264 else if (!strcmp (typename, "uint16"))
8265 klass = mono_defaults.uint16_class;
8266 else if (!strcmp (typename, "long"))
8267 klass = mono_defaults.int64_class;
8268 else if (!strcmp (typename, "ulong"))
8269 klass = mono_defaults.uint64_class;
8270 else if (!strcmp (typename, "float"))
8271 klass = mono_defaults.single_class;
8272 else if (!strcmp (typename, "double"))
8273 klass = mono_defaults.double_class;
8274 else if (!strcmp (typename, "object"))
8275 klass = mono_defaults.object_class;
8276 else if (!strcmp (typename, "obj"))
8277 klass = mono_defaults.object_class;
8278 else if (!strcmp (typename, "string"))
8279 klass = mono_defaults.string_class;
8280 else if (!strcmp (typename, "bool"))
8281 klass = mono_defaults.boolean_class;
8282 else if (!strcmp (typename, "boolean"))
8283 klass = mono_defaults.boolean_class;
8285 g_error ("%s", typename);
8286 g_assert_not_reached ();
8288 return &klass->byval_arg;
8292 * LOCKING: Take the corlib image lock.
8294 MonoMethodSignature*
8295 mono_create_icall_signature (const char *sigstr)
8300 MonoMethodSignature *res, *res2;
8301 MonoImage *corlib = mono_defaults.corlib;
8303 mono_image_lock (corlib);
8304 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8305 mono_image_unlock (corlib);
8310 parts = g_strsplit (sigstr, " ", 256);
8319 res = mono_metadata_signature_alloc (corlib, len - 1);
8324 * Under windows, the default pinvoke calling convention is STDCALL but
8327 res->call_convention = MONO_CALL_C;
8330 res->ret = type_from_typename (parts [0]);
8331 for (i = 1; i < len; ++i) {
8332 res->params [i - 1] = type_from_typename (parts [i]);
8337 mono_image_lock (corlib);
8338 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8340 res = res2; /*Value is allocated in the image pool*/
8342 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8343 mono_image_unlock (corlib);
8349 mono_find_jit_icall_by_name (const char *name)
8351 MonoJitICallInfo *info;
8352 g_assert (jit_icall_hash_name);
8355 info = g_hash_table_lookup (jit_icall_hash_name, name);
8356 mono_icall_unlock ();
8361 mono_find_jit_icall_by_addr (gconstpointer addr)
8363 MonoJitICallInfo *info;
8364 g_assert (jit_icall_hash_addr);
8367 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8368 mono_icall_unlock ();
8374 * mono_get_jit_icall_info:
8376 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8377 * caller should access it while holding the icall lock.
8380 mono_get_jit_icall_info (void)
8382 return jit_icall_hash_name;
8386 * mono_lookup_jit_icall_symbol:
8388 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8391 mono_lookup_jit_icall_symbol (const char *name)
8393 MonoJitICallInfo *info;
8394 const char *res = NULL;
8397 info = g_hash_table_lookup (jit_icall_hash_name, name);
8399 res = info->c_symbol;
8400 mono_icall_unlock ();
8405 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8408 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8409 mono_icall_unlock ();
8413 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8415 MonoJitICallInfo *info;
8422 if (!jit_icall_hash_name) {
8423 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8424 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8427 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8428 g_warning ("jit icall already defined \"%s\"\n", name);
8429 g_assert_not_reached ();
8432 info = g_new0 (MonoJitICallInfo, 1);
8437 info->c_symbol = c_symbol;
8440 info->wrapper = func;
8442 info->wrapper = NULL;
8445 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8446 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8448 mono_icall_unlock ();
8453 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8455 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);