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 MonoMethod *m, *dest;
1270 MonoType *type = NULL;
1271 MonoAssembly *assembly = NULL;
1272 MonoTypeNameParse info;
1273 char *temp_str = g_strdup (str);
1274 gboolean type_resolve = FALSE;
1276 MONO_ARCH_SAVE_REGS;
1278 /* mono_reflection_parse_type() mangles the string */
1279 if (!mono_reflection_parse_type (temp_str, &info)) {
1280 mono_reflection_free_type_info (&info);
1287 * We must compute the calling assembly as type loading must happen under a metadata context.
1288 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1289 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1291 m = mono_method_get_last_managed ();
1294 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1299 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1300 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1301 * to crash. This only seems to happen in some strange remoting
1302 * scenarios and I was unable to figure out what's happening there.
1303 * Dec 10, 2005 - Martin.
1307 assembly = dest->klass->image->assembly;
1308 type_resolve = TRUE;
1310 g_warning (G_STRLOC);
1313 if (info.assembly.name)
1314 assembly = mono_assembly_load (&info.assembly, assembly ? assembly->basedir : NULL, NULL);
1318 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1319 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1322 if (!info.assembly.name && !type) /* try mscorlib */
1323 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1325 if (assembly && !type && type_resolve) {
1326 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1327 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1330 mono_reflection_free_type_info (&info);
1336 return mono_type_get_object (mono_domain_get (), type);
1340 MonoReflectionType *
1341 mono_type_get (const char *str)
1343 char *copy = g_strdup (str);
1344 MonoReflectionType *type = type_from_name (copy, FALSE);
1351 ICALL_EXPORT MonoReflectionType*
1352 ves_icall_type_from_name (MonoString *name,
1353 MonoBoolean throwOnError,
1354 MonoBoolean ignoreCase)
1356 char *str = mono_string_to_utf8 (name);
1357 MonoReflectionType *type;
1359 type = type_from_name (str, ignoreCase);
1362 MonoException *e = NULL;
1365 e = mono_get_exception_type_load (name, NULL);
1367 mono_loader_clear_error ();
1369 mono_raise_exception (e);
1376 ICALL_EXPORT MonoReflectionType*
1377 ves_icall_type_from_handle (MonoType *handle)
1379 MonoDomain *domain = mono_domain_get ();
1381 MONO_ARCH_SAVE_REGS;
1383 return mono_type_get_object (domain, handle);
1386 ICALL_EXPORT MonoBoolean
1387 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1389 MONO_ARCH_SAVE_REGS;
1391 if (c && type->type && c->type)
1392 return mono_metadata_type_equal (type->type, c->type);
1394 return (type == c) ? TRUE : FALSE;
1397 /* System.TypeCode */
1416 TYPECODE_STRING = 18
1419 ICALL_EXPORT guint32
1420 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1422 int t = type->type->type;
1424 MONO_ARCH_SAVE_REGS;
1426 if (type->type->byref)
1427 return TYPECODE_OBJECT;
1431 case MONO_TYPE_VOID:
1432 return TYPECODE_OBJECT;
1433 case MONO_TYPE_BOOLEAN:
1434 return TYPECODE_BOOLEAN;
1436 return TYPECODE_BYTE;
1438 return TYPECODE_SBYTE;
1440 return TYPECODE_UINT16;
1442 return TYPECODE_INT16;
1443 case MONO_TYPE_CHAR:
1444 return TYPECODE_CHAR;
1448 return TYPECODE_OBJECT;
1450 return TYPECODE_UINT32;
1452 return TYPECODE_INT32;
1454 return TYPECODE_UINT64;
1456 return TYPECODE_INT64;
1458 return TYPECODE_SINGLE;
1460 return TYPECODE_DOUBLE;
1461 case MONO_TYPE_VALUETYPE: {
1462 MonoClass *klass = type->type->data.klass;
1464 if (klass->enumtype) {
1465 t = mono_class_enum_basetype (klass)->type;
1467 } else if (mono_is_corlib_image (klass->image)) {
1468 if (strcmp (klass->name_space, "System") == 0) {
1469 if (strcmp (klass->name, "Decimal") == 0)
1470 return TYPECODE_DECIMAL;
1471 else if (strcmp (klass->name, "DateTime") == 0)
1472 return TYPECODE_DATETIME;
1475 return TYPECODE_OBJECT;
1477 case MONO_TYPE_STRING:
1478 return TYPECODE_STRING;
1479 case MONO_TYPE_SZARRAY:
1480 case MONO_TYPE_ARRAY:
1481 case MONO_TYPE_OBJECT:
1483 case MONO_TYPE_MVAR:
1484 case MONO_TYPE_TYPEDBYREF:
1485 return TYPECODE_OBJECT;
1486 case MONO_TYPE_CLASS:
1488 MonoClass *klass = type->type->data.klass;
1489 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1490 if (strcmp (klass->name, "DBNull") == 0)
1491 return TYPECODE_DBNULL;
1494 return TYPECODE_OBJECT;
1495 case MONO_TYPE_GENERICINST:
1496 return TYPECODE_OBJECT;
1498 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1503 ICALL_EXPORT guint32
1504 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1510 MONO_ARCH_SAVE_REGS;
1512 g_assert (type != NULL);
1514 domain = ((MonoObject *)type)->vtable->domain;
1516 if (!c) /* FIXME: dont know what do do here */
1519 klass = mono_class_from_mono_type (type->type);
1520 klassc = mono_class_from_mono_type (c->type);
1522 /* Interface check requires a more complex setup so we
1523 * only do for them. Otherwise we simply avoid mono_class_init.
1525 if (check_interfaces) {
1526 mono_class_init_or_throw (klass);
1527 mono_class_init_or_throw (klassc);
1528 } else if (!klass->supertypes || !klassc->supertypes) {
1529 mono_class_setup_supertypes (klass);
1530 mono_class_setup_supertypes (klassc);
1533 if (type->type->byref)
1534 return klassc == mono_defaults.object_class;
1536 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1540 mono_type_is_primitive (MonoType *type)
1542 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1543 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1547 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1549 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1550 return mono_class_enum_basetype (type->data.klass);
1551 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1552 return mono_class_enum_basetype (type->data.generic_class->container_class);
1556 ICALL_EXPORT guint32
1557 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1563 MONO_ARCH_SAVE_REGS;
1565 g_assert (type != NULL);
1567 domain = ((MonoObject *)type)->vtable->domain;
1569 klass = mono_class_from_mono_type (type->type);
1570 klassc = mono_class_from_mono_type (c->type);
1572 if (type->type->byref ^ c->type->byref)
1575 if (type->type->byref) {
1576 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1577 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1579 klass = mono_class_from_mono_type (t);
1580 klassc = mono_class_from_mono_type (ot);
1582 if (mono_type_is_primitive (t)) {
1583 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1584 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1585 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1586 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1587 return t->type == ot->type;
1589 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1592 if (klass->valuetype)
1593 return klass == klassc;
1594 return klass->valuetype == klassc->valuetype;
1597 return mono_class_is_assignable_from (klass, klassc);
1600 ICALL_EXPORT guint32
1601 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1603 MonoClass *klass = mono_class_from_mono_type (type->type);
1604 mono_class_init_or_throw (klass);
1605 return mono_object_isinst (obj, klass) != NULL;
1608 ICALL_EXPORT guint32
1609 ves_icall_get_attributes (MonoReflectionType *type)
1611 MonoClass *klass = mono_class_from_mono_type (type->type);
1612 return klass->flags;
1615 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1616 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1618 MonoClass *klass = field->field->parent;
1619 MonoMarshalType *info;
1622 if (klass->generic_container ||
1623 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1626 info = mono_marshal_load_type_info (klass);
1628 for (i = 0; i < info->num_fields; ++i) {
1629 if (info->fields [i].field == field->field) {
1630 if (!info->fields [i].mspec)
1633 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1640 ICALL_EXPORT MonoReflectionField*
1641 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1643 gboolean found = FALSE;
1650 klass = handle->parent;
1652 klass = mono_class_from_mono_type (type);
1654 /* Check that the field belongs to the class */
1655 for (k = klass; k; k = k->parent) {
1656 if (k == handle->parent) {
1663 /* The managed code will throw the exception */
1667 return mono_field_get_object (mono_domain_get (), klass, handle);
1670 ICALL_EXPORT MonoArray*
1671 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1674 MonoType *type = mono_field_get_type_checked (field->field, &error);
1675 if (!mono_error_ok (&error))
1676 mono_error_raise_exception (&error);
1678 return type_array_from_modifiers (field->field->parent->image, type, optional);
1682 vell_icall_get_method_attributes (MonoMethod *method)
1684 return method->flags;
1688 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1691 MonoDomain *domain = mono_domain_get ();
1692 MonoMethodSignature* sig;
1693 MONO_ARCH_SAVE_REGS;
1695 sig = mono_method_signature_checked (method, &error);
1696 if (!mono_error_ok (&error))
1697 mono_error_raise_exception (&error);
1700 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1701 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1702 info->attrs = method->flags;
1703 info->implattrs = method->iflags;
1704 if (sig->call_convention == MONO_CALL_DEFAULT)
1705 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1707 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1712 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1715 ICALL_EXPORT MonoArray*
1716 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1718 MonoDomain *domain = mono_domain_get ();
1720 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1723 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1724 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1726 MonoDomain *domain = mono_domain_get ();
1727 MonoReflectionMarshalAsAttribute* res = NULL;
1728 MonoMarshalSpec **mspecs;
1731 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1732 mono_method_get_marshal_info (method, mspecs);
1735 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1737 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1739 mono_metadata_free_marshal_spec (mspecs [i]);
1746 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1748 MonoClass *parent = field->field->parent;
1749 if (!parent->size_inited)
1750 mono_class_init (parent);
1752 return field->field->offset - sizeof (MonoObject);
1755 ICALL_EXPORT MonoReflectionType*
1756 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1759 MONO_ARCH_SAVE_REGS;
1761 parent = declaring? field->field->parent: field->klass;
1763 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1766 ICALL_EXPORT MonoObject *
1767 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1769 MonoClass *fklass = field->klass;
1770 MonoClassField *cf = field->field;
1771 MonoDomain *domain = mono_object_domain (field);
1773 if (fklass->image->assembly->ref_only)
1774 mono_raise_exception (mono_get_exception_invalid_operation (
1775 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1777 if (mono_security_core_clr_enabled ())
1778 mono_security_core_clr_ensure_reflection_access_field (cf);
1780 return mono_field_get_value_object (domain, cf, obj);
1784 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1787 MonoClassField *cf = field->field;
1791 MONO_ARCH_SAVE_REGS;
1793 if (field->klass->image->assembly->ref_only)
1794 mono_raise_exception (mono_get_exception_invalid_operation (
1795 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1797 if (mono_security_core_clr_enabled ())
1798 mono_security_core_clr_ensure_reflection_access_field (cf);
1800 type = mono_field_get_type_checked (cf, &error);
1801 if (!mono_error_ok (&error))
1802 mono_error_raise_exception (&error);
1804 v = (gchar *) value;
1806 switch (type->type) {
1809 case MONO_TYPE_BOOLEAN:
1812 case MONO_TYPE_CHAR:
1821 case MONO_TYPE_VALUETYPE:
1824 v += sizeof (MonoObject);
1826 case MONO_TYPE_STRING:
1827 case MONO_TYPE_OBJECT:
1828 case MONO_TYPE_CLASS:
1829 case MONO_TYPE_ARRAY:
1830 case MONO_TYPE_SZARRAY:
1833 case MONO_TYPE_GENERICINST: {
1834 MonoGenericClass *gclass = type->data.generic_class;
1835 g_assert (!gclass->context.class_inst->is_open);
1837 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1838 MonoClass *nklass = mono_class_from_mono_type (type);
1839 MonoObject *nullable;
1842 * Convert the boxed vtype into a Nullable structure.
1843 * This is complicated by the fact that Nullables have
1844 * a variable structure.
1846 nullable = mono_object_new (mono_domain_get (), nklass);
1848 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1850 v = mono_object_unbox (nullable);
1853 if (gclass->container_class->valuetype && (v != NULL))
1854 v += sizeof (MonoObject);
1858 g_error ("type 0x%x not handled in "
1859 "ves_icall_FieldInfo_SetValueInternal", type->type);
1864 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1865 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1866 if (!vtable->initialized)
1867 mono_runtime_class_init (vtable);
1868 mono_field_static_set_value (vtable, cf, v);
1870 mono_field_set_value (obj, cf, v);
1874 ICALL_EXPORT MonoObject *
1875 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1877 MonoObject *o = NULL;
1878 MonoClassField *field = this->field;
1880 MonoDomain *domain = mono_object_domain (this);
1882 MonoTypeEnum def_type;
1883 const char *def_value;
1887 MONO_ARCH_SAVE_REGS;
1889 mono_class_init (field->parent);
1891 t = mono_field_get_type_checked (field, &error);
1892 if (!mono_error_ok (&error))
1893 mono_error_raise_exception (&error);
1895 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1896 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1898 if (field->parent->image->dynamic) {
1900 g_assert_not_reached ();
1903 def_value = mono_class_get_field_default_value (field, &def_type);
1904 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1905 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1907 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1911 case MONO_TYPE_BOOLEAN:
1914 case MONO_TYPE_CHAR:
1922 case MONO_TYPE_R8: {
1925 /* boxed value type */
1926 t = g_new0 (MonoType, 1);
1928 klass = mono_class_from_mono_type (t);
1930 o = mono_object_new (domain, klass);
1931 v = ((gchar *) o) + sizeof (MonoObject);
1932 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1935 case MONO_TYPE_STRING:
1936 case MONO_TYPE_CLASS:
1937 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1940 g_assert_not_reached ();
1946 ICALL_EXPORT MonoReflectionType*
1947 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1950 MonoClassField *field = ref_field->field;
1951 MonoType *type = mono_field_get_type_checked (field, &error);
1952 if (!mono_error_ok (&error))
1953 mono_error_raise_exception (&error);
1954 return mono_type_get_object (mono_object_domain (ref_field), type);
1957 ICALL_EXPORT MonoReflectionType*
1958 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1960 MonoMethod *method = rmethod->method.method;
1962 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1965 /* From MonoProperty.cs */
1967 PInfo_Attributes = 1,
1968 PInfo_GetMethod = 1 << 1,
1969 PInfo_SetMethod = 1 << 2,
1970 PInfo_ReflectedType = 1 << 3,
1971 PInfo_DeclaringType = 1 << 4,
1976 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1978 MonoDomain *domain = mono_object_domain (property);
1980 MONO_ARCH_SAVE_REGS;
1982 if ((req_info & PInfo_ReflectedType) != 0)
1983 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1984 if ((req_info & PInfo_DeclaringType) != 0)
1985 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1987 if ((req_info & PInfo_Name) != 0)
1988 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1990 if ((req_info & PInfo_Attributes) != 0)
1991 info->attrs = property->property->attrs;
1993 if ((req_info & PInfo_GetMethod) != 0)
1994 MONO_STRUCT_SETREF (info, get, property->property->get ?
1995 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1997 if ((req_info & PInfo_SetMethod) != 0)
1998 MONO_STRUCT_SETREF (info, set, property->property->set ?
1999 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2001 * There may be other methods defined for properties, though, it seems they are not exposed
2002 * in the reflection API
2007 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2009 MonoDomain *domain = mono_object_domain (event);
2011 MONO_ARCH_SAVE_REGS;
2013 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2014 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2016 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2017 info->attrs = event->event->attrs;
2018 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2019 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2020 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2022 #ifndef MONO_SMALL_CONFIG
2023 if (event->event->other) {
2025 while (event->event->other [n])
2027 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2029 for (i = 0; i < n; i++)
2030 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2036 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2041 mono_class_setup_interfaces (klass, error);
2042 if (!mono_error_ok (error))
2045 for (i = 0; i < klass->interface_count; i++) {
2046 ic = klass->interfaces [i];
2047 g_hash_table_insert (ifaces, ic, ic);
2049 collect_interfaces (ic, ifaces, error);
2050 if (!mono_error_ok (error))
2056 MonoArray *iface_array;
2057 MonoGenericContext *context;
2061 } FillIfaceArrayData;
2064 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2066 FillIfaceArrayData *data = user_data;
2067 MonoClass *ic = key;
2068 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2070 if (!mono_error_ok (data->error))
2073 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2074 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2075 if (!mono_error_ok (data->error))
2079 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2082 mono_metadata_free_type (inflated);
2085 ICALL_EXPORT MonoArray*
2086 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2089 MonoClass *class = mono_class_from_mono_type (type->type);
2091 FillIfaceArrayData data = { 0 };
2094 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2096 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2097 data.context = mono_class_get_context (class);
2098 class = class->generic_class->container_class;
2101 for (parent = class; parent; parent = parent->parent) {
2102 mono_class_setup_interfaces (parent, &error);
2103 if (!mono_error_ok (&error))
2105 collect_interfaces (parent, iface_hash, &error);
2106 if (!mono_error_ok (&error))
2110 data.error = &error;
2111 data.domain = mono_object_domain (type);
2113 len = g_hash_table_size (iface_hash);
2115 g_hash_table_destroy (iface_hash);
2116 if (!data.domain->empty_types)
2117 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2118 return data.domain->empty_types;
2121 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2122 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2123 if (!mono_error_ok (&error))
2126 g_hash_table_destroy (iface_hash);
2127 return data.iface_array;
2130 g_hash_table_destroy (iface_hash);
2131 mono_error_raise_exception (&error);
2136 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2138 gboolean variance_used;
2139 MonoClass *class = mono_class_from_mono_type (type->type);
2140 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2141 MonoReflectionMethod *member;
2144 int i = 0, len, ioffset;
2147 MONO_ARCH_SAVE_REGS;
2148 mono_class_init_or_throw (class);
2149 mono_class_init_or_throw (iclass);
2151 mono_class_setup_vtable (class);
2153 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2157 len = mono_class_num_methods (iclass);
2158 domain = mono_object_domain (type);
2159 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2160 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2162 while ((method = mono_class_get_methods (iclass, &iter))) {
2163 member = mono_method_get_object (domain, method, iclass);
2164 mono_array_setref (*methods, i, member);
2165 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2166 mono_array_setref (*targets, i, member);
2173 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2175 MonoClass *klass = mono_class_from_mono_type (type->type);
2176 mono_class_init_or_throw (klass);
2178 if (klass->image->dynamic) {
2179 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2180 *packing = tb->packing_size;
2181 *size = tb->class_size;
2183 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2187 ICALL_EXPORT MonoReflectionType*
2188 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2192 MONO_ARCH_SAVE_REGS;
2194 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2195 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2197 class = mono_class_from_mono_type (type->type);
2198 mono_class_init_or_throw (class);
2200 // GetElementType should only return a type for:
2201 // Array Pointer PassedByRef
2202 if (type->type->byref)
2203 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2204 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2205 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2206 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2207 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2212 ICALL_EXPORT MonoReflectionType*
2213 ves_icall_get_type_parent (MonoReflectionType *type)
2215 MonoClass *class = mono_class_from_mono_type (type->type);
2216 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2219 ICALL_EXPORT MonoBoolean
2220 ves_icall_type_ispointer (MonoReflectionType *type)
2222 MONO_ARCH_SAVE_REGS;
2224 return type->type->type == MONO_TYPE_PTR;
2227 ICALL_EXPORT MonoBoolean
2228 ves_icall_type_isprimitive (MonoReflectionType *type)
2230 MONO_ARCH_SAVE_REGS;
2232 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)));
2235 ICALL_EXPORT MonoBoolean
2236 ves_icall_type_isbyref (MonoReflectionType *type)
2238 MONO_ARCH_SAVE_REGS;
2240 return type->type->byref;
2243 ICALL_EXPORT MonoBoolean
2244 ves_icall_type_iscomobject (MonoReflectionType *type)
2246 MonoClass *klass = mono_class_from_mono_type (type->type);
2247 mono_class_init_or_throw (klass);
2249 return mono_class_is_com_object (klass);
2252 ICALL_EXPORT MonoReflectionModule*
2253 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2255 MonoClass *class = mono_class_from_mono_type (type->type);
2256 return mono_module_get_object (mono_object_domain (type), class->image);
2259 ICALL_EXPORT MonoReflectionAssembly*
2260 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2262 MonoDomain *domain = mono_domain_get ();
2263 MonoClass *class = mono_class_from_mono_type (type->type);
2264 return mono_assembly_get_object (domain, class->image->assembly);
2267 ICALL_EXPORT MonoReflectionType*
2268 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2270 MonoDomain *domain = mono_domain_get ();
2273 MONO_ARCH_SAVE_REGS;
2275 if (type->type->byref)
2277 if (type->type->type == MONO_TYPE_VAR)
2278 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2279 else if (type->type->type == MONO_TYPE_MVAR)
2280 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2282 class = mono_class_from_mono_type (type->type)->nested_in;
2284 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2287 ICALL_EXPORT MonoString*
2288 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2290 MonoDomain *domain = mono_domain_get ();
2291 MonoClass *class = mono_class_from_mono_type (type->type);
2293 if (type->type->byref) {
2294 char *n = g_strdup_printf ("%s&", class->name);
2295 MonoString *res = mono_string_new (domain, n);
2301 return mono_string_new (domain, class->name);
2305 ICALL_EXPORT MonoString*
2306 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2308 MonoDomain *domain = mono_domain_get ();
2309 MonoClass *class = mono_class_from_mono_type (type->type);
2311 while (class->nested_in)
2312 class = class->nested_in;
2314 if (class->name_space [0] == '\0')
2317 return mono_string_new (domain, class->name_space);
2321 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2325 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2326 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2328 class = mono_class_from_mono_type (type->type);
2333 ICALL_EXPORT MonoArray*
2334 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2337 MonoClass *klass, *pklass;
2338 MonoDomain *domain = mono_object_domain (type);
2339 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2341 MONO_ARCH_SAVE_REGS;
2343 klass = mono_class_from_mono_type (type->type);
2345 if (klass->generic_container) {
2346 MonoGenericContainer *container = klass->generic_container;
2347 res = mono_array_new_specific (array_vtable, container->type_argc);
2348 for (i = 0; i < container->type_argc; ++i) {
2349 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2350 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2352 } else if (klass->generic_class) {
2353 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2354 res = mono_array_new_specific (array_vtable, inst->type_argc);
2355 for (i = 0; i < inst->type_argc; ++i)
2356 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2358 res = mono_array_new_specific (array_vtable, 0);
2363 ICALL_EXPORT gboolean
2364 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2367 MONO_ARCH_SAVE_REGS;
2369 if (!IS_MONOTYPE (type))
2372 if (type->type->byref)
2375 klass = mono_class_from_mono_type (type->type);
2376 return klass->generic_container != NULL;
2379 ICALL_EXPORT MonoReflectionType*
2380 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2383 MONO_ARCH_SAVE_REGS;
2385 if (type->type->byref)
2388 klass = mono_class_from_mono_type (type->type);
2390 if (klass->generic_container) {
2391 return type; /* check this one */
2393 if (klass->generic_class) {
2394 MonoClass *generic_class = klass->generic_class->container_class;
2397 tb = mono_class_get_ref_info (generic_class);
2399 if (generic_class->wastypebuilder && tb)
2402 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2407 ICALL_EXPORT MonoReflectionType*
2408 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2411 MonoType *geninst, **types;
2414 g_assert (IS_MONOTYPE (type));
2415 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2417 count = mono_array_length (type_array);
2418 types = g_new0 (MonoType *, count);
2420 for (i = 0; i < count; i++) {
2421 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2422 types [i] = t->type;
2425 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2430 class = mono_class_from_mono_type (geninst);
2432 /*we might inflate to the GTD*/
2433 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2434 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2436 return mono_type_get_object (mono_object_domain (type), geninst);
2439 ICALL_EXPORT gboolean
2440 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2443 MONO_ARCH_SAVE_REGS;
2445 if (type->type->byref)
2448 klass = mono_class_from_mono_type (type->type);
2450 return klass->generic_class != NULL;
2453 ICALL_EXPORT gboolean
2454 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2457 MONO_ARCH_SAVE_REGS;
2459 if (!IS_MONOTYPE (type))
2462 if (type->type->byref)
2465 klass = mono_class_from_mono_type (type->type);
2466 return klass->generic_class != NULL || klass->generic_container != NULL;
2470 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2472 MONO_ARCH_SAVE_REGS;
2474 if (!IS_MONOTYPE (type))
2477 if (is_generic_parameter (type->type))
2478 return mono_type_get_generic_param_num (type->type);
2482 ICALL_EXPORT GenericParameterAttributes
2483 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2485 MONO_ARCH_SAVE_REGS;
2487 g_assert (IS_MONOTYPE (type));
2488 g_assert (is_generic_parameter (type->type));
2489 return mono_generic_param_info (type->type->data.generic_param)->flags;
2492 ICALL_EXPORT MonoArray *
2493 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2495 MonoGenericParamInfo *param_info;
2501 MONO_ARCH_SAVE_REGS;
2503 g_assert (IS_MONOTYPE (type));
2505 domain = mono_object_domain (type);
2506 param_info = mono_generic_param_info (type->type->data.generic_param);
2507 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2510 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2511 for (i = 0; i < count; i++)
2512 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2518 ICALL_EXPORT MonoBoolean
2519 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2521 MONO_ARCH_SAVE_REGS;
2522 return is_generic_parameter (type->type);
2525 ICALL_EXPORT MonoBoolean
2526 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2528 MONO_ARCH_SAVE_REGS;
2529 return is_generic_parameter (tb->type.type);
2533 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2534 MonoReflectionType *t)
2536 enumtype->type = t->type;
2539 ICALL_EXPORT MonoReflectionMethod*
2540 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2541 MonoReflectionMethod* generic)
2548 MONO_ARCH_SAVE_REGS;
2550 domain = ((MonoObject *)type)->vtable->domain;
2552 klass = mono_class_from_mono_type (type->type);
2553 mono_class_init_or_throw (klass);
2556 while ((method = mono_class_get_methods (klass, &iter))) {
2557 if (method->token == generic->method->token)
2558 return mono_method_get_object (domain, method, klass);
2566 ICALL_EXPORT MonoReflectionMethod *
2567 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2570 MonoType *type = ref_type->type;
2572 MONO_ARCH_SAVE_REGS;
2574 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2575 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2576 if (type->type == MONO_TYPE_VAR)
2579 method = mono_type_get_generic_param_owner (type)->owner.method;
2581 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2584 ICALL_EXPORT MonoReflectionDllImportAttribute*
2585 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2587 static MonoClass *DllImportAttributeClass = NULL;
2588 MonoDomain *domain = mono_domain_get ();
2589 MonoReflectionDllImportAttribute *attr;
2590 MonoImage *image = method->klass->image;
2591 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2592 MonoTableInfo *tables = image->tables;
2593 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2594 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2595 guint32 im_cols [MONO_IMPLMAP_SIZE];
2596 guint32 scope_token;
2597 const char *import = NULL;
2598 const char *scope = NULL;
2601 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2604 if (!DllImportAttributeClass) {
2605 DllImportAttributeClass =
2606 mono_class_from_name (mono_defaults.corlib,
2607 "System.Runtime.InteropServices", "DllImportAttribute");
2608 g_assert (DllImportAttributeClass);
2611 if (method->klass->image->dynamic) {
2612 MonoReflectionMethodAux *method_aux =
2613 g_hash_table_lookup (
2614 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2616 import = method_aux->dllentry;
2617 scope = method_aux->dll;
2620 if (!import || !scope) {
2621 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2626 if (piinfo->implmap_idx) {
2627 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2629 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2630 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2631 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2632 scope = mono_metadata_string_heap (image, scope_token);
2635 flags = piinfo->piflags;
2637 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2639 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2640 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2641 attr->call_conv = (flags & 0x700) >> 8;
2642 attr->charset = ((flags & 0x6) >> 1) + 1;
2643 if (attr->charset == 1)
2645 attr->exact_spelling = (flags & 0x1) != 0;
2646 attr->set_last_error = (flags & 0x40) != 0;
2647 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2648 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2649 attr->preserve_sig = FALSE;
2654 ICALL_EXPORT MonoReflectionMethod *
2655 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2657 MonoMethodInflated *imethod;
2660 MONO_ARCH_SAVE_REGS;
2662 if (method->method->is_generic)
2665 if (!method->method->is_inflated)
2668 imethod = (MonoMethodInflated *) method->method;
2670 result = imethod->declaring;
2671 /* Not a generic method. */
2672 if (!result->is_generic)
2675 if (method->method->klass->image->dynamic) {
2676 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2677 MonoReflectionMethod *res;
2680 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2681 * the dynamic case as well ?
2683 mono_image_lock ((MonoImage*)image);
2684 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2685 mono_image_unlock ((MonoImage*)image);
2691 if (imethod->context.class_inst) {
2692 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2693 /*Generic methods gets the context of the GTD.*/
2694 if (mono_class_get_context (klass))
2695 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2698 return mono_method_get_object (mono_object_domain (method), result, NULL);
2701 ICALL_EXPORT gboolean
2702 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2704 MONO_ARCH_SAVE_REGS;
2706 return mono_method_signature (method->method)->generic_param_count != 0;
2709 ICALL_EXPORT gboolean
2710 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2712 MONO_ARCH_SAVE_REGS;
2714 return method->method->is_generic;
2717 ICALL_EXPORT MonoArray*
2718 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2723 MONO_ARCH_SAVE_REGS;
2725 domain = mono_object_domain (method);
2727 if (method->method->is_inflated) {
2728 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2731 count = inst->type_argc;
2732 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2734 for (i = 0; i < count; i++)
2735 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2741 count = mono_method_signature (method->method)->generic_param_count;
2742 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2744 for (i = 0; i < count; i++) {
2745 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2746 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2747 MonoClass *pklass = mono_class_from_generic_parameter (
2748 param, method->method->klass->image, TRUE);
2749 mono_array_setref (res, i,
2750 mono_type_get_object (domain, &pklass->byval_arg));
2756 ICALL_EXPORT MonoObject *
2757 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2760 * Invoke from reflection is supposed to always be a virtual call (the API
2761 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2762 * greater flexibility.
2764 MonoMethod *m = method->method;
2765 MonoMethodSignature *sig = mono_method_signature (m);
2770 MONO_ARCH_SAVE_REGS;
2774 if (mono_security_core_clr_enabled ())
2775 mono_security_core_clr_ensure_reflection_access_method (m);
2777 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2778 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2779 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2784 if (!mono_object_isinst (this, m->klass)) {
2785 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2786 char *target_name = mono_type_get_full_name (m->klass);
2787 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2788 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2790 g_free (target_name);
2794 m = mono_object_get_virtual_method (this, m);
2795 /* must pass the pointer to the value for valuetype methods */
2796 if (m->klass->valuetype)
2797 obj = mono_object_unbox (this);
2798 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2799 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2804 if (sig->ret->byref) {
2805 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"));
2809 pcount = params? mono_array_length (params): 0;
2810 if (pcount != sig->param_count) {
2811 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2815 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2816 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."));
2820 image = m->klass->image;
2821 if (image->assembly->ref_only) {
2822 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."));
2826 if (image->dynamic && !((MonoDynamicImage*)image)->run) {
2827 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2831 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2834 intptr_t *lower_bounds;
2835 pcount = mono_array_length (params);
2836 lengths = alloca (sizeof (uintptr_t) * pcount);
2837 /* Note: the synthetized array .ctors have int32 as argument type */
2838 for (i = 0; i < pcount; ++i)
2839 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2841 if (m->klass->rank == pcount) {
2842 /* Only lengths provided. */
2843 lower_bounds = NULL;
2845 g_assert (pcount == (m->klass->rank * 2));
2846 /* lower bounds are first. */
2847 lower_bounds = (intptr_t*)lengths;
2848 lengths += m->klass->rank;
2851 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2853 return mono_runtime_invoke_array (m, obj, params, NULL);
2856 #ifndef DISABLE_REMOTING
2857 ICALL_EXPORT MonoObject *
2858 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2860 MonoDomain *domain = mono_object_domain (method);
2861 MonoMethod *m = method->method;
2862 MonoMethodSignature *sig = mono_method_signature (m);
2863 MonoArray *out_args;
2865 int i, j, outarg_count = 0;
2867 MONO_ARCH_SAVE_REGS;
2869 if (m->klass == mono_defaults.object_class) {
2871 if (!strcmp (m->name, "FieldGetter")) {
2872 MonoClass *k = this->vtable->klass;
2876 /* If this is a proxy, then it must be a CBO */
2877 if (k == mono_defaults.transparent_proxy_class) {
2878 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2879 this = tp->rp->unwrapped_server;
2881 k = this->vtable->klass;
2884 name = mono_array_get (params, MonoString *, 1);
2885 str = mono_string_to_utf8 (name);
2888 MonoClassField* field = mono_class_get_field_from_name (k, str);
2890 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2891 if (field_klass->valuetype)
2892 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2894 result = *((gpointer *)((char *)this + field->offset));
2896 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2897 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2898 mono_array_setref (out_args, 0, result);
2906 g_assert_not_reached ();
2908 } else if (!strcmp (m->name, "FieldSetter")) {
2909 MonoClass *k = this->vtable->klass;
2915 /* If this is a proxy, then it must be a CBO */
2916 if (k == mono_defaults.transparent_proxy_class) {
2917 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2918 this = tp->rp->unwrapped_server;
2920 k = this->vtable->klass;
2923 name = mono_array_get (params, MonoString *, 1);
2924 str = mono_string_to_utf8 (name);
2927 MonoClassField* field = mono_class_get_field_from_name (k, str);
2929 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2930 MonoObject *val = mono_array_get (params, gpointer, 2);
2932 if (field_klass->valuetype) {
2933 size = mono_type_size (field->type, &align);
2934 g_assert (size == mono_class_value_size (field_klass, NULL));
2935 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2937 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2940 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2941 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2951 g_assert_not_reached ();
2956 for (i = 0; i < mono_array_length (params); i++) {
2957 if (sig->params [i]->byref)
2961 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2963 /* handle constructors only for objects already allocated */
2964 if (!strcmp (method->method->name, ".ctor"))
2967 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2968 g_assert (!method->method->klass->valuetype);
2969 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2971 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2972 if (sig->params [i]->byref) {
2974 arg = mono_array_get (params, gpointer, i);
2975 mono_array_setref (out_args, j, arg);
2980 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2987 read_enum_value (char *mem, int type)
2991 return *(guint8*)mem;
2993 return *(gint8*)mem;
2995 return *(guint16*)mem;
2997 return *(gint16*)mem;
2999 return *(guint32*)mem;
3001 return *(gint32*)mem;
3003 return *(guint64*)mem;
3005 return *(gint64*)mem;
3007 g_assert_not_reached ();
3013 write_enum_value (char *mem, int type, guint64 value)
3017 case MONO_TYPE_I1: {
3018 guint8 *p = (guint8*)mem;
3023 case MONO_TYPE_I2: {
3024 guint16 *p = (void*)mem;
3029 case MONO_TYPE_I4: {
3030 guint32 *p = (void*)mem;
3035 case MONO_TYPE_I8: {
3036 guint64 *p = (void*)mem;
3041 g_assert_not_reached ();
3046 ICALL_EXPORT MonoObject *
3047 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3050 MonoClass *enumc, *objc;
3055 MONO_ARCH_SAVE_REGS;
3057 MONO_CHECK_ARG_NULL (enumType);
3058 MONO_CHECK_ARG_NULL (value);
3060 domain = mono_object_domain (enumType);
3061 enumc = mono_class_from_mono_type (enumType->type);
3063 mono_class_init_or_throw (enumc);
3065 objc = value->vtable->klass;
3067 if (!enumc->enumtype)
3068 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3069 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3070 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."));
3072 etype = mono_class_enum_basetype (enumc);
3074 /* MS throws this for typebuilders */
3075 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3077 res = mono_object_new (domain, enumc);
3078 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3079 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3084 ICALL_EXPORT MonoObject *
3085 ves_icall_System_Enum_get_value (MonoObject *this)
3093 MONO_ARCH_SAVE_REGS;
3098 g_assert (this->vtable->klass->enumtype);
3100 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3101 res = mono_object_new (mono_object_domain (this), enumc);
3102 dst = (char *)res + sizeof (MonoObject);
3103 src = (char *)this + sizeof (MonoObject);
3104 size = mono_class_value_size (enumc, NULL);
3106 memcpy (dst, src, size);
3111 ICALL_EXPORT MonoReflectionType *
3112 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3117 MONO_ARCH_SAVE_REGS;
3119 klass = mono_class_from_mono_type (type->type);
3120 mono_class_init_or_throw (klass);
3122 etype = mono_class_enum_basetype (klass);
3124 /* MS throws this for typebuilders */
3125 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3127 return mono_type_get_object (mono_object_domain (type), etype);
3131 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3133 gpointer tdata = (char *)this + sizeof (MonoObject);
3134 gpointer odata = (char *)other + sizeof (MonoObject);
3135 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3136 g_assert (basetype);
3138 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3139 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3140 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3143 return me > other ? 1 : -1; \
3146 switch (basetype->type) {
3148 COMPARE_ENUM_VALUES (guint8);
3150 COMPARE_ENUM_VALUES (gint8);
3151 case MONO_TYPE_CHAR:
3153 COMPARE_ENUM_VALUES (guint16);
3155 COMPARE_ENUM_VALUES (gint16);
3157 COMPARE_ENUM_VALUES (guint32);
3159 COMPARE_ENUM_VALUES (gint32);
3161 COMPARE_ENUM_VALUES (guint64);
3163 COMPARE_ENUM_VALUES (gint64);
3165 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3167 #undef COMPARE_ENUM_VALUES
3172 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3174 gpointer data = (char *)this + sizeof (MonoObject);
3175 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3176 g_assert (basetype);
3178 switch (basetype->type) {
3180 return *((gint8*)data);
3182 return *((guint8*)data);
3183 case MONO_TYPE_CHAR:
3185 return *((guint16*)data);
3188 return *((gint16*)data);
3190 return *((guint32*)data);
3192 return *((gint32*)data);
3194 case MONO_TYPE_I8: {
3195 gint64 value = *((gint64*)data);
3196 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3199 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3205 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3207 MonoDomain *domain = mono_object_domain (type);
3208 MonoClass *enumc = mono_class_from_mono_type (type->type);
3209 guint j = 0, nvalues, crow;
3211 MonoClassField *field;
3213 MONO_ARCH_SAVE_REGS;
3215 mono_class_init_or_throw (enumc);
3217 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3218 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3219 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3220 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3224 while ((field = mono_class_get_fields (enumc, &iter))) {
3227 MonoTypeEnum def_type;
3229 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3231 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3233 if (mono_field_is_deleted (field))
3235 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3237 p = mono_class_get_field_default_value (field, &def_type);
3238 len = mono_metadata_decode_blob_size (p, &p);
3239 switch (mono_class_enum_basetype (enumc)->type) {
3242 mono_array_set (info->values, gchar, j, *p);
3244 case MONO_TYPE_CHAR:
3247 mono_array_set (info->values, gint16, j, read16 (p));
3251 mono_array_set (info->values, gint32, j, read32 (p));
3255 mono_array_set (info->values, gint64, j, read64 (p));
3258 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3265 BFLAGS_IgnoreCase = 1,
3266 BFLAGS_DeclaredOnly = 2,
3267 BFLAGS_Instance = 4,
3269 BFLAGS_Public = 0x10,
3270 BFLAGS_NonPublic = 0x20,
3271 BFLAGS_FlattenHierarchy = 0x40,
3272 BFLAGS_InvokeMethod = 0x100,
3273 BFLAGS_CreateInstance = 0x200,
3274 BFLAGS_GetField = 0x400,
3275 BFLAGS_SetField = 0x800,
3276 BFLAGS_GetProperty = 0x1000,
3277 BFLAGS_SetProperty = 0x2000,
3278 BFLAGS_ExactBinding = 0x10000,
3279 BFLAGS_SuppressChangeType = 0x20000,
3280 BFLAGS_OptionalParamBinding = 0x40000
3283 ICALL_EXPORT MonoReflectionField *
3284 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3287 MonoClass *startklass, *klass;
3289 MonoClassField *field;
3292 int (*compare_func) (const char *s1, const char *s2) = NULL;
3293 domain = ((MonoObject *)type)->vtable->domain;
3294 klass = startklass = mono_class_from_mono_type (type->type);
3297 mono_raise_exception (mono_get_exception_argument_null ("name"));
3298 if (type->type->byref)
3301 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3304 if (klass->exception_type != MONO_EXCEPTION_NONE)
3305 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3308 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3309 guint32 flags = mono_field_get_flags (field);
3312 if (mono_field_is_deleted_with_flags (field, flags))
3314 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3315 if (bflags & BFLAGS_Public)
3317 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3318 if (bflags & BFLAGS_NonPublic) {
3325 if (flags & FIELD_ATTRIBUTE_STATIC) {
3326 if (bflags & BFLAGS_Static)
3327 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3330 if (bflags & BFLAGS_Instance)
3337 utf8_name = mono_string_to_utf8 (name);
3339 if (compare_func (mono_field_get_name (field), utf8_name)) {
3345 return mono_field_get_object (domain, klass, field);
3347 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3353 ICALL_EXPORT MonoArray*
3354 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3357 MonoClass *startklass, *klass, *refklass;
3362 MonoClassField *field;
3363 MonoPtrArray tmp_array;
3365 MONO_ARCH_SAVE_REGS;
3367 domain = ((MonoObject *)type)->vtable->domain;
3368 if (type->type->byref)
3369 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3370 klass = startklass = mono_class_from_mono_type (type->type);
3371 refklass = mono_class_from_mono_type (reftype->type);
3373 mono_ptr_array_init (tmp_array, 2);
3376 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3377 mono_ptr_array_destroy (tmp_array);
3378 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3382 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3383 guint32 flags = mono_field_get_flags (field);
3385 if (mono_field_is_deleted_with_flags (field, flags))
3387 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3388 if (bflags & BFLAGS_Public)
3390 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3391 if (bflags & BFLAGS_NonPublic) {
3398 if (flags & FIELD_ATTRIBUTE_STATIC) {
3399 if (bflags & BFLAGS_Static)
3400 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3403 if (bflags & BFLAGS_Instance)
3409 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3410 mono_ptr_array_append (tmp_array, member);
3412 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3415 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3417 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3418 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3420 mono_ptr_array_destroy (tmp_array);
3426 method_nonpublic (MonoMethod* method, gboolean start_klass)
3428 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3429 case METHOD_ATTRIBUTE_ASSEM:
3430 return (start_klass || mono_defaults.generic_ilist_class);
3431 case METHOD_ATTRIBUTE_PRIVATE:
3433 case METHOD_ATTRIBUTE_PUBLIC:
3441 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3444 MonoClass *startklass;
3447 int len, match, nslots;
3448 /*FIXME, use MonoBitSet*/
3449 guint32 method_slots_default [8];
3450 guint32 *method_slots = NULL;
3451 int (*compare_func) (const char *s1, const char *s2) = NULL;
3453 array = g_ptr_array_new ();
3459 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3461 /* An optimization for calls made from Delegate:CreateDelegate () */
3462 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3463 method = mono_get_delegate_invoke (klass);
3464 if (mono_loader_get_last_error ())
3467 g_ptr_array_add (array, method);
3471 mono_class_setup_vtable (klass);
3472 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3475 if (is_generic_parameter (&klass->byval_arg))
3476 nslots = mono_class_get_vtable_size (klass->parent);
3478 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3479 if (nslots >= sizeof (method_slots_default) * 8) {
3480 method_slots = g_new0 (guint32, nslots / 32 + 1);
3482 method_slots = method_slots_default;
3483 memset (method_slots, 0, sizeof (method_slots_default));
3486 mono_class_setup_vtable (klass);
3487 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3491 while ((method = mono_class_get_methods (klass, &iter))) {
3493 if (method->slot != -1) {
3494 g_assert (method->slot < nslots);
3495 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3497 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3498 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3501 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3503 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3504 if (bflags & BFLAGS_Public)
3506 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3512 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3513 if (bflags & BFLAGS_Static)
3514 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3517 if (bflags & BFLAGS_Instance)
3525 if (compare_func (name, method->name))
3530 g_ptr_array_add (array, method);
3532 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3534 if (method_slots != method_slots_default)
3535 g_free (method_slots);
3540 if (method_slots != method_slots_default)
3541 g_free (method_slots);
3542 g_ptr_array_free (array, TRUE);
3544 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3545 *ex = mono_class_get_exception_for_failure (klass);
3547 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3548 mono_loader_clear_error ();
3553 ICALL_EXPORT MonoArray*
3554 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3556 static MonoClass *MethodInfo_array;
3559 MonoVTable *array_vtable;
3560 MonoException *ex = NULL;
3561 const char *mname = NULL;
3562 GPtrArray *method_array;
3563 MonoClass *klass, *refklass;
3566 if (!MethodInfo_array) {
3567 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3568 mono_memory_barrier ();
3569 MethodInfo_array = klass;
3572 klass = mono_class_from_mono_type (type->type);
3573 refklass = mono_class_from_mono_type (reftype->type);
3574 domain = ((MonoObject *)type)->vtable->domain;
3575 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3576 if (type->type->byref)
3577 return mono_array_new_specific (array_vtable, 0);
3580 mname = mono_string_to_utf8 (name);
3582 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3583 g_free ((char*)mname);
3585 mono_raise_exception (ex);
3587 res = mono_array_new_specific (array_vtable, method_array->len);
3590 for (i = 0; i < method_array->len; ++i) {
3591 MonoMethod *method = g_ptr_array_index (method_array, i);
3592 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3595 g_ptr_array_free (method_array, TRUE);
3599 ICALL_EXPORT MonoArray*
3600 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3603 static MonoClass *System_Reflection_ConstructorInfo;
3604 MonoClass *startklass, *klass, *refklass;
3609 gpointer iter = NULL;
3610 MonoPtrArray tmp_array;
3612 MONO_ARCH_SAVE_REGS;
3614 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3616 domain = ((MonoObject *)type)->vtable->domain;
3617 if (type->type->byref)
3618 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3619 klass = startklass = mono_class_from_mono_type (type->type);
3620 refklass = mono_class_from_mono_type (reftype->type);
3622 if (!System_Reflection_ConstructorInfo)
3623 System_Reflection_ConstructorInfo = mono_class_from_name (
3624 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3627 while ((method = mono_class_get_methods (klass, &iter))) {
3629 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3631 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3632 if (bflags & BFLAGS_Public)
3635 if (bflags & BFLAGS_NonPublic)
3641 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3642 if (bflags & BFLAGS_Static)
3643 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3646 if (bflags & BFLAGS_Instance)
3652 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3654 mono_ptr_array_append (tmp_array, member);
3657 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3659 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3660 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3662 mono_ptr_array_destroy (tmp_array);
3668 property_hash (gconstpointer data)
3670 MonoProperty *prop = (MonoProperty*)data;
3672 return g_str_hash (prop->name);
3676 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3678 // Properties are hide-by-name-and-signature
3679 if (!g_str_equal (prop1->name, prop2->name))
3682 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3684 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3690 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3695 return method_nonpublic (accessor, start_klass);
3698 ICALL_EXPORT MonoArray*
3699 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3703 static MonoClass *System_Reflection_PropertyInfo;
3704 MonoClass *startklass, *klass;
3710 gchar *propname = NULL;
3711 int (*compare_func) (const char *s1, const char *s2) = NULL;
3713 GHashTable *properties = NULL;
3714 MonoPtrArray tmp_array;
3716 MONO_ARCH_SAVE_REGS;
3718 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3720 if (!System_Reflection_PropertyInfo)
3721 System_Reflection_PropertyInfo = mono_class_from_name (
3722 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3724 domain = ((MonoObject *)type)->vtable->domain;
3725 if (type->type->byref)
3726 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3727 klass = startklass = mono_class_from_mono_type (type->type);
3730 propname = mono_string_to_utf8 (name);
3731 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3734 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3736 mono_class_setup_vtable (klass);
3737 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3741 while ((prop = mono_class_get_properties (klass, &iter))) {
3747 flags = method->flags;
3750 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3751 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3752 if (bflags & BFLAGS_Public)
3754 } else if (bflags & BFLAGS_NonPublic) {
3755 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3756 property_accessor_nonpublic(prop->set, startklass == klass)) {
3763 if (flags & METHOD_ATTRIBUTE_STATIC) {
3764 if (bflags & BFLAGS_Static)
3765 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3768 if (bflags & BFLAGS_Instance)
3777 if (compare_func (propname, prop->name))
3781 if (g_hash_table_lookup (properties, prop))
3784 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3786 g_hash_table_insert (properties, prop, prop);
3788 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3791 g_hash_table_destroy (properties);
3794 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3795 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3796 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3798 mono_ptr_array_destroy (tmp_array);
3804 g_hash_table_destroy (properties);
3807 mono_ptr_array_destroy (tmp_array);
3809 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3810 ex = mono_class_get_exception_for_failure (klass);
3812 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3813 mono_loader_clear_error ();
3815 mono_raise_exception (ex);
3819 ICALL_EXPORT MonoReflectionEvent *
3820 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3823 MonoClass *klass, *startklass;
3828 int (*compare_func) (const char *s1, const char *s2);
3830 MONO_ARCH_SAVE_REGS;
3832 event_name = mono_string_to_utf8 (name);
3833 if (type->type->byref)
3835 klass = startklass = mono_class_from_mono_type (type->type);
3836 domain = mono_object_domain (type);
3838 mono_class_init_or_throw (klass);
3840 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3842 if (klass->exception_type != MONO_EXCEPTION_NONE)
3843 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3846 while ((event = mono_class_get_events (klass, &iter))) {
3847 if (compare_func (event->name, event_name))
3850 method = event->add;
3852 method = event->remove;
3854 method = event->raise;
3856 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3857 if (!(bflags & BFLAGS_Public))
3860 if (!(bflags & BFLAGS_NonPublic))
3862 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3866 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3867 if (!(bflags & BFLAGS_Static))
3869 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3872 if (!(bflags & BFLAGS_Instance))
3876 if (!(bflags & BFLAGS_NonPublic))
3879 g_free (event_name);
3880 return mono_event_get_object (domain, startklass, event);
3883 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3886 g_free (event_name);
3891 event_hash (gconstpointer data)
3893 MonoEvent *event = (MonoEvent*)data;
3895 return g_str_hash (event->name);
3899 event_equal (MonoEvent *event1, MonoEvent *event2)
3901 // Events are hide-by-name
3902 return g_str_equal (event1->name, event2->name);
3905 ICALL_EXPORT MonoArray*
3906 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3910 static MonoClass *System_Reflection_EventInfo;
3911 MonoClass *startklass, *klass;
3917 GHashTable *events = NULL;
3918 MonoPtrArray tmp_array;
3920 MONO_ARCH_SAVE_REGS;
3922 mono_ptr_array_init (tmp_array, 4);
3924 if (!System_Reflection_EventInfo)
3925 System_Reflection_EventInfo = mono_class_from_name (
3926 mono_defaults.corlib, "System.Reflection", "EventInfo");
3928 domain = mono_object_domain (type);
3929 if (type->type->byref)
3930 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3931 klass = startklass = mono_class_from_mono_type (type->type);
3933 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3935 mono_class_setup_vtable (klass);
3936 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3940 while ((event = mono_class_get_events (klass, &iter))) {
3942 method = event->add;
3944 method = event->remove;
3946 method = event->raise;
3948 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3949 if (bflags & BFLAGS_Public)
3951 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3952 if (bflags & BFLAGS_NonPublic)
3957 if (bflags & BFLAGS_NonPublic)
3963 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3964 if (bflags & BFLAGS_Static)
3965 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3968 if (bflags & BFLAGS_Instance)
3973 if (bflags & BFLAGS_Instance)
3978 if (g_hash_table_lookup (events, event))
3981 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3983 g_hash_table_insert (events, event, event);
3985 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3988 g_hash_table_destroy (events);
3990 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3992 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3993 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3995 mono_ptr_array_destroy (tmp_array);
4000 mono_ptr_array_destroy (tmp_array);
4001 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4002 ex = mono_class_get_exception_for_failure (klass);
4004 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4005 mono_loader_clear_error ();
4007 mono_raise_exception (ex);
4011 ICALL_EXPORT MonoReflectionType *
4012 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4020 MONO_ARCH_SAVE_REGS;
4023 mono_raise_exception (mono_get_exception_argument_null ("name"));
4025 domain = ((MonoObject *)type)->vtable->domain;
4026 if (type->type->byref)
4028 klass = mono_class_from_mono_type (type->type);
4030 str = mono_string_to_utf8 (name);
4033 if (klass->exception_type != MONO_EXCEPTION_NONE)
4034 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4037 * If a nested type is generic, return its generic type definition.
4038 * Note that this means that the return value is essentially a
4039 * nested type of the generic type definition of @klass.
4041 * A note in MSDN claims that a generic type definition can have
4042 * nested types that aren't generic. In any case, the container of that
4043 * nested type would be the generic type definition.
4045 if (klass->generic_class)
4046 klass = klass->generic_class->container_class;
4049 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4051 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4052 if (bflags & BFLAGS_Public)
4055 if (bflags & BFLAGS_NonPublic)
4060 if (strcmp (nested->name, str) == 0){
4062 return mono_type_get_object (domain, &nested->byval_arg);
4065 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4071 ICALL_EXPORT MonoArray*
4072 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4081 MonoPtrArray tmp_array;
4083 MONO_ARCH_SAVE_REGS;
4085 domain = ((MonoObject *)type)->vtable->domain;
4086 if (type->type->byref)
4087 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4088 klass = mono_class_from_mono_type (type->type);
4091 * If a nested type is generic, return its generic type definition.
4092 * Note that this means that the return value is essentially the set
4093 * of nested types of the generic type definition of @klass.
4095 * A note in MSDN claims that a generic type definition can have
4096 * nested types that aren't generic. In any case, the container of that
4097 * nested type would be the generic type definition.
4099 if (klass->generic_class)
4100 klass = klass->generic_class->container_class;
4102 mono_ptr_array_init (tmp_array, 1);
4104 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4106 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4107 if (bflags & BFLAGS_Public)
4110 if (bflags & BFLAGS_NonPublic)
4115 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4116 mono_ptr_array_append (tmp_array, member);
4119 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4121 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4122 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4124 mono_ptr_array_destroy (tmp_array);
4129 ICALL_EXPORT MonoReflectionType*
4130 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4133 MonoType *type = NULL;
4134 MonoTypeNameParse info;
4135 gboolean type_resolve;
4137 MONO_ARCH_SAVE_REGS;
4139 /* On MS.NET, this does not fire a TypeResolve event */
4140 type_resolve = TRUE;
4141 str = mono_string_to_utf8 (name);
4142 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4143 if (!mono_reflection_parse_type (str, &info)) {
4145 mono_reflection_free_type_info (&info);
4146 if (throwOnError) /* uhm: this is a parse error, though... */
4147 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4148 /*g_print ("failed parse\n");*/
4152 if (info.assembly.name) {
4154 mono_reflection_free_type_info (&info);
4156 /* 1.0 and 2.0 throw different exceptions */
4157 if (mono_defaults.generic_ilist_class)
4158 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4160 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4165 if (module != NULL) {
4167 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4172 if (assembly->assembly->dynamic) {
4173 /* Enumerate all modules */
4174 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4178 if (abuilder->modules) {
4179 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4180 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4181 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4187 if (!type && abuilder->loaded_modules) {
4188 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4189 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4190 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4197 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4199 mono_reflection_free_type_info (&info);
4201 MonoException *e = NULL;
4204 e = mono_get_exception_type_load (name, NULL);
4206 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4207 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4209 mono_loader_clear_error ();
4212 mono_raise_exception (e);
4215 } else if (mono_loader_get_last_error ()) {
4217 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4218 mono_loader_clear_error ();
4221 if (type->type == MONO_TYPE_CLASS) {
4222 MonoClass *klass = mono_type_get_class (type);
4224 if (mono_security_enabled () && !klass->exception_type)
4225 /* Some security problems are detected during generic vtable construction */
4226 mono_class_setup_vtable (klass);
4228 /* need to report exceptions ? */
4229 if (throwOnError && klass->exception_type) {
4230 /* report SecurityException (or others) that occured when loading the assembly */
4231 MonoException *exc = mono_class_get_exception_for_failure (klass);
4232 mono_loader_clear_error ();
4233 mono_raise_exception (exc);
4234 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4239 /* g_print ("got it\n"); */
4240 return mono_type_get_object (mono_object_domain (assembly), type);
4244 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4247 gchar *shadow_ini_file;
4250 /* Check for shadow-copied assembly */
4251 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4252 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4254 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4255 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4261 g_free (shadow_ini_file);
4262 if (content != NULL) {
4265 *filename = content;
4272 ICALL_EXPORT MonoString *
4273 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4275 MonoDomain *domain = mono_object_domain (assembly);
4276 MonoAssembly *mass = assembly->assembly;
4277 MonoString *res = NULL;
4282 MONO_ARCH_SAVE_REGS;
4284 if (g_path_is_absolute (mass->image->name)) {
4285 absolute = g_strdup (mass->image->name);
4286 dirname = g_path_get_dirname (absolute);
4288 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4289 dirname = g_strdup (mass->basedir);
4292 replace_shadow_path (domain, dirname, &absolute);
4297 for (i = strlen (absolute) - 1; i >= 0; i--)
4298 if (absolute [i] == '\\')
4303 uri = g_filename_to_uri (absolute, NULL, NULL);
4305 const char *prepend = "file://";
4307 if (*absolute == '/' && *(absolute + 1) == '/') {
4310 prepend = "file:///";
4313 uri = g_strconcat (prepend, absolute, NULL);
4317 res = mono_string_new (domain, uri);
4324 ICALL_EXPORT MonoBoolean
4325 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4327 MonoAssembly *mass = assembly->assembly;
4329 MONO_ARCH_SAVE_REGS;
4331 return mass->in_gac;
4334 ICALL_EXPORT MonoReflectionAssembly*
4335 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4339 MonoImageOpenStatus status;
4341 MONO_ARCH_SAVE_REGS;
4343 name = mono_string_to_utf8 (mname);
4344 res = mono_assembly_load_with_partial_name (name, &status);
4350 return mono_assembly_get_object (mono_domain_get (), res);
4353 ICALL_EXPORT MonoString *
4354 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4356 MonoDomain *domain = mono_object_domain (assembly);
4359 MONO_ARCH_SAVE_REGS;
4361 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4366 ICALL_EXPORT MonoBoolean
4367 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4369 MONO_ARCH_SAVE_REGS;
4371 return assembly->assembly->ref_only;
4374 ICALL_EXPORT MonoString *
4375 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4377 MonoDomain *domain = mono_object_domain (assembly);
4379 MONO_ARCH_SAVE_REGS;
4381 return mono_string_new (domain, assembly->assembly->image->version);
4384 ICALL_EXPORT MonoReflectionMethod*
4385 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4387 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4389 MONO_ARCH_SAVE_REGS;
4393 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4396 ICALL_EXPORT MonoReflectionModule*
4397 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4399 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4402 ICALL_EXPORT MonoArray*
4403 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4405 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4406 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4410 MONO_ARCH_SAVE_REGS;
4412 for (i = 0; i < table->rows; ++i) {
4413 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4414 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4420 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4422 static MonoClass *System_Version = NULL;
4423 static MonoMethod *create_version = NULL;
4427 if (!System_Version) {
4428 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4429 g_assert (System_Version);
4432 if (!create_version) {
4433 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4434 create_version = mono_method_desc_search_in_class (desc, System_Version);
4435 g_assert (create_version);
4436 mono_method_desc_free (desc);
4442 args [3] = &revision;
4443 result = mono_object_new (domain, System_Version);
4444 mono_runtime_invoke (create_version, result, args, NULL);
4449 ICALL_EXPORT MonoArray*
4450 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4452 static MonoClass *System_Reflection_AssemblyName;
4454 MonoDomain *domain = mono_object_domain (assembly);
4456 static MonoMethod *create_culture = NULL;
4457 MonoImage *image = assembly->assembly->image;
4460 MONO_ARCH_SAVE_REGS;
4462 if (!System_Reflection_AssemblyName)
4463 System_Reflection_AssemblyName = mono_class_from_name (
4464 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4466 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4469 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4471 if (count > 0 && !create_culture) {
4472 MonoMethodDesc *desc = mono_method_desc_new (
4473 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4474 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4475 g_assert (create_culture);
4476 mono_method_desc_free (desc);
4479 for (i = 0; i < count; i++) {
4480 MonoReflectionAssemblyName *aname;
4481 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4483 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4485 aname = (MonoReflectionAssemblyName *) mono_object_new (
4486 domain, System_Reflection_AssemblyName);
4488 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4490 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4491 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4492 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4493 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4494 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4495 aname->versioncompat = 1; /* SameMachine (default) */
4496 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4497 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4499 if (create_culture) {
4501 MonoBoolean assembly_ref = 1;
4502 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4503 args [1] = &assembly_ref;
4504 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4507 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4508 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4509 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4511 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4512 /* public key token isn't copied - the class library will
4513 automatically generate it from the public key if required */
4514 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4515 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4517 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4518 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4521 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4524 /* note: this function doesn't return the codebase on purpose (i.e. it can
4525 be used under partial trust as path information isn't present). */
4527 mono_array_setref (result, i, aname);
4532 /* move this in some file in mono/util/ */
4534 g_concat_dir_and_file (const char *dir, const char *file)
4536 g_return_val_if_fail (dir != NULL, NULL);
4537 g_return_val_if_fail (file != NULL, NULL);
4540 * If the directory name doesn't have a / on the end, we need
4541 * to add one so we get a proper path to the file
4543 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4544 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4546 return g_strconcat (dir, file, NULL);
4550 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4552 char *n = mono_string_to_utf8 (name);
4553 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4555 guint32 cols [MONO_MANIFEST_SIZE];
4556 guint32 impl, file_idx;
4560 MONO_ARCH_SAVE_REGS;
4562 for (i = 0; i < table->rows; ++i) {
4563 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4564 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4565 if (strcmp (val, n) == 0)
4569 if (i == table->rows)
4572 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4575 * this code should only be called after obtaining the
4576 * ResourceInfo and handling the other cases.
4578 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4579 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4581 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4586 module = assembly->assembly->image;
4588 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4590 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4593 ICALL_EXPORT gboolean
4594 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4596 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4598 guint32 cols [MONO_MANIFEST_SIZE];
4599 guint32 file_cols [MONO_FILE_SIZE];
4603 MONO_ARCH_SAVE_REGS;
4605 n = mono_string_to_utf8 (name);
4606 for (i = 0; i < table->rows; ++i) {
4607 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4608 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4609 if (strcmp (val, n) == 0)
4613 if (i == table->rows)
4616 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4617 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4620 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4621 case MONO_IMPLEMENTATION_FILE:
4622 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4623 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4624 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4625 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4626 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4627 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4630 info->location = RESOURCE_LOCATION_EMBEDDED;
4633 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4634 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4635 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4636 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4637 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4638 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4640 mono_raise_exception (ex);
4642 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4644 /* Obtain info recursively */
4645 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4646 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4649 case MONO_IMPLEMENTATION_EXP_TYPE:
4650 g_assert_not_reached ();
4658 ICALL_EXPORT MonoObject*
4659 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4661 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4662 MonoArray *result = NULL;
4667 MONO_ARCH_SAVE_REGS;
4669 /* check hash if needed */
4671 n = mono_string_to_utf8 (name);
4672 for (i = 0; i < table->rows; ++i) {
4673 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4674 if (strcmp (val, n) == 0) {
4677 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4678 fn = mono_string_new (mono_object_domain (assembly), n);
4680 return (MonoObject*)fn;
4688 for (i = 0; i < table->rows; ++i) {
4689 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4693 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4696 for (i = 0; i < table->rows; ++i) {
4697 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4698 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4699 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4700 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4705 return (MonoObject*)result;
4708 ICALL_EXPORT MonoArray*
4709 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4711 MonoDomain *domain = mono_domain_get();
4714 int i, j, file_count = 0;
4715 MonoImage **modules;
4716 guint32 module_count, real_module_count;
4717 MonoTableInfo *table;
4718 guint32 cols [MONO_FILE_SIZE];
4719 MonoImage *image = assembly->assembly->image;
4721 g_assert (image != NULL);
4722 g_assert (!assembly->assembly->dynamic);
4724 table = &image->tables [MONO_TABLE_FILE];
4725 file_count = table->rows;
4727 modules = image->modules;
4728 module_count = image->module_count;
4730 real_module_count = 0;
4731 for (i = 0; i < module_count; ++i)
4733 real_module_count ++;
4735 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4736 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4738 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4740 for (i = 0; i < module_count; ++i)
4742 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4746 for (i = 0; i < file_count; ++i, ++j) {
4747 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4748 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4749 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4751 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4753 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4754 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4756 mono_array_setref (res, j, mono_module_get_object (domain, m));
4763 ICALL_EXPORT MonoReflectionMethod*
4764 ves_icall_GetCurrentMethod (void)
4766 MonoMethod *m = mono_method_get_last_managed ();
4768 while (m->is_inflated)
4769 m = ((MonoMethodInflated*)m)->declaring;
4771 return mono_method_get_object (mono_domain_get (), m, NULL);
4776 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4779 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4780 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4781 //method is inflated, we should inflate it on the other class
4782 MonoGenericContext ctx;
4783 ctx.method_inst = inflated->context.method_inst;
4784 ctx.class_inst = inflated->context.class_inst;
4785 if (klass->generic_class)
4786 ctx.class_inst = klass->generic_class->context.class_inst;
4787 else if (klass->generic_container)
4788 ctx.class_inst = klass->generic_container->context.class_inst;
4789 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4792 mono_class_setup_methods (method->klass);
4793 if (method->klass->exception_type)
4795 for (i = 0; i < method->klass->method.count; ++i) {
4796 if (method->klass->methods [i] == method) {
4801 mono_class_setup_methods (klass);
4802 if (klass->exception_type)
4804 g_assert (offset >= 0 && offset < klass->method.count);
4805 return klass->methods [offset];
4808 ICALL_EXPORT MonoReflectionMethod*
4809 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4813 klass = mono_class_from_mono_type (type);
4814 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4816 if (method->klass != klass) {
4817 method = mono_method_get_equivalent_method (method, klass);
4822 klass = method->klass;
4823 return mono_method_get_object (mono_domain_get (), method, klass);
4826 ICALL_EXPORT MonoReflectionMethod*
4827 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4829 return mono_method_get_object (mono_domain_get (), method, NULL);
4832 ICALL_EXPORT MonoReflectionMethodBody*
4833 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4835 return mono_method_body_get_object (mono_domain_get (), method);
4838 ICALL_EXPORT MonoReflectionAssembly*
4839 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4841 MonoMethod *dest = NULL;
4843 MONO_ARCH_SAVE_REGS;
4845 mono_stack_walk_no_il (get_executing, &dest);
4847 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4851 ICALL_EXPORT MonoReflectionAssembly*
4852 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4854 MonoDomain* domain = mono_domain_get ();
4856 MONO_ARCH_SAVE_REGS;
4858 if (!domain->entry_assembly)
4861 return mono_assembly_get_object (domain, domain->entry_assembly);
4864 ICALL_EXPORT MonoReflectionAssembly*
4865 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4870 MONO_ARCH_SAVE_REGS;
4873 mono_stack_walk_no_il (get_executing, &dest);
4875 mono_stack_walk_no_il (get_caller, &dest);
4878 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4881 ICALL_EXPORT MonoString *
4882 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4883 gboolean assembly_qualified)
4885 MonoDomain *domain = mono_object_domain (object);
4886 MonoTypeNameFormat format;
4891 format = assembly_qualified ?
4892 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4893 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4895 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4897 name = mono_type_get_name_full (object->type, format);
4901 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4906 res = mono_string_new (domain, name);
4913 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4915 MonoClass *klass = mono_class_from_mono_type (this->type);
4916 mono_class_init_or_throw (klass);
4917 return mono_security_core_clr_class_level (klass);
4921 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4923 static MonoMethod *create_culture = NULL;
4926 const char *pkey_ptr;
4928 MonoBoolean assembly_ref = 0;
4930 MONO_ARCH_SAVE_REGS;
4932 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4933 aname->major = name->major;
4934 aname->minor = name->minor;
4935 aname->build = name->build;
4936 aname->flags = name->flags;
4937 aname->revision = name->revision;
4938 aname->hashalg = name->hash_alg;
4939 aname->versioncompat = 1; /* SameMachine (default) */
4940 aname->processor_architecture = name->arch;
4942 if (by_default_version)
4943 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4946 if (absolute != NULL && *absolute != '\0') {
4947 const gchar *prepend = "file://";
4950 codebase = g_strdup (absolute);
4955 for (i = strlen (codebase) - 1; i >= 0; i--)
4956 if (codebase [i] == '\\')
4959 if (*codebase == '/' && *(codebase + 1) == '/') {
4962 prepend = "file:///";
4966 result = g_strconcat (prepend, codebase, NULL);
4972 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4976 if (!create_culture) {
4977 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4978 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4979 g_assert (create_culture);
4980 mono_method_desc_free (desc);
4983 if (name->culture) {
4984 args [0] = mono_string_new (domain, name->culture);
4985 args [1] = &assembly_ref;
4986 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4989 if (name->public_key) {
4990 pkey_ptr = (char*)name->public_key;
4991 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4993 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4994 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4995 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4996 } else if (default_publickey) {
4997 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4998 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5001 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5002 if (name->public_key_token [0]) {
5006 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5007 p = mono_array_addr (aname->keyToken, char, 0);
5009 for (i = 0, j = 0; i < 8; i++) {
5010 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5011 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5014 } else if (default_token) {
5015 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5019 ICALL_EXPORT MonoString *
5020 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5022 MonoDomain *domain = mono_object_domain (assembly);
5023 MonoAssembly *mass = assembly->assembly;
5027 name = mono_stringify_assembly_name (&mass->aname);
5028 res = mono_string_new (domain, name);
5035 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5038 MonoAssembly *mass = assembly->assembly;
5040 MONO_ARCH_SAVE_REGS;
5042 if (g_path_is_absolute (mass->image->name)) {
5043 fill_reflection_assembly_name (mono_object_domain (assembly),
5044 aname, &mass->aname, mass->image->name, TRUE,
5048 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5050 fill_reflection_assembly_name (mono_object_domain (assembly),
5051 aname, &mass->aname, absolute, TRUE, TRUE,
5058 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5061 MonoImageOpenStatus status = MONO_IMAGE_OK;
5064 MonoAssemblyName name;
5067 MONO_ARCH_SAVE_REGS;
5069 filename = mono_string_to_utf8 (fname);
5071 dirname = g_path_get_dirname (filename);
5072 replace_shadow_path (mono_domain_get (), dirname, &filename);
5075 image = mono_image_open (filename, &status);
5081 if (status == MONO_IMAGE_IMAGE_INVALID)
5082 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5084 exc = mono_get_exception_file_not_found2 (NULL, fname);
5085 mono_raise_exception (exc);
5088 res = mono_assembly_fill_assembly_name (image, &name);
5090 mono_image_close (image);
5092 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5095 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5099 mono_image_close (image);
5102 ICALL_EXPORT MonoBoolean
5103 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5104 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5106 MonoBoolean result = FALSE;
5107 MonoDeclSecurityEntry entry;
5109 /* SecurityAction.RequestMinimum */
5110 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5111 *minimum = entry.blob;
5112 *minLength = entry.size;
5115 /* SecurityAction.RequestOptional */
5116 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5117 *optional = entry.blob;
5118 *optLength = entry.size;
5121 /* SecurityAction.RequestRefuse */
5122 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5123 *refused = entry.blob;
5124 *refLength = entry.size;
5132 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5136 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5138 guint32 attrs, visibility;
5140 /* we start the count from 1 because we skip the special type <Module> */
5143 for (i = 1; i < tdef->rows; ++i) {
5144 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5145 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5146 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5150 count = tdef->rows - 1;
5152 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5153 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5155 for (i = 1; i < tdef->rows; ++i) {
5156 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5157 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5158 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5159 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5161 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5163 MonoLoaderError *error;
5166 error = mono_loader_get_last_error ();
5167 g_assert (error != NULL);
5169 ex = mono_loader_error_prepare_exception (error);
5170 mono_array_setref (*exceptions, count, ex);
5172 if (mono_loader_get_last_error ())
5173 mono_loader_clear_error ();
5181 ICALL_EXPORT MonoArray*
5182 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5184 MonoArray *res = NULL;
5185 MonoArray *exceptions = NULL;
5186 MonoImage *image = NULL;
5187 MonoTableInfo *table = NULL;
5190 int i, len, ex_count;
5192 MONO_ARCH_SAVE_REGS;
5194 domain = mono_object_domain (assembly);
5196 g_assert (!assembly->assembly->dynamic);
5197 image = assembly->assembly->image;
5198 table = &image->tables [MONO_TABLE_FILE];
5199 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5201 /* Append data from all modules in the assembly */
5202 for (i = 0; i < table->rows; ++i) {
5203 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5204 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5207 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5208 /* Append the new types to the end of the array */
5209 if (mono_array_length (res2) > 0) {
5211 MonoArray *res3, *ex3;
5213 len1 = mono_array_length (res);
5214 len2 = mono_array_length (res2);
5216 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5217 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5218 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5221 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5222 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5223 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5230 /* the ReflectionTypeLoadException must have all the types (Types property),
5231 * NULL replacing types which throws an exception. The LoaderException must
5232 * contain all exceptions for NULL items.
5235 len = mono_array_length (res);
5238 for (i = 0; i < len; i++) {
5239 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5243 klass = mono_type_get_class (t->type);
5244 if ((klass != NULL) && klass->exception_type) {
5245 /* keep the class in the list */
5246 list = g_list_append (list, klass);
5247 /* and replace Type with NULL */
5248 mono_array_setref (res, i, NULL);
5255 if (list || ex_count) {
5257 MonoException *exc = NULL;
5258 MonoArray *exl = NULL;
5259 int j, length = g_list_length (list) + ex_count;
5261 mono_loader_clear_error ();
5263 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5264 /* Types for which mono_class_get () succeeded */
5265 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5266 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5267 mono_array_setref (exl, i, exc);
5269 /* Types for which it don't */
5270 for (j = 0; j < mono_array_length (exceptions); ++j) {
5271 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5273 g_assert (i < length);
5274 mono_array_setref (exl, i, exc);
5281 exc = mono_get_exception_reflection_type_load (res, exl);
5282 mono_loader_clear_error ();
5283 mono_raise_exception (exc);
5289 ICALL_EXPORT gboolean
5290 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5292 MonoAssemblyName aname;
5293 MonoDomain *domain = mono_object_domain (name);
5295 gboolean is_version_defined;
5296 gboolean is_token_defined;
5298 aname.public_key = NULL;
5299 val = mono_string_to_utf8 (assname);
5300 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5301 g_free ((guint8*) aname.public_key);
5306 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5307 FALSE, is_token_defined);
5309 mono_assembly_name_free (&aname);
5310 g_free ((guint8*) aname.public_key);
5316 ICALL_EXPORT MonoReflectionType*
5317 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5319 MonoDomain *domain = mono_object_domain (module);
5322 MONO_ARCH_SAVE_REGS;
5324 g_assert (module->image);
5326 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5327 /* These images do not have a global type */
5330 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5331 return mono_type_get_object (domain, &klass->byval_arg);
5335 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5337 /*if (module->image)
5338 mono_image_close (module->image);*/
5341 ICALL_EXPORT MonoString*
5342 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5344 MonoDomain *domain = mono_object_domain (module);
5346 MONO_ARCH_SAVE_REGS;
5348 g_assert (module->image);
5349 return mono_string_new (domain, module->image->guid);
5352 ICALL_EXPORT gpointer
5353 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5356 if (module->image && module->image->is_module_handle)
5357 return module->image->raw_data;
5360 return (gpointer) (-1);
5364 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5366 if (image->dynamic) {
5367 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5368 *pe_kind = dyn->pe_kind;
5369 *machine = dyn->machine;
5372 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5373 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5378 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5380 return (image->md_version_major << 16) | (image->md_version_minor);
5383 ICALL_EXPORT MonoArray*
5384 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5386 MonoArray *exceptions;
5389 MONO_ARCH_SAVE_REGS;
5392 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5394 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5395 for (i = 0; i < mono_array_length (exceptions); ++i) {
5396 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5398 mono_raise_exception (ex);
5405 mono_memberref_is_method (MonoImage *image, guint32 token)
5407 if (!image->dynamic) {
5408 guint32 cols [MONO_MEMBERREF_SIZE];
5410 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5411 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5412 mono_metadata_decode_blob_size (sig, &sig);
5413 return (*sig != 0x6);
5415 MonoClass *handle_class;
5417 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5420 return mono_defaults.methodhandle_class == handle_class;
5425 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5428 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5429 mono_array_addr (type_args, MonoType*, 0));
5431 context->class_inst = NULL;
5433 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5434 mono_array_addr (method_args, MonoType*, 0));
5436 context->method_inst = NULL;
5439 ICALL_EXPORT MonoType*
5440 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5443 int table = mono_metadata_token_table (token);
5444 int index = mono_metadata_token_index (token);
5445 MonoGenericContext context;
5447 *error = ResolveTokenError_Other;
5449 /* Validate token */
5450 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5451 (table != MONO_TABLE_TYPESPEC)) {
5452 *error = ResolveTokenError_BadTable;
5456 if (image->dynamic) {
5457 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5458 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5459 return klass ? &klass->byval_arg : NULL;
5462 init_generic_context_from_args (&context, type_args, method_args);
5463 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5464 return klass ? &klass->byval_arg : NULL;
5467 if ((index <= 0) || (index > image->tables [table].rows)) {
5468 *error = ResolveTokenError_OutOfRange;
5472 init_generic_context_from_args (&context, type_args, method_args);
5473 klass = mono_class_get_full (image, token, &context);
5475 if (mono_loader_get_last_error ())
5476 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5479 return &klass->byval_arg;
5484 ICALL_EXPORT MonoMethod*
5485 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5487 int table = mono_metadata_token_table (token);
5488 int index = mono_metadata_token_index (token);
5489 MonoGenericContext context;
5492 *error = ResolveTokenError_Other;
5494 /* Validate token */
5495 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5496 (table != MONO_TABLE_MEMBERREF)) {
5497 *error = ResolveTokenError_BadTable;
5501 if (image->dynamic) {
5502 if (table == MONO_TABLE_METHOD)
5503 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5505 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5506 *error = ResolveTokenError_BadTable;
5510 init_generic_context_from_args (&context, type_args, method_args);
5511 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5514 if ((index <= 0) || (index > image->tables [table].rows)) {
5515 *error = ResolveTokenError_OutOfRange;
5518 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5519 *error = ResolveTokenError_BadTable;
5523 init_generic_context_from_args (&context, type_args, method_args);
5524 method = mono_get_method_full (image, token, NULL, &context);
5526 if (mono_loader_get_last_error ())
5527 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5532 ICALL_EXPORT MonoString*
5533 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5535 int index = mono_metadata_token_index (token);
5537 *error = ResolveTokenError_Other;
5539 /* Validate token */
5540 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5541 *error = ResolveTokenError_BadTable;
5546 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5548 if ((index <= 0) || (index >= image->heap_us.size)) {
5549 *error = ResolveTokenError_OutOfRange;
5553 /* FIXME: What to do if the index points into the middle of a string ? */
5555 return mono_ldstr (mono_domain_get (), image, index);
5558 ICALL_EXPORT MonoClassField*
5559 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5562 int table = mono_metadata_token_table (token);
5563 int index = mono_metadata_token_index (token);
5564 MonoGenericContext context;
5565 MonoClassField *field;
5567 *error = ResolveTokenError_Other;
5569 /* Validate token */
5570 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5571 *error = ResolveTokenError_BadTable;
5575 if (image->dynamic) {
5576 if (table == MONO_TABLE_FIELD)
5577 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5579 if (mono_memberref_is_method (image, token)) {
5580 *error = ResolveTokenError_BadTable;
5584 init_generic_context_from_args (&context, type_args, method_args);
5585 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5588 if ((index <= 0) || (index > image->tables [table].rows)) {
5589 *error = ResolveTokenError_OutOfRange;
5592 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5593 *error = ResolveTokenError_BadTable;
5597 init_generic_context_from_args (&context, type_args, method_args);
5598 field = mono_field_from_token (image, token, &klass, &context);
5600 if (mono_loader_get_last_error ())
5601 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5607 ICALL_EXPORT MonoObject*
5608 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5610 int table = mono_metadata_token_table (token);
5612 *error = ResolveTokenError_Other;
5615 case MONO_TABLE_TYPEDEF:
5616 case MONO_TABLE_TYPEREF:
5617 case MONO_TABLE_TYPESPEC: {
5618 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5620 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5624 case MONO_TABLE_METHOD:
5625 case MONO_TABLE_METHODSPEC: {
5626 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5628 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5632 case MONO_TABLE_FIELD: {
5633 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5635 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5639 case MONO_TABLE_MEMBERREF:
5640 if (mono_memberref_is_method (image, token)) {
5641 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5643 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5648 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5650 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5657 *error = ResolveTokenError_BadTable;
5663 ICALL_EXPORT MonoArray*
5664 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5666 int table = mono_metadata_token_table (token);
5667 int idx = mono_metadata_token_index (token);
5668 MonoTableInfo *tables = image->tables;
5673 *error = ResolveTokenError_OutOfRange;
5675 /* FIXME: Support other tables ? */
5676 if (table != MONO_TABLE_STANDALONESIG)
5682 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5685 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5687 ptr = mono_metadata_blob_heap (image, sig);
5688 len = mono_metadata_decode_blob_size (ptr, &ptr);
5690 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5691 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5695 ICALL_EXPORT MonoReflectionType*
5696 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5699 int isbyref = 0, rank;
5700 char *str = mono_string_to_utf8 (smodifiers);
5703 MONO_ARCH_SAVE_REGS;
5705 klass = mono_class_from_mono_type (tb->type.type);
5707 /* logic taken from mono_reflection_parse_type(): keep in sync */
5711 if (isbyref) { /* only one level allowed by the spec */
5718 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5721 klass = mono_ptr_class_get (&klass->byval_arg);
5722 mono_class_init (klass);
5733 else if (*p != '*') { /* '*' means unknown lower bound */
5744 klass = mono_array_class_get (klass, rank);
5745 mono_class_init (klass);
5752 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5755 ICALL_EXPORT MonoBoolean
5756 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5761 MONO_ARCH_SAVE_REGS;
5764 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5770 check_for_invalid_type (MonoClass *klass)
5774 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5777 name = mono_type_get_full_name (klass);
5778 str = mono_string_new (mono_domain_get (), name);
5780 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5783 ICALL_EXPORT MonoReflectionType *
5784 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5786 MonoClass *klass, *aklass;
5788 MONO_ARCH_SAVE_REGS;
5790 klass = mono_class_from_mono_type (type->type);
5791 check_for_invalid_type (klass);
5793 if (rank == 0) //single dimentional array
5794 aklass = mono_array_class_get (klass, 1);
5796 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5798 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5801 ICALL_EXPORT MonoReflectionType *
5802 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5806 MONO_ARCH_SAVE_REGS;
5808 klass = mono_class_from_mono_type (type->type);
5809 mono_class_init_or_throw (klass);
5810 check_for_invalid_type (klass);
5812 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5815 ICALL_EXPORT MonoReflectionType *
5816 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5818 MonoClass *klass, *pklass;
5820 klass = mono_class_from_mono_type (type->type);
5821 mono_class_init_or_throw (klass);
5822 check_for_invalid_type (klass);
5824 pklass = mono_ptr_class_get (type->type);
5826 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5829 ICALL_EXPORT MonoObject *
5830 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5831 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5833 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5834 MonoObject *delegate;
5836 MonoMethod *method = info->method;
5838 MONO_ARCH_SAVE_REGS;
5840 mono_class_init_or_throw (delegate_class);
5842 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5844 if (mono_security_core_clr_enabled ()) {
5845 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5849 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5851 if (method->dynamic) {
5852 /* Creating a trampoline would leak memory */
5853 func = mono_compile_method (method);
5855 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5856 method = mono_object_get_virtual_method (target, method);
5857 func = mono_create_ftnptr (mono_domain_get (),
5858 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5861 mono_delegate_ctor_with_method (delegate, target, func, method);
5867 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5869 /* Reset the invoke impl to the default one */
5870 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5874 * Magic number to convert a time which is relative to
5875 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5877 #define EPOCH_ADJUST ((guint64)62135596800LL)
5880 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5882 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5885 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5887 convert_to_absolute_date(SYSTEMTIME *date)
5889 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5890 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5891 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5892 /* from the calendar FAQ */
5893 int a = (14 - date->wMonth) / 12;
5894 int y = date->wYear - a;
5895 int m = date->wMonth + 12 * a - 2;
5896 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5898 /* d is now the day of the week for the first of the month (0 == Sunday) */
5900 int day_of_week = date->wDayOfWeek;
5902 /* set day_in_month to the first day in the month which falls on day_of_week */
5903 int day_in_month = 1 + (day_of_week - d);
5904 if (day_in_month <= 0)
5907 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5908 date->wDay = day_in_month + (date->wDay - 1) * 7;
5909 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5916 * Return's the offset from GMT of a local time.
5918 * tm is a local time
5919 * t is the same local time as seconds.
5922 gmt_offset(struct tm *tm, time_t t)
5924 #if defined (HAVE_TM_GMTOFF)
5925 return tm->tm_gmtoff;
5930 g.tm_isdst = tm->tm_isdst;
5932 return (int)difftime(t, t2);
5937 * This is heavily based on zdump.c from glibc 2.2.
5939 * * data[0]: start of daylight saving time (in DateTime ticks).
5940 * * data[1]: end of daylight saving time (in DateTime ticks).
5941 * * data[2]: utcoffset (in TimeSpan ticks).
5942 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5943 * * name[0]: name of this timezone when not daylight saving.
5944 * * name[1]: name of this timezone when daylight saving.
5946 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5947 * the class library allows years between 1 and 9999.
5949 * Returns true on success and zero on failure.
5951 ICALL_EXPORT guint32
5952 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5955 MonoDomain *domain = mono_domain_get ();
5956 struct tm start, tt;
5959 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5960 int day, transitioned;
5963 gmtoff_st = gmtoff_ds = transitioned = 0;
5965 MONO_ARCH_SAVE_REGS;
5967 MONO_CHECK_ARG_NULL (data);
5968 MONO_CHECK_ARG_NULL (names);
5970 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5971 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5974 * no info is better than crashing: we'll need our own tz data
5975 * to make this work properly, anyway. The range is probably
5976 * reduced to 1970 .. 2037 because that is what mktime is
5977 * guaranteed to support (we get into an infinite loop
5981 memset (&start, 0, sizeof (start));
5984 start.tm_year = year-1900;
5986 t = mktime (&start);
5988 if ((year < 1970) || (year > 2037) || (t == -1)) {
5990 tt = *localtime (&t);
5991 strftime (tzone, sizeof (tzone), "%Z", &tt);
5992 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5993 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5997 gmtoff = gmt_offset (&start, t);
5999 /* For each day of the year, calculate the tm_gmtoff. */
6000 for (day = 0; day < 365 && transitioned < 2; day++) {
6003 tt = *localtime (&t);
6005 gmtoff_after = gmt_offset(&tt, t);
6007 /* Daylight saving starts or ends here. */
6008 if (gmtoff_after != gmtoff) {
6012 /* Try to find the exact hour when daylight saving starts/ends. */
6016 tt1 = *localtime (&t1);
6017 } while (gmt_offset (&tt1, t1) != gmtoff);
6019 /* Try to find the exact minute when daylight saving starts/ends. */
6022 tt1 = *localtime (&t1);
6023 } while (gmt_offset (&tt1, t1) == gmtoff);
6025 strftime (tzone, sizeof (tzone), "%Z", &tt);
6027 /* Write data, if we're already in daylight saving, we're done. */
6029 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6030 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6031 if (gmtoff_ds == 0) {
6033 gmtoff_ds = gmtoff_after;
6040 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6041 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6042 if (gmtoff_ds == 0) {
6043 gmtoff_st = gmtoff_after;
6049 /* This is only set once when we enter daylight saving. */
6051 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6052 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6054 gmtoff = gmt_offset (&tt, t);
6058 if (transitioned < 2) {
6059 strftime (tzone, sizeof (tzone), "%Z", &tt);
6060 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6061 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6062 mono_array_set ((*data), gint64, 0, 0);
6063 mono_array_set ((*data), gint64, 1, 0);
6064 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6065 mono_array_set ((*data), gint64, 3, 0);
6070 MonoDomain *domain = mono_domain_get ();
6071 TIME_ZONE_INFORMATION tz_info;
6076 tz_id = GetTimeZoneInformation (&tz_info);
6077 if (tz_id == TIME_ZONE_ID_INVALID)
6080 MONO_CHECK_ARG_NULL (data);
6081 MONO_CHECK_ARG_NULL (names);
6083 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6084 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6086 for (i = 0; i < 32; ++i)
6087 if (!tz_info.DaylightName [i])
6089 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6090 for (i = 0; i < 32; ++i)
6091 if (!tz_info.StandardName [i])
6093 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6095 if ((year <= 1601) || (year > 30827)) {
6097 * According to MSDN, the MS time functions can't handle dates outside
6103 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6104 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6105 tz_info.StandardDate.wYear = year;
6106 convert_to_absolute_date(&tz_info.StandardDate);
6107 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6112 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6113 tz_info.DaylightDate.wYear = year;
6114 convert_to_absolute_date(&tz_info.DaylightDate);
6115 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6120 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6122 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6123 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6131 static inline gint32
6132 mono_array_get_byte_length (MonoArray *array)
6138 klass = array->obj.vtable->klass;
6140 if (array->bounds == NULL)
6141 length = array->max_length;
6144 for (i = 0; i < klass->rank; ++ i)
6145 length *= array->bounds [i].length;
6148 switch (klass->element_class->byval_arg.type) {
6151 case MONO_TYPE_BOOLEAN:
6155 case MONO_TYPE_CHAR:
6163 return length * sizeof (gpointer);
6174 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6176 MONO_ARCH_SAVE_REGS;
6178 return mono_array_get_byte_length (array);
6182 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6184 MONO_ARCH_SAVE_REGS;
6186 return mono_array_get (array, gint8, idx);
6190 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6192 MONO_ARCH_SAVE_REGS;
6194 mono_array_set (array, gint8, idx, value);
6197 ICALL_EXPORT MonoBoolean
6198 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6200 guint8 *src_buf, *dest_buf;
6202 MONO_ARCH_SAVE_REGS;
6204 /* This is called directly from the class libraries without going through the managed wrapper */
6205 MONO_CHECK_ARG_NULL (src);
6206 MONO_CHECK_ARG_NULL (dest);
6208 /* watch out for integer overflow */
6209 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6212 src_buf = (guint8 *)src->vector + src_offset;
6213 dest_buf = (guint8 *)dest->vector + dest_offset;
6216 memcpy (dest_buf, src_buf, count);
6218 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6223 #ifndef DISABLE_REMOTING
6224 ICALL_EXPORT MonoObject *
6225 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6227 MonoDomain *domain = mono_object_domain (this);
6229 MonoRealProxy *rp = ((MonoRealProxy *)this);
6230 MonoTransparentProxy *tp;
6234 MONO_ARCH_SAVE_REGS;
6236 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6237 tp = (MonoTransparentProxy*) res;
6239 MONO_OBJECT_SETREF (tp, rp, rp);
6240 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6241 klass = mono_class_from_mono_type (type);
6243 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6244 tp->remote_class = mono_remote_class (domain, class_name, klass);
6246 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6250 ICALL_EXPORT MonoReflectionType *
6251 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6253 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6257 /* System.Environment */
6260 ves_icall_System_Environment_get_UserName (void)
6262 MONO_ARCH_SAVE_REGS;
6264 /* using glib is more portable */
6265 return mono_string_new (mono_domain_get (), g_get_user_name ());
6269 ICALL_EXPORT MonoString *
6270 ves_icall_System_Environment_get_MachineName (void)
6272 #if defined (HOST_WIN32)
6277 len = MAX_COMPUTERNAME_LENGTH + 1;
6278 buf = g_new (gunichar2, len);
6281 if (GetComputerName (buf, (PDWORD) &len))
6282 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6286 #elif !defined(DISABLE_SOCKETS)
6290 if (gethostname (buf, sizeof (buf)) == 0)
6291 result = mono_string_new (mono_domain_get (), buf);
6297 return mono_string_new (mono_domain_get (), "mono");
6302 ves_icall_System_Environment_get_Platform (void)
6304 #if defined (TARGET_WIN32)
6307 #elif defined(__MACH__)
6310 // Notice that the value is hidden from user code, and only exposed
6311 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6312 // define and making assumptions based on Unix/128/4 values before there
6313 // was a MacOS define. Lots of code would assume that not-Unix meant
6314 // Windows, but in this case, it would be OSX.
6323 ICALL_EXPORT MonoString *
6324 ves_icall_System_Environment_get_NewLine (void)
6326 MONO_ARCH_SAVE_REGS;
6328 #if defined (HOST_WIN32)
6329 return mono_string_new (mono_domain_get (), "\r\n");
6331 return mono_string_new (mono_domain_get (), "\n");
6335 ICALL_EXPORT MonoString *
6336 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6341 MONO_ARCH_SAVE_REGS;
6346 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6347 value = g_getenv (utf8_name);
6354 return mono_string_new (mono_domain_get (), value);
6358 * There is no standard way to get at environ.
6361 #ifndef __MINGW32_VERSION
6362 #if defined(__APPLE__) && !defined (__arm__)
6363 /* Apple defines this in crt_externs.h but doesn't provide that header for
6364 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6365 * in fact exist on all implementations (so far)
6367 gchar ***_NSGetEnviron(void);
6368 #define environ (*_NSGetEnviron())
6376 ICALL_EXPORT MonoArray *
6377 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6388 env_strings = GetEnvironmentStrings();
6391 env_string = env_strings;
6392 while (*env_string != '\0') {
6393 /* weird case that MS seems to skip */
6394 if (*env_string != '=')
6396 while (*env_string != '\0')
6402 domain = mono_domain_get ();
6403 names = mono_array_new (domain, mono_defaults.string_class, n);
6407 env_string = env_strings;
6408 while (*env_string != '\0') {
6409 /* weird case that MS seems to skip */
6410 if (*env_string != '=') {
6411 equal_str = wcschr(env_string, '=');
6412 g_assert(equal_str);
6413 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6414 mono_array_setref (names, n, str);
6417 while (*env_string != '\0')
6422 FreeEnvironmentStrings (env_strings);
6434 MONO_ARCH_SAVE_REGS;
6437 for (e = environ; *e != 0; ++ e)
6440 domain = mono_domain_get ();
6441 names = mono_array_new (domain, mono_defaults.string_class, n);
6444 for (e = environ; *e != 0; ++ e) {
6445 parts = g_strsplit (*e, "=", 2);
6447 str = mono_string_new (domain, *parts);
6448 mono_array_setref (names, n, str);
6461 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6463 #if !GLIB_CHECK_VERSION(2,4,0)
6464 #define g_setenv(a,b,c) setenv(a,b,c)
6465 #define g_unsetenv(a) unsetenv(a)
6469 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6474 gunichar2 *utf16_name, *utf16_value;
6476 gchar *utf8_name, *utf8_value;
6479 MONO_ARCH_SAVE_REGS;
6482 utf16_name = mono_string_to_utf16 (name);
6483 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6484 SetEnvironmentVariable (utf16_name, NULL);
6485 g_free (utf16_name);
6489 utf16_value = mono_string_to_utf16 (value);
6491 SetEnvironmentVariable (utf16_name, utf16_value);
6493 g_free (utf16_name);
6494 g_free (utf16_value);
6496 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6498 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6499 g_unsetenv (utf8_name);
6504 utf8_value = mono_string_to_utf8_checked (value, &error);
6505 if (!mono_error_ok (&error)) {
6507 mono_error_raise_exception (&error);
6509 g_setenv (utf8_name, utf8_value, TRUE);
6512 g_free (utf8_value);
6517 ves_icall_System_Environment_Exit (int result)
6519 MONO_ARCH_SAVE_REGS;
6521 mono_environment_exitcode_set (result);
6523 /* FIXME: There are some cleanup hangs that should be worked out, but
6524 * if the program is going to exit, everything will be cleaned up when
6525 * NaCl exits anyway.
6527 #ifndef __native_client__
6528 if (!mono_runtime_try_shutdown ())
6529 mono_thread_exit ();
6531 /* Suspend all managed threads since the runtime is going away */
6532 mono_thread_suspend_all_other_threads ();
6534 mono_runtime_quit ();
6537 /* we may need to do some cleanup here... */
6541 ICALL_EXPORT MonoString*
6542 ves_icall_System_Environment_GetGacPath (void)
6544 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6547 ICALL_EXPORT MonoString*
6548 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6550 #if defined (HOST_WIN32)
6551 #ifndef CSIDL_FLAG_CREATE
6552 #define CSIDL_FLAG_CREATE 0x8000
6555 WCHAR path [MAX_PATH];
6556 /* Create directory if no existing */
6557 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6561 return mono_string_new_utf16 (mono_domain_get (), path, len);
6564 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6566 return mono_string_new (mono_domain_get (), "");
6569 ICALL_EXPORT MonoArray *
6570 ves_icall_System_Environment_GetLogicalDrives (void)
6572 gunichar2 buf [256], *ptr, *dname;
6574 guint initial_size = 127, size = 128;
6577 MonoString *drivestr;
6578 MonoDomain *domain = mono_domain_get ();
6581 MONO_ARCH_SAVE_REGS;
6586 while (size > initial_size) {
6587 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6588 if (size > initial_size) {
6591 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6592 initial_size = size;
6606 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6611 while (*u16) { u16++; len ++; }
6612 drivestr = mono_string_new_utf16 (domain, dname, len);
6613 mono_array_setref (result, ndrives++, drivestr);
6623 ICALL_EXPORT MonoString *
6624 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6626 gunichar2 volume_name [MAX_PATH + 1];
6628 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6630 return mono_string_from_utf16 (volume_name);
6633 ICALL_EXPORT MonoString *
6634 ves_icall_System_Environment_InternalGetHome (void)
6636 MONO_ARCH_SAVE_REGS;
6638 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6641 static const char *encodings [] = {
6643 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6644 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6645 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6647 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6648 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6649 "x_unicode_2_0_utf_7",
6651 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6652 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6654 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6657 "unicodefffe", "utf_16be",
6664 * Returns the internal codepage, if the value of "int_code_page" is
6665 * 1 at entry, and we can not compute a suitable code page number,
6666 * returns the code page as a string
6668 ICALL_EXPORT MonoString*
6669 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6674 char *codepage = NULL;
6676 int want_name = *int_code_page;
6679 *int_code_page = -1;
6680 MONO_ARCH_SAVE_REGS;
6682 g_get_charset (&cset);
6683 c = codepage = strdup (cset);
6684 for (c = codepage; *c; c++){
6685 if (isascii (*c) && isalpha (*c))
6690 /* g_print ("charset: %s\n", cset); */
6692 /* handle some common aliases */
6695 for (i = 0; p != 0; ){
6696 if ((gssize) p < 7){
6698 p = encodings [++i];
6701 if (strcmp (p, codepage) == 0){
6702 *int_code_page = code;
6705 p = encodings [++i];
6708 if (strstr (codepage, "utf_8") != NULL)
6709 *int_code_page |= 0x10000000;
6712 if (want_name && *int_code_page == -1)
6713 return mono_string_new (mono_domain_get (), cset);
6718 ICALL_EXPORT MonoBoolean
6719 ves_icall_System_Environment_get_HasShutdownStarted (void)
6721 if (mono_runtime_is_shutting_down ())
6724 if (mono_domain_is_unloading (mono_domain_get ()))
6731 ves_icall_System_Environment_BroadcastSettingChange (void)
6734 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6739 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6740 MonoReflectionMethod *method,
6741 MonoArray *out_args)
6743 MONO_ARCH_SAVE_REGS;
6745 mono_message_init (mono_object_domain (this), this, method, out_args);
6748 #ifndef DISABLE_REMOTING
6749 ICALL_EXPORT MonoBoolean
6750 ves_icall_IsTransparentProxy (MonoObject *proxy)
6752 MONO_ARCH_SAVE_REGS;
6757 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6763 ICALL_EXPORT MonoReflectionMethod *
6764 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6765 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6769 MonoMethod **vtable;
6770 MonoMethod *res = NULL;
6772 MONO_CHECK_ARG_NULL (rtype);
6773 MONO_CHECK_ARG_NULL (rmethod);
6775 method = rmethod->method;
6776 klass = mono_class_from_mono_type (rtype->type);
6777 mono_class_init_or_throw (klass);
6779 if (MONO_CLASS_IS_INTERFACE (klass))
6782 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6785 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6786 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6792 mono_class_setup_vtable (klass);
6793 vtable = klass->vtable;
6795 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6796 gboolean variance_used = FALSE;
6797 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6798 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6800 res = vtable [offs + method->slot];
6802 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6805 if (method->slot != -1)
6806 res = vtable [method->slot];
6812 return mono_method_get_object (mono_domain_get (), res, NULL);
6816 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6821 MONO_ARCH_SAVE_REGS;
6823 klass = mono_class_from_mono_type (type->type);
6824 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6826 mono_vtable_set_is_remote (vtable, enable);
6829 #else /* DISABLE_REMOTING */
6832 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6834 g_assert_not_reached ();
6839 ICALL_EXPORT MonoObject *
6840 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6845 MONO_ARCH_SAVE_REGS;
6847 domain = mono_object_domain (type);
6848 klass = mono_class_from_mono_type (type->type);
6849 mono_class_init_or_throw (klass);
6851 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6852 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6854 if (klass->rank >= 1) {
6855 g_assert (klass->rank == 1);
6856 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6858 /* Bypass remoting object creation check */
6859 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6863 ICALL_EXPORT MonoString *
6864 ves_icall_System_IO_get_temp_path (void)
6866 MONO_ARCH_SAVE_REGS;
6868 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6871 #ifndef PLATFORM_NO_DRIVEINFO
6872 ICALL_EXPORT MonoBoolean
6873 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6874 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6878 ULARGE_INTEGER wapi_free_bytes_avail;
6879 ULARGE_INTEGER wapi_total_number_of_bytes;
6880 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6882 MONO_ARCH_SAVE_REGS;
6884 *error = ERROR_SUCCESS;
6885 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6886 &wapi_total_number_of_free_bytes);
6889 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6890 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6891 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6893 *free_bytes_avail = 0;
6894 *total_number_of_bytes = 0;
6895 *total_number_of_free_bytes = 0;
6896 *error = GetLastError ();
6902 ICALL_EXPORT guint32
6903 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6905 MONO_ARCH_SAVE_REGS;
6907 return GetDriveType (mono_string_chars (root_path_name));
6911 ICALL_EXPORT gpointer
6912 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6914 MONO_ARCH_SAVE_REGS;
6916 return mono_compile_method (method);
6919 ICALL_EXPORT MonoString *
6920 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6925 MONO_ARCH_SAVE_REGS;
6927 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6929 #if defined (HOST_WIN32)
6930 /* Avoid mixing '/' and '\\' */
6933 for (i = strlen (path) - 1; i >= 0; i--)
6934 if (path [i] == '/')
6938 mcpath = mono_string_new (mono_domain_get (), path);
6945 get_bundled_app_config (void)
6947 const gchar *app_config;
6950 gchar *config_file_name, *config_file_path;
6954 MONO_ARCH_SAVE_REGS;
6956 domain = mono_domain_get ();
6957 file = domain->setup->configuration_file;
6961 // Retrieve config file and remove the extension
6962 config_file_name = mono_string_to_utf8 (file);
6963 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6964 if (!config_file_path)
6965 config_file_path = config_file_name;
6966 len = strlen (config_file_path) - strlen (".config");
6967 module = g_malloc0 (len + 1);
6968 memcpy (module, config_file_path, len);
6969 // Get the config file from the module name
6970 app_config = mono_config_string_for_assembly_file (module);
6973 if (config_file_name != config_file_path)
6974 g_free (config_file_name);
6975 g_free (config_file_path);
6980 return mono_string_new (mono_domain_get (), app_config);
6984 get_bundled_machine_config (void)
6986 const gchar *machine_config;
6988 MONO_ARCH_SAVE_REGS;
6990 machine_config = mono_get_machine_config ();
6992 if (!machine_config)
6995 return mono_string_new (mono_domain_get (), machine_config);
6998 ICALL_EXPORT MonoString *
6999 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7004 MONO_ARCH_SAVE_REGS;
7006 path = g_path_get_dirname (mono_get_config_dir ());
7008 #if defined (HOST_WIN32)
7009 /* Avoid mixing '/' and '\\' */
7012 for (i = strlen (path) - 1; i >= 0; i--)
7013 if (path [i] == '/')
7017 ipath = mono_string_new (mono_domain_get (), path);
7023 ICALL_EXPORT gboolean
7024 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7026 MonoPEResourceDataEntry *entry;
7029 MONO_ARCH_SAVE_REGS;
7031 if (!assembly || !result || !size)
7036 image = assembly->assembly->image;
7037 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7041 *result = mono_image_rva_map (image, entry->rde_data_offset);
7046 *size = entry->rde_size;
7051 ICALL_EXPORT MonoBoolean
7052 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7054 return mono_is_debugger_attached ();
7057 ICALL_EXPORT MonoBoolean
7058 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7060 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7061 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7067 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7069 if (mono_get_runtime_callbacks ()->debug_log)
7070 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7074 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7076 #if defined (HOST_WIN32)
7077 OutputDebugString (mono_string_chars (message));
7079 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7083 /* Only used for value types */
7084 ICALL_EXPORT MonoObject *
7085 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7090 MONO_ARCH_SAVE_REGS;
7092 domain = mono_object_domain (type);
7093 klass = mono_class_from_mono_type (type->type);
7094 mono_class_init_or_throw (klass);
7096 if (mono_class_is_nullable (klass))
7097 /* No arguments -> null */
7100 return mono_object_new (domain, klass);
7103 ICALL_EXPORT MonoReflectionMethod *
7104 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7106 MonoClass *klass, *parent;
7107 MonoMethod *method = m->method;
7108 MonoMethod *result = NULL;
7111 MONO_ARCH_SAVE_REGS;
7113 if (method->klass == NULL)
7116 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7117 MONO_CLASS_IS_INTERFACE (method->klass) ||
7118 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7121 slot = mono_method_get_vtable_slot (method);
7125 klass = method->klass;
7126 if (klass->generic_class)
7127 klass = klass->generic_class->container_class;
7130 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7131 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7132 mono_class_setup_vtable (parent);
7133 if (parent->vtable_size <= slot)
7138 klass = klass->parent;
7143 if (klass == method->klass)
7146 /*This is possible if definition == FALSE.
7147 * Do it here to be really sure we don't read invalid memory.
7149 if (slot >= klass->vtable_size)
7152 mono_class_setup_vtable (klass);
7154 result = klass->vtable [slot];
7155 if (result == NULL) {
7156 /* It is an abstract method */
7157 gpointer iter = NULL;
7158 while ((result = mono_class_get_methods (klass, &iter)))
7159 if (result->slot == slot)
7166 return mono_method_get_object (mono_domain_get (), result, NULL);
7169 ICALL_EXPORT MonoString*
7170 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7172 MonoMethod *method = m->method;
7174 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7179 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7181 MONO_ARCH_SAVE_REGS;
7183 iter->sig = *(MonoMethodSignature**)argsp;
7185 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7186 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7189 /* FIXME: it's not documented what start is exactly... */
7193 iter->args = argsp + sizeof (gpointer);
7195 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7197 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7200 ICALL_EXPORT MonoTypedRef
7201 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7203 guint32 i, arg_size;
7206 MONO_ARCH_SAVE_REGS;
7208 i = iter->sig->sentinelpos + iter->next_arg;
7210 g_assert (i < iter->sig->param_count);
7212 res.type = iter->sig->params [i];
7213 res.klass = mono_class_from_mono_type (res.type);
7214 arg_size = mono_type_stack_size (res.type, &align);
7215 #if defined(__arm__) || defined(__mips__)
7216 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7218 res.value = iter->args;
7219 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7220 /* Values are stored as 8 byte register sized objects, but 'value'
7221 * is dereferenced as a pointer in other routines.
7223 res.value = (char*)res.value + 4;
7225 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7226 if (arg_size <= sizeof (gpointer)) {
7228 int padding = arg_size - mono_type_size (res.type, &dummy);
7229 res.value = (guint8*)res.value + padding;
7232 iter->args = (char*)iter->args + arg_size;
7235 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7240 ICALL_EXPORT MonoTypedRef
7241 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7243 guint32 i, arg_size;
7246 MONO_ARCH_SAVE_REGS;
7248 i = iter->sig->sentinelpos + iter->next_arg;
7250 g_assert (i < iter->sig->param_count);
7252 while (i < iter->sig->param_count) {
7253 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7255 res.type = iter->sig->params [i];
7256 res.klass = mono_class_from_mono_type (res.type);
7257 /* FIXME: endianess issue... */
7258 arg_size = mono_type_stack_size (res.type, &align);
7259 #if defined(__arm__) || defined(__mips__)
7260 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7262 res.value = iter->args;
7263 iter->args = (char*)iter->args + arg_size;
7265 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7268 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7276 ICALL_EXPORT MonoType*
7277 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7280 MONO_ARCH_SAVE_REGS;
7282 i = iter->sig->sentinelpos + iter->next_arg;
7284 g_assert (i < iter->sig->param_count);
7286 return iter->sig->params [i];
7289 ICALL_EXPORT MonoObject*
7290 mono_TypedReference_ToObject (MonoTypedRef tref)
7292 MONO_ARCH_SAVE_REGS;
7294 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7295 MonoObject** objp = tref.value;
7299 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7302 ICALL_EXPORT MonoObject*
7303 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7305 MONO_ARCH_SAVE_REGS;
7307 if (MONO_TYPE_IS_REFERENCE (type)) {
7308 MonoObject** objp = value;
7312 return mono_value_box (mono_domain_get (), klass, value);
7316 prelink_method (MonoMethod *method)
7318 const char *exc_class, *exc_arg;
7319 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7321 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7323 mono_raise_exception(
7324 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7326 /* create the wrapper, too? */
7330 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7332 MONO_ARCH_SAVE_REGS;
7333 prelink_method (method->method);
7337 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7339 MonoClass *klass = mono_class_from_mono_type (type->type);
7341 gpointer iter = NULL;
7342 MONO_ARCH_SAVE_REGS;
7344 mono_class_init_or_throw (klass);
7346 while ((m = mono_class_get_methods (klass, &iter)))
7350 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7352 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7353 gint32 const **exponents,
7354 gunichar2 const **digitLowerTable,
7355 gunichar2 const **digitUpperTable,
7356 gint64 const **tenPowersList,
7357 gint32 const **decHexDigits)
7359 *mantissas = Formatter_MantissaBitsTable;
7360 *exponents = Formatter_TensExponentTable;
7361 *digitLowerTable = Formatter_DigitLowerTable;
7362 *digitUpperTable = Formatter_DigitUpperTable;
7363 *tenPowersList = Formatter_TenPowersList;
7364 *decHexDigits = Formatter_DecHexDigits;
7368 get_category_data (int version,
7369 guint8 const **category_data,
7370 guint16 const **category_astral_index)
7372 *category_astral_index = NULL;
7374 #ifndef DISABLE_NET_4_0
7376 *category_data = CategoryData_v4;
7377 #ifndef DISABLE_ASTRAL
7378 *category_astral_index = CategoryData_v4_astral_index;
7384 *category_data = CategoryData_v2;
7385 #ifndef DISABLE_ASTRAL
7386 *category_astral_index = CategoryData_v2_astral_index;
7390 /* These parameters are "readonly" in corlib/System/Char.cs */
7392 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7393 guint8 const **category_data,
7394 guint16 const **category_astral_index,
7395 guint8 const **numeric_data,
7396 gdouble const **numeric_data_values,
7397 guint16 const **to_lower_data_low,
7398 guint16 const **to_lower_data_high,
7399 guint16 const **to_upper_data_low,
7400 guint16 const **to_upper_data_high)
7402 get_category_data (category_data_version, category_data, category_astral_index);
7403 *numeric_data = NumericData;
7404 *numeric_data_values = NumericDataValues;
7405 *to_lower_data_low = ToLowerDataLow;
7406 *to_lower_data_high = ToLowerDataHigh;
7407 *to_upper_data_low = ToUpperDataLow;
7408 *to_upper_data_high = ToUpperDataHigh;
7412 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7414 return method->method->token;
7418 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7419 * and avoid useless allocations.
7422 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7426 for (i = 0; i < type->num_mods; ++i) {
7427 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7432 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7434 for (i = 0; i < type->num_mods; ++i) {
7435 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7436 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7437 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7444 ICALL_EXPORT MonoArray*
7445 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7447 MonoType *type = param->ClassImpl->type;
7448 MonoClass *member_class = mono_object_class (param->MemberImpl);
7449 MonoMethod *method = NULL;
7452 MonoMethodSignature *sig;
7454 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7455 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7456 method = rmethod->method;
7457 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7458 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7459 if (!(method = prop->property->get))
7460 method = prop->property->set;
7463 char *type_name = mono_type_get_full_name (member_class);
7464 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7465 MonoException *ex = mono_get_exception_not_supported (msg);
7468 mono_raise_exception (ex);
7471 image = method->klass->image;
7472 pos = param->PositionImpl;
7473 sig = mono_method_signature (method);
7477 type = sig->params [pos];
7479 return type_array_from_modifiers (image, type, optional);
7483 get_property_type (MonoProperty *prop)
7485 MonoMethodSignature *sig;
7487 sig = mono_method_signature (prop->get);
7489 } else if (prop->set) {
7490 sig = mono_method_signature (prop->set);
7491 return sig->params [sig->param_count - 1];
7496 ICALL_EXPORT MonoArray*
7497 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7499 MonoType *type = get_property_type (property->property);
7500 MonoImage *image = property->klass->image;
7504 return type_array_from_modifiers (image, type, optional);
7508 *Construct a MonoType suited to be used to decode a constant blob object.
7510 * @type is the target type which will be constructed
7511 * @blob_type is the blob type, for example, that comes from the constant table
7512 * @real_type is the expected constructed type.
7515 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7517 type->type = blob_type;
7518 type->data.klass = NULL;
7519 if (blob_type == MONO_TYPE_CLASS)
7520 type->data.klass = mono_defaults.object_class;
7521 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7522 /* For enums, we need to use the base type */
7523 type->type = MONO_TYPE_VALUETYPE;
7524 type->data.klass = mono_class_from_mono_type (real_type);
7526 type->data.klass = mono_class_from_mono_type (real_type);
7529 ICALL_EXPORT MonoObject*
7530 property_info_get_default_value (MonoReflectionProperty *property)
7533 MonoProperty *prop = property->property;
7534 MonoType *type = get_property_type (prop);
7535 MonoDomain *domain = mono_object_domain (property);
7536 MonoTypeEnum def_type;
7537 const char *def_value;
7540 mono_class_init (prop->parent);
7542 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7543 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7545 def_value = mono_class_get_property_default_value (prop, &def_type);
7547 mono_type_from_blob_type (&blob_type, def_type, type);
7548 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7553 ICALL_EXPORT MonoBoolean
7554 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7556 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7557 MonoCustomAttrInfo *cinfo;
7560 mono_class_init_or_throw (attr_class);
7562 cinfo = mono_reflection_get_custom_attrs_info (obj);
7565 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7567 mono_custom_attrs_free (cinfo);
7571 ICALL_EXPORT MonoArray*
7572 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7574 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7579 mono_class_init_or_throw (attr_class);
7581 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7582 mono_error_raise_exception (&error);
7584 if (mono_loader_get_last_error ()) {
7585 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7586 g_assert_not_reached ();
7594 ICALL_EXPORT MonoString*
7595 ves_icall_Mono_Runtime_GetDisplayName (void)
7598 MonoString *display_name;
7600 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7601 display_name = mono_string_new (mono_domain_get (), info);
7603 return display_name;
7606 ICALL_EXPORT MonoString*
7607 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7609 MonoString *message;
7613 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7614 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7617 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7619 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7627 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7628 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7629 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7630 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7631 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7632 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7633 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7634 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7638 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7643 gunichar2 last, prev_last, prev2_last;
7650 int havePadding = 0;
7652 last = prev_last = 0, prev2_last = 0;
7653 for (i = 0; i < ilength; i++) {
7655 if (c >= sizeof (dbase64)) {
7656 exc = mono_exception_from_name_msg (mono_get_corlib (),
7657 "System", "FormatException",
7658 "Invalid character found.");
7659 mono_raise_exception (exc);
7660 } else if (isspace (c)) {
7662 } else if (havePadding && c != '=') {
7663 exc = mono_exception_from_name_msg (mono_get_corlib (),
7664 "System", "FormatException",
7665 "Invalid character found.");
7666 mono_raise_exception (exc);
7668 if (c == '=') havePadding = 1;
7669 prev2_last = prev_last;
7675 olength = ilength - ignored;
7677 if (allowWhitespaceOnly && olength == 0) {
7678 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7681 if ((olength & 3) != 0 || olength <= 0) {
7682 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7683 "FormatException", "Invalid length.");
7684 mono_raise_exception (exc);
7687 if (prev2_last == '=') {
7688 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7689 mono_raise_exception (exc);
7692 olength = (olength * 3) / 4;
7696 if (prev_last == '=')
7699 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7700 res_ptr = mono_array_addr (result, guchar, 0);
7701 for (i = 0; i < ilength; ) {
7704 for (k = 0; k < 4 && i < ilength;) {
7710 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7711 exc = mono_exception_from_name_msg (mono_get_corlib (),
7712 "System", "FormatException",
7713 "Invalid character found.");
7714 mono_raise_exception (exc);
7719 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7721 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7723 *res_ptr++ = (b [2] << 6) | b [3];
7725 while (i < ilength && isspace (start [i]))
7732 ICALL_EXPORT MonoArray *
7733 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7735 MONO_ARCH_SAVE_REGS;
7737 return base64_to_byte_array (mono_string_chars (str),
7738 mono_string_length (str), allowWhitespaceOnly);
7741 ICALL_EXPORT MonoArray *
7742 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7744 MONO_ARCH_SAVE_REGS;
7746 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7750 #ifndef DISABLE_ICALL_TABLES
7752 #define ICALL_TYPE(id,name,first)
7753 #define ICALL(id,name,func) Icall_ ## id,
7756 #include "metadata/icall-def.h"
7762 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7763 #define ICALL(id,name,func)
7765 #include "metadata/icall-def.h"
7771 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7772 #define ICALL(id,name,func)
7774 guint16 first_icall;
7777 static const IcallTypeDesc
7778 icall_type_descs [] = {
7779 #include "metadata/icall-def.h"
7783 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7786 #define ICALL_TYPE(id,name,first)
7789 #ifdef HAVE_ARRAY_ELEM_INIT
7790 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7791 #define MSGSTRFIELD1(line) str##line
7793 static const struct msgstrtn_t {
7794 #define ICALL(id,name,func)
7796 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7797 #include "metadata/icall-def.h"
7799 } icall_type_names_str = {
7800 #define ICALL_TYPE(id,name,first) (name),
7801 #include "metadata/icall-def.h"
7804 static const guint16 icall_type_names_idx [] = {
7805 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7806 #include "metadata/icall-def.h"
7809 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7811 static const struct msgstr_t {
7813 #define ICALL_TYPE(id,name,first)
7814 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7815 #include "metadata/icall-def.h"
7817 } icall_names_str = {
7818 #define ICALL(id,name,func) (name),
7819 #include "metadata/icall-def.h"
7822 static const guint16 icall_names_idx [] = {
7823 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7824 #include "metadata/icall-def.h"
7827 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7833 #define ICALL_TYPE(id,name,first) name,
7834 #define ICALL(id,name,func)
7835 static const char* const
7836 icall_type_names [] = {
7837 #include "metadata/icall-def.h"
7841 #define icall_type_name_get(id) (icall_type_names [(id)])
7845 #define ICALL_TYPE(id,name,first)
7846 #define ICALL(id,name,func) name,
7847 static const char* const
7849 #include "metadata/icall-def.h"
7852 #define icall_name_get(id) icall_names [(id)]
7854 #endif /* !HAVE_ARRAY_ELEM_INIT */
7858 #define ICALL_TYPE(id,name,first)
7859 #define ICALL(id,name,func) func,
7860 static const gconstpointer
7861 icall_functions [] = {
7862 #include "metadata/icall-def.h"
7866 #ifdef ENABLE_ICALL_SYMBOL_MAP
7869 #define ICALL_TYPE(id,name,first)
7870 #define ICALL(id,name,func) #func,
7871 static const gconstpointer
7872 icall_symbols [] = {
7873 #include "metadata/icall-def.h"
7878 #endif /* DISABLE_ICALL_TABLES */
7880 static mono_mutex_t icall_mutex;
7881 static GHashTable *icall_hash = NULL;
7882 static GHashTable *jit_icall_hash_name = NULL;
7883 static GHashTable *jit_icall_hash_addr = NULL;
7886 mono_icall_init (void)
7888 #ifndef DISABLE_ICALL_TABLES
7891 /* check that tables are sorted: disable in release */
7894 const char *prev_class = NULL;
7895 const char *prev_method;
7897 for (i = 0; i < Icall_type_num; ++i) {
7898 const IcallTypeDesc *desc;
7901 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7902 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7903 prev_class = icall_type_name_get (i);
7904 desc = &icall_type_descs [i];
7905 num_icalls = icall_desc_num_icalls (desc);
7906 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7907 for (j = 0; j < num_icalls; ++j) {
7908 const char *methodn = icall_name_get (desc->first_icall + j);
7909 if (prev_method && strcmp (prev_method, methodn) >= 0)
7910 g_print ("method %s should come before method %s\n", methodn, prev_method);
7911 prev_method = methodn;
7917 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7918 mono_mutex_init (&icall_mutex);
7922 mono_icall_lock (void)
7924 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7928 mono_icall_unlock (void)
7930 mono_locks_mutex_release (&icall_mutex, IcallLock);
7934 mono_icall_cleanup (void)
7936 g_hash_table_destroy (icall_hash);
7937 g_hash_table_destroy (jit_icall_hash_name);
7938 g_hash_table_destroy (jit_icall_hash_addr);
7939 mono_mutex_destroy (&icall_mutex);
7943 mono_add_internal_call (const char *name, gconstpointer method)
7947 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7949 mono_icall_unlock ();
7952 #ifndef DISABLE_ICALL_TABLES
7954 #ifdef HAVE_ARRAY_ELEM_INIT
7956 compare_method_imap (const void *key, const void *elem)
7958 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7959 return strcmp (key, method_name);
7963 find_method_icall (const IcallTypeDesc *imap, const char *name)
7965 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);
7968 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7972 compare_class_imap (const void *key, const void *elem)
7974 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7975 return strcmp (key, class_name);
7978 static const IcallTypeDesc*
7979 find_class_icalls (const char *name)
7981 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7984 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7987 #else /* HAVE_ARRAY_ELEM_INIT */
7990 compare_method_imap (const void *key, const void *elem)
7992 const char** method_name = (const char**)elem;
7993 return strcmp (key, *method_name);
7997 find_method_icall (const IcallTypeDesc *imap, const char *name)
7999 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8002 return (gpointer)icall_functions [(nameslot - icall_names)];
8006 compare_class_imap (const void *key, const void *elem)
8008 const char** class_name = (const char**)elem;
8009 return strcmp (key, *class_name);
8012 static const IcallTypeDesc*
8013 find_class_icalls (const char *name)
8015 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8018 return &icall_type_descs [nameslot - icall_type_names];
8021 #endif /* HAVE_ARRAY_ELEM_INIT */
8023 #endif /* DISABLE_ICALL_TABLES */
8026 * we should probably export this as an helper (handle nested types).
8027 * Returns the number of chars written in buf.
8030 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8032 int nspacelen, cnamelen;
8033 nspacelen = strlen (klass->name_space);
8034 cnamelen = strlen (klass->name);
8035 if (nspacelen + cnamelen + 2 > bufsize)
8038 memcpy (buf, klass->name_space, nspacelen);
8039 buf [nspacelen ++] = '.';
8041 memcpy (buf + nspacelen, klass->name, cnamelen);
8042 buf [nspacelen + cnamelen] = 0;
8043 return nspacelen + cnamelen;
8046 #ifdef DISABLE_ICALL_TABLES
8048 no_icall_table (void)
8050 g_assert_not_reached ();
8055 mono_lookup_internal_call (MonoMethod *method)
8060 int typelen = 0, mlen, siglen;
8062 #ifndef DISABLE_ICALL_TABLES
8063 const IcallTypeDesc *imap = NULL;
8066 g_assert (method != NULL);
8068 if (method->is_inflated)
8069 method = ((MonoMethodInflated *) method)->declaring;
8071 if (method->klass->nested_in) {
8072 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8076 mname [pos++] = '/';
8079 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8085 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8090 #ifndef DISABLE_ICALL_TABLES
8091 imap = find_class_icalls (mname);
8094 mname [typelen] = ':';
8095 mname [typelen + 1] = ':';
8097 mlen = strlen (method->name);
8098 memcpy (mname + typelen + 2, method->name, mlen);
8099 sigstart = mname + typelen + 2 + mlen;
8102 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8103 siglen = strlen (tmpsig);
8104 if (typelen + mlen + siglen + 6 > sizeof (mname))
8107 memcpy (sigstart + 1, tmpsig, siglen);
8108 sigstart [siglen + 1] = ')';
8109 sigstart [siglen + 2] = 0;
8114 res = g_hash_table_lookup (icall_hash, mname);
8116 mono_icall_unlock ();;
8119 /* try without signature */
8121 res = g_hash_table_lookup (icall_hash, mname);
8123 mono_icall_unlock ();
8127 #ifdef DISABLE_ICALL_TABLES
8128 mono_icall_unlock ();
8129 /* Fail only when the result is actually used */
8130 /* mono_marshal_get_native_wrapper () depends on this */
8131 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8132 return ves_icall_System_String_ctor_RedirectToCreateString;
8134 return no_icall_table;
8136 /* it wasn't found in the static call tables */
8138 mono_icall_unlock ();
8141 res = find_method_icall (imap, sigstart - mlen);
8143 mono_icall_unlock ();
8146 /* try _with_ signature */
8148 res = find_method_icall (imap, sigstart - mlen);
8150 mono_icall_unlock ();
8154 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8155 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8156 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8157 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8158 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");
8159 g_print ("If you see other errors or faults after this message they are probably related\n");
8160 g_print ("and you need to fix your mono install first.\n");
8162 mono_icall_unlock ();
8168 #ifdef ENABLE_ICALL_SYMBOL_MAP
8170 func_cmp (gconstpointer key, gconstpointer p)
8172 return (gsize)key - (gsize)*(gsize*)p;
8177 * mono_lookup_icall_symbol:
8179 * Given the icall METHOD, returns its C symbol.
8182 mono_lookup_icall_symbol (MonoMethod *m)
8184 #ifdef DISABLE_ICALL_TABLES
8185 g_assert_not_reached ();
8188 #ifdef ENABLE_ICALL_SYMBOL_MAP
8192 static gconstpointer *functions_sorted;
8193 static const char**symbols_sorted;
8194 static gboolean inited;
8199 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8200 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8201 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8202 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8203 /* Bubble sort the two arrays */
8207 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8208 if (functions_sorted [i] > functions_sorted [i + 1]) {
8211 tmp = functions_sorted [i];
8212 functions_sorted [i] = functions_sorted [i + 1];
8213 functions_sorted [i + 1] = tmp;
8214 tmp = symbols_sorted [i];
8215 symbols_sorted [i] = symbols_sorted [i + 1];
8216 symbols_sorted [i + 1] = tmp;
8223 func = mono_lookup_internal_call (m);
8226 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8230 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8232 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8233 g_assert_not_reached ();
8240 type_from_typename (char *typename)
8242 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8244 if (!strcmp (typename, "int"))
8245 klass = mono_defaults.int_class;
8246 else if (!strcmp (typename, "ptr"))
8247 klass = mono_defaults.int_class;
8248 else if (!strcmp (typename, "void"))
8249 klass = mono_defaults.void_class;
8250 else if (!strcmp (typename, "int32"))
8251 klass = mono_defaults.int32_class;
8252 else if (!strcmp (typename, "uint32"))
8253 klass = mono_defaults.uint32_class;
8254 else if (!strcmp (typename, "int8"))
8255 klass = mono_defaults.sbyte_class;
8256 else if (!strcmp (typename, "uint8"))
8257 klass = mono_defaults.byte_class;
8258 else if (!strcmp (typename, "int16"))
8259 klass = mono_defaults.int16_class;
8260 else if (!strcmp (typename, "uint16"))
8261 klass = mono_defaults.uint16_class;
8262 else if (!strcmp (typename, "long"))
8263 klass = mono_defaults.int64_class;
8264 else if (!strcmp (typename, "ulong"))
8265 klass = mono_defaults.uint64_class;
8266 else if (!strcmp (typename, "float"))
8267 klass = mono_defaults.single_class;
8268 else if (!strcmp (typename, "double"))
8269 klass = mono_defaults.double_class;
8270 else if (!strcmp (typename, "object"))
8271 klass = mono_defaults.object_class;
8272 else if (!strcmp (typename, "obj"))
8273 klass = mono_defaults.object_class;
8274 else if (!strcmp (typename, "string"))
8275 klass = mono_defaults.string_class;
8276 else if (!strcmp (typename, "bool"))
8277 klass = mono_defaults.boolean_class;
8278 else if (!strcmp (typename, "boolean"))
8279 klass = mono_defaults.boolean_class;
8281 g_error ("%s", typename);
8282 g_assert_not_reached ();
8284 return &klass->byval_arg;
8288 * LOCKING: Take the corlib image lock.
8290 MonoMethodSignature*
8291 mono_create_icall_signature (const char *sigstr)
8296 MonoMethodSignature *res, *res2;
8297 MonoImage *corlib = mono_defaults.corlib;
8299 mono_image_lock (corlib);
8300 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8301 mono_image_unlock (corlib);
8306 parts = g_strsplit (sigstr, " ", 256);
8315 res = mono_metadata_signature_alloc (corlib, len - 1);
8320 * Under windows, the default pinvoke calling convention is STDCALL but
8323 res->call_convention = MONO_CALL_C;
8326 res->ret = type_from_typename (parts [0]);
8327 for (i = 1; i < len; ++i) {
8328 res->params [i - 1] = type_from_typename (parts [i]);
8333 mono_image_lock (corlib);
8334 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8336 res = res2; /*Value is allocated in the image pool*/
8338 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8339 mono_image_unlock (corlib);
8345 mono_find_jit_icall_by_name (const char *name)
8347 MonoJitICallInfo *info;
8348 g_assert (jit_icall_hash_name);
8351 info = g_hash_table_lookup (jit_icall_hash_name, name);
8352 mono_icall_unlock ();
8357 mono_find_jit_icall_by_addr (gconstpointer addr)
8359 MonoJitICallInfo *info;
8360 g_assert (jit_icall_hash_addr);
8363 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8364 mono_icall_unlock ();
8370 * mono_get_jit_icall_info:
8372 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8373 * caller should access it while holding the icall lock.
8376 mono_get_jit_icall_info (void)
8378 return jit_icall_hash_name;
8382 * mono_lookup_jit_icall_symbol:
8384 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8387 mono_lookup_jit_icall_symbol (const char *name)
8389 MonoJitICallInfo *info;
8390 const char *res = NULL;
8393 info = g_hash_table_lookup (jit_icall_hash_name, name);
8395 res = info->c_symbol;
8396 mono_icall_unlock ();
8401 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8404 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8405 mono_icall_unlock ();
8409 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8411 MonoJitICallInfo *info;
8418 if (!jit_icall_hash_name) {
8419 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8420 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8423 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8424 g_warning ("jit icall already defined \"%s\"\n", name);
8425 g_assert_not_reached ();
8428 info = g_new0 (MonoJitICallInfo, 1);
8433 info->c_symbol = c_symbol;
8436 info->wrapper = func;
8438 info->wrapper = NULL;
8441 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8442 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8444 mono_icall_unlock ();
8449 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8451 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);