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/mono-route.h>
49 #include <mono/metadata/socket-io.h>
50 #include <mono/metadata/mono-endian.h>
51 #include <mono/metadata/tokentype.h>
52 #include <mono/metadata/domain-internals.h>
53 #include <mono/metadata/metadata-internals.h>
54 #include <mono/metadata/class-internals.h>
55 #include <mono/metadata/marshal.h>
56 #include <mono/metadata/gc-internal.h>
57 #include <mono/metadata/mono-gc.h>
58 #include <mono/metadata/rand.h>
59 #include <mono/metadata/sysmath.h>
60 #include <mono/metadata/string-icalls.h>
61 #include <mono/metadata/debug-helpers.h>
62 #include <mono/metadata/process.h>
63 #include <mono/metadata/environment.h>
64 #include <mono/metadata/profiler-private.h>
65 #include <mono/metadata/locales.h>
66 #include <mono/metadata/filewatcher.h>
67 #include <mono/metadata/char-conversions.h>
68 #include <mono/metadata/security.h>
69 #include <mono/metadata/mono-config.h>
70 #include <mono/metadata/cil-coff.h>
71 #include <mono/metadata/number-formatter.h>
72 #include <mono/metadata/security-manager.h>
73 #include <mono/metadata/security-core-clr.h>
74 #include <mono/metadata/mono-perfcounters.h>
75 #include <mono/metadata/mono-debug.h>
76 #include <mono/metadata/mono-ptr-array.h>
77 #include <mono/metadata/verify-internals.h>
78 #include <mono/metadata/runtime.h>
79 #include <mono/metadata/file-mmap.h>
80 #include <mono/io-layer/io-layer.h>
81 #include <mono/utils/strtod.h>
82 #include <mono/utils/monobitset.h>
83 #include <mono/utils/mono-time.h>
84 #include <mono/utils/mono-proclib.h>
85 #include <mono/utils/mono-string.h>
86 #include <mono/utils/mono-error-internals.h>
87 #include <mono/utils/mono-mmap.h>
88 #include <mono/utils/mono-io-portability.h>
89 #include <mono/utils/mono-digest.h>
90 #include <mono/utils/bsearch.h>
91 #include <mono/utils/mono-mutex.h>
92 #include <mono/utils/mono-threads.h>
94 #if defined (HOST_WIN32)
100 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
102 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
105 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
107 static inline MonoBoolean
108 is_generic_parameter (MonoType *type)
110 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
114 mono_class_init_or_throw (MonoClass *klass)
116 if (!mono_class_init (klass))
117 mono_raise_exception (mono_class_get_exception_for_failure (klass));
121 * We expect a pointer to a char, not a string
123 ICALL_EXPORT gboolean
124 mono_double_ParseImpl (char *ptr, double *result)
126 gchar *endptr = NULL;
132 /* mono_strtod () is not thread-safe */
133 mono_mutex_lock (&mono_strtod_mutex);
134 *result = mono_strtod (ptr, &endptr);
135 mono_mutex_unlock (&mono_strtod_mutex);
138 if (!*ptr || (endptr && *endptr))
144 ICALL_EXPORT MonoObject *
145 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
154 ao = (MonoArray *)this;
155 ac = (MonoClass *)ao->obj.vtable->klass;
157 esize = mono_array_element_size (ac);
158 ea = (gpointer*)((char*)ao->vector + (pos * esize));
160 if (ac->element_class->valuetype)
161 return mono_value_box (this->vtable->domain, ac->element_class, ea);
166 ICALL_EXPORT MonoObject *
167 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
175 MONO_CHECK_ARG_NULL (idxs);
177 io = (MonoArray *)idxs;
178 ic = (MonoClass *)io->obj.vtable->klass;
180 ao = (MonoArray *)this;
181 ac = (MonoClass *)ao->obj.vtable->klass;
183 g_assert (ic->rank == 1);
184 if (io->bounds != NULL || io->max_length != ac->rank)
185 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
187 ind = (gint32 *)io->vector;
189 if (ao->bounds == NULL) {
190 if (*ind < 0 || *ind >= ao->max_length)
191 mono_raise_exception (mono_get_exception_index_out_of_range ());
193 return ves_icall_System_Array_GetValueImpl (this, *ind);
196 for (i = 0; i < ac->rank; i++)
197 if ((ind [i] < ao->bounds [i].lower_bound) ||
198 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
199 mono_raise_exception (mono_get_exception_index_out_of_range ());
201 pos = ind [0] - ao->bounds [0].lower_bound;
202 for (i = 1; i < ac->rank; i++)
203 pos = pos*ao->bounds [i].length + ind [i] -
204 ao->bounds [i].lower_bound;
206 return ves_icall_System_Array_GetValueImpl (this, pos);
210 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
224 vc = value->vtable->klass;
228 ac = this->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)this->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero_atomic (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_raise_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
250 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
251 if (esize < vsize + (extra)) \
252 mono_raise_exception (mono_get_exception_argument ( \
253 "value", "not a widening conversion")); \
256 #define INVALID_CAST G_STMT_START{ \
257 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
258 mono_raise_exception (mono_get_exception_invalid_cast ()); \
261 /* Check element (destination) type. */
262 switch (ec->byval_arg.type) {
263 case MONO_TYPE_STRING:
264 switch (vc->byval_arg.type) {
265 case MONO_TYPE_STRING:
271 case MONO_TYPE_BOOLEAN:
272 switch (vc->byval_arg.type) {
273 case MONO_TYPE_BOOLEAN:
286 NO_WIDENING_CONVERSION;
293 if (!ec->valuetype) {
294 if (!mono_object_isinst (value, ec))
296 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
300 if (mono_object_isinst (value, ec)) {
301 if (ec->has_references)
302 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
304 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
311 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
313 et = ec->byval_arg.type;
314 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
315 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
317 vt = vc->byval_arg.type;
318 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
319 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
321 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
327 case MONO_TYPE_CHAR: \
328 CHECK_WIDENING_CONVERSION(0); \
329 *(etype *) ea = (etype) u64; \
331 /* You can't assign a signed value to an unsigned array. */ \
336 /* You can't assign a floating point number to an integer array. */ \
339 NO_WIDENING_CONVERSION; \
343 #define ASSIGN_SIGNED(etype) G_STMT_START{\
349 CHECK_WIDENING_CONVERSION(0); \
350 *(etype *) ea = (etype) i64; \
352 /* You can assign an unsigned value to a signed array if the array's */ \
353 /* element size is larger than the value size. */ \
358 case MONO_TYPE_CHAR: \
359 CHECK_WIDENING_CONVERSION(1); \
360 *(etype *) ea = (etype) u64; \
362 /* You can't assign a floating point number to an integer array. */ \
365 NO_WIDENING_CONVERSION; \
369 #define ASSIGN_REAL(etype) G_STMT_START{\
373 CHECK_WIDENING_CONVERSION(0); \
374 *(etype *) ea = (etype) r64; \
376 /* All integer values fit into a floating point array, so we don't */ \
377 /* need to CHECK_WIDENING_CONVERSION here. */ \
382 *(etype *) ea = (etype) i64; \
388 case MONO_TYPE_CHAR: \
389 *(etype *) ea = (etype) u64; \
396 u64 = *(guint8 *) va;
399 u64 = *(guint16 *) va;
402 u64 = *(guint32 *) va;
405 u64 = *(guint64 *) va;
411 i64 = *(gint16 *) va;
414 i64 = *(gint32 *) va;
417 i64 = *(gint64 *) va;
420 r64 = *(gfloat *) va;
423 r64 = *(gdouble *) va;
426 u64 = *(guint16 *) va;
428 case MONO_TYPE_BOOLEAN:
429 /* Boolean is only compatible with itself. */
442 NO_WIDENING_CONVERSION;
449 /* If we can't do a direct copy, let's try a widening conversion. */
452 ASSIGN_UNSIGNED (guint16);
454 ASSIGN_UNSIGNED (guint8);
456 ASSIGN_UNSIGNED (guint16);
458 ASSIGN_UNSIGNED (guint32);
460 ASSIGN_UNSIGNED (guint64);
462 ASSIGN_SIGNED (gint8);
464 ASSIGN_SIGNED (gint16);
466 ASSIGN_SIGNED (gint32);
468 ASSIGN_SIGNED (gint64);
470 ASSIGN_REAL (gfloat);
472 ASSIGN_REAL (gdouble);
476 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
480 #undef NO_WIDENING_CONVERSION
481 #undef CHECK_WIDENING_CONVERSION
482 #undef ASSIGN_UNSIGNED
488 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
496 MONO_CHECK_ARG_NULL (idxs);
498 ic = idxs->obj.vtable->klass;
499 ac = this->obj.vtable->klass;
501 g_assert (ic->rank == 1);
502 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
503 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
505 ind = (gint32 *)idxs->vector;
507 if (this->bounds == NULL) {
508 if (*ind < 0 || *ind >= this->max_length)
509 mono_raise_exception (mono_get_exception_index_out_of_range ());
511 ves_icall_System_Array_SetValueImpl (this, value, *ind);
515 for (i = 0; i < ac->rank; i++)
516 if ((ind [i] < this->bounds [i].lower_bound) ||
517 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
518 mono_raise_exception (mono_get_exception_index_out_of_range ());
520 pos = ind [0] - this->bounds [0].lower_bound;
521 for (i = 1; i < ac->rank; i++)
522 pos = pos * this->bounds [i].length + ind [i] -
523 this->bounds [i].lower_bound;
525 ves_icall_System_Array_SetValueImpl (this, value, pos);
528 ICALL_EXPORT MonoArray *
529 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
531 MonoClass *aklass, *klass;
534 gboolean bounded = FALSE;
538 MONO_CHECK_ARG_NULL (type);
539 MONO_CHECK_ARG_NULL (lengths);
541 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
543 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
545 for (i = 0; i < mono_array_length (lengths); i++)
546 if (mono_array_get (lengths, gint32, i) < 0)
547 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
549 klass = mono_class_from_mono_type (type->type);
550 mono_class_init_or_throw (klass);
552 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
553 /* vectors are not the same as one dimensional arrays with no-zero bounds */
558 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
560 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
561 for (i = 0; i < aklass->rank; ++i) {
562 sizes [i] = mono_array_get (lengths, guint32, i);
564 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
566 sizes [i + aklass->rank] = 0;
569 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
574 ICALL_EXPORT MonoArray *
575 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
577 MonoClass *aklass, *klass;
580 gboolean bounded = FALSE;
584 MONO_CHECK_ARG_NULL (type);
585 MONO_CHECK_ARG_NULL (lengths);
587 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
589 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
591 for (i = 0; i < mono_array_length (lengths); i++)
592 if ((mono_array_get (lengths, gint64, i) < 0) ||
593 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
594 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
596 klass = mono_class_from_mono_type (type->type);
597 mono_class_init_or_throw (klass);
599 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
600 /* vectors are not the same as one dimensional arrays with no-zero bounds */
605 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
607 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
608 for (i = 0; i < aklass->rank; ++i) {
609 sizes [i] = mono_array_get (lengths, guint64, i);
611 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
613 sizes [i + aklass->rank] = 0;
616 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
622 ves_icall_System_Array_GetRank (MonoObject *this)
626 return this->vtable->klass->rank;
630 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
632 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
637 if ((dimension < 0) || (dimension >= rank))
638 mono_raise_exception (mono_get_exception_index_out_of_range ());
640 if (this->bounds == NULL)
641 length = this->max_length;
643 length = this->bounds [dimension].length;
645 #ifdef MONO_BIG_ARRAYS
646 if (length > G_MAXINT32)
647 mono_raise_exception (mono_get_exception_overflow ());
653 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
655 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
659 if ((dimension < 0) || (dimension >= rank))
660 mono_raise_exception (mono_get_exception_index_out_of_range ());
662 if (this->bounds == NULL)
663 return this->max_length;
665 return this->bounds [dimension].length;
669 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
671 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
675 if ((dimension < 0) || (dimension >= rank))
676 mono_raise_exception (mono_get_exception_index_out_of_range ());
678 if (this->bounds == NULL)
681 return this->bounds [dimension].lower_bound;
685 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
687 int sz = mono_array_element_size (mono_object_class (arr));
688 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
691 ICALL_EXPORT gboolean
692 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
697 MonoVTable *src_vtable;
698 MonoVTable *dest_vtable;
699 MonoClass *src_class;
700 MonoClass *dest_class;
702 src_vtable = source->obj.vtable;
703 dest_vtable = dest->obj.vtable;
705 if (src_vtable->rank != dest_vtable->rank)
708 if (source->bounds || dest->bounds)
711 /* there's no integer overflow since mono_array_length returns an unsigned integer */
712 if ((dest_idx + length > mono_array_length_fast (dest)) ||
713 (source_idx + length > mono_array_length_fast (source)))
716 src_class = src_vtable->klass->element_class;
717 dest_class = dest_vtable->klass->element_class;
720 * Handle common cases.
723 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
724 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
726 if (src_class == mono_defaults.object_class && dest_class->valuetype)
729 /* Check if we're copying a char[] <==> (u)short[] */
730 if (src_class != dest_class) {
731 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
734 /* 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. */
735 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
739 if (dest_class->valuetype) {
740 element_size = mono_array_element_size (source->obj.vtable->klass);
741 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
742 if (dest_class->has_references) {
743 mono_value_copy_array (dest, dest_idx, source_addr, length);
745 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
746 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
749 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
756 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
765 ao = (MonoArray *)this;
766 ac = (MonoClass *)ao->obj.vtable->klass;
768 esize = mono_array_element_size (ac);
769 ea = (gpointer*)((char*)ao->vector + (pos * esize));
771 mono_gc_memmove_atomic (value, ea, esize);
775 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
784 ao = (MonoArray *)this;
785 ac = (MonoClass *)ao->obj.vtable->klass;
786 ec = ac->element_class;
788 esize = mono_array_element_size (ac);
789 ea = (gpointer*)((char*)ao->vector + (pos * esize));
791 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
792 g_assert (esize == sizeof (gpointer));
793 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
795 g_assert (ec->inited);
796 g_assert (esize == mono_class_value_size (ec, NULL));
797 if (ec->has_references)
798 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
800 mono_gc_memmove_atomic (ea, value, esize);
805 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
807 MonoClass *klass = array->obj.vtable->klass;
808 guint32 size = mono_array_element_size (klass);
809 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
811 const char *field_data;
813 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
814 MonoException *exc = mono_get_exception_argument("array",
815 "Cannot initialize array of non-primitive type.");
816 mono_raise_exception (exc);
819 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
820 MonoException *exc = mono_get_exception_argument("field_handle",
821 "Field doesn't have an RVA");
822 mono_raise_exception (exc);
825 size *= array->max_length;
826 field_data = mono_field_get_data (field_handle);
828 if (size > mono_type_size (field_handle->type, &align)) {
829 MonoException *exc = mono_get_exception_argument("field_handle",
830 "Field not large enough to fill array");
831 mono_raise_exception (exc);
834 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
836 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
837 guint ## n *src = (guint ## n *) field_data; \
838 guint ## n *end = (guint ## n *)((char*)src + size); \
840 for (; src < end; data++, src++) { \
841 *data = read ## n (src); \
845 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
847 switch (type->type) {
864 memcpy (mono_array_addr (array, char, 0), field_data, size);
868 memcpy (mono_array_addr (array, char, 0), field_data, size);
873 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
877 return offsetof (MonoString, chars);
880 ICALL_EXPORT MonoObject *
881 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
885 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
888 return mono_object_clone (obj);
892 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
897 MONO_CHECK_ARG_NULL (handle);
899 klass = mono_class_from_mono_type (handle);
900 MONO_CHECK_ARG (handle, klass);
902 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
904 /* This will call the type constructor */
905 mono_runtime_class_init (vtable);
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
913 mono_image_check_for_module_cctor (image);
914 if (image->has_module_cctor) {
915 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
916 mono_error_raise_exception (&error);
917 /*It's fine to raise the exception here*/
918 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
922 ICALL_EXPORT MonoBoolean
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
928 /* later make this configurable and per-arch */
929 int min_size = 4096 * 4 * sizeof (void*);
930 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
931 /* if we have no info we are optimistic and assume there is enough room */
935 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
939 current = (guint8 *)&stack_addr;
940 if (current > stack_addr) {
941 if ((current - stack_addr) < min_size)
944 if (current - (stack_addr - stack_size) < min_size)
950 ICALL_EXPORT MonoObject *
951 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
955 return mono_object_clone (this);
959 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
962 MonoObject **values = NULL;
965 gint32 result = (int)(gsize)mono_defaults.int32_class;
966 MonoClassField* field;
971 klass = mono_object_class (this);
973 if (mono_class_num_fields (klass) == 0)
977 * Compute the starting value of the hashcode for fields of primitive
978 * types, and return the remaining fields in an array to the managed side.
979 * This way, we can avoid costly reflection operations in managed code.
982 while ((field = mono_class_get_fields (klass, &iter))) {
983 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
985 if (mono_field_is_deleted (field))
987 /* FIXME: Add more types */
988 switch (field->type->type) {
990 result ^= *(gint32*)((guint8*)this + field->offset);
992 case MONO_TYPE_STRING: {
994 s = *(MonoString**)((guint8*)this + field->offset);
996 result ^= mono_string_hash (s);
1001 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1002 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1003 values [count++] = o;
1009 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1010 for (i = 0; i < count; ++i)
1011 mono_array_setref (*fields, i, values [i]);
1018 ICALL_EXPORT MonoBoolean
1019 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1022 MonoObject **values = NULL;
1024 MonoClassField* field;
1028 MONO_ARCH_SAVE_REGS;
1030 MONO_CHECK_ARG_NULL (that);
1032 if (this->vtable != that->vtable)
1035 klass = mono_object_class (this);
1037 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1038 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1041 * Do the comparison for fields of primitive type and return a result if
1042 * possible. Otherwise, return the remaining fields in an array to the
1043 * managed side. This way, we can avoid costly reflection operations in
1048 while ((field = mono_class_get_fields (klass, &iter))) {
1049 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1051 if (mono_field_is_deleted (field))
1053 /* FIXME: Add more types */
1054 switch (field->type->type) {
1057 case MONO_TYPE_BOOLEAN:
1058 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1063 case MONO_TYPE_CHAR:
1064 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1069 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1074 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1078 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1082 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1087 case MONO_TYPE_STRING: {
1088 MonoString *s1, *s2;
1089 guint32 s1len, s2len;
1090 s1 = *(MonoString**)((guint8*)this + field->offset);
1091 s2 = *(MonoString**)((guint8*)that + field->offset);
1094 if ((s1 == NULL) || (s2 == NULL))
1096 s1len = mono_string_length (s1);
1097 s2len = mono_string_length (s2);
1101 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1107 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1108 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1109 values [count++] = o;
1110 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1111 values [count++] = o;
1114 if (klass->enumtype)
1115 /* enums only have one non-static field */
1121 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1122 for (i = 0; i < count; ++i)
1123 mono_array_setref_fast (*fields, i, values [i]);
1130 ICALL_EXPORT MonoReflectionType *
1131 ves_icall_System_Object_GetType (MonoObject *obj)
1133 MONO_ARCH_SAVE_REGS;
1135 #ifndef DISABLE_REMOTING
1136 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1137 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1140 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1144 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1146 MONO_ARCH_SAVE_REGS;
1148 mtype->type = &obj->vtable->klass->byval_arg;
1149 g_assert (mtype->type->type);
1153 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1155 MONO_ARCH_SAVE_REGS;
1157 MONO_CHECK_ARG_NULL (obj);
1159 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1163 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1164 MonoReflectionMethod *method,
1165 MonoArray *opt_param_types)
1167 MONO_ARCH_SAVE_REGS;
1169 MONO_CHECK_ARG_NULL (method);
1171 return mono_image_create_method_token (
1172 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1176 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1178 MONO_ARCH_SAVE_REGS;
1180 mono_image_create_pefile (mb, file);
1184 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1186 MONO_ARCH_SAVE_REGS;
1188 mono_image_build_metadata (mb);
1192 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1194 MONO_ARCH_SAVE_REGS;
1196 mono_image_register_token (mb->dynamic_image, token, obj);
1200 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1202 MonoMethod **dest = data;
1204 /* skip unmanaged frames */
1220 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1222 MonoMethod **dest = data;
1224 /* skip unmanaged frames */
1229 if (!strcmp (m->klass->name_space, "System.Reflection"))
1238 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1240 MonoMethod **dest = data;
1242 /* skip unmanaged frames */
1246 if (m->wrapper_type != MONO_WRAPPER_NONE)
1249 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1263 static MonoReflectionType *
1264 type_from_name (const char *str, MonoBoolean ignoreCase)
1266 MonoMethod *m, *dest;
1268 MonoType *type = NULL;
1269 MonoAssembly *assembly = NULL;
1270 MonoTypeNameParse info;
1271 char *temp_str = g_strdup (str);
1272 gboolean type_resolve = FALSE;
1274 MONO_ARCH_SAVE_REGS;
1276 /* mono_reflection_parse_type() mangles the string */
1277 if (!mono_reflection_parse_type (temp_str, &info)) {
1278 mono_reflection_free_type_info (&info);
1285 * We must compute the calling assembly as type loading must happen under a metadata context.
1286 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1287 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1289 m = mono_method_get_last_managed ();
1292 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1297 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1298 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1299 * to crash. This only seems to happen in some strange remoting
1300 * scenarios and I was unable to figure out what's happening there.
1301 * Dec 10, 2005 - Martin.
1305 assembly = dest->klass->image->assembly;
1306 type_resolve = TRUE;
1308 g_warning (G_STRLOC);
1311 if (info.assembly.name)
1312 assembly = mono_assembly_load (&info.assembly, assembly ? assembly->basedir : NULL, NULL);
1316 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1317 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1320 if (!info.assembly.name && !type) /* try mscorlib */
1321 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1323 if (assembly && !type && type_resolve) {
1324 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1325 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1328 mono_reflection_free_type_info (&info);
1334 return mono_type_get_object (mono_domain_get (), type);
1338 MonoReflectionType *
1339 mono_type_get (const char *str)
1341 char *copy = g_strdup (str);
1342 MonoReflectionType *type = type_from_name (copy, FALSE);
1349 ICALL_EXPORT MonoReflectionType*
1350 ves_icall_type_from_name (MonoString *name,
1351 MonoBoolean throwOnError,
1352 MonoBoolean ignoreCase)
1354 char *str = mono_string_to_utf8 (name);
1355 MonoReflectionType *type;
1357 type = type_from_name (str, ignoreCase);
1360 MonoException *e = NULL;
1363 e = mono_get_exception_type_load (name, NULL);
1365 mono_loader_clear_error ();
1367 mono_raise_exception (e);
1374 ICALL_EXPORT MonoReflectionType*
1375 ves_icall_type_from_handle (MonoType *handle)
1377 MonoDomain *domain = mono_domain_get ();
1379 MONO_ARCH_SAVE_REGS;
1381 return mono_type_get_object (domain, handle);
1384 ICALL_EXPORT MonoBoolean
1385 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1387 MONO_ARCH_SAVE_REGS;
1389 if (c && type->type && c->type)
1390 return mono_metadata_type_equal (type->type, c->type);
1392 return (type == c) ? TRUE : FALSE;
1395 /* System.TypeCode */
1414 TYPECODE_STRING = 18
1417 ICALL_EXPORT guint32
1418 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1420 int t = type->type->type;
1422 MONO_ARCH_SAVE_REGS;
1424 if (type->type->byref)
1425 return TYPECODE_OBJECT;
1429 case MONO_TYPE_VOID:
1430 return TYPECODE_OBJECT;
1431 case MONO_TYPE_BOOLEAN:
1432 return TYPECODE_BOOLEAN;
1434 return TYPECODE_BYTE;
1436 return TYPECODE_SBYTE;
1438 return TYPECODE_UINT16;
1440 return TYPECODE_INT16;
1441 case MONO_TYPE_CHAR:
1442 return TYPECODE_CHAR;
1446 return TYPECODE_OBJECT;
1448 return TYPECODE_UINT32;
1450 return TYPECODE_INT32;
1452 return TYPECODE_UINT64;
1454 return TYPECODE_INT64;
1456 return TYPECODE_SINGLE;
1458 return TYPECODE_DOUBLE;
1459 case MONO_TYPE_VALUETYPE: {
1460 MonoClass *klass = type->type->data.klass;
1462 if (klass->enumtype) {
1463 t = mono_class_enum_basetype (klass)->type;
1465 } else if (mono_is_corlib_image (klass->image)) {
1466 if (strcmp (klass->name_space, "System") == 0) {
1467 if (strcmp (klass->name, "Decimal") == 0)
1468 return TYPECODE_DECIMAL;
1469 else if (strcmp (klass->name, "DateTime") == 0)
1470 return TYPECODE_DATETIME;
1473 return TYPECODE_OBJECT;
1475 case MONO_TYPE_STRING:
1476 return TYPECODE_STRING;
1477 case MONO_TYPE_SZARRAY:
1478 case MONO_TYPE_ARRAY:
1479 case MONO_TYPE_OBJECT:
1481 case MONO_TYPE_MVAR:
1482 case MONO_TYPE_TYPEDBYREF:
1483 return TYPECODE_OBJECT;
1484 case MONO_TYPE_CLASS:
1486 MonoClass *klass = type->type->data.klass;
1487 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1488 if (strcmp (klass->name, "DBNull") == 0)
1489 return TYPECODE_DBNULL;
1492 return TYPECODE_OBJECT;
1493 case MONO_TYPE_GENERICINST:
1494 return TYPECODE_OBJECT;
1496 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1501 ICALL_EXPORT guint32
1502 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1508 MONO_ARCH_SAVE_REGS;
1510 g_assert (type != NULL);
1512 domain = ((MonoObject *)type)->vtable->domain;
1514 if (!c) /* FIXME: dont know what do do here */
1517 klass = mono_class_from_mono_type (type->type);
1518 klassc = mono_class_from_mono_type (c->type);
1520 /* Interface check requires a more complex setup so we
1521 * only do for them. Otherwise we simply avoid mono_class_init.
1523 if (check_interfaces) {
1524 mono_class_init_or_throw (klass);
1525 mono_class_init_or_throw (klassc);
1526 } else if (!klass->supertypes || !klassc->supertypes) {
1527 mono_class_setup_supertypes (klass);
1528 mono_class_setup_supertypes (klassc);
1531 if (type->type->byref)
1532 return klassc == mono_defaults.object_class;
1534 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1538 mono_type_is_primitive (MonoType *type)
1540 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1541 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1545 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1547 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1548 return mono_class_enum_basetype (type->data.klass);
1549 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1550 return mono_class_enum_basetype (type->data.generic_class->container_class);
1554 ICALL_EXPORT guint32
1555 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1561 MONO_ARCH_SAVE_REGS;
1563 g_assert (type != NULL);
1565 domain = ((MonoObject *)type)->vtable->domain;
1567 klass = mono_class_from_mono_type (type->type);
1568 klassc = mono_class_from_mono_type (c->type);
1570 if (type->type->byref ^ c->type->byref)
1573 if (type->type->byref) {
1574 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1575 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1577 klass = mono_class_from_mono_type (t);
1578 klassc = mono_class_from_mono_type (ot);
1580 if (mono_type_is_primitive (t)) {
1581 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1582 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1583 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1584 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1585 return t->type == ot->type;
1587 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1590 if (klass->valuetype)
1591 return klass == klassc;
1592 return klass->valuetype == klassc->valuetype;
1595 return mono_class_is_assignable_from (klass, klassc);
1598 ICALL_EXPORT guint32
1599 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1601 MonoClass *klass = mono_class_from_mono_type (type->type);
1602 mono_class_init_or_throw (klass);
1603 return mono_object_isinst (obj, klass) != NULL;
1606 ICALL_EXPORT guint32
1607 ves_icall_get_attributes (MonoReflectionType *type)
1609 MonoClass *klass = mono_class_from_mono_type (type->type);
1610 return klass->flags;
1613 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1614 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1616 MonoClass *klass = field->field->parent;
1617 MonoMarshalType *info;
1621 if (klass->generic_container ||
1622 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1625 ftype = mono_field_get_type (field->field);
1626 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1629 info = mono_marshal_load_type_info (klass);
1631 for (i = 0; i < info->num_fields; ++i) {
1632 if (info->fields [i].field == field->field) {
1633 if (!info->fields [i].mspec)
1636 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1643 ICALL_EXPORT MonoReflectionField*
1644 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1646 gboolean found = FALSE;
1653 klass = handle->parent;
1655 klass = mono_class_from_mono_type (type);
1657 /* Check that the field belongs to the class */
1658 for (k = klass; k; k = k->parent) {
1659 if (k == handle->parent) {
1666 /* The managed code will throw the exception */
1670 return mono_field_get_object (mono_domain_get (), klass, handle);
1673 ICALL_EXPORT MonoArray*
1674 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1677 MonoType *type = mono_field_get_type_checked (field->field, &error);
1678 mono_error_raise_exception (&error);
1680 return type_array_from_modifiers (field->field->parent->image, type, optional);
1684 vell_icall_get_method_attributes (MonoMethod *method)
1686 return method->flags;
1690 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1693 MonoDomain *domain = mono_domain_get ();
1694 MonoMethodSignature* sig;
1695 MONO_ARCH_SAVE_REGS;
1697 sig = mono_method_signature_checked (method, &error);
1698 if (!mono_error_ok (&error))
1699 mono_error_raise_exception (&error);
1702 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1703 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1704 info->attrs = method->flags;
1705 info->implattrs = method->iflags;
1706 if (sig->call_convention == MONO_CALL_DEFAULT)
1707 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1709 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1714 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1717 ICALL_EXPORT MonoArray*
1718 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1720 MonoDomain *domain = mono_domain_get ();
1722 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1725 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1726 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1728 MonoDomain *domain = mono_domain_get ();
1729 MonoReflectionMarshalAsAttribute* res = NULL;
1730 MonoMarshalSpec **mspecs;
1733 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1734 mono_method_get_marshal_info (method, mspecs);
1737 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1739 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1741 mono_metadata_free_marshal_spec (mspecs [i]);
1748 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1750 MonoClass *parent = field->field->parent;
1751 if (!parent->size_inited)
1752 mono_class_init (parent);
1753 mono_class_setup_fields_locking (parent);
1755 return field->field->offset - sizeof (MonoObject);
1758 ICALL_EXPORT MonoReflectionType*
1759 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1762 MONO_ARCH_SAVE_REGS;
1764 parent = declaring? field->field->parent: field->klass;
1766 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1769 ICALL_EXPORT MonoObject *
1770 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1772 MonoClass *fklass = field->klass;
1773 MonoClassField *cf = field->field;
1774 MonoDomain *domain = mono_object_domain (field);
1776 if (fklass->image->assembly->ref_only)
1777 mono_raise_exception (mono_get_exception_invalid_operation (
1778 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1780 if (mono_security_core_clr_enabled ())
1781 mono_security_core_clr_ensure_reflection_access_field (cf);
1783 return mono_field_get_value_object (domain, cf, obj);
1787 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1790 MonoClassField *cf = field->field;
1794 MONO_ARCH_SAVE_REGS;
1796 if (field->klass->image->assembly->ref_only)
1797 mono_raise_exception (mono_get_exception_invalid_operation (
1798 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1800 if (mono_security_core_clr_enabled ())
1801 mono_security_core_clr_ensure_reflection_access_field (cf);
1803 type = mono_field_get_type_checked (cf, &error);
1804 if (!mono_error_ok (&error))
1805 mono_error_raise_exception (&error);
1807 v = (gchar *) value;
1809 switch (type->type) {
1812 case MONO_TYPE_BOOLEAN:
1815 case MONO_TYPE_CHAR:
1824 case MONO_TYPE_VALUETYPE:
1827 v += sizeof (MonoObject);
1829 case MONO_TYPE_STRING:
1830 case MONO_TYPE_OBJECT:
1831 case MONO_TYPE_CLASS:
1832 case MONO_TYPE_ARRAY:
1833 case MONO_TYPE_SZARRAY:
1836 case MONO_TYPE_GENERICINST: {
1837 MonoGenericClass *gclass = type->data.generic_class;
1838 g_assert (!gclass->context.class_inst->is_open);
1840 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1841 MonoClass *nklass = mono_class_from_mono_type (type);
1842 MonoObject *nullable;
1845 * Convert the boxed vtype into a Nullable structure.
1846 * This is complicated by the fact that Nullables have
1847 * a variable structure.
1849 nullable = mono_object_new (mono_domain_get (), nklass);
1851 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1853 v = mono_object_unbox (nullable);
1856 if (gclass->container_class->valuetype && (v != NULL))
1857 v += sizeof (MonoObject);
1861 g_error ("type 0x%x not handled in "
1862 "ves_icall_FieldInfo_SetValueInternal", type->type);
1867 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1868 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1869 if (!vtable->initialized)
1870 mono_runtime_class_init (vtable);
1871 mono_field_static_set_value (vtable, cf, v);
1873 mono_field_set_value (obj, cf, v);
1877 ICALL_EXPORT MonoObject *
1878 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1880 MonoObject *o = NULL;
1881 MonoClassField *field = this->field;
1883 MonoDomain *domain = mono_object_domain (this);
1885 MonoTypeEnum def_type;
1886 const char *def_value;
1890 MONO_ARCH_SAVE_REGS;
1892 mono_class_init (field->parent);
1894 t = mono_field_get_type_checked (field, &error);
1895 if (!mono_error_ok (&error))
1896 mono_error_raise_exception (&error);
1898 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1899 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1901 if (image_is_dynamic (field->parent->image)) {
1902 MonoClass *klass = field->parent;
1903 int fidx = field - klass->fields;
1905 g_assert (fidx >= 0 && fidx < klass->field.count);
1906 g_assert (klass->ext);
1907 g_assert (klass->ext->field_def_values);
1908 def_type = klass->ext->field_def_values [fidx].def_type;
1909 def_value = klass->ext->field_def_values [fidx].data;
1910 if (def_type == MONO_TYPE_END)
1911 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1913 def_value = mono_class_get_field_default_value (field, &def_type);
1914 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1916 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1919 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1923 case MONO_TYPE_BOOLEAN:
1926 case MONO_TYPE_CHAR:
1934 case MONO_TYPE_R8: {
1937 /* boxed value type */
1938 t = g_new0 (MonoType, 1);
1940 klass = mono_class_from_mono_type (t);
1942 o = mono_object_new (domain, klass);
1943 v = ((gchar *) o) + sizeof (MonoObject);
1944 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1947 case MONO_TYPE_STRING:
1948 case MONO_TYPE_CLASS:
1949 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1952 g_assert_not_reached ();
1958 ICALL_EXPORT MonoReflectionType*
1959 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1962 MonoClassField *field = ref_field->field;
1963 MonoType *type = mono_field_get_type_checked (field, &error);
1964 if (!mono_error_ok (&error))
1965 mono_error_raise_exception (&error);
1966 return mono_type_get_object (mono_object_domain (ref_field), type);
1969 ICALL_EXPORT MonoReflectionType*
1970 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1972 MonoMethod *method = rmethod->method.method;
1974 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1977 /* From MonoProperty.cs */
1979 PInfo_Attributes = 1,
1980 PInfo_GetMethod = 1 << 1,
1981 PInfo_SetMethod = 1 << 2,
1982 PInfo_ReflectedType = 1 << 3,
1983 PInfo_DeclaringType = 1 << 4,
1988 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1990 MonoDomain *domain = mono_object_domain (property);
1992 MONO_ARCH_SAVE_REGS;
1994 if ((req_info & PInfo_ReflectedType) != 0)
1995 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1996 if ((req_info & PInfo_DeclaringType) != 0)
1997 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1999 if ((req_info & PInfo_Name) != 0)
2000 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2002 if ((req_info & PInfo_Attributes) != 0)
2003 info->attrs = property->property->attrs;
2005 if ((req_info & PInfo_GetMethod) != 0)
2006 MONO_STRUCT_SETREF (info, get, property->property->get ?
2007 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2009 if ((req_info & PInfo_SetMethod) != 0)
2010 MONO_STRUCT_SETREF (info, set, property->property->set ?
2011 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2013 * There may be other methods defined for properties, though, it seems they are not exposed
2014 * in the reflection API
2019 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2021 MonoDomain *domain = mono_object_domain (event);
2023 MONO_ARCH_SAVE_REGS;
2025 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2026 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2028 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2029 info->attrs = event->event->attrs;
2030 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2031 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2032 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2034 #ifndef MONO_SMALL_CONFIG
2035 if (event->event->other) {
2037 while (event->event->other [n])
2039 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2041 for (i = 0; i < n; i++)
2042 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2048 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2053 mono_class_setup_interfaces (klass, error);
2054 if (!mono_error_ok (error))
2057 for (i = 0; i < klass->interface_count; i++) {
2058 ic = klass->interfaces [i];
2059 g_hash_table_insert (ifaces, ic, ic);
2061 collect_interfaces (ic, ifaces, error);
2062 if (!mono_error_ok (error))
2068 MonoArray *iface_array;
2069 MonoGenericContext *context;
2073 } FillIfaceArrayData;
2076 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2078 FillIfaceArrayData *data = user_data;
2079 MonoClass *ic = key;
2080 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2082 if (!mono_error_ok (data->error))
2085 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2086 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2087 if (!mono_error_ok (data->error))
2091 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2094 mono_metadata_free_type (inflated);
2097 ICALL_EXPORT MonoArray*
2098 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2101 MonoClass *class = mono_class_from_mono_type (type->type);
2103 FillIfaceArrayData data = { 0 };
2106 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2108 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2109 data.context = mono_class_get_context (class);
2110 class = class->generic_class->container_class;
2113 for (parent = class; parent; parent = parent->parent) {
2114 mono_class_setup_interfaces (parent, &error);
2115 if (!mono_error_ok (&error))
2117 collect_interfaces (parent, iface_hash, &error);
2118 if (!mono_error_ok (&error))
2122 data.error = &error;
2123 data.domain = mono_object_domain (type);
2125 len = g_hash_table_size (iface_hash);
2127 g_hash_table_destroy (iface_hash);
2128 if (!data.domain->empty_types)
2129 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2130 return data.domain->empty_types;
2133 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2134 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2135 if (!mono_error_ok (&error))
2138 g_hash_table_destroy (iface_hash);
2139 return data.iface_array;
2142 g_hash_table_destroy (iface_hash);
2143 mono_error_raise_exception (&error);
2148 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2150 gboolean variance_used;
2151 MonoClass *class = mono_class_from_mono_type (type->type);
2152 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2153 MonoReflectionMethod *member;
2156 int i = 0, len, ioffset;
2159 MONO_ARCH_SAVE_REGS;
2160 mono_class_init_or_throw (class);
2161 mono_class_init_or_throw (iclass);
2163 mono_class_setup_vtable (class);
2165 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2169 len = mono_class_num_methods (iclass);
2170 domain = mono_object_domain (type);
2171 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2172 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2174 while ((method = mono_class_get_methods (iclass, &iter))) {
2175 member = mono_method_get_object (domain, method, iclass);
2176 mono_array_setref (*methods, i, member);
2177 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2178 mono_array_setref (*targets, i, member);
2185 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2187 MonoClass *klass = mono_class_from_mono_type (type->type);
2188 mono_class_init_or_throw (klass);
2190 if (image_is_dynamic (klass->image)) {
2191 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2192 *packing = tb->packing_size;
2193 *size = tb->class_size;
2195 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2199 ICALL_EXPORT MonoReflectionType*
2200 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2204 MONO_ARCH_SAVE_REGS;
2206 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2207 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2209 class = mono_class_from_mono_type (type->type);
2210 mono_class_init_or_throw (class);
2212 // GetElementType should only return a type for:
2213 // Array Pointer PassedByRef
2214 if (type->type->byref)
2215 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2216 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2217 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2218 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2219 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2224 ICALL_EXPORT MonoReflectionType*
2225 ves_icall_get_type_parent (MonoReflectionType *type)
2227 MonoClass *class = mono_class_from_mono_type (type->type);
2228 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2231 ICALL_EXPORT MonoBoolean
2232 ves_icall_type_ispointer (MonoReflectionType *type)
2234 MONO_ARCH_SAVE_REGS;
2236 return type->type->type == MONO_TYPE_PTR;
2239 ICALL_EXPORT MonoBoolean
2240 ves_icall_type_isprimitive (MonoReflectionType *type)
2242 MONO_ARCH_SAVE_REGS;
2244 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)));
2247 ICALL_EXPORT MonoBoolean
2248 ves_icall_type_isbyref (MonoReflectionType *type)
2250 MONO_ARCH_SAVE_REGS;
2252 return type->type->byref;
2255 ICALL_EXPORT MonoBoolean
2256 ves_icall_type_iscomobject (MonoReflectionType *type)
2258 MonoClass *klass = mono_class_from_mono_type (type->type);
2259 mono_class_init_or_throw (klass);
2261 return mono_class_is_com_object (klass);
2264 ICALL_EXPORT MonoReflectionModule*
2265 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2267 MonoClass *class = mono_class_from_mono_type (type->type);
2268 return mono_module_get_object (mono_object_domain (type), class->image);
2271 ICALL_EXPORT MonoReflectionAssembly*
2272 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2274 MonoDomain *domain = mono_domain_get ();
2275 MonoClass *class = mono_class_from_mono_type (type->type);
2276 return mono_assembly_get_object (domain, class->image->assembly);
2279 ICALL_EXPORT MonoReflectionType*
2280 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2282 MonoDomain *domain = mono_domain_get ();
2285 MONO_ARCH_SAVE_REGS;
2287 if (type->type->byref)
2289 if (type->type->type == MONO_TYPE_VAR) {
2290 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2291 class = param ? param->owner.klass : NULL;
2292 } else if (type->type->type == MONO_TYPE_MVAR) {
2293 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2294 class = param ? param->owner.method->klass : NULL;
2296 class = mono_class_from_mono_type (type->type)->nested_in;
2299 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2302 ICALL_EXPORT MonoString*
2303 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2305 MonoDomain *domain = mono_domain_get ();
2306 MonoClass *class = mono_class_from_mono_type (type->type);
2308 if (type->type->byref) {
2309 char *n = g_strdup_printf ("%s&", class->name);
2310 MonoString *res = mono_string_new (domain, n);
2316 return mono_string_new (domain, class->name);
2320 ICALL_EXPORT MonoString*
2321 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2323 MonoDomain *domain = mono_domain_get ();
2324 MonoClass *class = mono_class_from_mono_type (type->type);
2326 while (class->nested_in)
2327 class = class->nested_in;
2329 if (class->name_space [0] == '\0')
2332 return mono_string_new (domain, class->name_space);
2336 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2340 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2341 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2343 class = mono_class_from_mono_type (type->type);
2348 ICALL_EXPORT MonoArray*
2349 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2352 MonoClass *klass, *pklass;
2353 MonoDomain *domain = mono_object_domain (type);
2354 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2356 MONO_ARCH_SAVE_REGS;
2358 klass = mono_class_from_mono_type (type->type);
2360 if (klass->generic_container) {
2361 MonoGenericContainer *container = klass->generic_container;
2362 res = mono_array_new_specific (array_vtable, container->type_argc);
2363 for (i = 0; i < container->type_argc; ++i) {
2364 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2365 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2367 } else if (klass->generic_class) {
2368 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2369 res = mono_array_new_specific (array_vtable, inst->type_argc);
2370 for (i = 0; i < inst->type_argc; ++i)
2371 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2373 res = mono_array_new_specific (array_vtable, 0);
2378 ICALL_EXPORT gboolean
2379 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2382 MONO_ARCH_SAVE_REGS;
2384 if (!IS_MONOTYPE (type))
2387 if (type->type->byref)
2390 klass = mono_class_from_mono_type (type->type);
2391 return klass->generic_container != NULL;
2394 ICALL_EXPORT MonoReflectionType*
2395 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2398 MONO_ARCH_SAVE_REGS;
2400 if (type->type->byref)
2403 klass = mono_class_from_mono_type (type->type);
2405 if (klass->generic_container) {
2406 return type; /* check this one */
2408 if (klass->generic_class) {
2409 MonoClass *generic_class = klass->generic_class->container_class;
2412 tb = mono_class_get_ref_info (generic_class);
2414 if (generic_class->wastypebuilder && tb)
2417 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2422 ICALL_EXPORT MonoReflectionType*
2423 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2426 MonoType *geninst, **types;
2429 g_assert (IS_MONOTYPE (type));
2430 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2432 count = mono_array_length (type_array);
2433 types = g_new0 (MonoType *, count);
2435 for (i = 0; i < count; i++) {
2436 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2437 types [i] = t->type;
2440 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2445 class = mono_class_from_mono_type (geninst);
2447 /*we might inflate to the GTD*/
2448 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2449 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2451 return mono_type_get_object (mono_object_domain (type), geninst);
2454 ICALL_EXPORT gboolean
2455 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2458 MONO_ARCH_SAVE_REGS;
2460 if (type->type->byref)
2463 klass = mono_class_from_mono_type (type->type);
2465 return klass->generic_class != NULL;
2468 ICALL_EXPORT gboolean
2469 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2472 MONO_ARCH_SAVE_REGS;
2474 if (!IS_MONOTYPE (type))
2477 if (type->type->byref)
2480 klass = mono_class_from_mono_type (type->type);
2481 return klass->generic_class != NULL || klass->generic_container != NULL;
2485 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2487 MONO_ARCH_SAVE_REGS;
2489 if (!IS_MONOTYPE (type))
2492 if (is_generic_parameter (type->type))
2493 return mono_type_get_generic_param_num (type->type);
2497 ICALL_EXPORT GenericParameterAttributes
2498 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2500 MONO_ARCH_SAVE_REGS;
2502 g_assert (IS_MONOTYPE (type));
2503 g_assert (is_generic_parameter (type->type));
2504 return mono_generic_param_info (type->type->data.generic_param)->flags;
2507 ICALL_EXPORT MonoArray *
2508 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2510 MonoGenericParamInfo *param_info;
2516 MONO_ARCH_SAVE_REGS;
2518 g_assert (IS_MONOTYPE (type));
2520 domain = mono_object_domain (type);
2521 param_info = mono_generic_param_info (type->type->data.generic_param);
2522 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2525 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2526 for (i = 0; i < count; i++)
2527 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2533 ICALL_EXPORT MonoBoolean
2534 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2536 MONO_ARCH_SAVE_REGS;
2537 return is_generic_parameter (type->type);
2540 ICALL_EXPORT MonoBoolean
2541 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2543 MONO_ARCH_SAVE_REGS;
2544 return is_generic_parameter (tb->type.type);
2548 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2549 MonoReflectionType *t)
2551 enumtype->type = t->type;
2554 ICALL_EXPORT MonoReflectionMethod*
2555 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2556 MonoReflectionMethod* generic)
2563 MONO_ARCH_SAVE_REGS;
2565 domain = ((MonoObject *)type)->vtable->domain;
2567 klass = mono_class_from_mono_type (type->type);
2568 mono_class_init_or_throw (klass);
2571 while ((method = mono_class_get_methods (klass, &iter))) {
2572 if (method->token == generic->method->token)
2573 return mono_method_get_object (domain, method, klass);
2581 ICALL_EXPORT MonoReflectionMethod *
2582 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2585 MonoType *type = ref_type->type;
2587 MONO_ARCH_SAVE_REGS;
2589 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2590 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2591 if (type->type == MONO_TYPE_VAR)
2594 method = mono_type_get_generic_param_owner (type)->owner.method;
2596 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2599 ICALL_EXPORT MonoReflectionDllImportAttribute*
2600 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2602 static MonoClass *DllImportAttributeClass = NULL;
2603 MonoDomain *domain = mono_domain_get ();
2604 MonoReflectionDllImportAttribute *attr;
2605 MonoImage *image = method->klass->image;
2606 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2607 MonoTableInfo *tables = image->tables;
2608 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2609 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2610 guint32 im_cols [MONO_IMPLMAP_SIZE];
2611 guint32 scope_token;
2612 const char *import = NULL;
2613 const char *scope = NULL;
2616 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2619 if (!DllImportAttributeClass) {
2620 DllImportAttributeClass =
2621 mono_class_from_name (mono_defaults.corlib,
2622 "System.Runtime.InteropServices", "DllImportAttribute");
2623 g_assert (DllImportAttributeClass);
2626 if (image_is_dynamic (method->klass->image)) {
2627 MonoReflectionMethodAux *method_aux =
2628 g_hash_table_lookup (
2629 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2631 import = method_aux->dllentry;
2632 scope = method_aux->dll;
2635 if (!import || !scope) {
2636 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2641 if (piinfo->implmap_idx) {
2642 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2644 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2645 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2646 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2647 scope = mono_metadata_string_heap (image, scope_token);
2650 flags = piinfo->piflags;
2652 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2654 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2655 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2656 attr->call_conv = (flags & 0x700) >> 8;
2657 attr->charset = ((flags & 0x6) >> 1) + 1;
2658 if (attr->charset == 1)
2660 attr->exact_spelling = (flags & 0x1) != 0;
2661 attr->set_last_error = (flags & 0x40) != 0;
2662 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2663 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2664 attr->preserve_sig = FALSE;
2669 ICALL_EXPORT MonoReflectionMethod *
2670 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2672 MonoMethodInflated *imethod;
2675 MONO_ARCH_SAVE_REGS;
2677 if (method->method->is_generic)
2680 if (!method->method->is_inflated)
2683 imethod = (MonoMethodInflated *) method->method;
2685 result = imethod->declaring;
2686 /* Not a generic method. */
2687 if (!result->is_generic)
2690 if (image_is_dynamic (method->method->klass->image)) {
2691 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2692 MonoReflectionMethod *res;
2695 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2696 * the dynamic case as well ?
2698 mono_image_lock ((MonoImage*)image);
2699 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2700 mono_image_unlock ((MonoImage*)image);
2706 if (imethod->context.class_inst) {
2707 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2708 /*Generic methods gets the context of the GTD.*/
2709 if (mono_class_get_context (klass))
2710 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2713 return mono_method_get_object (mono_object_domain (method), result, NULL);
2716 ICALL_EXPORT gboolean
2717 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2719 MONO_ARCH_SAVE_REGS;
2721 return mono_method_signature (method->method)->generic_param_count != 0;
2724 ICALL_EXPORT gboolean
2725 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2727 MONO_ARCH_SAVE_REGS;
2729 return method->method->is_generic;
2732 ICALL_EXPORT MonoArray*
2733 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2738 MONO_ARCH_SAVE_REGS;
2740 domain = mono_object_domain (method);
2742 if (method->method->is_inflated) {
2743 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2746 count = inst->type_argc;
2747 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2749 for (i = 0; i < count; i++)
2750 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2756 count = mono_method_signature (method->method)->generic_param_count;
2757 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2759 for (i = 0; i < count; i++) {
2760 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2761 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2762 MonoClass *pklass = mono_class_from_generic_parameter (
2763 param, method->method->klass->image, TRUE);
2764 mono_array_setref (res, i,
2765 mono_type_get_object (domain, &pklass->byval_arg));
2771 ICALL_EXPORT MonoObject *
2772 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2775 * Invoke from reflection is supposed to always be a virtual call (the API
2776 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2777 * greater flexibility.
2779 MonoMethod *m = method->method;
2780 MonoMethodSignature *sig = mono_method_signature (m);
2785 MONO_ARCH_SAVE_REGS;
2789 if (mono_security_core_clr_enabled ())
2790 mono_security_core_clr_ensure_reflection_access_method (m);
2792 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2793 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2794 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2799 if (!mono_object_isinst (this, m->klass)) {
2800 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2801 char *target_name = mono_type_get_full_name (m->klass);
2802 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2803 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2805 g_free (target_name);
2809 m = mono_object_get_virtual_method (this, m);
2810 /* must pass the pointer to the value for valuetype methods */
2811 if (m->klass->valuetype)
2812 obj = mono_object_unbox (this);
2813 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2814 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2819 if (sig->ret->byref) {
2820 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"));
2824 pcount = params? mono_array_length (params): 0;
2825 if (pcount != sig->param_count) {
2826 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2830 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2831 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."));
2835 image = m->klass->image;
2836 if (image->assembly->ref_only) {
2837 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."));
2841 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2842 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2846 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2849 intptr_t *lower_bounds;
2850 pcount = mono_array_length (params);
2851 lengths = alloca (sizeof (uintptr_t) * pcount);
2852 /* Note: the synthetized array .ctors have int32 as argument type */
2853 for (i = 0; i < pcount; ++i)
2854 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2856 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2857 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2858 MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2860 for (i = 0; i < mono_array_length (arr); ++i) {
2861 MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
2863 mono_array_setref_fast (arr, i, subarray);
2865 return (MonoObject*)arr;
2868 if (m->klass->rank == pcount) {
2869 /* Only lengths provided. */
2870 lower_bounds = NULL;
2872 g_assert (pcount == (m->klass->rank * 2));
2873 /* lower bounds are first. */
2874 lower_bounds = (intptr_t*)lengths;
2875 lengths += m->klass->rank;
2878 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2880 return mono_runtime_invoke_array (m, obj, params, NULL);
2883 #ifndef DISABLE_REMOTING
2884 ICALL_EXPORT MonoObject *
2885 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2887 MonoDomain *domain = mono_object_domain (method);
2888 MonoMethod *m = method->method;
2889 MonoMethodSignature *sig = mono_method_signature (m);
2890 MonoArray *out_args;
2892 int i, j, outarg_count = 0;
2894 MONO_ARCH_SAVE_REGS;
2896 if (m->klass == mono_defaults.object_class) {
2898 if (!strcmp (m->name, "FieldGetter")) {
2899 MonoClass *k = this->vtable->klass;
2903 /* If this is a proxy, then it must be a CBO */
2904 if (k == mono_defaults.transparent_proxy_class) {
2905 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2906 this = tp->rp->unwrapped_server;
2908 k = this->vtable->klass;
2911 name = mono_array_get (params, MonoString *, 1);
2912 str = mono_string_to_utf8 (name);
2915 MonoClassField* field = mono_class_get_field_from_name (k, str);
2917 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2918 if (field_klass->valuetype)
2919 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2921 result = *((gpointer *)((char *)this + field->offset));
2923 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2924 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2925 mono_array_setref (out_args, 0, result);
2933 g_assert_not_reached ();
2935 } else if (!strcmp (m->name, "FieldSetter")) {
2936 MonoClass *k = this->vtable->klass;
2942 /* If this is a proxy, then it must be a CBO */
2943 if (k == mono_defaults.transparent_proxy_class) {
2944 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2945 this = tp->rp->unwrapped_server;
2947 k = this->vtable->klass;
2950 name = mono_array_get (params, MonoString *, 1);
2951 str = mono_string_to_utf8 (name);
2954 MonoClassField* field = mono_class_get_field_from_name (k, str);
2956 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2957 MonoObject *val = mono_array_get (params, gpointer, 2);
2959 if (field_klass->valuetype) {
2960 size = mono_type_size (field->type, &align);
2961 g_assert (size == mono_class_value_size (field_klass, NULL));
2962 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2964 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2967 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2968 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2978 g_assert_not_reached ();
2983 for (i = 0; i < mono_array_length (params); i++) {
2984 if (sig->params [i]->byref)
2988 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2990 /* handle constructors only for objects already allocated */
2991 if (!strcmp (method->method->name, ".ctor"))
2994 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2995 g_assert (!method->method->klass->valuetype);
2996 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2998 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2999 if (sig->params [i]->byref) {
3001 arg = mono_array_get (params, gpointer, i);
3002 mono_array_setref (out_args, j, arg);
3007 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3014 read_enum_value (char *mem, int type)
3017 case MONO_TYPE_BOOLEAN:
3019 return *(guint8*)mem;
3021 return *(gint8*)mem;
3022 case MONO_TYPE_CHAR:
3024 return *(guint16*)mem;
3026 return *(gint16*)mem;
3028 return *(guint32*)mem;
3030 return *(gint32*)mem;
3032 return *(guint64*)mem;
3034 return *(gint64*)mem;
3036 g_assert_not_reached ();
3042 write_enum_value (char *mem, int type, guint64 value)
3046 case MONO_TYPE_I1: {
3047 guint8 *p = (guint8*)mem;
3052 case MONO_TYPE_I2: {
3053 guint16 *p = (void*)mem;
3058 case MONO_TYPE_I4: {
3059 guint32 *p = (void*)mem;
3064 case MONO_TYPE_I8: {
3065 guint64 *p = (void*)mem;
3070 g_assert_not_reached ();
3075 ICALL_EXPORT MonoObject *
3076 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3079 MonoClass *enumc, *objc;
3084 MONO_ARCH_SAVE_REGS;
3086 MONO_CHECK_ARG_NULL (enumType);
3087 MONO_CHECK_ARG_NULL (value);
3089 domain = mono_object_domain (enumType);
3090 enumc = mono_class_from_mono_type (enumType->type);
3092 mono_class_init_or_throw (enumc);
3094 objc = value->vtable->klass;
3096 if (!enumc->enumtype)
3097 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3098 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_BOOLEAN && objc->byval_arg.type <= MONO_TYPE_U8)))
3099 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."));
3101 etype = mono_class_enum_basetype (enumc);
3103 /* MS throws this for typebuilders */
3104 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3106 res = mono_object_new (domain, enumc);
3107 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3108 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3113 ICALL_EXPORT MonoObject *
3114 ves_icall_System_Enum_get_value (MonoObject *this)
3122 MONO_ARCH_SAVE_REGS;
3127 g_assert (this->vtable->klass->enumtype);
3129 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3130 res = mono_object_new (mono_object_domain (this), enumc);
3131 dst = (char *)res + sizeof (MonoObject);
3132 src = (char *)this + sizeof (MonoObject);
3133 size = mono_class_value_size (enumc, NULL);
3135 memcpy (dst, src, size);
3140 ICALL_EXPORT MonoReflectionType *
3141 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3146 MONO_ARCH_SAVE_REGS;
3148 klass = mono_class_from_mono_type (type->type);
3149 mono_class_init_or_throw (klass);
3151 etype = mono_class_enum_basetype (klass);
3153 /* MS throws this for typebuilders */
3154 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3156 return mono_type_get_object (mono_object_domain (type), etype);
3160 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3162 gpointer tdata = (char *)this + sizeof (MonoObject);
3163 gpointer odata = (char *)other + sizeof (MonoObject);
3164 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3165 g_assert (basetype);
3167 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3168 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3169 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3172 return me > other ? 1 : -1; \
3175 switch (basetype->type) {
3177 COMPARE_ENUM_VALUES (guint8);
3179 COMPARE_ENUM_VALUES (gint8);
3180 case MONO_TYPE_CHAR:
3182 COMPARE_ENUM_VALUES (guint16);
3184 COMPARE_ENUM_VALUES (gint16);
3186 COMPARE_ENUM_VALUES (guint32);
3188 COMPARE_ENUM_VALUES (gint32);
3190 COMPARE_ENUM_VALUES (guint64);
3192 COMPARE_ENUM_VALUES (gint64);
3194 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3196 #undef COMPARE_ENUM_VALUES
3201 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3203 gpointer data = (char *)this + sizeof (MonoObject);
3204 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3205 g_assert (basetype);
3207 switch (basetype->type) {
3209 return *((gint8*)data);
3211 return *((guint8*)data);
3212 case MONO_TYPE_CHAR:
3214 return *((guint16*)data);
3217 return *((gint16*)data);
3219 return *((guint32*)data);
3221 return *((gint32*)data);
3223 case MONO_TYPE_I8: {
3224 gint64 value = *((gint64*)data);
3225 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3228 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3234 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3236 MonoDomain *domain = mono_object_domain (type);
3237 MonoClass *enumc = mono_class_from_mono_type (type->type);
3238 guint j = 0, nvalues, crow;
3240 MonoClassField *field;
3242 MONO_ARCH_SAVE_REGS;
3244 mono_class_init_or_throw (enumc);
3246 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3247 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3248 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3249 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3253 while ((field = mono_class_get_fields (enumc, &iter))) {
3256 MonoTypeEnum def_type;
3258 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3260 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3262 if (mono_field_is_deleted (field))
3264 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3266 p = mono_class_get_field_default_value (field, &def_type);
3267 len = mono_metadata_decode_blob_size (p, &p);
3268 switch (mono_class_enum_basetype (enumc)->type) {
3271 mono_array_set (info->values, gchar, j, *p);
3273 case MONO_TYPE_CHAR:
3276 mono_array_set (info->values, gint16, j, read16 (p));
3280 mono_array_set (info->values, gint32, j, read32 (p));
3284 mono_array_set (info->values, gint64, j, read64 (p));
3287 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3294 BFLAGS_IgnoreCase = 1,
3295 BFLAGS_DeclaredOnly = 2,
3296 BFLAGS_Instance = 4,
3298 BFLAGS_Public = 0x10,
3299 BFLAGS_NonPublic = 0x20,
3300 BFLAGS_FlattenHierarchy = 0x40,
3301 BFLAGS_InvokeMethod = 0x100,
3302 BFLAGS_CreateInstance = 0x200,
3303 BFLAGS_GetField = 0x400,
3304 BFLAGS_SetField = 0x800,
3305 BFLAGS_GetProperty = 0x1000,
3306 BFLAGS_SetProperty = 0x2000,
3307 BFLAGS_ExactBinding = 0x10000,
3308 BFLAGS_SuppressChangeType = 0x20000,
3309 BFLAGS_OptionalParamBinding = 0x40000
3312 ICALL_EXPORT MonoReflectionField *
3313 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3316 MonoClass *startklass, *klass;
3318 MonoClassField *field;
3321 int (*compare_func) (const char *s1, const char *s2) = NULL;
3322 domain = ((MonoObject *)type)->vtable->domain;
3323 klass = startklass = mono_class_from_mono_type (type->type);
3326 mono_raise_exception (mono_get_exception_argument_null ("name"));
3327 if (type->type->byref)
3330 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3333 if (klass->exception_type != MONO_EXCEPTION_NONE)
3334 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3337 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3338 guint32 flags = mono_field_get_flags (field);
3341 if (mono_field_is_deleted_with_flags (field, flags))
3343 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3344 if (bflags & BFLAGS_Public)
3346 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3347 if (bflags & BFLAGS_NonPublic) {
3354 if (flags & FIELD_ATTRIBUTE_STATIC) {
3355 if (bflags & BFLAGS_Static)
3356 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3359 if (bflags & BFLAGS_Instance)
3366 utf8_name = mono_string_to_utf8 (name);
3368 if (compare_func (mono_field_get_name (field), utf8_name)) {
3374 return mono_field_get_object (domain, klass, field);
3376 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3382 ICALL_EXPORT MonoArray*
3383 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3386 MonoClass *startklass, *klass, *refklass;
3391 MonoClassField *field;
3392 MonoPtrArray tmp_array;
3394 MONO_ARCH_SAVE_REGS;
3396 domain = ((MonoObject *)type)->vtable->domain;
3397 if (type->type->byref)
3398 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3399 klass = startklass = mono_class_from_mono_type (type->type);
3400 refklass = mono_class_from_mono_type (reftype->type);
3402 mono_ptr_array_init (tmp_array, 2);
3405 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3406 mono_ptr_array_destroy (tmp_array);
3407 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3411 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3412 guint32 flags = mono_field_get_flags (field);
3414 if (mono_field_is_deleted_with_flags (field, flags))
3416 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3417 if (bflags & BFLAGS_Public)
3419 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3420 if (bflags & BFLAGS_NonPublic) {
3427 if (flags & FIELD_ATTRIBUTE_STATIC) {
3428 if (bflags & BFLAGS_Static)
3429 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3432 if (bflags & BFLAGS_Instance)
3438 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3439 mono_ptr_array_append (tmp_array, member);
3441 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3444 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3446 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3447 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3449 mono_ptr_array_destroy (tmp_array);
3455 method_nonpublic (MonoMethod* method, gboolean start_klass)
3457 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3458 case METHOD_ATTRIBUTE_ASSEM:
3459 return (start_klass || mono_defaults.generic_ilist_class);
3460 case METHOD_ATTRIBUTE_PRIVATE:
3462 case METHOD_ATTRIBUTE_PUBLIC:
3470 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3473 MonoClass *startklass;
3476 int len, match, nslots;
3477 /*FIXME, use MonoBitSet*/
3478 guint32 method_slots_default [8];
3479 guint32 *method_slots = NULL;
3480 int (*compare_func) (const char *s1, const char *s2) = NULL;
3482 array = g_ptr_array_new ();
3488 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3490 /* An optimization for calls made from Delegate:CreateDelegate () */
3491 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3492 method = mono_get_delegate_invoke (klass);
3493 if (mono_loader_get_last_error ())
3496 g_ptr_array_add (array, method);
3500 mono_class_setup_vtable (klass);
3501 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3504 if (is_generic_parameter (&klass->byval_arg))
3505 nslots = mono_class_get_vtable_size (klass->parent);
3507 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3508 if (nslots >= sizeof (method_slots_default) * 8) {
3509 method_slots = g_new0 (guint32, nslots / 32 + 1);
3511 method_slots = method_slots_default;
3512 memset (method_slots, 0, sizeof (method_slots_default));
3515 mono_class_setup_vtable (klass);
3516 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3520 while ((method = mono_class_get_methods (klass, &iter))) {
3522 if (method->slot != -1) {
3523 g_assert (method->slot < nslots);
3524 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3526 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3527 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3530 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3532 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3533 if (bflags & BFLAGS_Public)
3535 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3541 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3542 if (bflags & BFLAGS_Static)
3543 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3546 if (bflags & BFLAGS_Instance)
3554 if (compare_func (name, method->name))
3559 g_ptr_array_add (array, method);
3561 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3563 if (method_slots != method_slots_default)
3564 g_free (method_slots);
3569 if (method_slots != method_slots_default)
3570 g_free (method_slots);
3571 g_ptr_array_free (array, TRUE);
3573 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3574 *ex = mono_class_get_exception_for_failure (klass);
3576 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3577 mono_loader_clear_error ();
3582 ICALL_EXPORT MonoArray*
3583 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3585 static MonoClass *MethodInfo_array;
3588 MonoVTable *array_vtable;
3589 MonoException *ex = NULL;
3590 const char *mname = NULL;
3591 GPtrArray *method_array;
3592 MonoClass *klass, *refklass;
3595 if (!MethodInfo_array) {
3596 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3597 mono_memory_barrier ();
3598 MethodInfo_array = klass;
3601 klass = mono_class_from_mono_type (type->type);
3602 refklass = mono_class_from_mono_type (reftype->type);
3603 domain = ((MonoObject *)type)->vtable->domain;
3604 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3605 if (type->type->byref)
3606 return mono_array_new_specific (array_vtable, 0);
3609 mname = mono_string_to_utf8 (name);
3611 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3612 g_free ((char*)mname);
3614 mono_raise_exception (ex);
3616 res = mono_array_new_specific (array_vtable, method_array->len);
3619 for (i = 0; i < method_array->len; ++i) {
3620 MonoMethod *method = g_ptr_array_index (method_array, i);
3621 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3624 g_ptr_array_free (method_array, TRUE);
3628 ICALL_EXPORT MonoArray*
3629 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3632 static MonoClass *System_Reflection_ConstructorInfo;
3633 MonoClass *startklass, *klass, *refklass;
3638 gpointer iter = NULL;
3639 MonoPtrArray tmp_array;
3641 MONO_ARCH_SAVE_REGS;
3643 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3645 domain = ((MonoObject *)type)->vtable->domain;
3646 if (type->type->byref)
3647 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3648 klass = startklass = mono_class_from_mono_type (type->type);
3649 refklass = mono_class_from_mono_type (reftype->type);
3651 if (!System_Reflection_ConstructorInfo)
3652 System_Reflection_ConstructorInfo = mono_class_from_name (
3653 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3656 while ((method = mono_class_get_methods (klass, &iter))) {
3658 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3660 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3661 if (bflags & BFLAGS_Public)
3664 if (bflags & BFLAGS_NonPublic)
3670 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3671 if (bflags & BFLAGS_Static)
3672 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3675 if (bflags & BFLAGS_Instance)
3681 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3683 mono_ptr_array_append (tmp_array, member);
3686 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3688 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3689 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3691 mono_ptr_array_destroy (tmp_array);
3697 property_hash (gconstpointer data)
3699 MonoProperty *prop = (MonoProperty*)data;
3701 return g_str_hash (prop->name);
3705 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3707 // Properties are hide-by-name-and-signature
3708 if (!g_str_equal (prop1->name, prop2->name))
3711 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3713 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3719 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3724 return method_nonpublic (accessor, start_klass);
3727 ICALL_EXPORT MonoArray*
3728 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3732 static MonoClass *System_Reflection_PropertyInfo;
3733 MonoClass *startklass, *klass;
3739 gchar *propname = NULL;
3740 int (*compare_func) (const char *s1, const char *s2) = NULL;
3742 GHashTable *properties = NULL;
3743 MonoPtrArray tmp_array;
3745 MONO_ARCH_SAVE_REGS;
3747 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3749 if (!System_Reflection_PropertyInfo)
3750 System_Reflection_PropertyInfo = mono_class_from_name (
3751 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3753 domain = ((MonoObject *)type)->vtable->domain;
3754 if (type->type->byref)
3755 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3756 klass = startklass = mono_class_from_mono_type (type->type);
3759 propname = mono_string_to_utf8 (name);
3760 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3763 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3765 mono_class_setup_vtable (klass);
3766 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3770 while ((prop = mono_class_get_properties (klass, &iter))) {
3776 flags = method->flags;
3779 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3780 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3781 if (bflags & BFLAGS_Public)
3783 } else if (bflags & BFLAGS_NonPublic) {
3784 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3785 property_accessor_nonpublic(prop->set, startklass == klass)) {
3792 if (flags & METHOD_ATTRIBUTE_STATIC) {
3793 if (bflags & BFLAGS_Static)
3794 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3797 if (bflags & BFLAGS_Instance)
3806 if (compare_func (propname, prop->name))
3810 if (g_hash_table_lookup (properties, prop))
3813 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3815 g_hash_table_insert (properties, prop, prop);
3817 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3820 g_hash_table_destroy (properties);
3823 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3824 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3825 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3827 mono_ptr_array_destroy (tmp_array);
3833 g_hash_table_destroy (properties);
3836 mono_ptr_array_destroy (tmp_array);
3838 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3839 ex = mono_class_get_exception_for_failure (klass);
3841 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3842 mono_loader_clear_error ();
3844 mono_raise_exception (ex);
3848 ICALL_EXPORT MonoReflectionEvent *
3849 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3852 MonoClass *klass, *startklass;
3857 int (*compare_func) (const char *s1, const char *s2);
3859 MONO_ARCH_SAVE_REGS;
3861 event_name = mono_string_to_utf8 (name);
3862 if (type->type->byref)
3864 klass = startklass = mono_class_from_mono_type (type->type);
3865 domain = mono_object_domain (type);
3867 mono_class_init_or_throw (klass);
3869 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3871 if (klass->exception_type != MONO_EXCEPTION_NONE)
3872 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3875 while ((event = mono_class_get_events (klass, &iter))) {
3876 if (compare_func (event->name, event_name))
3879 method = event->add;
3881 method = event->remove;
3883 method = event->raise;
3885 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3886 if (!(bflags & BFLAGS_Public))
3889 if (!(bflags & BFLAGS_NonPublic))
3891 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3895 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3896 if (!(bflags & BFLAGS_Static))
3898 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3901 if (!(bflags & BFLAGS_Instance))
3905 if (!(bflags & BFLAGS_NonPublic))
3908 g_free (event_name);
3909 return mono_event_get_object (domain, startklass, event);
3912 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3915 g_free (event_name);
3920 event_hash (gconstpointer data)
3922 MonoEvent *event = (MonoEvent*)data;
3924 return g_str_hash (event->name);
3928 event_equal (MonoEvent *event1, MonoEvent *event2)
3930 // Events are hide-by-name
3931 return g_str_equal (event1->name, event2->name);
3934 ICALL_EXPORT MonoArray*
3935 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3939 static MonoClass *System_Reflection_EventInfo;
3940 MonoClass *startklass, *klass;
3946 GHashTable *events = NULL;
3947 MonoPtrArray tmp_array;
3949 MONO_ARCH_SAVE_REGS;
3951 mono_ptr_array_init (tmp_array, 4);
3953 if (!System_Reflection_EventInfo)
3954 System_Reflection_EventInfo = mono_class_from_name (
3955 mono_defaults.corlib, "System.Reflection", "EventInfo");
3957 domain = mono_object_domain (type);
3958 if (type->type->byref)
3959 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3960 klass = startklass = mono_class_from_mono_type (type->type);
3962 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3964 mono_class_setup_vtable (klass);
3965 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3969 while ((event = mono_class_get_events (klass, &iter))) {
3971 method = event->add;
3973 method = event->remove;
3975 method = event->raise;
3977 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3978 if (bflags & BFLAGS_Public)
3980 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3981 if (bflags & BFLAGS_NonPublic)
3986 if (bflags & BFLAGS_NonPublic)
3992 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3993 if (bflags & BFLAGS_Static)
3994 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3997 if (bflags & BFLAGS_Instance)
4002 if (bflags & BFLAGS_Instance)
4007 if (g_hash_table_lookup (events, event))
4010 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4012 g_hash_table_insert (events, event, event);
4014 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4017 g_hash_table_destroy (events);
4019 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4021 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4022 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4024 mono_ptr_array_destroy (tmp_array);
4029 mono_ptr_array_destroy (tmp_array);
4030 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4031 ex = mono_class_get_exception_for_failure (klass);
4033 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4034 mono_loader_clear_error ();
4036 mono_raise_exception (ex);
4040 ICALL_EXPORT MonoReflectionType *
4041 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4049 MONO_ARCH_SAVE_REGS;
4052 mono_raise_exception (mono_get_exception_argument_null ("name"));
4054 domain = ((MonoObject *)type)->vtable->domain;
4055 if (type->type->byref)
4057 klass = mono_class_from_mono_type (type->type);
4059 str = mono_string_to_utf8 (name);
4062 if (klass->exception_type != MONO_EXCEPTION_NONE)
4063 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4066 * If a nested type is generic, return its generic type definition.
4067 * Note that this means that the return value is essentially a
4068 * nested type of the generic type definition of @klass.
4070 * A note in MSDN claims that a generic type definition can have
4071 * nested types that aren't generic. In any case, the container of that
4072 * nested type would be the generic type definition.
4074 if (klass->generic_class)
4075 klass = klass->generic_class->container_class;
4078 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4080 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4081 if (bflags & BFLAGS_Public)
4084 if (bflags & BFLAGS_NonPublic)
4089 if (strcmp (nested->name, str) == 0){
4091 return mono_type_get_object (domain, &nested->byval_arg);
4094 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4100 ICALL_EXPORT MonoArray*
4101 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4110 MonoPtrArray tmp_array;
4112 MONO_ARCH_SAVE_REGS;
4114 domain = ((MonoObject *)type)->vtable->domain;
4115 if (type->type->byref)
4116 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4117 klass = mono_class_from_mono_type (type->type);
4120 * If a nested type is generic, return its generic type definition.
4121 * Note that this means that the return value is essentially the set
4122 * of nested types of the generic type definition of @klass.
4124 * A note in MSDN claims that a generic type definition can have
4125 * nested types that aren't generic. In any case, the container of that
4126 * nested type would be the generic type definition.
4128 if (klass->generic_class)
4129 klass = klass->generic_class->container_class;
4131 mono_ptr_array_init (tmp_array, 1);
4133 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4135 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4136 if (bflags & BFLAGS_Public)
4139 if (bflags & BFLAGS_NonPublic)
4144 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4145 mono_ptr_array_append (tmp_array, member);
4148 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4150 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4151 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4153 mono_ptr_array_destroy (tmp_array);
4158 ICALL_EXPORT MonoReflectionType*
4159 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4162 MonoType *type = NULL;
4163 MonoTypeNameParse info;
4164 gboolean type_resolve;
4166 MONO_ARCH_SAVE_REGS;
4168 /* On MS.NET, this does not fire a TypeResolve event */
4169 type_resolve = TRUE;
4170 str = mono_string_to_utf8 (name);
4171 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4172 if (!mono_reflection_parse_type (str, &info)) {
4174 mono_reflection_free_type_info (&info);
4175 if (throwOnError) /* uhm: this is a parse error, though... */
4176 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4177 /*g_print ("failed parse\n");*/
4181 if (info.assembly.name) {
4183 mono_reflection_free_type_info (&info);
4185 /* 1.0 and 2.0 throw different exceptions */
4186 if (mono_defaults.generic_ilist_class)
4187 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4189 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4194 if (module != NULL) {
4196 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4201 if (assembly_is_dynamic (assembly->assembly)) {
4202 /* Enumerate all modules */
4203 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4207 if (abuilder->modules) {
4208 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4209 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4210 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4216 if (!type && abuilder->loaded_modules) {
4217 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4218 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4219 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4226 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4228 mono_reflection_free_type_info (&info);
4230 MonoException *e = NULL;
4233 e = mono_get_exception_type_load (name, NULL);
4235 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4236 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4238 mono_loader_clear_error ();
4241 mono_raise_exception (e);
4244 } else if (mono_loader_get_last_error ()) {
4246 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4247 mono_loader_clear_error ();
4250 if (type->type == MONO_TYPE_CLASS) {
4251 MonoClass *klass = mono_type_get_class (type);
4253 if (mono_security_enabled () && !klass->exception_type)
4254 /* Some security problems are detected during generic vtable construction */
4255 mono_class_setup_vtable (klass);
4257 /* need to report exceptions ? */
4258 if (throwOnError && klass->exception_type) {
4259 /* report SecurityException (or others) that occured when loading the assembly */
4260 MonoException *exc = mono_class_get_exception_for_failure (klass);
4261 mono_loader_clear_error ();
4262 mono_raise_exception (exc);
4263 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4268 /* g_print ("got it\n"); */
4269 return mono_type_get_object (mono_object_domain (assembly), type);
4273 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4276 gchar *shadow_ini_file;
4279 /* Check for shadow-copied assembly */
4280 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4281 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4283 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4284 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4290 g_free (shadow_ini_file);
4291 if (content != NULL) {
4294 *filename = content;
4301 ICALL_EXPORT MonoString *
4302 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4304 MonoDomain *domain = mono_object_domain (assembly);
4305 MonoAssembly *mass = assembly->assembly;
4306 MonoString *res = NULL;
4311 MONO_ARCH_SAVE_REGS;
4313 if (g_path_is_absolute (mass->image->name)) {
4314 absolute = g_strdup (mass->image->name);
4315 dirname = g_path_get_dirname (absolute);
4317 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4318 dirname = g_strdup (mass->basedir);
4321 replace_shadow_path (domain, dirname, &absolute);
4326 for (i = strlen (absolute) - 1; i >= 0; i--)
4327 if (absolute [i] == '\\')
4332 uri = g_filename_to_uri (absolute, NULL, NULL);
4334 const char *prepend = "file://";
4336 if (*absolute == '/' && *(absolute + 1) == '/') {
4339 prepend = "file:///";
4342 uri = g_strconcat (prepend, absolute, NULL);
4346 res = mono_string_new (domain, uri);
4353 ICALL_EXPORT MonoBoolean
4354 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4356 MonoAssembly *mass = assembly->assembly;
4358 MONO_ARCH_SAVE_REGS;
4360 return mass->in_gac;
4363 ICALL_EXPORT MonoReflectionAssembly*
4364 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4368 MonoImageOpenStatus status;
4370 MONO_ARCH_SAVE_REGS;
4372 name = mono_string_to_utf8 (mname);
4373 res = mono_assembly_load_with_partial_name (name, &status);
4379 return mono_assembly_get_object (mono_domain_get (), res);
4382 ICALL_EXPORT MonoString *
4383 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4385 MonoDomain *domain = mono_object_domain (assembly);
4388 MONO_ARCH_SAVE_REGS;
4390 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4395 ICALL_EXPORT MonoBoolean
4396 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4398 MONO_ARCH_SAVE_REGS;
4400 return assembly->assembly->ref_only;
4403 ICALL_EXPORT MonoString *
4404 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4406 MonoDomain *domain = mono_object_domain (assembly);
4408 MONO_ARCH_SAVE_REGS;
4410 return mono_string_new (domain, assembly->assembly->image->version);
4413 ICALL_EXPORT MonoReflectionMethod*
4414 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4416 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4418 MONO_ARCH_SAVE_REGS;
4422 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4425 ICALL_EXPORT MonoReflectionModule*
4426 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4428 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4431 ICALL_EXPORT MonoArray*
4432 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4434 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4435 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4439 MONO_ARCH_SAVE_REGS;
4441 for (i = 0; i < table->rows; ++i) {
4442 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4443 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4449 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4451 static MonoClass *System_Version = NULL;
4452 static MonoMethod *create_version = NULL;
4456 if (!System_Version) {
4457 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4458 g_assert (System_Version);
4461 if (!create_version) {
4462 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4463 create_version = mono_method_desc_search_in_class (desc, System_Version);
4464 g_assert (create_version);
4465 mono_method_desc_free (desc);
4471 args [3] = &revision;
4472 result = mono_object_new (domain, System_Version);
4473 mono_runtime_invoke (create_version, result, args, NULL);
4478 ICALL_EXPORT MonoArray*
4479 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4481 static MonoClass *System_Reflection_AssemblyName;
4483 MonoDomain *domain = mono_object_domain (assembly);
4485 static MonoMethod *create_culture = NULL;
4486 MonoImage *image = assembly->assembly->image;
4489 MONO_ARCH_SAVE_REGS;
4491 if (!System_Reflection_AssemblyName)
4492 System_Reflection_AssemblyName = mono_class_from_name (
4493 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4495 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4498 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4500 if (count > 0 && !create_culture) {
4501 MonoMethodDesc *desc = mono_method_desc_new (
4502 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4503 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4504 g_assert (create_culture);
4505 mono_method_desc_free (desc);
4508 for (i = 0; i < count; i++) {
4509 MonoReflectionAssemblyName *aname;
4510 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4512 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4514 aname = (MonoReflectionAssemblyName *) mono_object_new (
4515 domain, System_Reflection_AssemblyName);
4517 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4519 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4520 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4521 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4522 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4523 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4524 aname->versioncompat = 1; /* SameMachine (default) */
4525 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4526 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4528 if (create_culture) {
4530 MonoBoolean assembly_ref = 1;
4531 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4532 args [1] = &assembly_ref;
4533 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4536 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4537 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4538 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4540 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4541 /* public key token isn't copied - the class library will
4542 automatically generate it from the public key if required */
4543 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4544 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4546 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4547 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4550 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4553 /* note: this function doesn't return the codebase on purpose (i.e. it can
4554 be used under partial trust as path information isn't present). */
4556 mono_array_setref (result, i, aname);
4561 /* move this in some file in mono/util/ */
4563 g_concat_dir_and_file (const char *dir, const char *file)
4565 g_return_val_if_fail (dir != NULL, NULL);
4566 g_return_val_if_fail (file != NULL, NULL);
4569 * If the directory name doesn't have a / on the end, we need
4570 * to add one so we get a proper path to the file
4572 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4573 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4575 return g_strconcat (dir, file, NULL);
4579 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4581 char *n = mono_string_to_utf8 (name);
4582 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4584 guint32 cols [MONO_MANIFEST_SIZE];
4585 guint32 impl, file_idx;
4589 MONO_ARCH_SAVE_REGS;
4591 for (i = 0; i < table->rows; ++i) {
4592 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4593 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4594 if (strcmp (val, n) == 0)
4598 if (i == table->rows)
4601 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4604 * this code should only be called after obtaining the
4605 * ResourceInfo and handling the other cases.
4607 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4608 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4610 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4615 module = assembly->assembly->image;
4617 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4619 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4622 ICALL_EXPORT gboolean
4623 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4625 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4627 guint32 cols [MONO_MANIFEST_SIZE];
4628 guint32 file_cols [MONO_FILE_SIZE];
4632 MONO_ARCH_SAVE_REGS;
4634 n = mono_string_to_utf8 (name);
4635 for (i = 0; i < table->rows; ++i) {
4636 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4637 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4638 if (strcmp (val, n) == 0)
4642 if (i == table->rows)
4645 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4646 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4649 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4650 case MONO_IMPLEMENTATION_FILE:
4651 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4652 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4653 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4654 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4655 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4656 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4659 info->location = RESOURCE_LOCATION_EMBEDDED;
4662 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4663 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4664 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4665 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4666 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4667 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4669 mono_raise_exception (ex);
4671 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4673 /* Obtain info recursively */
4674 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4675 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4678 case MONO_IMPLEMENTATION_EXP_TYPE:
4679 g_assert_not_reached ();
4687 ICALL_EXPORT MonoObject*
4688 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4690 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4691 MonoArray *result = NULL;
4696 MONO_ARCH_SAVE_REGS;
4698 /* check hash if needed */
4700 n = mono_string_to_utf8 (name);
4701 for (i = 0; i < table->rows; ++i) {
4702 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4703 if (strcmp (val, n) == 0) {
4706 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4707 fn = mono_string_new (mono_object_domain (assembly), n);
4709 return (MonoObject*)fn;
4717 for (i = 0; i < table->rows; ++i) {
4718 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4722 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4725 for (i = 0; i < table->rows; ++i) {
4726 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4727 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4728 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4729 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4734 return (MonoObject*)result;
4737 ICALL_EXPORT MonoArray*
4738 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4740 MonoDomain *domain = mono_domain_get();
4743 int i, j, file_count = 0;
4744 MonoImage **modules;
4745 guint32 module_count, real_module_count;
4746 MonoTableInfo *table;
4747 guint32 cols [MONO_FILE_SIZE];
4748 MonoImage *image = assembly->assembly->image;
4750 g_assert (image != NULL);
4751 g_assert (!assembly_is_dynamic (assembly->assembly));
4753 table = &image->tables [MONO_TABLE_FILE];
4754 file_count = table->rows;
4756 modules = image->modules;
4757 module_count = image->module_count;
4759 real_module_count = 0;
4760 for (i = 0; i < module_count; ++i)
4762 real_module_count ++;
4764 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4765 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4767 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4769 for (i = 0; i < module_count; ++i)
4771 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4775 for (i = 0; i < file_count; ++i, ++j) {
4776 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4777 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4778 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4780 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4782 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4783 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4785 mono_array_setref (res, j, mono_module_get_object (domain, m));
4792 ICALL_EXPORT MonoReflectionMethod*
4793 ves_icall_GetCurrentMethod (void)
4795 MonoMethod *m = mono_method_get_last_managed ();
4797 while (m->is_inflated)
4798 m = ((MonoMethodInflated*)m)->declaring;
4800 return mono_method_get_object (mono_domain_get (), m, NULL);
4805 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4808 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4809 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4810 //method is inflated, we should inflate it on the other class
4811 MonoGenericContext ctx;
4812 ctx.method_inst = inflated->context.method_inst;
4813 ctx.class_inst = inflated->context.class_inst;
4814 if (klass->generic_class)
4815 ctx.class_inst = klass->generic_class->context.class_inst;
4816 else if (klass->generic_container)
4817 ctx.class_inst = klass->generic_container->context.class_inst;
4818 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4821 mono_class_setup_methods (method->klass);
4822 if (method->klass->exception_type)
4824 for (i = 0; i < method->klass->method.count; ++i) {
4825 if (method->klass->methods [i] == method) {
4830 mono_class_setup_methods (klass);
4831 if (klass->exception_type)
4833 g_assert (offset >= 0 && offset < klass->method.count);
4834 return klass->methods [offset];
4837 ICALL_EXPORT MonoReflectionMethod*
4838 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4842 klass = mono_class_from_mono_type (type);
4843 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4845 if (method->klass != klass) {
4846 method = mono_method_get_equivalent_method (method, klass);
4851 klass = method->klass;
4852 return mono_method_get_object (mono_domain_get (), method, klass);
4855 ICALL_EXPORT MonoReflectionMethod*
4856 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4858 return mono_method_get_object (mono_domain_get (), method, NULL);
4861 ICALL_EXPORT MonoReflectionMethodBody*
4862 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4864 return mono_method_body_get_object (mono_domain_get (), method);
4867 ICALL_EXPORT MonoReflectionAssembly*
4868 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4870 MonoMethod *dest = NULL;
4872 MONO_ARCH_SAVE_REGS;
4874 mono_stack_walk_no_il (get_executing, &dest);
4876 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4880 ICALL_EXPORT MonoReflectionAssembly*
4881 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4883 MonoDomain* domain = mono_domain_get ();
4885 MONO_ARCH_SAVE_REGS;
4887 if (!domain->entry_assembly)
4890 return mono_assembly_get_object (domain, domain->entry_assembly);
4893 ICALL_EXPORT MonoReflectionAssembly*
4894 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4899 MONO_ARCH_SAVE_REGS;
4902 mono_stack_walk_no_il (get_executing, &dest);
4904 mono_stack_walk_no_il (get_caller, &dest);
4907 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4910 ICALL_EXPORT MonoString *
4911 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4912 gboolean assembly_qualified)
4914 MonoDomain *domain = mono_object_domain (object);
4915 MonoTypeNameFormat format;
4920 format = assembly_qualified ?
4921 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4922 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4924 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4926 name = mono_type_get_name_full (object->type, format);
4930 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4935 res = mono_string_new (domain, name);
4942 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4944 MonoClass *klass = mono_class_from_mono_type (this->type);
4945 mono_class_init_or_throw (klass);
4946 return mono_security_core_clr_class_level (klass);
4950 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4952 static MonoMethod *create_culture = NULL;
4955 const char *pkey_ptr;
4957 MonoBoolean assembly_ref = 0;
4959 MONO_ARCH_SAVE_REGS;
4961 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4962 aname->major = name->major;
4963 aname->minor = name->minor;
4964 aname->build = name->build;
4965 aname->flags = name->flags;
4966 aname->revision = name->revision;
4967 aname->hashalg = name->hash_alg;
4968 aname->versioncompat = 1; /* SameMachine (default) */
4969 aname->processor_architecture = name->arch;
4971 if (by_default_version)
4972 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4975 if (absolute != NULL && *absolute != '\0') {
4976 const gchar *prepend = "file://";
4979 codebase = g_strdup (absolute);
4984 for (i = strlen (codebase) - 1; i >= 0; i--)
4985 if (codebase [i] == '\\')
4988 if (*codebase == '/' && *(codebase + 1) == '/') {
4991 prepend = "file:///";
4995 result = g_strconcat (prepend, codebase, NULL);
5001 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5005 if (!create_culture) {
5006 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5007 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5008 g_assert (create_culture);
5009 mono_method_desc_free (desc);
5012 if (name->culture) {
5013 args [0] = mono_string_new (domain, name->culture);
5014 args [1] = &assembly_ref;
5015 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5018 if (name->public_key) {
5019 pkey_ptr = (char*)name->public_key;
5020 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5022 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5023 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5024 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5025 } else if (default_publickey) {
5026 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5027 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5030 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5031 if (name->public_key_token [0]) {
5035 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5036 p = mono_array_addr (aname->keyToken, char, 0);
5038 for (i = 0, j = 0; i < 8; i++) {
5039 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5040 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5043 } else if (default_token) {
5044 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5048 ICALL_EXPORT MonoString *
5049 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5051 MonoDomain *domain = mono_object_domain (assembly);
5052 MonoAssembly *mass = assembly->assembly;
5056 name = mono_stringify_assembly_name (&mass->aname);
5057 res = mono_string_new (domain, name);
5064 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5067 MonoAssembly *mass = assembly->assembly;
5069 MONO_ARCH_SAVE_REGS;
5071 if (g_path_is_absolute (mass->image->name)) {
5072 fill_reflection_assembly_name (mono_object_domain (assembly),
5073 aname, &mass->aname, mass->image->name, TRUE,
5077 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5079 fill_reflection_assembly_name (mono_object_domain (assembly),
5080 aname, &mass->aname, absolute, TRUE, TRUE,
5087 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5090 MonoImageOpenStatus status = MONO_IMAGE_OK;
5093 MonoAssemblyName name;
5096 MONO_ARCH_SAVE_REGS;
5098 filename = mono_string_to_utf8 (fname);
5100 dirname = g_path_get_dirname (filename);
5101 replace_shadow_path (mono_domain_get (), dirname, &filename);
5104 image = mono_image_open (filename, &status);
5110 if (status == MONO_IMAGE_IMAGE_INVALID)
5111 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5113 exc = mono_get_exception_file_not_found2 (NULL, fname);
5114 mono_raise_exception (exc);
5117 res = mono_assembly_fill_assembly_name (image, &name);
5119 mono_image_close (image);
5121 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5124 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5128 mono_image_close (image);
5131 ICALL_EXPORT MonoBoolean
5132 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5133 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5135 MonoBoolean result = FALSE;
5136 MonoDeclSecurityEntry entry;
5138 /* SecurityAction.RequestMinimum */
5139 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5140 *minimum = entry.blob;
5141 *minLength = entry.size;
5144 /* SecurityAction.RequestOptional */
5145 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5146 *optional = entry.blob;
5147 *optLength = entry.size;
5150 /* SecurityAction.RequestRefuse */
5151 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5152 *refused = entry.blob;
5153 *refLength = entry.size;
5161 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5165 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5167 guint32 attrs, visibility;
5169 /* we start the count from 1 because we skip the special type <Module> */
5172 for (i = 1; i < tdef->rows; ++i) {
5173 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5174 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5175 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5179 count = tdef->rows - 1;
5181 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5182 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5184 for (i = 1; i < tdef->rows; ++i) {
5185 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5186 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5187 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5189 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5190 g_assert (!mono_loader_get_last_error ()); /* Plug any leaks */
5193 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5195 MonoException *ex = mono_error_convert_to_exception (&error);
5196 mono_array_setref (*exceptions, count, ex);
5205 ICALL_EXPORT MonoArray*
5206 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5208 MonoArray *res = NULL;
5209 MonoArray *exceptions = NULL;
5210 MonoImage *image = NULL;
5211 MonoTableInfo *table = NULL;
5214 int i, len, ex_count;
5216 MONO_ARCH_SAVE_REGS;
5218 domain = mono_object_domain (assembly);
5220 g_assert (!assembly_is_dynamic (assembly->assembly));
5221 image = assembly->assembly->image;
5222 table = &image->tables [MONO_TABLE_FILE];
5223 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5225 /* Append data from all modules in the assembly */
5226 for (i = 0; i < table->rows; ++i) {
5227 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5228 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5231 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5232 /* Append the new types to the end of the array */
5233 if (mono_array_length (res2) > 0) {
5235 MonoArray *res3, *ex3;
5237 len1 = mono_array_length (res);
5238 len2 = mono_array_length (res2);
5240 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5241 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5242 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5245 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5246 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5247 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5254 /* the ReflectionTypeLoadException must have all the types (Types property),
5255 * NULL replacing types which throws an exception. The LoaderException must
5256 * contain all exceptions for NULL items.
5259 len = mono_array_length (res);
5262 for (i = 0; i < len; i++) {
5263 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5267 klass = mono_type_get_class (t->type);
5268 if ((klass != NULL) && klass->exception_type) {
5269 /* keep the class in the list */
5270 list = g_list_append (list, klass);
5271 /* and replace Type with NULL */
5272 mono_array_setref (res, i, NULL);
5279 if (list || ex_count) {
5281 MonoException *exc = NULL;
5282 MonoArray *exl = NULL;
5283 int j, length = g_list_length (list) + ex_count;
5285 mono_loader_clear_error ();
5287 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5288 /* Types for which mono_class_get_checked () succeeded */
5289 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5290 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5291 mono_array_setref (exl, i, exc);
5293 /* Types for which it don't */
5294 for (j = 0; j < mono_array_length (exceptions); ++j) {
5295 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5297 g_assert (i < length);
5298 mono_array_setref (exl, i, exc);
5305 exc = mono_get_exception_reflection_type_load (res, exl);
5306 mono_loader_clear_error ();
5307 mono_raise_exception (exc);
5313 ICALL_EXPORT gboolean
5314 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5316 MonoAssemblyName aname;
5317 MonoDomain *domain = mono_object_domain (name);
5319 gboolean is_version_defined;
5320 gboolean is_token_defined;
5322 aname.public_key = NULL;
5323 val = mono_string_to_utf8 (assname);
5324 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5325 g_free ((guint8*) aname.public_key);
5330 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5331 FALSE, is_token_defined);
5333 mono_assembly_name_free (&aname);
5334 g_free ((guint8*) aname.public_key);
5340 ICALL_EXPORT MonoReflectionType*
5341 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5344 MonoDomain *domain = mono_object_domain (module);
5347 MONO_ARCH_SAVE_REGS;
5349 g_assert (module->image);
5351 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5352 /* These images do not have a global type */
5355 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5356 mono_error_raise_exception (&error);
5357 return mono_type_get_object (domain, &klass->byval_arg);
5361 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5363 /*if (module->image)
5364 mono_image_close (module->image);*/
5367 ICALL_EXPORT MonoString*
5368 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5370 MonoDomain *domain = mono_object_domain (module);
5372 MONO_ARCH_SAVE_REGS;
5374 g_assert (module->image);
5375 return mono_string_new (domain, module->image->guid);
5378 ICALL_EXPORT gpointer
5379 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5382 if (module->image && module->image->is_module_handle)
5383 return module->image->raw_data;
5386 return (gpointer) (-1);
5390 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5392 if (image_is_dynamic (image)) {
5393 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5394 *pe_kind = dyn->pe_kind;
5395 *machine = dyn->machine;
5398 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5399 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5404 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5406 return (image->md_version_major << 16) | (image->md_version_minor);
5409 ICALL_EXPORT MonoArray*
5410 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5412 MonoArray *exceptions;
5415 MONO_ARCH_SAVE_REGS;
5418 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5420 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5421 for (i = 0; i < mono_array_length (exceptions); ++i) {
5422 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5424 mono_raise_exception (ex);
5431 mono_memberref_is_method (MonoImage *image, guint32 token)
5433 if (!image_is_dynamic (image)) {
5434 guint32 cols [MONO_MEMBERREF_SIZE];
5436 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5437 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5438 mono_metadata_decode_blob_size (sig, &sig);
5439 return (*sig != 0x6);
5441 MonoClass *handle_class;
5443 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5446 return mono_defaults.methodhandle_class == handle_class;
5451 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5454 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5455 mono_array_addr (type_args, MonoType*, 0));
5457 context->class_inst = NULL;
5459 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5460 mono_array_addr (method_args, MonoType*, 0));
5462 context->method_inst = NULL;
5465 ICALL_EXPORT MonoType*
5466 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5469 int table = mono_metadata_token_table (token);
5470 int index = mono_metadata_token_index (token);
5471 MonoGenericContext context;
5474 *resolve_error = ResolveTokenError_Other;
5476 /* Validate token */
5477 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5478 (table != MONO_TABLE_TYPESPEC)) {
5479 *resolve_error = ResolveTokenError_BadTable;
5483 if (image_is_dynamic (image)) {
5484 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5485 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5486 return klass ? &klass->byval_arg : NULL;
5489 init_generic_context_from_args (&context, type_args, method_args);
5490 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5491 return klass ? &klass->byval_arg : NULL;
5494 if ((index <= 0) || (index > image->tables [table].rows)) {
5495 *resolve_error = ResolveTokenError_OutOfRange;
5499 init_generic_context_from_args (&context, type_args, method_args);
5500 klass = mono_class_get_checked (image, token, &error);
5502 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5503 mono_error_raise_exception (&error);
5506 return &klass->byval_arg;
5511 ICALL_EXPORT MonoMethod*
5512 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5514 int table = mono_metadata_token_table (token);
5515 int index = mono_metadata_token_index (token);
5516 MonoGenericContext context;
5519 *error = ResolveTokenError_Other;
5521 /* Validate token */
5522 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5523 (table != MONO_TABLE_MEMBERREF)) {
5524 *error = ResolveTokenError_BadTable;
5528 if (image_is_dynamic (image)) {
5529 if (table == MONO_TABLE_METHOD)
5530 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5532 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5533 *error = ResolveTokenError_BadTable;
5537 init_generic_context_from_args (&context, type_args, method_args);
5538 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5541 if ((index <= 0) || (index > image->tables [table].rows)) {
5542 *error = ResolveTokenError_OutOfRange;
5545 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5546 *error = ResolveTokenError_BadTable;
5550 init_generic_context_from_args (&context, type_args, method_args);
5551 method = mono_get_method_full (image, token, NULL, &context);
5553 if (mono_loader_get_last_error ())
5554 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5559 ICALL_EXPORT MonoString*
5560 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5562 int index = mono_metadata_token_index (token);
5564 *error = ResolveTokenError_Other;
5566 /* Validate token */
5567 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5568 *error = ResolveTokenError_BadTable;
5572 if (image_is_dynamic (image))
5573 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5575 if ((index <= 0) || (index >= image->heap_us.size)) {
5576 *error = ResolveTokenError_OutOfRange;
5580 /* FIXME: What to do if the index points into the middle of a string ? */
5582 return mono_ldstr (mono_domain_get (), image, index);
5585 ICALL_EXPORT MonoClassField*
5586 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5590 int table = mono_metadata_token_table (token);
5591 int index = mono_metadata_token_index (token);
5592 MonoGenericContext context;
5593 MonoClassField *field;
5595 *resolve_error = ResolveTokenError_Other;
5597 /* Validate token */
5598 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5599 *resolve_error = ResolveTokenError_BadTable;
5603 if (image_is_dynamic (image)) {
5604 if (table == MONO_TABLE_FIELD)
5605 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5607 if (mono_memberref_is_method (image, token)) {
5608 *resolve_error = ResolveTokenError_BadTable;
5612 init_generic_context_from_args (&context, type_args, method_args);
5613 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5616 if ((index <= 0) || (index > image->tables [table].rows)) {
5617 *resolve_error = ResolveTokenError_OutOfRange;
5620 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5621 *resolve_error = ResolveTokenError_BadTable;
5625 init_generic_context_from_args (&context, type_args, method_args);
5626 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5627 mono_error_raise_exception (&error);
5633 ICALL_EXPORT MonoObject*
5634 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5636 int table = mono_metadata_token_table (token);
5638 *error = ResolveTokenError_Other;
5641 case MONO_TABLE_TYPEDEF:
5642 case MONO_TABLE_TYPEREF:
5643 case MONO_TABLE_TYPESPEC: {
5644 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5646 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5650 case MONO_TABLE_METHOD:
5651 case MONO_TABLE_METHODSPEC: {
5652 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5654 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5658 case MONO_TABLE_FIELD: {
5659 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5661 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5665 case MONO_TABLE_MEMBERREF:
5666 if (mono_memberref_is_method (image, token)) {
5667 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5669 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5674 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5676 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5683 *error = ResolveTokenError_BadTable;
5689 ICALL_EXPORT MonoArray*
5690 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5692 int table = mono_metadata_token_table (token);
5693 int idx = mono_metadata_token_index (token);
5694 MonoTableInfo *tables = image->tables;
5699 *error = ResolveTokenError_OutOfRange;
5701 /* FIXME: Support other tables ? */
5702 if (table != MONO_TABLE_STANDALONESIG)
5705 if (image_is_dynamic (image))
5708 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5711 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5713 ptr = mono_metadata_blob_heap (image, sig);
5714 len = mono_metadata_decode_blob_size (ptr, &ptr);
5716 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5717 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5721 ICALL_EXPORT MonoReflectionType*
5722 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5725 int isbyref = 0, rank;
5726 char *str = mono_string_to_utf8 (smodifiers);
5729 MONO_ARCH_SAVE_REGS;
5731 klass = mono_class_from_mono_type (tb->type.type);
5733 /* logic taken from mono_reflection_parse_type(): keep in sync */
5737 if (isbyref) { /* only one level allowed by the spec */
5744 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5747 klass = mono_ptr_class_get (&klass->byval_arg);
5748 mono_class_init (klass);
5759 else if (*p != '*') { /* '*' means unknown lower bound */
5770 klass = mono_array_class_get (klass, rank);
5771 mono_class_init (klass);
5778 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5781 ICALL_EXPORT MonoBoolean
5782 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5787 MONO_ARCH_SAVE_REGS;
5790 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5796 check_for_invalid_type (MonoClass *klass)
5800 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5803 name = mono_type_get_full_name (klass);
5804 str = mono_string_new (mono_domain_get (), name);
5806 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5809 ICALL_EXPORT MonoReflectionType *
5810 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5812 MonoClass *klass, *aklass;
5814 MONO_ARCH_SAVE_REGS;
5816 klass = mono_class_from_mono_type (type->type);
5817 check_for_invalid_type (klass);
5819 if (rank == 0) //single dimentional array
5820 aklass = mono_array_class_get (klass, 1);
5822 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5824 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5827 ICALL_EXPORT MonoReflectionType *
5828 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5832 MONO_ARCH_SAVE_REGS;
5834 klass = mono_class_from_mono_type (type->type);
5835 mono_class_init_or_throw (klass);
5836 check_for_invalid_type (klass);
5838 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5841 ICALL_EXPORT MonoReflectionType *
5842 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5844 MonoClass *klass, *pklass;
5846 klass = mono_class_from_mono_type (type->type);
5847 mono_class_init_or_throw (klass);
5848 check_for_invalid_type (klass);
5850 pklass = mono_ptr_class_get (type->type);
5852 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5855 ICALL_EXPORT MonoObject *
5856 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5857 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5859 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5860 MonoObject *delegate;
5862 MonoMethod *method = info->method;
5864 MONO_ARCH_SAVE_REGS;
5866 mono_class_init_or_throw (delegate_class);
5868 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5870 if (mono_security_core_clr_enabled ()) {
5871 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5875 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5877 if (method_is_dynamic (method)) {
5878 /* Creating a trampoline would leak memory */
5879 func = mono_compile_method (method);
5881 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5882 method = mono_object_get_virtual_method (target, method);
5883 func = mono_create_ftnptr (mono_domain_get (),
5884 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5887 mono_delegate_ctor_with_method (delegate, target, func, method);
5893 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5895 /* Reset the invoke impl to the default one */
5896 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5900 * Magic number to convert a time which is relative to
5901 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5903 #define EPOCH_ADJUST ((guint64)62135596800LL)
5906 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5908 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5911 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5913 convert_to_absolute_date(SYSTEMTIME *date)
5915 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5916 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5917 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5918 /* from the calendar FAQ */
5919 int a = (14 - date->wMonth) / 12;
5920 int y = date->wYear - a;
5921 int m = date->wMonth + 12 * a - 2;
5922 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5924 /* d is now the day of the week for the first of the month (0 == Sunday) */
5926 int day_of_week = date->wDayOfWeek;
5928 /* set day_in_month to the first day in the month which falls on day_of_week */
5929 int day_in_month = 1 + (day_of_week - d);
5930 if (day_in_month <= 0)
5933 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5934 date->wDay = day_in_month + (date->wDay - 1) * 7;
5935 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5942 * Return's the offset from GMT of a local time.
5944 * tm is a local time
5945 * t is the same local time as seconds.
5948 gmt_offset(struct tm *tm, time_t t)
5950 #if defined (HAVE_TM_GMTOFF)
5951 return tm->tm_gmtoff;
5956 g.tm_isdst = tm->tm_isdst;
5958 return (int)difftime(t, t2);
5963 * This is heavily based on zdump.c from glibc 2.2.
5965 * * data[0]: start of daylight saving time (in DateTime ticks).
5966 * * data[1]: end of daylight saving time (in DateTime ticks).
5967 * * data[2]: utcoffset (in TimeSpan ticks).
5968 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5969 * * name[0]: name of this timezone when not daylight saving.
5970 * * name[1]: name of this timezone when daylight saving.
5972 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5973 * the class library allows years between 1 and 9999.
5975 * Returns true on success and zero on failure.
5977 ICALL_EXPORT guint32
5978 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5981 MonoDomain *domain = mono_domain_get ();
5982 struct tm start, tt;
5985 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5986 int day, transitioned;
5989 gmtoff_st = gmtoff_ds = transitioned = 0;
5991 MONO_ARCH_SAVE_REGS;
5993 MONO_CHECK_ARG_NULL (data);
5994 MONO_CHECK_ARG_NULL (names);
5996 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5997 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
6000 * no info is better than crashing: we'll need our own tz data
6001 * to make this work properly, anyway. The range is probably
6002 * reduced to 1970 .. 2037 because that is what mktime is
6003 * guaranteed to support (we get into an infinite loop
6007 memset (&start, 0, sizeof (start));
6010 start.tm_year = year-1900;
6012 t = mktime (&start);
6014 if ((year < 1970) || (year > 2037) || (t == -1)) {
6016 tt = *localtime (&t);
6017 strftime (tzone, sizeof (tzone), "%Z", &tt);
6018 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6019 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6023 gmtoff = gmt_offset (&start, t);
6025 /* For each day of the year, calculate the tm_gmtoff. */
6026 for (day = 0; day < 365 && transitioned < 2; day++) {
6029 tt = *localtime (&t);
6031 gmtoff_after = gmt_offset(&tt, t);
6033 /* Daylight saving starts or ends here. */
6034 if (gmtoff_after != gmtoff) {
6038 /* Try to find the exact hour when daylight saving starts/ends. */
6042 tt1 = *localtime (&t1);
6043 } while (gmt_offset (&tt1, t1) != gmtoff);
6045 /* Try to find the exact minute when daylight saving starts/ends. */
6048 tt1 = *localtime (&t1);
6049 } while (gmt_offset (&tt1, t1) == gmtoff);
6051 strftime (tzone, sizeof (tzone), "%Z", &tt);
6053 /* Write data, if we're already in daylight saving, we're done. */
6055 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6056 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6057 if (gmtoff_ds == 0) {
6059 gmtoff_ds = gmtoff_after;
6066 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6067 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6068 if (gmtoff_ds == 0) {
6069 gmtoff_st = gmtoff_after;
6075 /* This is only set once when we enter daylight saving. */
6077 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6078 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6080 gmtoff = gmt_offset (&tt, t);
6084 if (transitioned < 2) {
6085 strftime (tzone, sizeof (tzone), "%Z", &tt);
6086 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6087 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6088 mono_array_set ((*data), gint64, 0, 0);
6089 mono_array_set ((*data), gint64, 1, 0);
6090 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6091 mono_array_set ((*data), gint64, 3, 0);
6096 MonoDomain *domain = mono_domain_get ();
6097 TIME_ZONE_INFORMATION tz_info;
6102 tz_id = GetTimeZoneInformation (&tz_info);
6103 if (tz_id == TIME_ZONE_ID_INVALID)
6106 MONO_CHECK_ARG_NULL (data);
6107 MONO_CHECK_ARG_NULL (names);
6109 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6110 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6112 for (i = 0; i < 32; ++i)
6113 if (!tz_info.DaylightName [i])
6115 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6116 for (i = 0; i < 32; ++i)
6117 if (!tz_info.StandardName [i])
6119 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6121 if ((year <= 1601) || (year > 30827)) {
6123 * According to MSDN, the MS time functions can't handle dates outside
6129 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6130 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6131 tz_info.StandardDate.wYear = year;
6132 convert_to_absolute_date(&tz_info.StandardDate);
6133 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6138 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6139 tz_info.DaylightDate.wYear = year;
6140 convert_to_absolute_date(&tz_info.DaylightDate);
6141 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6146 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6148 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6149 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6157 static inline gint32
6158 mono_array_get_byte_length (MonoArray *array)
6164 klass = array->obj.vtable->klass;
6166 if (array->bounds == NULL)
6167 length = array->max_length;
6170 for (i = 0; i < klass->rank; ++ i)
6171 length *= array->bounds [i].length;
6174 switch (klass->element_class->byval_arg.type) {
6177 case MONO_TYPE_BOOLEAN:
6181 case MONO_TYPE_CHAR:
6189 return length * sizeof (gpointer);
6200 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6202 MONO_ARCH_SAVE_REGS;
6204 return mono_array_get_byte_length (array);
6208 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6210 MONO_ARCH_SAVE_REGS;
6212 return mono_array_get (array, gint8, idx);
6216 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6218 MONO_ARCH_SAVE_REGS;
6220 mono_array_set (array, gint8, idx, value);
6223 ICALL_EXPORT MonoBoolean
6224 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6226 guint8 *src_buf, *dest_buf;
6228 MONO_ARCH_SAVE_REGS;
6230 /* This is called directly from the class libraries without going through the managed wrapper */
6231 MONO_CHECK_ARG_NULL (src);
6232 MONO_CHECK_ARG_NULL (dest);
6234 /* watch out for integer overflow */
6235 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6238 src_buf = (guint8 *)src->vector + src_offset;
6239 dest_buf = (guint8 *)dest->vector + dest_offset;
6242 memcpy (dest_buf, src_buf, count);
6244 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6249 #ifndef DISABLE_REMOTING
6250 ICALL_EXPORT MonoObject *
6251 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6253 MonoDomain *domain = mono_object_domain (this);
6255 MonoRealProxy *rp = ((MonoRealProxy *)this);
6256 MonoTransparentProxy *tp;
6260 MONO_ARCH_SAVE_REGS;
6262 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6263 tp = (MonoTransparentProxy*) res;
6265 MONO_OBJECT_SETREF (tp, rp, rp);
6266 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6267 klass = mono_class_from_mono_type (type);
6269 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6270 tp->remote_class = mono_remote_class (domain, class_name, klass);
6272 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6276 ICALL_EXPORT MonoReflectionType *
6277 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6279 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6283 /* System.Environment */
6286 ves_icall_System_Environment_get_UserName (void)
6288 MONO_ARCH_SAVE_REGS;
6290 /* using glib is more portable */
6291 return mono_string_new (mono_domain_get (), g_get_user_name ());
6295 ICALL_EXPORT MonoString *
6296 ves_icall_System_Environment_get_MachineName (void)
6298 #if defined (HOST_WIN32)
6303 len = MAX_COMPUTERNAME_LENGTH + 1;
6304 buf = g_new (gunichar2, len);
6307 if (GetComputerName (buf, (PDWORD) &len))
6308 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6312 #elif !defined(DISABLE_SOCKETS)
6316 if (gethostname (buf, sizeof (buf)) == 0)
6317 result = mono_string_new (mono_domain_get (), buf);
6323 return mono_string_new (mono_domain_get (), "mono");
6328 ves_icall_System_Environment_get_Platform (void)
6330 #if defined (TARGET_WIN32)
6333 #elif defined(__MACH__)
6336 // Notice that the value is hidden from user code, and only exposed
6337 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6338 // define and making assumptions based on Unix/128/4 values before there
6339 // was a MacOS define. Lots of code would assume that not-Unix meant
6340 // Windows, but in this case, it would be OSX.
6349 ICALL_EXPORT MonoString *
6350 ves_icall_System_Environment_get_NewLine (void)
6352 MONO_ARCH_SAVE_REGS;
6354 #if defined (HOST_WIN32)
6355 return mono_string_new (mono_domain_get (), "\r\n");
6357 return mono_string_new (mono_domain_get (), "\n");
6361 ICALL_EXPORT MonoString *
6362 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6367 MONO_ARCH_SAVE_REGS;
6372 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6373 value = g_getenv (utf8_name);
6380 return mono_string_new (mono_domain_get (), value);
6384 * There is no standard way to get at environ.
6387 #ifndef __MINGW32_VERSION
6388 #if defined(__APPLE__) && !defined (__arm__)
6389 /* Apple defines this in crt_externs.h but doesn't provide that header for
6390 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6391 * in fact exist on all implementations (so far)
6393 gchar ***_NSGetEnviron(void);
6394 #define environ (*_NSGetEnviron())
6402 ICALL_EXPORT MonoArray *
6403 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6414 env_strings = GetEnvironmentStrings();
6417 env_string = env_strings;
6418 while (*env_string != '\0') {
6419 /* weird case that MS seems to skip */
6420 if (*env_string != '=')
6422 while (*env_string != '\0')
6428 domain = mono_domain_get ();
6429 names = mono_array_new (domain, mono_defaults.string_class, n);
6433 env_string = env_strings;
6434 while (*env_string != '\0') {
6435 /* weird case that MS seems to skip */
6436 if (*env_string != '=') {
6437 equal_str = wcschr(env_string, '=');
6438 g_assert(equal_str);
6439 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6440 mono_array_setref (names, n, str);
6443 while (*env_string != '\0')
6448 FreeEnvironmentStrings (env_strings);
6460 MONO_ARCH_SAVE_REGS;
6463 for (e = environ; *e != 0; ++ e)
6466 domain = mono_domain_get ();
6467 names = mono_array_new (domain, mono_defaults.string_class, n);
6470 for (e = environ; *e != 0; ++ e) {
6471 parts = g_strsplit (*e, "=", 2);
6473 str = mono_string_new (domain, *parts);
6474 mono_array_setref (names, n, str);
6487 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6489 #if !GLIB_CHECK_VERSION(2,4,0)
6490 #define g_setenv(a,b,c) setenv(a,b,c)
6491 #define g_unsetenv(a) unsetenv(a)
6495 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6498 gunichar2 *utf16_name, *utf16_value;
6500 gchar *utf8_name, *utf8_value;
6504 MONO_ARCH_SAVE_REGS;
6507 utf16_name = mono_string_to_utf16 (name);
6508 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6509 SetEnvironmentVariable (utf16_name, NULL);
6510 g_free (utf16_name);
6514 utf16_value = mono_string_to_utf16 (value);
6516 SetEnvironmentVariable (utf16_name, utf16_value);
6518 g_free (utf16_name);
6519 g_free (utf16_value);
6521 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6523 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6524 g_unsetenv (utf8_name);
6529 utf8_value = mono_string_to_utf8_checked (value, &error);
6530 if (!mono_error_ok (&error)) {
6532 mono_error_raise_exception (&error);
6534 g_setenv (utf8_name, utf8_value, TRUE);
6537 g_free (utf8_value);
6542 ves_icall_System_Environment_Exit (int result)
6544 MONO_ARCH_SAVE_REGS;
6546 mono_environment_exitcode_set (result);
6548 /* FIXME: There are some cleanup hangs that should be worked out, but
6549 * if the program is going to exit, everything will be cleaned up when
6550 * NaCl exits anyway.
6552 #ifndef __native_client__
6553 if (!mono_runtime_try_shutdown ())
6554 mono_thread_exit ();
6556 /* Suspend all managed threads since the runtime is going away */
6557 mono_thread_suspend_all_other_threads ();
6559 mono_runtime_quit ();
6562 /* we may need to do some cleanup here... */
6566 ICALL_EXPORT MonoString*
6567 ves_icall_System_Environment_GetGacPath (void)
6569 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6572 ICALL_EXPORT MonoString*
6573 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6575 #if defined (HOST_WIN32)
6576 #ifndef CSIDL_FLAG_CREATE
6577 #define CSIDL_FLAG_CREATE 0x8000
6580 WCHAR path [MAX_PATH];
6581 /* Create directory if no existing */
6582 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6586 return mono_string_new_utf16 (mono_domain_get (), path, len);
6589 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6591 return mono_string_new (mono_domain_get (), "");
6594 ICALL_EXPORT MonoArray *
6595 ves_icall_System_Environment_GetLogicalDrives (void)
6597 gunichar2 buf [256], *ptr, *dname;
6599 guint initial_size = 127, size = 128;
6602 MonoString *drivestr;
6603 MonoDomain *domain = mono_domain_get ();
6606 MONO_ARCH_SAVE_REGS;
6611 while (size > initial_size) {
6612 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6613 if (size > initial_size) {
6616 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6617 initial_size = size;
6631 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6636 while (*u16) { u16++; len ++; }
6637 drivestr = mono_string_new_utf16 (domain, dname, len);
6638 mono_array_setref (result, ndrives++, drivestr);
6648 ICALL_EXPORT MonoString *
6649 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6651 gunichar2 volume_name [MAX_PATH + 1];
6653 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6655 return mono_string_from_utf16 (volume_name);
6658 ICALL_EXPORT MonoString *
6659 ves_icall_System_Environment_InternalGetHome (void)
6661 MONO_ARCH_SAVE_REGS;
6663 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6666 static const char *encodings [] = {
6668 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6669 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6670 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6672 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6673 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6674 "x_unicode_2_0_utf_7",
6676 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6677 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6679 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6682 "unicodefffe", "utf_16be",
6689 * Returns the internal codepage, if the value of "int_code_page" is
6690 * 1 at entry, and we can not compute a suitable code page number,
6691 * returns the code page as a string
6693 ICALL_EXPORT MonoString*
6694 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6699 char *codepage = NULL;
6701 int want_name = *int_code_page;
6704 *int_code_page = -1;
6705 MONO_ARCH_SAVE_REGS;
6707 g_get_charset (&cset);
6708 c = codepage = strdup (cset);
6709 for (c = codepage; *c; c++){
6710 if (isascii (*c) && isalpha (*c))
6715 /* g_print ("charset: %s\n", cset); */
6717 /* handle some common aliases */
6720 for (i = 0; p != 0; ){
6721 if ((gssize) p < 7){
6723 p = encodings [++i];
6726 if (strcmp (p, codepage) == 0){
6727 *int_code_page = code;
6730 p = encodings [++i];
6733 if (strstr (codepage, "utf_8") != NULL)
6734 *int_code_page |= 0x10000000;
6737 if (want_name && *int_code_page == -1)
6738 return mono_string_new (mono_domain_get (), cset);
6743 ICALL_EXPORT MonoBoolean
6744 ves_icall_System_Environment_get_HasShutdownStarted (void)
6746 if (mono_runtime_is_shutting_down ())
6749 if (mono_domain_is_unloading (mono_domain_get ()))
6756 ves_icall_System_Environment_BroadcastSettingChange (void)
6759 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6764 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6765 MonoReflectionMethod *method,
6766 MonoArray *out_args)
6768 MONO_ARCH_SAVE_REGS;
6770 mono_message_init (mono_object_domain (this), this, method, out_args);
6773 #ifndef DISABLE_REMOTING
6774 ICALL_EXPORT MonoBoolean
6775 ves_icall_IsTransparentProxy (MonoObject *proxy)
6777 MONO_ARCH_SAVE_REGS;
6782 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6788 ICALL_EXPORT MonoReflectionMethod *
6789 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6790 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6794 MonoMethod **vtable;
6795 MonoMethod *res = NULL;
6797 MONO_CHECK_ARG_NULL (rtype);
6798 MONO_CHECK_ARG_NULL (rmethod);
6800 method = rmethod->method;
6801 klass = mono_class_from_mono_type (rtype->type);
6802 mono_class_init_or_throw (klass);
6804 if (MONO_CLASS_IS_INTERFACE (klass))
6807 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6810 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6811 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6817 mono_class_setup_vtable (klass);
6818 vtable = klass->vtable;
6820 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6821 gboolean variance_used = FALSE;
6822 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6823 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6825 res = vtable [offs + method->slot];
6827 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6830 if (method->slot != -1)
6831 res = vtable [method->slot];
6837 return mono_method_get_object (mono_domain_get (), res, NULL);
6841 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6846 MONO_ARCH_SAVE_REGS;
6848 klass = mono_class_from_mono_type (type->type);
6849 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6851 mono_vtable_set_is_remote (vtable, enable);
6854 #else /* DISABLE_REMOTING */
6857 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6859 g_assert_not_reached ();
6864 ICALL_EXPORT MonoObject *
6865 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6870 MONO_ARCH_SAVE_REGS;
6872 domain = mono_object_domain (type);
6873 klass = mono_class_from_mono_type (type->type);
6874 mono_class_init_or_throw (klass);
6876 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6877 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6879 if (klass->rank >= 1) {
6880 g_assert (klass->rank == 1);
6881 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6883 /* Bypass remoting object creation check */
6884 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6888 ICALL_EXPORT MonoString *
6889 ves_icall_System_IO_get_temp_path (void)
6891 MONO_ARCH_SAVE_REGS;
6893 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6896 #ifndef PLATFORM_NO_DRIVEINFO
6897 ICALL_EXPORT MonoBoolean
6898 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6899 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6903 ULARGE_INTEGER wapi_free_bytes_avail;
6904 ULARGE_INTEGER wapi_total_number_of_bytes;
6905 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6907 MONO_ARCH_SAVE_REGS;
6909 *error = ERROR_SUCCESS;
6910 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6911 &wapi_total_number_of_free_bytes);
6914 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6915 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6916 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6918 *free_bytes_avail = 0;
6919 *total_number_of_bytes = 0;
6920 *total_number_of_free_bytes = 0;
6921 *error = GetLastError ();
6927 ICALL_EXPORT guint32
6928 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6930 MONO_ARCH_SAVE_REGS;
6932 return GetDriveType (mono_string_chars (root_path_name));
6936 ICALL_EXPORT gpointer
6937 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6939 MONO_ARCH_SAVE_REGS;
6941 return mono_compile_method (method);
6944 ICALL_EXPORT MonoString *
6945 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6950 MONO_ARCH_SAVE_REGS;
6952 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6954 #if defined (HOST_WIN32)
6955 /* Avoid mixing '/' and '\\' */
6958 for (i = strlen (path) - 1; i >= 0; i--)
6959 if (path [i] == '/')
6963 mcpath = mono_string_new (mono_domain_get (), path);
6970 get_bundled_app_config (void)
6972 const gchar *app_config;
6975 gchar *config_file_name, *config_file_path;
6979 MONO_ARCH_SAVE_REGS;
6981 domain = mono_domain_get ();
6982 file = domain->setup->configuration_file;
6986 // Retrieve config file and remove the extension
6987 config_file_name = mono_string_to_utf8 (file);
6988 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6989 if (!config_file_path)
6990 config_file_path = config_file_name;
6991 len = strlen (config_file_path) - strlen (".config");
6992 module = g_malloc0 (len + 1);
6993 memcpy (module, config_file_path, len);
6994 // Get the config file from the module name
6995 app_config = mono_config_string_for_assembly_file (module);
6998 if (config_file_name != config_file_path)
6999 g_free (config_file_name);
7000 g_free (config_file_path);
7005 return mono_string_new (mono_domain_get (), app_config);
7009 get_bundled_machine_config (void)
7011 const gchar *machine_config;
7013 MONO_ARCH_SAVE_REGS;
7015 machine_config = mono_get_machine_config ();
7017 if (!machine_config)
7020 return mono_string_new (mono_domain_get (), machine_config);
7023 ICALL_EXPORT MonoString *
7024 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7029 MONO_ARCH_SAVE_REGS;
7031 path = g_path_get_dirname (mono_get_config_dir ());
7033 #if defined (HOST_WIN32)
7034 /* Avoid mixing '/' and '\\' */
7037 for (i = strlen (path) - 1; i >= 0; i--)
7038 if (path [i] == '/')
7042 ipath = mono_string_new (mono_domain_get (), path);
7048 ICALL_EXPORT gboolean
7049 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7051 MonoPEResourceDataEntry *entry;
7054 MONO_ARCH_SAVE_REGS;
7056 if (!assembly || !result || !size)
7061 image = assembly->assembly->image;
7062 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7066 *result = mono_image_rva_map (image, entry->rde_data_offset);
7071 *size = entry->rde_size;
7076 ICALL_EXPORT MonoBoolean
7077 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7079 return mono_is_debugger_attached ();
7082 ICALL_EXPORT MonoBoolean
7083 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7085 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7086 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7092 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7094 if (mono_get_runtime_callbacks ()->debug_log)
7095 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7099 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7101 #if defined (HOST_WIN32)
7102 OutputDebugString (mono_string_chars (message));
7104 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7108 /* Only used for value types */
7109 ICALL_EXPORT MonoObject *
7110 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7115 MONO_ARCH_SAVE_REGS;
7117 domain = mono_object_domain (type);
7118 klass = mono_class_from_mono_type (type->type);
7119 mono_class_init_or_throw (klass);
7121 if (mono_class_is_nullable (klass))
7122 /* No arguments -> null */
7125 return mono_object_new (domain, klass);
7128 ICALL_EXPORT MonoReflectionMethod *
7129 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7131 MonoClass *klass, *parent;
7132 MonoMethod *method = m->method;
7133 MonoMethod *result = NULL;
7136 MONO_ARCH_SAVE_REGS;
7138 if (method->klass == NULL)
7141 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7142 MONO_CLASS_IS_INTERFACE (method->klass) ||
7143 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7146 slot = mono_method_get_vtable_slot (method);
7150 klass = method->klass;
7151 if (klass->generic_class)
7152 klass = klass->generic_class->container_class;
7155 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7156 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7157 mono_class_setup_vtable (parent);
7158 if (parent->vtable_size <= slot)
7163 klass = klass->parent;
7168 if (klass == method->klass)
7171 /*This is possible if definition == FALSE.
7172 * Do it here to be really sure we don't read invalid memory.
7174 if (slot >= klass->vtable_size)
7177 mono_class_setup_vtable (klass);
7179 result = klass->vtable [slot];
7180 if (result == NULL) {
7181 /* It is an abstract method */
7182 gpointer iter = NULL;
7183 while ((result = mono_class_get_methods (klass, &iter)))
7184 if (result->slot == slot)
7191 return mono_method_get_object (mono_domain_get (), result, NULL);
7194 ICALL_EXPORT MonoString*
7195 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7197 MonoMethod *method = m->method;
7199 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7204 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7206 MONO_ARCH_SAVE_REGS;
7208 iter->sig = *(MonoMethodSignature**)argsp;
7210 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7211 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7214 /* FIXME: it's not documented what start is exactly... */
7218 iter->args = argsp + sizeof (gpointer);
7220 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7222 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7225 ICALL_EXPORT MonoTypedRef
7226 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7228 guint32 i, arg_size;
7231 MONO_ARCH_SAVE_REGS;
7233 i = iter->sig->sentinelpos + iter->next_arg;
7235 g_assert (i < iter->sig->param_count);
7237 res.type = iter->sig->params [i];
7238 res.klass = mono_class_from_mono_type (res.type);
7239 arg_size = mono_type_stack_size (res.type, &align);
7240 #if defined(__arm__) || defined(__mips__)
7241 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7243 res.value = iter->args;
7244 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7245 /* Values are stored as 8 byte register sized objects, but 'value'
7246 * is dereferenced as a pointer in other routines.
7248 res.value = (char*)res.value + 4;
7250 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7251 if (arg_size <= sizeof (gpointer)) {
7253 int padding = arg_size - mono_type_size (res.type, &dummy);
7254 res.value = (guint8*)res.value + padding;
7257 iter->args = (char*)iter->args + arg_size;
7260 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7265 ICALL_EXPORT MonoTypedRef
7266 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7268 guint32 i, arg_size;
7271 MONO_ARCH_SAVE_REGS;
7273 i = iter->sig->sentinelpos + iter->next_arg;
7275 g_assert (i < iter->sig->param_count);
7277 while (i < iter->sig->param_count) {
7278 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7280 res.type = iter->sig->params [i];
7281 res.klass = mono_class_from_mono_type (res.type);
7282 /* FIXME: endianess issue... */
7283 arg_size = mono_type_stack_size (res.type, &align);
7284 #if defined(__arm__) || defined(__mips__)
7285 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7287 res.value = iter->args;
7288 iter->args = (char*)iter->args + arg_size;
7290 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7293 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7301 ICALL_EXPORT MonoType*
7302 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7305 MONO_ARCH_SAVE_REGS;
7307 i = iter->sig->sentinelpos + iter->next_arg;
7309 g_assert (i < iter->sig->param_count);
7311 return iter->sig->params [i];
7314 ICALL_EXPORT MonoObject*
7315 mono_TypedReference_ToObject (MonoTypedRef tref)
7317 MONO_ARCH_SAVE_REGS;
7319 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7320 MonoObject** objp = tref.value;
7324 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7327 ICALL_EXPORT MonoObject*
7328 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7330 MONO_ARCH_SAVE_REGS;
7332 if (MONO_TYPE_IS_REFERENCE (type)) {
7333 MonoObject** objp = value;
7337 return mono_value_box (mono_domain_get (), klass, value);
7341 prelink_method (MonoMethod *method)
7343 const char *exc_class, *exc_arg;
7344 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7346 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7348 mono_raise_exception(
7349 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7351 /* create the wrapper, too? */
7355 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7357 MONO_ARCH_SAVE_REGS;
7358 prelink_method (method->method);
7362 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7364 MonoClass *klass = mono_class_from_mono_type (type->type);
7366 gpointer iter = NULL;
7367 MONO_ARCH_SAVE_REGS;
7369 mono_class_init_or_throw (klass);
7371 while ((m = mono_class_get_methods (klass, &iter)))
7375 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7377 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7378 gint32 const **exponents,
7379 gunichar2 const **digitLowerTable,
7380 gunichar2 const **digitUpperTable,
7381 gint64 const **tenPowersList,
7382 gint32 const **decHexDigits)
7384 *mantissas = Formatter_MantissaBitsTable;
7385 *exponents = Formatter_TensExponentTable;
7386 *digitLowerTable = Formatter_DigitLowerTable;
7387 *digitUpperTable = Formatter_DigitUpperTable;
7388 *tenPowersList = Formatter_TenPowersList;
7389 *decHexDigits = Formatter_DecHexDigits;
7393 get_category_data (int version,
7394 guint8 const **category_data,
7395 guint16 const **category_astral_index)
7397 *category_astral_index = NULL;
7399 #ifndef DISABLE_NET_4_0
7401 *category_data = CategoryData_v4;
7402 #ifndef DISABLE_ASTRAL
7403 *category_astral_index = CategoryData_v4_astral_index;
7409 *category_data = CategoryData_v2;
7410 #ifndef DISABLE_ASTRAL
7411 *category_astral_index = CategoryData_v2_astral_index;
7415 /* These parameters are "readonly" in corlib/System/Char.cs */
7417 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7418 guint8 const **category_data,
7419 guint16 const **category_astral_index,
7420 guint8 const **numeric_data,
7421 gdouble const **numeric_data_values,
7422 guint16 const **to_lower_data_low,
7423 guint16 const **to_lower_data_high,
7424 guint16 const **to_upper_data_low,
7425 guint16 const **to_upper_data_high)
7427 get_category_data (category_data_version, category_data, category_astral_index);
7428 *numeric_data = NumericData;
7429 *numeric_data_values = NumericDataValues;
7430 *to_lower_data_low = ToLowerDataLow;
7431 *to_lower_data_high = ToLowerDataHigh;
7432 *to_upper_data_low = ToUpperDataLow;
7433 *to_upper_data_high = ToUpperDataHigh;
7437 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7438 * and avoid useless allocations.
7443 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7447 for (i = 0; i < type->num_mods; ++i) {
7448 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7453 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7455 for (i = 0; i < type->num_mods; ++i) {
7456 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7458 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7459 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7460 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7467 ICALL_EXPORT MonoArray*
7468 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7470 MonoType *type = param->ClassImpl->type;
7471 MonoClass *member_class = mono_object_class (param->MemberImpl);
7472 MonoMethod *method = NULL;
7475 MonoMethodSignature *sig;
7477 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7478 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7479 method = rmethod->method;
7480 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7481 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7482 if (!(method = prop->property->get))
7483 method = prop->property->set;
7486 char *type_name = mono_type_get_full_name (member_class);
7487 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7488 MonoException *ex = mono_get_exception_not_supported (msg);
7491 mono_raise_exception (ex);
7494 image = method->klass->image;
7495 pos = param->PositionImpl;
7496 sig = mono_method_signature (method);
7500 type = sig->params [pos];
7502 return type_array_from_modifiers (image, type, optional);
7506 get_property_type (MonoProperty *prop)
7508 MonoMethodSignature *sig;
7510 sig = mono_method_signature (prop->get);
7512 } else if (prop->set) {
7513 sig = mono_method_signature (prop->set);
7514 return sig->params [sig->param_count - 1];
7519 ICALL_EXPORT MonoArray*
7520 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7522 MonoType *type = get_property_type (property->property);
7523 MonoImage *image = property->klass->image;
7527 return type_array_from_modifiers (image, type, optional);
7531 *Construct a MonoType suited to be used to decode a constant blob object.
7533 * @type is the target type which will be constructed
7534 * @blob_type is the blob type, for example, that comes from the constant table
7535 * @real_type is the expected constructed type.
7538 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7540 type->type = blob_type;
7541 type->data.klass = NULL;
7542 if (blob_type == MONO_TYPE_CLASS)
7543 type->data.klass = mono_defaults.object_class;
7544 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7545 /* For enums, we need to use the base type */
7546 type->type = MONO_TYPE_VALUETYPE;
7547 type->data.klass = mono_class_from_mono_type (real_type);
7549 type->data.klass = mono_class_from_mono_type (real_type);
7552 ICALL_EXPORT MonoObject*
7553 property_info_get_default_value (MonoReflectionProperty *property)
7556 MonoProperty *prop = property->property;
7557 MonoType *type = get_property_type (prop);
7558 MonoDomain *domain = mono_object_domain (property);
7559 MonoTypeEnum def_type;
7560 const char *def_value;
7563 mono_class_init (prop->parent);
7565 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7566 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7568 def_value = mono_class_get_property_default_value (prop, &def_type);
7570 mono_type_from_blob_type (&blob_type, def_type, type);
7571 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7576 ICALL_EXPORT MonoBoolean
7577 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7579 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7580 MonoCustomAttrInfo *cinfo;
7583 mono_class_init_or_throw (attr_class);
7585 cinfo = mono_reflection_get_custom_attrs_info (obj);
7588 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7590 mono_custom_attrs_free (cinfo);
7594 ICALL_EXPORT MonoArray*
7595 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7597 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7602 mono_class_init_or_throw (attr_class);
7604 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7605 mono_error_raise_exception (&error);
7607 if (mono_loader_get_last_error ()) {
7608 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7609 g_assert_not_reached ();
7617 ICALL_EXPORT MonoString*
7618 ves_icall_Mono_Runtime_GetDisplayName (void)
7621 MonoString *display_name;
7623 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7624 display_name = mono_string_new (mono_domain_get (), info);
7626 return display_name;
7629 ICALL_EXPORT MonoString*
7630 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7632 MonoString *message;
7636 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7637 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7640 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7642 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7650 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7651 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7652 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7653 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7654 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7655 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7656 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7657 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7661 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7666 gunichar2 last, prev_last, prev2_last;
7673 int havePadding = 0;
7675 last = prev_last = 0, prev2_last = 0;
7676 for (i = 0; i < ilength; i++) {
7678 if (c >= sizeof (dbase64)) {
7679 exc = mono_exception_from_name_msg (mono_get_corlib (),
7680 "System", "FormatException",
7681 "Invalid character found.");
7682 mono_raise_exception (exc);
7683 } else if (isspace (c)) {
7685 } else if (havePadding && c != '=') {
7686 exc = mono_exception_from_name_msg (mono_get_corlib (),
7687 "System", "FormatException",
7688 "Invalid character found.");
7689 mono_raise_exception (exc);
7691 if (c == '=') havePadding = 1;
7692 prev2_last = prev_last;
7698 olength = ilength - ignored;
7700 if (allowWhitespaceOnly && olength == 0) {
7701 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7704 if ((olength & 3) != 0 || olength <= 0) {
7705 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7706 "FormatException", "Invalid length.");
7707 mono_raise_exception (exc);
7710 if (prev2_last == '=') {
7711 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7712 mono_raise_exception (exc);
7715 olength = (olength * 3) / 4;
7719 if (prev_last == '=')
7722 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7723 res_ptr = mono_array_addr (result, guchar, 0);
7724 for (i = 0; i < ilength; ) {
7727 for (k = 0; k < 4 && i < ilength;) {
7733 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7734 exc = mono_exception_from_name_msg (mono_get_corlib (),
7735 "System", "FormatException",
7736 "Invalid character found.");
7737 mono_raise_exception (exc);
7742 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7744 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7746 *res_ptr++ = (b [2] << 6) | b [3];
7748 while (i < ilength && isspace (start [i]))
7755 ICALL_EXPORT MonoArray *
7756 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7758 MONO_ARCH_SAVE_REGS;
7760 return base64_to_byte_array (mono_string_chars (str),
7761 mono_string_length (str), allowWhitespaceOnly);
7764 ICALL_EXPORT MonoArray *
7765 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7767 MONO_ARCH_SAVE_REGS;
7769 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7773 #ifndef DISABLE_ICALL_TABLES
7775 #define ICALL_TYPE(id,name,first)
7776 #define ICALL(id,name,func) Icall_ ## id,
7779 #include "metadata/icall-def.h"
7785 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7786 #define ICALL(id,name,func)
7788 #include "metadata/icall-def.h"
7794 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7795 #define ICALL(id,name,func)
7797 guint16 first_icall;
7800 static const IcallTypeDesc
7801 icall_type_descs [] = {
7802 #include "metadata/icall-def.h"
7806 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7809 #define ICALL_TYPE(id,name,first)
7812 #ifdef HAVE_ARRAY_ELEM_INIT
7813 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7814 #define MSGSTRFIELD1(line) str##line
7816 static const struct msgstrtn_t {
7817 #define ICALL(id,name,func)
7819 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7820 #include "metadata/icall-def.h"
7822 } icall_type_names_str = {
7823 #define ICALL_TYPE(id,name,first) (name),
7824 #include "metadata/icall-def.h"
7827 static const guint16 icall_type_names_idx [] = {
7828 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7829 #include "metadata/icall-def.h"
7832 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7834 static const struct msgstr_t {
7836 #define ICALL_TYPE(id,name,first)
7837 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7838 #include "metadata/icall-def.h"
7840 } icall_names_str = {
7841 #define ICALL(id,name,func) (name),
7842 #include "metadata/icall-def.h"
7845 static const guint16 icall_names_idx [] = {
7846 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7847 #include "metadata/icall-def.h"
7850 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7856 #define ICALL_TYPE(id,name,first) name,
7857 #define ICALL(id,name,func)
7858 static const char* const
7859 icall_type_names [] = {
7860 #include "metadata/icall-def.h"
7864 #define icall_type_name_get(id) (icall_type_names [(id)])
7868 #define ICALL_TYPE(id,name,first)
7869 #define ICALL(id,name,func) name,
7870 static const char* const
7872 #include "metadata/icall-def.h"
7875 #define icall_name_get(id) icall_names [(id)]
7877 #endif /* !HAVE_ARRAY_ELEM_INIT */
7881 #define ICALL_TYPE(id,name,first)
7882 #define ICALL(id,name,func) func,
7883 static const gconstpointer
7884 icall_functions [] = {
7885 #include "metadata/icall-def.h"
7889 #ifdef ENABLE_ICALL_SYMBOL_MAP
7892 #define ICALL_TYPE(id,name,first)
7893 #define ICALL(id,name,func) #func,
7894 static const gconstpointer
7895 icall_symbols [] = {
7896 #include "metadata/icall-def.h"
7901 #endif /* DISABLE_ICALL_TABLES */
7903 static mono_mutex_t icall_mutex;
7904 static GHashTable *icall_hash = NULL;
7905 static GHashTable *jit_icall_hash_name = NULL;
7906 static GHashTable *jit_icall_hash_addr = NULL;
7909 mono_icall_init (void)
7911 #ifndef DISABLE_ICALL_TABLES
7914 /* check that tables are sorted: disable in release */
7917 const char *prev_class = NULL;
7918 const char *prev_method;
7920 for (i = 0; i < Icall_type_num; ++i) {
7921 const IcallTypeDesc *desc;
7924 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7925 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7926 prev_class = icall_type_name_get (i);
7927 desc = &icall_type_descs [i];
7928 num_icalls = icall_desc_num_icalls (desc);
7929 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7930 for (j = 0; j < num_icalls; ++j) {
7931 const char *methodn = icall_name_get (desc->first_icall + j);
7932 if (prev_method && strcmp (prev_method, methodn) >= 0)
7933 g_print ("method %s should come before method %s\n", methodn, prev_method);
7934 prev_method = methodn;
7940 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7941 mono_mutex_init (&icall_mutex);
7945 mono_icall_lock (void)
7947 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7951 mono_icall_unlock (void)
7953 mono_locks_mutex_release (&icall_mutex, IcallLock);
7957 mono_icall_cleanup (void)
7959 g_hash_table_destroy (icall_hash);
7960 g_hash_table_destroy (jit_icall_hash_name);
7961 g_hash_table_destroy (jit_icall_hash_addr);
7962 mono_mutex_destroy (&icall_mutex);
7966 mono_add_internal_call (const char *name, gconstpointer method)
7970 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7972 mono_icall_unlock ();
7975 #ifndef DISABLE_ICALL_TABLES
7977 #ifdef HAVE_ARRAY_ELEM_INIT
7979 compare_method_imap (const void *key, const void *elem)
7981 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7982 return strcmp (key, method_name);
7986 find_method_icall (const IcallTypeDesc *imap, const char *name)
7988 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);
7991 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7995 compare_class_imap (const void *key, const void *elem)
7997 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7998 return strcmp (key, class_name);
8001 static const IcallTypeDesc*
8002 find_class_icalls (const char *name)
8004 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
8007 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8010 #else /* HAVE_ARRAY_ELEM_INIT */
8013 compare_method_imap (const void *key, const void *elem)
8015 const char** method_name = (const char**)elem;
8016 return strcmp (key, *method_name);
8020 find_method_icall (const IcallTypeDesc *imap, const char *name)
8022 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8025 return (gpointer)icall_functions [(nameslot - icall_names)];
8029 compare_class_imap (const void *key, const void *elem)
8031 const char** class_name = (const char**)elem;
8032 return strcmp (key, *class_name);
8035 static const IcallTypeDesc*
8036 find_class_icalls (const char *name)
8038 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8041 return &icall_type_descs [nameslot - icall_type_names];
8044 #endif /* HAVE_ARRAY_ELEM_INIT */
8046 #endif /* DISABLE_ICALL_TABLES */
8049 * we should probably export this as an helper (handle nested types).
8050 * Returns the number of chars written in buf.
8053 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8055 int nspacelen, cnamelen;
8056 nspacelen = strlen (klass->name_space);
8057 cnamelen = strlen (klass->name);
8058 if (nspacelen + cnamelen + 2 > bufsize)
8061 memcpy (buf, klass->name_space, nspacelen);
8062 buf [nspacelen ++] = '.';
8064 memcpy (buf + nspacelen, klass->name, cnamelen);
8065 buf [nspacelen + cnamelen] = 0;
8066 return nspacelen + cnamelen;
8069 #ifdef DISABLE_ICALL_TABLES
8071 no_icall_table (void)
8073 g_assert_not_reached ();
8078 mono_lookup_internal_call (MonoMethod *method)
8083 int typelen = 0, mlen, siglen;
8085 #ifndef DISABLE_ICALL_TABLES
8086 const IcallTypeDesc *imap = NULL;
8089 g_assert (method != NULL);
8091 if (method->is_inflated)
8092 method = ((MonoMethodInflated *) method)->declaring;
8094 if (method->klass->nested_in) {
8095 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8099 mname [pos++] = '/';
8102 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8108 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8113 #ifndef DISABLE_ICALL_TABLES
8114 imap = find_class_icalls (mname);
8117 mname [typelen] = ':';
8118 mname [typelen + 1] = ':';
8120 mlen = strlen (method->name);
8121 memcpy (mname + typelen + 2, method->name, mlen);
8122 sigstart = mname + typelen + 2 + mlen;
8125 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8126 siglen = strlen (tmpsig);
8127 if (typelen + mlen + siglen + 6 > sizeof (mname))
8130 memcpy (sigstart + 1, tmpsig, siglen);
8131 sigstart [siglen + 1] = ')';
8132 sigstart [siglen + 2] = 0;
8137 res = g_hash_table_lookup (icall_hash, mname);
8139 mono_icall_unlock ();;
8142 /* try without signature */
8144 res = g_hash_table_lookup (icall_hash, mname);
8146 mono_icall_unlock ();
8150 #ifdef DISABLE_ICALL_TABLES
8151 mono_icall_unlock ();
8152 /* Fail only when the result is actually used */
8153 /* mono_marshal_get_native_wrapper () depends on this */
8154 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8155 return ves_icall_System_String_ctor_RedirectToCreateString;
8157 return no_icall_table;
8159 /* it wasn't found in the static call tables */
8161 mono_icall_unlock ();
8164 res = find_method_icall (imap, sigstart - mlen);
8166 mono_icall_unlock ();
8169 /* try _with_ signature */
8171 res = find_method_icall (imap, sigstart - mlen);
8173 mono_icall_unlock ();
8177 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8178 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8179 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8180 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8181 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");
8182 g_print ("If you see other errors or faults after this message they are probably related\n");
8183 g_print ("and you need to fix your mono install first.\n");
8185 mono_icall_unlock ();
8191 #ifdef ENABLE_ICALL_SYMBOL_MAP
8193 func_cmp (gconstpointer key, gconstpointer p)
8195 return (gsize)key - (gsize)*(gsize*)p;
8200 * mono_lookup_icall_symbol:
8202 * Given the icall METHOD, returns its C symbol.
8205 mono_lookup_icall_symbol (MonoMethod *m)
8207 #ifdef DISABLE_ICALL_TABLES
8208 g_assert_not_reached ();
8211 #ifdef ENABLE_ICALL_SYMBOL_MAP
8215 static gconstpointer *functions_sorted;
8216 static const char**symbols_sorted;
8217 static gboolean inited;
8222 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8223 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8224 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8225 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8226 /* Bubble sort the two arrays */
8230 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8231 if (functions_sorted [i] > functions_sorted [i + 1]) {
8234 tmp = functions_sorted [i];
8235 functions_sorted [i] = functions_sorted [i + 1];
8236 functions_sorted [i + 1] = tmp;
8237 tmp = symbols_sorted [i];
8238 symbols_sorted [i] = symbols_sorted [i + 1];
8239 symbols_sorted [i + 1] = tmp;
8246 func = mono_lookup_internal_call (m);
8249 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8253 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8255 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8256 g_assert_not_reached ();
8263 type_from_typename (char *typename)
8265 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8267 if (!strcmp (typename, "int"))
8268 klass = mono_defaults.int_class;
8269 else if (!strcmp (typename, "ptr"))
8270 klass = mono_defaults.int_class;
8271 else if (!strcmp (typename, "void"))
8272 klass = mono_defaults.void_class;
8273 else if (!strcmp (typename, "int32"))
8274 klass = mono_defaults.int32_class;
8275 else if (!strcmp (typename, "uint32"))
8276 klass = mono_defaults.uint32_class;
8277 else if (!strcmp (typename, "int8"))
8278 klass = mono_defaults.sbyte_class;
8279 else if (!strcmp (typename, "uint8"))
8280 klass = mono_defaults.byte_class;
8281 else if (!strcmp (typename, "int16"))
8282 klass = mono_defaults.int16_class;
8283 else if (!strcmp (typename, "uint16"))
8284 klass = mono_defaults.uint16_class;
8285 else if (!strcmp (typename, "long"))
8286 klass = mono_defaults.int64_class;
8287 else if (!strcmp (typename, "ulong"))
8288 klass = mono_defaults.uint64_class;
8289 else if (!strcmp (typename, "float"))
8290 klass = mono_defaults.single_class;
8291 else if (!strcmp (typename, "double"))
8292 klass = mono_defaults.double_class;
8293 else if (!strcmp (typename, "object"))
8294 klass = mono_defaults.object_class;
8295 else if (!strcmp (typename, "obj"))
8296 klass = mono_defaults.object_class;
8297 else if (!strcmp (typename, "string"))
8298 klass = mono_defaults.string_class;
8299 else if (!strcmp (typename, "bool"))
8300 klass = mono_defaults.boolean_class;
8301 else if (!strcmp (typename, "boolean"))
8302 klass = mono_defaults.boolean_class;
8304 g_error ("%s", typename);
8305 g_assert_not_reached ();
8307 return &klass->byval_arg;
8311 * LOCKING: Take the corlib image lock.
8313 MonoMethodSignature*
8314 mono_create_icall_signature (const char *sigstr)
8319 MonoMethodSignature *res, *res2;
8320 MonoImage *corlib = mono_defaults.corlib;
8322 mono_image_lock (corlib);
8323 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8324 mono_image_unlock (corlib);
8329 parts = g_strsplit (sigstr, " ", 256);
8338 res = mono_metadata_signature_alloc (corlib, len - 1);
8343 * Under windows, the default pinvoke calling convention is STDCALL but
8346 res->call_convention = MONO_CALL_C;
8349 res->ret = type_from_typename (parts [0]);
8350 for (i = 1; i < len; ++i) {
8351 res->params [i - 1] = type_from_typename (parts [i]);
8356 mono_image_lock (corlib);
8357 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8359 res = res2; /*Value is allocated in the image pool*/
8361 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8362 mono_image_unlock (corlib);
8368 mono_find_jit_icall_by_name (const char *name)
8370 MonoJitICallInfo *info;
8371 g_assert (jit_icall_hash_name);
8374 info = g_hash_table_lookup (jit_icall_hash_name, name);
8375 mono_icall_unlock ();
8380 mono_find_jit_icall_by_addr (gconstpointer addr)
8382 MonoJitICallInfo *info;
8383 g_assert (jit_icall_hash_addr);
8386 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8387 mono_icall_unlock ();
8393 * mono_get_jit_icall_info:
8395 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8396 * caller should access it while holding the icall lock.
8399 mono_get_jit_icall_info (void)
8401 return jit_icall_hash_name;
8405 * mono_lookup_jit_icall_symbol:
8407 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8410 mono_lookup_jit_icall_symbol (const char *name)
8412 MonoJitICallInfo *info;
8413 const char *res = NULL;
8416 info = g_hash_table_lookup (jit_icall_hash_name, name);
8418 res = info->c_symbol;
8419 mono_icall_unlock ();
8424 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8427 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8428 mono_icall_unlock ();
8432 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8434 MonoJitICallInfo *info;
8441 if (!jit_icall_hash_name) {
8442 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8443 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8446 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8447 g_warning ("jit icall already defined \"%s\"\n", name);
8448 g_assert_not_reached ();
8451 info = g_new0 (MonoJitICallInfo, 1);
8456 info->c_symbol = c_symbol;
8459 info->wrapper = func;
8461 info->wrapper = NULL;
8464 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8465 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8467 mono_icall_unlock ();
8472 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8474 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);