5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
10 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * Copyright 2011-2014 Xamarin Inc (http://www.xamarin.com).
23 #ifdef HAVE_SYS_TIME_H
29 #if defined (HOST_WIN32)
32 #if defined (HAVE_WCHAR_H)
36 #include "mono/utils/mono-membar.h"
37 #include <mono/metadata/object.h>
38 #include <mono/metadata/threads.h>
39 #include <mono/metadata/threads-types.h>
40 #include <mono/metadata/threadpool.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/assembly.h>
44 #include <mono/metadata/tabledefs.h>
45 #include <mono/metadata/exception.h>
46 #include <mono/metadata/file-io.h>
47 #include <mono/metadata/console-io.h>
48 #include <mono/metadata/socket-io.h>
49 #include <mono/metadata/mono-endian.h>
50 #include <mono/metadata/tokentype.h>
51 #include <mono/metadata/domain-internals.h>
52 #include <mono/metadata/metadata-internals.h>
53 #include <mono/metadata/class-internals.h>
54 #include <mono/metadata/marshal.h>
55 #include <mono/metadata/gc-internal.h>
56 #include <mono/metadata/mono-gc.h>
57 #include <mono/metadata/rand.h>
58 #include <mono/metadata/sysmath.h>
59 #include <mono/metadata/string-icalls.h>
60 #include <mono/metadata/debug-helpers.h>
61 #include <mono/metadata/process.h>
62 #include <mono/metadata/environment.h>
63 #include <mono/metadata/profiler-private.h>
64 #include <mono/metadata/locales.h>
65 #include <mono/metadata/filewatcher.h>
66 #include <mono/metadata/char-conversions.h>
67 #include <mono/metadata/security.h>
68 #include <mono/metadata/mono-config.h>
69 #include <mono/metadata/cil-coff.h>
70 #include <mono/metadata/number-formatter.h>
71 #include <mono/metadata/security-manager.h>
72 #include <mono/metadata/security-core-clr.h>
73 #include <mono/metadata/mono-perfcounters.h>
74 #include <mono/metadata/mono-debug.h>
75 #include <mono/metadata/mono-ptr-array.h>
76 #include <mono/metadata/verify-internals.h>
77 #include <mono/metadata/runtime.h>
78 #include <mono/metadata/file-mmap.h>
79 #include <mono/io-layer/io-layer.h>
80 #include <mono/utils/strtod.h>
81 #include <mono/utils/monobitset.h>
82 #include <mono/utils/mono-time.h>
83 #include <mono/utils/mono-proclib.h>
84 #include <mono/utils/mono-string.h>
85 #include <mono/utils/mono-error-internals.h>
86 #include <mono/utils/mono-mmap.h>
87 #include <mono/utils/mono-io-portability.h>
88 #include <mono/utils/mono-digest.h>
89 #include <mono/utils/bsearch.h>
90 #include <mono/utils/mono-mutex.h>
91 #include <mono/utils/mono-threads.h>
93 #if defined (HOST_WIN32)
99 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
101 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
104 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
106 static inline MonoBoolean
107 is_generic_parameter (MonoType *type)
109 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
113 mono_class_init_or_throw (MonoClass *klass)
115 if (!mono_class_init (klass))
116 mono_raise_exception (mono_class_get_exception_for_failure (klass));
120 * We expect a pointer to a char, not a string
122 ICALL_EXPORT gboolean
123 mono_double_ParseImpl (char *ptr, double *result)
125 gchar *endptr = NULL;
132 *result = strtod (ptr, &endptr);
135 /* mono_strtod () is not thread-safe */
136 EnterCriticalSection (&mono_strtod_mutex);
137 *result = mono_strtod (ptr, &endptr);
138 LeaveCriticalSection (&mono_strtod_mutex);
142 if (!*ptr || (endptr && *endptr))
148 ICALL_EXPORT MonoObject *
149 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
158 ao = (MonoArray *)this;
159 ac = (MonoClass *)ao->obj.vtable->klass;
161 esize = mono_array_element_size (ac);
162 ea = (gpointer*)((char*)ao->vector + (pos * esize));
164 if (ac->element_class->valuetype)
165 return mono_value_box (this->vtable->domain, ac->element_class, ea);
170 ICALL_EXPORT MonoObject *
171 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
179 MONO_CHECK_ARG_NULL (idxs);
181 io = (MonoArray *)idxs;
182 ic = (MonoClass *)io->obj.vtable->klass;
184 ao = (MonoArray *)this;
185 ac = (MonoClass *)ao->obj.vtable->klass;
187 g_assert (ic->rank == 1);
188 if (io->bounds != NULL || io->max_length != ac->rank)
189 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
191 ind = (gint32 *)io->vector;
193 if (ao->bounds == NULL) {
194 if (*ind < 0 || *ind >= ao->max_length)
195 mono_raise_exception (mono_get_exception_index_out_of_range ());
197 return ves_icall_System_Array_GetValueImpl (this, *ind);
200 for (i = 0; i < ac->rank; i++)
201 if ((ind [i] < ao->bounds [i].lower_bound) ||
202 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
203 mono_raise_exception (mono_get_exception_index_out_of_range ());
205 pos = ind [0] - ao->bounds [0].lower_bound;
206 for (i = 1; i < ac->rank; i++)
207 pos = pos*ao->bounds [i].length + ind [i] -
208 ao->bounds [i].lower_bound;
210 return ves_icall_System_Array_GetValueImpl (this, pos);
214 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
216 MonoClass *ac, *vc, *ec;
228 vc = value->vtable->klass;
232 ac = this->obj.vtable->klass;
233 ec = ac->element_class;
235 esize = mono_array_element_size (ac);
236 ea = (gpointer*)((char*)this->vector + (pos * esize));
237 va = (gpointer*)((char*)value + sizeof (MonoObject));
239 if (mono_class_is_nullable (ec)) {
240 mono_nullable_init ((guint8*)ea, value, ec);
245 mono_gc_bzero_atomic (ea, esize);
249 #define NO_WIDENING_CONVERSION G_STMT_START{\
250 mono_raise_exception (mono_get_exception_argument ( \
251 "value", "not a widening conversion")); \
254 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
255 if (esize < vsize + (extra)) \
256 mono_raise_exception (mono_get_exception_argument ( \
257 "value", "not a widening conversion")); \
260 #define INVALID_CAST G_STMT_START{ \
261 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
262 mono_raise_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
290 NO_WIDENING_CONVERSION;
297 if (!ec->valuetype) {
298 if (!mono_object_isinst (value, ec))
300 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
304 if (mono_object_isinst (value, ec)) {
305 if (ec->has_references)
306 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
308 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
315 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
317 et = ec->byval_arg.type;
318 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
319 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
321 vt = vc->byval_arg.type;
322 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
323 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
325 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
331 case MONO_TYPE_CHAR: \
332 CHECK_WIDENING_CONVERSION(0); \
333 *(etype *) ea = (etype) u64; \
335 /* You can't assign a signed value to an unsigned array. */ \
340 /* You can't assign a floating point number to an integer array. */ \
343 NO_WIDENING_CONVERSION; \
347 #define ASSIGN_SIGNED(etype) G_STMT_START{\
353 CHECK_WIDENING_CONVERSION(0); \
354 *(etype *) ea = (etype) i64; \
356 /* You can assign an unsigned value to a signed array if the array's */ \
357 /* element size is larger than the value size. */ \
362 case MONO_TYPE_CHAR: \
363 CHECK_WIDENING_CONVERSION(1); \
364 *(etype *) ea = (etype) u64; \
366 /* You can't assign a floating point number to an integer array. */ \
369 NO_WIDENING_CONVERSION; \
373 #define ASSIGN_REAL(etype) G_STMT_START{\
377 CHECK_WIDENING_CONVERSION(0); \
378 *(etype *) ea = (etype) r64; \
380 /* All integer values fit into a floating point array, so we don't */ \
381 /* need to CHECK_WIDENING_CONVERSION here. */ \
386 *(etype *) ea = (etype) i64; \
392 case MONO_TYPE_CHAR: \
393 *(etype *) ea = (etype) u64; \
400 u64 = *(guint8 *) va;
403 u64 = *(guint16 *) va;
406 u64 = *(guint32 *) va;
409 u64 = *(guint64 *) va;
415 i64 = *(gint16 *) va;
418 i64 = *(gint32 *) va;
421 i64 = *(gint64 *) va;
424 r64 = *(gfloat *) va;
427 r64 = *(gdouble *) va;
430 u64 = *(guint16 *) va;
432 case MONO_TYPE_BOOLEAN:
433 /* Boolean is only compatible with itself. */
446 NO_WIDENING_CONVERSION;
453 /* If we can't do a direct copy, let's try a widening conversion. */
456 ASSIGN_UNSIGNED (guint16);
458 ASSIGN_UNSIGNED (guint8);
460 ASSIGN_UNSIGNED (guint16);
462 ASSIGN_UNSIGNED (guint32);
464 ASSIGN_UNSIGNED (guint64);
466 ASSIGN_SIGNED (gint8);
468 ASSIGN_SIGNED (gint16);
470 ASSIGN_SIGNED (gint32);
472 ASSIGN_SIGNED (gint64);
474 ASSIGN_REAL (gfloat);
476 ASSIGN_REAL (gdouble);
480 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
484 #undef NO_WIDENING_CONVERSION
485 #undef CHECK_WIDENING_CONVERSION
486 #undef ASSIGN_UNSIGNED
492 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
500 MONO_CHECK_ARG_NULL (idxs);
502 ic = idxs->obj.vtable->klass;
503 ac = this->obj.vtable->klass;
505 g_assert (ic->rank == 1);
506 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
507 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
509 ind = (gint32 *)idxs->vector;
511 if (this->bounds == NULL) {
512 if (*ind < 0 || *ind >= this->max_length)
513 mono_raise_exception (mono_get_exception_index_out_of_range ());
515 ves_icall_System_Array_SetValueImpl (this, value, *ind);
519 for (i = 0; i < ac->rank; i++)
520 if ((ind [i] < this->bounds [i].lower_bound) ||
521 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
522 mono_raise_exception (mono_get_exception_index_out_of_range ());
524 pos = ind [0] - this->bounds [0].lower_bound;
525 for (i = 1; i < ac->rank; i++)
526 pos = pos * this->bounds [i].length + ind [i] -
527 this->bounds [i].lower_bound;
529 ves_icall_System_Array_SetValueImpl (this, value, pos);
532 ICALL_EXPORT MonoArray *
533 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
535 MonoClass *aklass, *klass;
538 gboolean bounded = FALSE;
542 MONO_CHECK_ARG_NULL (type);
543 MONO_CHECK_ARG_NULL (lengths);
545 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
547 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
549 for (i = 0; i < mono_array_length (lengths); i++)
550 if (mono_array_get (lengths, gint32, i) < 0)
551 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
553 klass = mono_class_from_mono_type (type->type);
554 mono_class_init_or_throw (klass);
556 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
557 /* vectors are not the same as one dimensional arrays with no-zero bounds */
562 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
564 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
565 for (i = 0; i < aklass->rank; ++i) {
566 sizes [i] = mono_array_get (lengths, guint32, i);
568 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
570 sizes [i + aklass->rank] = 0;
573 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
578 ICALL_EXPORT MonoArray *
579 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
581 MonoClass *aklass, *klass;
584 gboolean bounded = FALSE;
588 MONO_CHECK_ARG_NULL (type);
589 MONO_CHECK_ARG_NULL (lengths);
591 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
593 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
595 for (i = 0; i < mono_array_length (lengths); i++)
596 if ((mono_array_get (lengths, gint64, i) < 0) ||
597 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
598 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
600 klass = mono_class_from_mono_type (type->type);
601 mono_class_init_or_throw (klass);
603 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
604 /* vectors are not the same as one dimensional arrays with no-zero bounds */
609 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
611 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
612 for (i = 0; i < aklass->rank; ++i) {
613 sizes [i] = mono_array_get (lengths, guint64, i);
615 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
617 sizes [i + aklass->rank] = 0;
620 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
626 ves_icall_System_Array_GetRank (MonoObject *this)
630 return this->vtable->klass->rank;
634 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
636 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
641 if ((dimension < 0) || (dimension >= rank))
642 mono_raise_exception (mono_get_exception_index_out_of_range ());
644 if (this->bounds == NULL)
645 length = this->max_length;
647 length = this->bounds [dimension].length;
649 #ifdef MONO_BIG_ARRAYS
650 if (length > G_MAXINT32)
651 mono_raise_exception (mono_get_exception_overflow ());
657 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
659 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
663 if ((dimension < 0) || (dimension >= rank))
664 mono_raise_exception (mono_get_exception_index_out_of_range ());
666 if (this->bounds == NULL)
667 return this->max_length;
669 return this->bounds [dimension].length;
673 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
675 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
679 if ((dimension < 0) || (dimension >= rank))
680 mono_raise_exception (mono_get_exception_index_out_of_range ());
682 if (this->bounds == NULL)
685 return this->bounds [dimension].lower_bound;
689 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
691 int sz = mono_array_element_size (mono_object_class (arr));
692 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
695 ICALL_EXPORT gboolean
696 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
701 MonoVTable *src_vtable;
702 MonoVTable *dest_vtable;
703 MonoClass *src_class;
704 MonoClass *dest_class;
706 src_vtable = source->obj.vtable;
707 dest_vtable = dest->obj.vtable;
709 if (src_vtable->rank != dest_vtable->rank)
712 if (source->bounds || dest->bounds)
715 /* there's no integer overflow since mono_array_length returns an unsigned integer */
716 if ((dest_idx + length > mono_array_length_fast (dest)) ||
717 (source_idx + length > mono_array_length_fast (source)))
720 src_class = src_vtable->klass->element_class;
721 dest_class = dest_vtable->klass->element_class;
724 * Handle common cases.
727 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
728 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
730 if (src_class == mono_defaults.object_class && dest_class->valuetype)
733 /* Check if we're copying a char[] <==> (u)short[] */
734 if (src_class != dest_class) {
735 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
738 /* 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. */
739 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
743 if (dest_class->valuetype) {
744 element_size = mono_array_element_size (source->obj.vtable->klass);
745 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
746 if (dest_class->has_references) {
747 mono_value_copy_array (dest, dest_idx, source_addr, length);
749 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
750 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
753 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
760 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
769 ao = (MonoArray *)this;
770 ac = (MonoClass *)ao->obj.vtable->klass;
772 esize = mono_array_element_size (ac);
773 ea = (gpointer*)((char*)ao->vector + (pos * esize));
775 mono_gc_memmove_atomic (value, ea, esize);
779 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
788 ao = (MonoArray *)this;
789 ac = (MonoClass *)ao->obj.vtable->klass;
790 ec = ac->element_class;
792 esize = mono_array_element_size (ac);
793 ea = (gpointer*)((char*)ao->vector + (pos * esize));
795 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
796 g_assert (esize == sizeof (gpointer));
797 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
799 g_assert (ec->inited);
800 g_assert (esize == mono_class_value_size (ec, NULL));
801 if (ec->has_references)
802 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
804 mono_gc_memmove_atomic (ea, value, esize);
809 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
811 MonoClass *klass = array->obj.vtable->klass;
812 guint32 size = mono_array_element_size (klass);
813 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
815 const char *field_data;
817 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
818 MonoException *exc = mono_get_exception_argument("array",
819 "Cannot initialize array of non-primitive type.");
820 mono_raise_exception (exc);
823 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
824 MonoException *exc = mono_get_exception_argument("field_handle",
825 "Field doesn't have an RVA");
826 mono_raise_exception (exc);
829 size *= array->max_length;
830 field_data = mono_field_get_data (field_handle);
832 if (size > mono_type_size (field_handle->type, &align)) {
833 MonoException *exc = mono_get_exception_argument("field_handle",
834 "Field not large enough to fill array");
835 mono_raise_exception (exc);
838 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
840 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
841 guint ## n *src = (guint ## n *) field_data; \
842 guint ## n *end = (guint ## n *)((char*)src + size); \
844 for (; src < end; data++, src++) { \
845 *data = read ## n (src); \
849 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
851 switch (type->type) {
868 memcpy (mono_array_addr (array, char, 0), field_data, size);
872 memcpy (mono_array_addr (array, char, 0), field_data, size);
877 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
881 return offsetof (MonoString, chars);
884 ICALL_EXPORT MonoObject *
885 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
889 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
892 return mono_object_clone (obj);
896 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
901 MONO_CHECK_ARG_NULL (handle);
903 klass = mono_class_from_mono_type (handle);
904 MONO_CHECK_ARG (handle, klass);
906 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
908 /* This will call the type constructor */
909 mono_runtime_class_init (vtable);
913 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
917 mono_image_check_for_module_cctor (image);
918 if (image->has_module_cctor) {
919 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
920 /*It's fine to raise the exception here*/
921 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
925 ICALL_EXPORT MonoBoolean
926 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
931 /* later make this configurable and per-arch */
932 int min_size = 4096 * 4 * sizeof (void*);
933 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
934 /* if we have no info we are optimistic and assume there is enough room */
938 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
942 current = (guint8 *)&stack_addr;
943 if (current > stack_addr) {
944 if ((current - stack_addr) < min_size)
947 if (current - (stack_addr - stack_size) < min_size)
953 ICALL_EXPORT MonoObject *
954 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
958 return mono_object_clone (this);
962 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
965 MonoObject **values = NULL;
968 gint32 result = (int)(gsize)mono_defaults.int32_class;
969 MonoClassField* field;
974 klass = mono_object_class (this);
976 if (mono_class_num_fields (klass) == 0)
980 * Compute the starting value of the hashcode for fields of primitive
981 * types, and return the remaining fields in an array to the managed side.
982 * This way, we can avoid costly reflection operations in managed code.
985 while ((field = mono_class_get_fields (klass, &iter))) {
986 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
988 if (mono_field_is_deleted (field))
990 /* FIXME: Add more types */
991 switch (field->type->type) {
993 result ^= *(gint32*)((guint8*)this + field->offset);
995 case MONO_TYPE_STRING: {
997 s = *(MonoString**)((guint8*)this + field->offset);
999 result ^= mono_string_hash (s);
1004 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1005 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1006 values [count++] = o;
1012 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1013 for (i = 0; i < count; ++i)
1014 mono_array_setref (*fields, i, values [i]);
1021 ICALL_EXPORT MonoBoolean
1022 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1025 MonoObject **values = NULL;
1027 MonoClassField* field;
1031 MONO_ARCH_SAVE_REGS;
1033 MONO_CHECK_ARG_NULL (that);
1035 if (this->vtable != that->vtable)
1038 klass = mono_object_class (this);
1040 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1041 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1044 * Do the comparison for fields of primitive type and return a result if
1045 * possible. Otherwise, return the remaining fields in an array to the
1046 * managed side. This way, we can avoid costly reflection operations in
1051 while ((field = mono_class_get_fields (klass, &iter))) {
1052 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1054 if (mono_field_is_deleted (field))
1056 /* FIXME: Add more types */
1057 switch (field->type->type) {
1060 case MONO_TYPE_BOOLEAN:
1061 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1066 case MONO_TYPE_CHAR:
1067 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1072 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1077 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1081 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1085 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1090 case MONO_TYPE_STRING: {
1091 MonoString *s1, *s2;
1092 guint32 s1len, s2len;
1093 s1 = *(MonoString**)((guint8*)this + field->offset);
1094 s2 = *(MonoString**)((guint8*)that + field->offset);
1097 if ((s1 == NULL) || (s2 == NULL))
1099 s1len = mono_string_length (s1);
1100 s2len = mono_string_length (s2);
1104 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1110 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1111 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1112 values [count++] = o;
1113 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1114 values [count++] = o;
1117 if (klass->enumtype)
1118 /* enums only have one non-static field */
1124 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1125 for (i = 0; i < count; ++i)
1126 mono_array_setref_fast (*fields, i, values [i]);
1133 ICALL_EXPORT MonoReflectionType *
1134 ves_icall_System_Object_GetType (MonoObject *obj)
1136 MONO_ARCH_SAVE_REGS;
1138 #ifndef DISABLE_REMOTING
1139 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1140 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1143 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1147 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1149 MONO_ARCH_SAVE_REGS;
1151 mtype->type = &obj->vtable->klass->byval_arg;
1152 g_assert (mtype->type->type);
1156 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1158 MONO_ARCH_SAVE_REGS;
1160 MONO_CHECK_ARG_NULL (obj);
1162 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1166 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1167 MonoReflectionMethod *method,
1168 MonoArray *opt_param_types)
1170 MONO_ARCH_SAVE_REGS;
1172 MONO_CHECK_ARG_NULL (method);
1174 return mono_image_create_method_token (
1175 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1179 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1181 MONO_ARCH_SAVE_REGS;
1183 mono_image_create_pefile (mb, file);
1187 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1189 MONO_ARCH_SAVE_REGS;
1191 mono_image_build_metadata (mb);
1195 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1197 MONO_ARCH_SAVE_REGS;
1199 mono_image_register_token (mb->dynamic_image, token, obj);
1203 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1205 MonoMethod **dest = data;
1207 /* skip unmanaged frames */
1223 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1225 MonoMethod **dest = data;
1227 /* skip unmanaged frames */
1232 if (!strcmp (m->klass->name_space, "System.Reflection"))
1241 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1243 MonoMethod **dest = data;
1245 /* skip unmanaged frames */
1249 if (m->wrapper_type != MONO_WRAPPER_NONE)
1252 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1266 static MonoReflectionType *
1267 type_from_name (const char *str, MonoBoolean ignoreCase)
1269 MonoMethod *m, *dest;
1271 MonoType *type = NULL;
1272 MonoAssembly *assembly = NULL;
1273 MonoTypeNameParse info;
1274 char *temp_str = g_strdup (str);
1275 gboolean type_resolve = FALSE;
1277 MONO_ARCH_SAVE_REGS;
1279 /* mono_reflection_parse_type() mangles the string */
1280 if (!mono_reflection_parse_type (temp_str, &info)) {
1281 mono_reflection_free_type_info (&info);
1288 * We must compute the calling assembly as type loading must happen under a metadata context.
1289 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1290 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1292 m = mono_method_get_last_managed ();
1295 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1300 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1301 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1302 * to crash. This only seems to happen in some strange remoting
1303 * scenarios and I was unable to figure out what's happening there.
1304 * Dec 10, 2005 - Martin.
1308 assembly = dest->klass->image->assembly;
1309 type_resolve = TRUE;
1311 g_warning (G_STRLOC);
1314 if (info.assembly.name)
1315 assembly = mono_assembly_load (&info.assembly, assembly ? assembly->basedir : NULL, NULL);
1319 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1320 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1323 if (!info.assembly.name && !type) /* try mscorlib */
1324 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1326 if (assembly && !type && type_resolve) {
1327 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1328 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1331 mono_reflection_free_type_info (&info);
1337 return mono_type_get_object (mono_domain_get (), type);
1341 MonoReflectionType *
1342 mono_type_get (const char *str)
1344 char *copy = g_strdup (str);
1345 MonoReflectionType *type = type_from_name (copy, FALSE);
1352 ICALL_EXPORT MonoReflectionType*
1353 ves_icall_type_from_name (MonoString *name,
1354 MonoBoolean throwOnError,
1355 MonoBoolean ignoreCase)
1357 char *str = mono_string_to_utf8 (name);
1358 MonoReflectionType *type;
1360 type = type_from_name (str, ignoreCase);
1363 MonoException *e = NULL;
1366 e = mono_get_exception_type_load (name, NULL);
1368 mono_loader_clear_error ();
1370 mono_raise_exception (e);
1377 ICALL_EXPORT MonoReflectionType*
1378 ves_icall_type_from_handle (MonoType *handle)
1380 MonoDomain *domain = mono_domain_get ();
1382 MONO_ARCH_SAVE_REGS;
1384 return mono_type_get_object (domain, handle);
1387 ICALL_EXPORT MonoBoolean
1388 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1390 MONO_ARCH_SAVE_REGS;
1392 if (c && type->type && c->type)
1393 return mono_metadata_type_equal (type->type, c->type);
1395 return (type == c) ? TRUE : FALSE;
1398 /* System.TypeCode */
1417 TYPECODE_STRING = 18
1420 ICALL_EXPORT guint32
1421 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1423 int t = type->type->type;
1425 MONO_ARCH_SAVE_REGS;
1427 if (type->type->byref)
1428 return TYPECODE_OBJECT;
1432 case MONO_TYPE_VOID:
1433 return TYPECODE_OBJECT;
1434 case MONO_TYPE_BOOLEAN:
1435 return TYPECODE_BOOLEAN;
1437 return TYPECODE_BYTE;
1439 return TYPECODE_SBYTE;
1441 return TYPECODE_UINT16;
1443 return TYPECODE_INT16;
1444 case MONO_TYPE_CHAR:
1445 return TYPECODE_CHAR;
1449 return TYPECODE_OBJECT;
1451 return TYPECODE_UINT32;
1453 return TYPECODE_INT32;
1455 return TYPECODE_UINT64;
1457 return TYPECODE_INT64;
1459 return TYPECODE_SINGLE;
1461 return TYPECODE_DOUBLE;
1462 case MONO_TYPE_VALUETYPE: {
1463 MonoClass *klass = type->type->data.klass;
1465 if (klass->enumtype) {
1466 t = mono_class_enum_basetype (klass)->type;
1468 } else if (mono_is_corlib_image (klass->image)) {
1469 if (strcmp (klass->name_space, "System") == 0) {
1470 if (strcmp (klass->name, "Decimal") == 0)
1471 return TYPECODE_DECIMAL;
1472 else if (strcmp (klass->name, "DateTime") == 0)
1473 return TYPECODE_DATETIME;
1476 return TYPECODE_OBJECT;
1478 case MONO_TYPE_STRING:
1479 return TYPECODE_STRING;
1480 case MONO_TYPE_SZARRAY:
1481 case MONO_TYPE_ARRAY:
1482 case MONO_TYPE_OBJECT:
1484 case MONO_TYPE_MVAR:
1485 case MONO_TYPE_TYPEDBYREF:
1486 return TYPECODE_OBJECT;
1487 case MONO_TYPE_CLASS:
1489 MonoClass *klass = type->type->data.klass;
1490 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1491 if (strcmp (klass->name, "DBNull") == 0)
1492 return TYPECODE_DBNULL;
1495 return TYPECODE_OBJECT;
1496 case MONO_TYPE_GENERICINST:
1497 return TYPECODE_OBJECT;
1499 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1504 ICALL_EXPORT guint32
1505 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1511 MONO_ARCH_SAVE_REGS;
1513 g_assert (type != NULL);
1515 domain = ((MonoObject *)type)->vtable->domain;
1517 if (!c) /* FIXME: dont know what do do here */
1520 klass = mono_class_from_mono_type (type->type);
1521 klassc = mono_class_from_mono_type (c->type);
1523 /* Interface check requires a more complex setup so we
1524 * only do for them. Otherwise we simply avoid mono_class_init.
1526 if (check_interfaces) {
1527 mono_class_init_or_throw (klass);
1528 mono_class_init_or_throw (klassc);
1529 } else if (!klass->supertypes || !klassc->supertypes) {
1530 mono_class_setup_supertypes (klass);
1531 mono_class_setup_supertypes (klassc);
1534 if (type->type->byref)
1535 return klassc == mono_defaults.object_class;
1537 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1541 mono_type_is_primitive (MonoType *type)
1543 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1544 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1548 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1550 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1551 return mono_class_enum_basetype (type->data.klass);
1552 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1553 return mono_class_enum_basetype (type->data.generic_class->container_class);
1557 ICALL_EXPORT guint32
1558 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1564 MONO_ARCH_SAVE_REGS;
1566 g_assert (type != NULL);
1568 domain = ((MonoObject *)type)->vtable->domain;
1570 klass = mono_class_from_mono_type (type->type);
1571 klassc = mono_class_from_mono_type (c->type);
1573 if (type->type->byref ^ c->type->byref)
1576 if (type->type->byref) {
1577 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1578 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1580 klass = mono_class_from_mono_type (t);
1581 klassc = mono_class_from_mono_type (ot);
1583 if (mono_type_is_primitive (t)) {
1584 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1585 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1586 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1587 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1588 return t->type == ot->type;
1590 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1593 if (klass->valuetype)
1594 return klass == klassc;
1595 return klass->valuetype == klassc->valuetype;
1598 return mono_class_is_assignable_from (klass, klassc);
1601 ICALL_EXPORT guint32
1602 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1604 MonoClass *klass = mono_class_from_mono_type (type->type);
1605 mono_class_init_or_throw (klass);
1606 return mono_object_isinst (obj, klass) != NULL;
1609 ICALL_EXPORT guint32
1610 ves_icall_get_attributes (MonoReflectionType *type)
1612 MonoClass *klass = mono_class_from_mono_type (type->type);
1613 return klass->flags;
1616 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1617 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1619 MonoClass *klass = field->field->parent;
1620 MonoMarshalType *info;
1623 if (klass->generic_container ||
1624 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1627 info = mono_marshal_load_type_info (klass);
1629 for (i = 0; i < info->num_fields; ++i) {
1630 if (info->fields [i].field == field->field) {
1631 if (!info->fields [i].mspec)
1634 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1641 ICALL_EXPORT MonoReflectionField*
1642 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1644 gboolean found = FALSE;
1651 klass = handle->parent;
1653 klass = mono_class_from_mono_type (type);
1655 /* Check that the field belongs to the class */
1656 for (k = klass; k; k = k->parent) {
1657 if (k == handle->parent) {
1664 /* The managed code will throw the exception */
1668 return mono_field_get_object (mono_domain_get (), klass, handle);
1671 ICALL_EXPORT MonoArray*
1672 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1675 MonoType *type = mono_field_get_type_checked (field->field, &error);
1676 if (!mono_error_ok (&error))
1677 mono_error_raise_exception (&error);
1679 return type_array_from_modifiers (field->field->parent->image, type, optional);
1683 vell_icall_get_method_attributes (MonoMethod *method)
1685 return method->flags;
1689 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1692 MonoDomain *domain = mono_domain_get ();
1693 MonoMethodSignature* sig;
1694 MONO_ARCH_SAVE_REGS;
1696 sig = mono_method_signature_checked (method, &error);
1697 if (!mono_error_ok (&error))
1698 mono_error_raise_exception (&error);
1701 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1702 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1703 info->attrs = method->flags;
1704 info->implattrs = method->iflags;
1705 if (sig->call_convention == MONO_CALL_DEFAULT)
1706 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1708 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1713 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1716 ICALL_EXPORT MonoArray*
1717 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1719 MonoDomain *domain = mono_domain_get ();
1721 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1724 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1725 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1727 MonoDomain *domain = mono_domain_get ();
1728 MonoReflectionMarshalAsAttribute* res = NULL;
1729 MonoMarshalSpec **mspecs;
1732 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1733 mono_method_get_marshal_info (method, mspecs);
1736 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1738 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1740 mono_metadata_free_marshal_spec (mspecs [i]);
1747 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1749 MonoClass *parent = field->field->parent;
1750 if (!parent->size_inited)
1751 mono_class_init (parent);
1753 return field->field->offset - sizeof (MonoObject);
1756 ICALL_EXPORT MonoReflectionType*
1757 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1760 MONO_ARCH_SAVE_REGS;
1762 parent = declaring? field->field->parent: field->klass;
1764 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1767 ICALL_EXPORT MonoObject *
1768 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1770 MonoClass *fklass = field->klass;
1771 MonoClassField *cf = field->field;
1772 MonoDomain *domain = mono_object_domain (field);
1774 if (fklass->image->assembly->ref_only)
1775 mono_raise_exception (mono_get_exception_invalid_operation (
1776 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1778 if (mono_security_core_clr_enabled ())
1779 mono_security_core_clr_ensure_reflection_access_field (cf);
1781 return mono_field_get_value_object (domain, cf, obj);
1785 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1788 MonoClassField *cf = field->field;
1792 MONO_ARCH_SAVE_REGS;
1794 if (field->klass->image->assembly->ref_only)
1795 mono_raise_exception (mono_get_exception_invalid_operation (
1796 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1798 if (mono_security_core_clr_enabled ())
1799 mono_security_core_clr_ensure_reflection_access_field (cf);
1801 type = mono_field_get_type_checked (cf, &error);
1802 if (!mono_error_ok (&error))
1803 mono_error_raise_exception (&error);
1805 v = (gchar *) value;
1807 switch (type->type) {
1810 case MONO_TYPE_BOOLEAN:
1813 case MONO_TYPE_CHAR:
1822 case MONO_TYPE_VALUETYPE:
1825 v += sizeof (MonoObject);
1827 case MONO_TYPE_STRING:
1828 case MONO_TYPE_OBJECT:
1829 case MONO_TYPE_CLASS:
1830 case MONO_TYPE_ARRAY:
1831 case MONO_TYPE_SZARRAY:
1834 case MONO_TYPE_GENERICINST: {
1835 MonoGenericClass *gclass = type->data.generic_class;
1836 g_assert (!gclass->context.class_inst->is_open);
1838 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1839 MonoClass *nklass = mono_class_from_mono_type (type);
1840 MonoObject *nullable;
1843 * Convert the boxed vtype into a Nullable structure.
1844 * This is complicated by the fact that Nullables have
1845 * a variable structure.
1847 nullable = mono_object_new (mono_domain_get (), nklass);
1849 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1851 v = mono_object_unbox (nullable);
1854 if (gclass->container_class->valuetype && (v != NULL))
1855 v += sizeof (MonoObject);
1859 g_error ("type 0x%x not handled in "
1860 "ves_icall_FieldInfo_SetValueInternal", type->type);
1865 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1866 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1867 if (!vtable->initialized)
1868 mono_runtime_class_init (vtable);
1869 mono_field_static_set_value (vtable, cf, v);
1871 mono_field_set_value (obj, cf, v);
1875 ICALL_EXPORT MonoObject *
1876 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1878 MonoObject *o = NULL;
1879 MonoClassField *field = this->field;
1881 MonoDomain *domain = mono_object_domain (this);
1883 MonoTypeEnum def_type;
1884 const char *def_value;
1888 MONO_ARCH_SAVE_REGS;
1890 mono_class_init (field->parent);
1892 t = mono_field_get_type_checked (field, &error);
1893 if (!mono_error_ok (&error))
1894 mono_error_raise_exception (&error);
1896 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1897 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1899 if (field->parent->image->dynamic) {
1901 g_assert_not_reached ();
1904 def_value = mono_class_get_field_default_value (field, &def_type);
1905 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1906 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1908 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1912 case MONO_TYPE_BOOLEAN:
1915 case MONO_TYPE_CHAR:
1923 case MONO_TYPE_R8: {
1926 /* boxed value type */
1927 t = g_new0 (MonoType, 1);
1929 klass = mono_class_from_mono_type (t);
1931 o = mono_object_new (domain, klass);
1932 v = ((gchar *) o) + sizeof (MonoObject);
1933 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1936 case MONO_TYPE_STRING:
1937 case MONO_TYPE_CLASS:
1938 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1941 g_assert_not_reached ();
1947 ICALL_EXPORT MonoReflectionType*
1948 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1951 MonoClassField *field = ref_field->field;
1952 MonoType *type = mono_field_get_type_checked (field, &error);
1953 if (!mono_error_ok (&error))
1954 mono_error_raise_exception (&error);
1955 return mono_type_get_object (mono_object_domain (ref_field), type);
1958 ICALL_EXPORT MonoReflectionType*
1959 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1961 MonoMethod *method = rmethod->method.method;
1963 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1966 /* From MonoProperty.cs */
1968 PInfo_Attributes = 1,
1969 PInfo_GetMethod = 1 << 1,
1970 PInfo_SetMethod = 1 << 2,
1971 PInfo_ReflectedType = 1 << 3,
1972 PInfo_DeclaringType = 1 << 4,
1977 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1979 MonoDomain *domain = mono_object_domain (property);
1981 MONO_ARCH_SAVE_REGS;
1983 if ((req_info & PInfo_ReflectedType) != 0)
1984 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1985 if ((req_info & PInfo_DeclaringType) != 0)
1986 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1988 if ((req_info & PInfo_Name) != 0)
1989 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1991 if ((req_info & PInfo_Attributes) != 0)
1992 info->attrs = property->property->attrs;
1994 if ((req_info & PInfo_GetMethod) != 0)
1995 MONO_STRUCT_SETREF (info, get, property->property->get ?
1996 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1998 if ((req_info & PInfo_SetMethod) != 0)
1999 MONO_STRUCT_SETREF (info, set, property->property->set ?
2000 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2002 * There may be other methods defined for properties, though, it seems they are not exposed
2003 * in the reflection API
2008 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2010 MonoDomain *domain = mono_object_domain (event);
2012 MONO_ARCH_SAVE_REGS;
2014 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2015 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2017 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2018 info->attrs = event->event->attrs;
2019 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2020 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2021 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2023 #ifndef MONO_SMALL_CONFIG
2024 if (event->event->other) {
2026 while (event->event->other [n])
2028 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2030 for (i = 0; i < n; i++)
2031 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2037 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2042 mono_class_setup_interfaces (klass, error);
2043 if (!mono_error_ok (error))
2046 for (i = 0; i < klass->interface_count; i++) {
2047 ic = klass->interfaces [i];
2048 g_hash_table_insert (ifaces, ic, ic);
2050 collect_interfaces (ic, ifaces, error);
2051 if (!mono_error_ok (error))
2057 MonoArray *iface_array;
2058 MonoGenericContext *context;
2062 } FillIfaceArrayData;
2065 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2067 FillIfaceArrayData *data = user_data;
2068 MonoClass *ic = key;
2069 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2071 if (!mono_error_ok (data->error))
2074 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2075 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2076 if (!mono_error_ok (data->error))
2080 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2083 mono_metadata_free_type (inflated);
2086 ICALL_EXPORT MonoArray*
2087 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2090 MonoClass *class = mono_class_from_mono_type (type->type);
2092 FillIfaceArrayData data = { 0 };
2095 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2097 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2098 data.context = mono_class_get_context (class);
2099 class = class->generic_class->container_class;
2102 for (parent = class; parent; parent = parent->parent) {
2103 mono_class_setup_interfaces (parent, &error);
2104 if (!mono_error_ok (&error))
2106 collect_interfaces (parent, iface_hash, &error);
2107 if (!mono_error_ok (&error))
2111 data.error = &error;
2112 data.domain = mono_object_domain (type);
2114 len = g_hash_table_size (iface_hash);
2116 g_hash_table_destroy (iface_hash);
2117 if (!data.domain->empty_types)
2118 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2119 return data.domain->empty_types;
2122 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2123 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2124 if (!mono_error_ok (&error))
2127 g_hash_table_destroy (iface_hash);
2128 return data.iface_array;
2131 g_hash_table_destroy (iface_hash);
2132 mono_error_raise_exception (&error);
2137 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2139 gboolean variance_used;
2140 MonoClass *class = mono_class_from_mono_type (type->type);
2141 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2142 MonoReflectionMethod *member;
2145 int i = 0, len, ioffset;
2148 MONO_ARCH_SAVE_REGS;
2149 mono_class_init_or_throw (class);
2150 mono_class_init_or_throw (iclass);
2152 mono_class_setup_vtable (class);
2154 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2158 len = mono_class_num_methods (iclass);
2159 domain = mono_object_domain (type);
2160 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2161 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2163 while ((method = mono_class_get_methods (iclass, &iter))) {
2164 member = mono_method_get_object (domain, method, iclass);
2165 mono_array_setref (*methods, i, member);
2166 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2167 mono_array_setref (*targets, i, member);
2174 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2176 MonoClass *klass = mono_class_from_mono_type (type->type);
2177 mono_class_init_or_throw (klass);
2179 if (klass->image->dynamic) {
2180 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2181 *packing = tb->packing_size;
2182 *size = tb->class_size;
2184 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2188 ICALL_EXPORT MonoReflectionType*
2189 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2193 MONO_ARCH_SAVE_REGS;
2195 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2196 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2198 class = mono_class_from_mono_type (type->type);
2199 mono_class_init_or_throw (class);
2201 // GetElementType should only return a type for:
2202 // Array Pointer PassedByRef
2203 if (type->type->byref)
2204 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2205 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2206 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2207 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2208 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2213 ICALL_EXPORT MonoReflectionType*
2214 ves_icall_get_type_parent (MonoReflectionType *type)
2216 MonoClass *class = mono_class_from_mono_type (type->type);
2217 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2220 ICALL_EXPORT MonoBoolean
2221 ves_icall_type_ispointer (MonoReflectionType *type)
2223 MONO_ARCH_SAVE_REGS;
2225 return type->type->type == MONO_TYPE_PTR;
2228 ICALL_EXPORT MonoBoolean
2229 ves_icall_type_isprimitive (MonoReflectionType *type)
2231 MONO_ARCH_SAVE_REGS;
2233 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)));
2236 ICALL_EXPORT MonoBoolean
2237 ves_icall_type_isbyref (MonoReflectionType *type)
2239 MONO_ARCH_SAVE_REGS;
2241 return type->type->byref;
2244 ICALL_EXPORT MonoBoolean
2245 ves_icall_type_iscomobject (MonoReflectionType *type)
2247 MonoClass *klass = mono_class_from_mono_type (type->type);
2248 mono_class_init_or_throw (klass);
2250 return mono_class_is_com_object (klass);
2253 ICALL_EXPORT MonoReflectionModule*
2254 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2256 MonoClass *class = mono_class_from_mono_type (type->type);
2257 return mono_module_get_object (mono_object_domain (type), class->image);
2260 ICALL_EXPORT MonoReflectionAssembly*
2261 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2263 MonoDomain *domain = mono_domain_get ();
2264 MonoClass *class = mono_class_from_mono_type (type->type);
2265 return mono_assembly_get_object (domain, class->image->assembly);
2268 ICALL_EXPORT MonoReflectionType*
2269 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2271 MonoDomain *domain = mono_domain_get ();
2274 MONO_ARCH_SAVE_REGS;
2276 if (type->type->byref)
2278 if (type->type->type == MONO_TYPE_VAR)
2279 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2280 else if (type->type->type == MONO_TYPE_MVAR)
2281 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2283 class = mono_class_from_mono_type (type->type)->nested_in;
2285 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2288 ICALL_EXPORT MonoString*
2289 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2291 MonoDomain *domain = mono_domain_get ();
2292 MonoClass *class = mono_class_from_mono_type (type->type);
2294 if (type->type->byref) {
2295 char *n = g_strdup_printf ("%s&", class->name);
2296 MonoString *res = mono_string_new (domain, n);
2302 return mono_string_new (domain, class->name);
2306 ICALL_EXPORT MonoString*
2307 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2309 MonoDomain *domain = mono_domain_get ();
2310 MonoClass *class = mono_class_from_mono_type (type->type);
2312 while (class->nested_in)
2313 class = class->nested_in;
2315 if (class->name_space [0] == '\0')
2318 return mono_string_new (domain, class->name_space);
2322 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2326 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2327 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2329 class = mono_class_from_mono_type (type->type);
2334 ICALL_EXPORT MonoArray*
2335 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2338 MonoClass *klass, *pklass;
2339 MonoDomain *domain = mono_object_domain (type);
2340 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2342 MONO_ARCH_SAVE_REGS;
2344 klass = mono_class_from_mono_type (type->type);
2346 if (klass->generic_container) {
2347 MonoGenericContainer *container = klass->generic_container;
2348 res = mono_array_new_specific (array_vtable, container->type_argc);
2349 for (i = 0; i < container->type_argc; ++i) {
2350 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2351 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2353 } else if (klass->generic_class) {
2354 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2355 res = mono_array_new_specific (array_vtable, inst->type_argc);
2356 for (i = 0; i < inst->type_argc; ++i)
2357 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2359 res = mono_array_new_specific (array_vtable, 0);
2364 ICALL_EXPORT gboolean
2365 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2368 MONO_ARCH_SAVE_REGS;
2370 if (!IS_MONOTYPE (type))
2373 if (type->type->byref)
2376 klass = mono_class_from_mono_type (type->type);
2377 return klass->generic_container != NULL;
2380 ICALL_EXPORT MonoReflectionType*
2381 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2384 MONO_ARCH_SAVE_REGS;
2386 if (type->type->byref)
2389 klass = mono_class_from_mono_type (type->type);
2391 if (klass->generic_container) {
2392 return type; /* check this one */
2394 if (klass->generic_class) {
2395 MonoClass *generic_class = klass->generic_class->container_class;
2398 tb = mono_class_get_ref_info (generic_class);
2400 if (generic_class->wastypebuilder && tb)
2403 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2408 ICALL_EXPORT MonoReflectionType*
2409 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2412 MonoType *geninst, **types;
2415 g_assert (IS_MONOTYPE (type));
2416 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2418 count = mono_array_length (type_array);
2419 types = g_new0 (MonoType *, count);
2421 for (i = 0; i < count; i++) {
2422 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2423 types [i] = t->type;
2426 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2431 class = mono_class_from_mono_type (geninst);
2433 /*we might inflate to the GTD*/
2434 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2435 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2437 return mono_type_get_object (mono_object_domain (type), geninst);
2440 ICALL_EXPORT gboolean
2441 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2444 MONO_ARCH_SAVE_REGS;
2446 if (type->type->byref)
2449 klass = mono_class_from_mono_type (type->type);
2451 return klass->generic_class != NULL;
2454 ICALL_EXPORT gboolean
2455 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2458 MONO_ARCH_SAVE_REGS;
2460 if (!IS_MONOTYPE (type))
2463 if (type->type->byref)
2466 klass = mono_class_from_mono_type (type->type);
2467 return klass->generic_class != NULL || klass->generic_container != NULL;
2471 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2473 MONO_ARCH_SAVE_REGS;
2475 if (!IS_MONOTYPE (type))
2478 if (is_generic_parameter (type->type))
2479 return mono_type_get_generic_param_num (type->type);
2483 ICALL_EXPORT GenericParameterAttributes
2484 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2486 MONO_ARCH_SAVE_REGS;
2488 g_assert (IS_MONOTYPE (type));
2489 g_assert (is_generic_parameter (type->type));
2490 return mono_generic_param_info (type->type->data.generic_param)->flags;
2493 ICALL_EXPORT MonoArray *
2494 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2496 MonoGenericParamInfo *param_info;
2502 MONO_ARCH_SAVE_REGS;
2504 g_assert (IS_MONOTYPE (type));
2506 domain = mono_object_domain (type);
2507 param_info = mono_generic_param_info (type->type->data.generic_param);
2508 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2511 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2512 for (i = 0; i < count; i++)
2513 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2519 ICALL_EXPORT MonoBoolean
2520 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2522 MONO_ARCH_SAVE_REGS;
2523 return is_generic_parameter (type->type);
2526 ICALL_EXPORT MonoBoolean
2527 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2529 MONO_ARCH_SAVE_REGS;
2530 return is_generic_parameter (tb->type.type);
2534 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2535 MonoReflectionType *t)
2537 enumtype->type = t->type;
2540 ICALL_EXPORT MonoReflectionMethod*
2541 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2542 MonoReflectionMethod* generic)
2549 MONO_ARCH_SAVE_REGS;
2551 domain = ((MonoObject *)type)->vtable->domain;
2553 klass = mono_class_from_mono_type (type->type);
2554 mono_class_init_or_throw (klass);
2557 while ((method = mono_class_get_methods (klass, &iter))) {
2558 if (method->token == generic->method->token)
2559 return mono_method_get_object (domain, method, klass);
2567 ICALL_EXPORT MonoReflectionMethod *
2568 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2571 MonoType *type = ref_type->type;
2573 MONO_ARCH_SAVE_REGS;
2575 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2576 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2577 if (type->type == MONO_TYPE_VAR)
2580 method = mono_type_get_generic_param_owner (type)->owner.method;
2582 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2585 ICALL_EXPORT MonoReflectionDllImportAttribute*
2586 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2588 static MonoClass *DllImportAttributeClass = NULL;
2589 MonoDomain *domain = mono_domain_get ();
2590 MonoReflectionDllImportAttribute *attr;
2591 MonoImage *image = method->klass->image;
2592 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2593 MonoTableInfo *tables = image->tables;
2594 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2595 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2596 guint32 im_cols [MONO_IMPLMAP_SIZE];
2597 guint32 scope_token;
2598 const char *import = NULL;
2599 const char *scope = NULL;
2602 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2605 if (!DllImportAttributeClass) {
2606 DllImportAttributeClass =
2607 mono_class_from_name (mono_defaults.corlib,
2608 "System.Runtime.InteropServices", "DllImportAttribute");
2609 g_assert (DllImportAttributeClass);
2612 if (method->klass->image->dynamic) {
2613 MonoReflectionMethodAux *method_aux =
2614 g_hash_table_lookup (
2615 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2617 import = method_aux->dllentry;
2618 scope = method_aux->dll;
2621 if (!import || !scope) {
2622 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2627 if (piinfo->implmap_idx) {
2628 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2630 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2631 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2632 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2633 scope = mono_metadata_string_heap (image, scope_token);
2636 flags = piinfo->piflags;
2638 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2640 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2641 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2642 attr->call_conv = (flags & 0x700) >> 8;
2643 attr->charset = ((flags & 0x6) >> 1) + 1;
2644 if (attr->charset == 1)
2646 attr->exact_spelling = (flags & 0x1) != 0;
2647 attr->set_last_error = (flags & 0x40) != 0;
2648 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2649 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2650 attr->preserve_sig = FALSE;
2655 ICALL_EXPORT MonoReflectionMethod *
2656 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2658 MonoMethodInflated *imethod;
2661 MONO_ARCH_SAVE_REGS;
2663 if (method->method->is_generic)
2666 if (!method->method->is_inflated)
2669 imethod = (MonoMethodInflated *) method->method;
2671 result = imethod->declaring;
2672 /* Not a generic method. */
2673 if (!result->is_generic)
2676 if (method->method->klass->image->dynamic) {
2677 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2678 MonoReflectionMethod *res;
2681 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2682 * the dynamic case as well ?
2684 mono_image_lock ((MonoImage*)image);
2685 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2686 mono_image_unlock ((MonoImage*)image);
2692 if (imethod->context.class_inst) {
2693 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2694 /*Generic methods gets the context of the GTD.*/
2695 if (mono_class_get_context (klass))
2696 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2699 return mono_method_get_object (mono_object_domain (method), result, NULL);
2702 ICALL_EXPORT gboolean
2703 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2705 MONO_ARCH_SAVE_REGS;
2707 return mono_method_signature (method->method)->generic_param_count != 0;
2710 ICALL_EXPORT gboolean
2711 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2713 MONO_ARCH_SAVE_REGS;
2715 return method->method->is_generic;
2718 ICALL_EXPORT MonoArray*
2719 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2724 MONO_ARCH_SAVE_REGS;
2726 domain = mono_object_domain (method);
2728 if (method->method->is_inflated) {
2729 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2732 count = inst->type_argc;
2733 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2735 for (i = 0; i < count; i++)
2736 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2742 count = mono_method_signature (method->method)->generic_param_count;
2743 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2745 for (i = 0; i < count; i++) {
2746 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2747 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2748 MonoClass *pklass = mono_class_from_generic_parameter (
2749 param, method->method->klass->image, TRUE);
2750 mono_array_setref (res, i,
2751 mono_type_get_object (domain, &pklass->byval_arg));
2757 ICALL_EXPORT MonoObject *
2758 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2761 * Invoke from reflection is supposed to always be a virtual call (the API
2762 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2763 * greater flexibility.
2765 MonoMethod *m = method->method;
2766 MonoMethodSignature *sig = mono_method_signature (m);
2771 MONO_ARCH_SAVE_REGS;
2775 if (mono_security_core_clr_enabled ())
2776 mono_security_core_clr_ensure_reflection_access_method (m);
2778 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2779 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2780 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2785 if (!mono_object_isinst (this, m->klass)) {
2786 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2787 char *target_name = mono_type_get_full_name (m->klass);
2788 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2789 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2791 g_free (target_name);
2795 m = mono_object_get_virtual_method (this, m);
2796 /* must pass the pointer to the value for valuetype methods */
2797 if (m->klass->valuetype)
2798 obj = mono_object_unbox (this);
2799 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2800 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2805 if (sig->ret->byref) {
2806 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"));
2810 pcount = params? mono_array_length (params): 0;
2811 if (pcount != sig->param_count) {
2812 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2816 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2817 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."));
2821 image = m->klass->image;
2822 if (image->assembly->ref_only) {
2823 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."));
2827 if (image->dynamic && !((MonoDynamicImage*)image)->run) {
2828 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2832 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2835 intptr_t *lower_bounds;
2836 pcount = mono_array_length (params);
2837 lengths = alloca (sizeof (uintptr_t) * pcount);
2838 /* Note: the synthetized array .ctors have int32 as argument type */
2839 for (i = 0; i < pcount; ++i)
2840 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2842 if (m->klass->rank == pcount) {
2843 /* Only lengths provided. */
2844 lower_bounds = NULL;
2846 g_assert (pcount == (m->klass->rank * 2));
2847 /* lower bounds are first. */
2848 lower_bounds = (intptr_t*)lengths;
2849 lengths += m->klass->rank;
2852 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2854 return mono_runtime_invoke_array (m, obj, params, NULL);
2857 #ifndef DISABLE_REMOTING
2858 ICALL_EXPORT MonoObject *
2859 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2861 MonoDomain *domain = mono_object_domain (method);
2862 MonoMethod *m = method->method;
2863 MonoMethodSignature *sig = mono_method_signature (m);
2864 MonoArray *out_args;
2866 int i, j, outarg_count = 0;
2868 MONO_ARCH_SAVE_REGS;
2870 if (m->klass == mono_defaults.object_class) {
2872 if (!strcmp (m->name, "FieldGetter")) {
2873 MonoClass *k = this->vtable->klass;
2877 /* If this is a proxy, then it must be a CBO */
2878 if (k == mono_defaults.transparent_proxy_class) {
2879 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2880 this = tp->rp->unwrapped_server;
2882 k = this->vtable->klass;
2885 name = mono_array_get (params, MonoString *, 1);
2886 str = mono_string_to_utf8 (name);
2889 MonoClassField* field = mono_class_get_field_from_name (k, str);
2891 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2892 if (field_klass->valuetype)
2893 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2895 result = *((gpointer *)((char *)this + field->offset));
2897 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2898 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2899 mono_array_setref (out_args, 0, result);
2907 g_assert_not_reached ();
2909 } else if (!strcmp (m->name, "FieldSetter")) {
2910 MonoClass *k = this->vtable->klass;
2916 /* If this is a proxy, then it must be a CBO */
2917 if (k == mono_defaults.transparent_proxy_class) {
2918 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2919 this = tp->rp->unwrapped_server;
2921 k = this->vtable->klass;
2924 name = mono_array_get (params, MonoString *, 1);
2925 str = mono_string_to_utf8 (name);
2928 MonoClassField* field = mono_class_get_field_from_name (k, str);
2930 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2931 MonoObject *val = mono_array_get (params, gpointer, 2);
2933 if (field_klass->valuetype) {
2934 size = mono_type_size (field->type, &align);
2935 g_assert (size == mono_class_value_size (field_klass, NULL));
2936 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2938 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2941 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2942 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2952 g_assert_not_reached ();
2957 for (i = 0; i < mono_array_length (params); i++) {
2958 if (sig->params [i]->byref)
2962 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2964 /* handle constructors only for objects already allocated */
2965 if (!strcmp (method->method->name, ".ctor"))
2968 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2969 g_assert (!method->method->klass->valuetype);
2970 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2972 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2973 if (sig->params [i]->byref) {
2975 arg = mono_array_get (params, gpointer, i);
2976 mono_array_setref (out_args, j, arg);
2981 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2988 read_enum_value (char *mem, int type)
2992 return *(guint8*)mem;
2994 return *(gint8*)mem;
2996 return *(guint16*)mem;
2998 return *(gint16*)mem;
3000 return *(guint32*)mem;
3002 return *(gint32*)mem;
3004 return *(guint64*)mem;
3006 return *(gint64*)mem;
3008 g_assert_not_reached ();
3014 write_enum_value (char *mem, int type, guint64 value)
3018 case MONO_TYPE_I1: {
3019 guint8 *p = (guint8*)mem;
3024 case MONO_TYPE_I2: {
3025 guint16 *p = (void*)mem;
3030 case MONO_TYPE_I4: {
3031 guint32 *p = (void*)mem;
3036 case MONO_TYPE_I8: {
3037 guint64 *p = (void*)mem;
3042 g_assert_not_reached ();
3047 ICALL_EXPORT MonoObject *
3048 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3051 MonoClass *enumc, *objc;
3056 MONO_ARCH_SAVE_REGS;
3058 MONO_CHECK_ARG_NULL (enumType);
3059 MONO_CHECK_ARG_NULL (value);
3061 domain = mono_object_domain (enumType);
3062 enumc = mono_class_from_mono_type (enumType->type);
3064 mono_class_init_or_throw (enumc);
3066 objc = value->vtable->klass;
3068 if (!enumc->enumtype)
3069 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3070 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3071 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."));
3073 etype = mono_class_enum_basetype (enumc);
3075 /* MS throws this for typebuilders */
3076 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3078 res = mono_object_new (domain, enumc);
3079 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3080 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3085 ICALL_EXPORT MonoObject *
3086 ves_icall_System_Enum_get_value (MonoObject *this)
3094 MONO_ARCH_SAVE_REGS;
3099 g_assert (this->vtable->klass->enumtype);
3101 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3102 res = mono_object_new (mono_object_domain (this), enumc);
3103 dst = (char *)res + sizeof (MonoObject);
3104 src = (char *)this + sizeof (MonoObject);
3105 size = mono_class_value_size (enumc, NULL);
3107 memcpy (dst, src, size);
3112 ICALL_EXPORT MonoReflectionType *
3113 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3118 MONO_ARCH_SAVE_REGS;
3120 klass = mono_class_from_mono_type (type->type);
3121 mono_class_init_or_throw (klass);
3123 etype = mono_class_enum_basetype (klass);
3125 /* MS throws this for typebuilders */
3126 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3128 return mono_type_get_object (mono_object_domain (type), etype);
3132 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3134 gpointer tdata = (char *)this + sizeof (MonoObject);
3135 gpointer odata = (char *)other + sizeof (MonoObject);
3136 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3137 g_assert (basetype);
3139 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3140 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3141 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3144 return me > other ? 1 : -1; \
3147 switch (basetype->type) {
3149 COMPARE_ENUM_VALUES (guint8);
3151 COMPARE_ENUM_VALUES (gint8);
3152 case MONO_TYPE_CHAR:
3154 COMPARE_ENUM_VALUES (guint16);
3156 COMPARE_ENUM_VALUES (gint16);
3158 COMPARE_ENUM_VALUES (guint32);
3160 COMPARE_ENUM_VALUES (gint32);
3162 COMPARE_ENUM_VALUES (guint64);
3164 COMPARE_ENUM_VALUES (gint64);
3166 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3168 #undef COMPARE_ENUM_VALUES
3173 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3175 gpointer data = (char *)this + sizeof (MonoObject);
3176 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3177 g_assert (basetype);
3179 switch (basetype->type) {
3181 return *((gint8*)data);
3183 return *((guint8*)data);
3184 case MONO_TYPE_CHAR:
3186 return *((guint16*)data);
3189 return *((gint16*)data);
3191 return *((guint32*)data);
3193 return *((gint32*)data);
3195 case MONO_TYPE_I8: {
3196 gint64 value = *((gint64*)data);
3197 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3200 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3206 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3208 MonoDomain *domain = mono_object_domain (type);
3209 MonoClass *enumc = mono_class_from_mono_type (type->type);
3210 guint j = 0, nvalues, crow;
3212 MonoClassField *field;
3214 MONO_ARCH_SAVE_REGS;
3216 mono_class_init_or_throw (enumc);
3218 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3219 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3220 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3221 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3225 while ((field = mono_class_get_fields (enumc, &iter))) {
3228 MonoTypeEnum def_type;
3230 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3232 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3234 if (mono_field_is_deleted (field))
3236 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3238 p = mono_class_get_field_default_value (field, &def_type);
3239 len = mono_metadata_decode_blob_size (p, &p);
3240 switch (mono_class_enum_basetype (enumc)->type) {
3243 mono_array_set (info->values, gchar, j, *p);
3245 case MONO_TYPE_CHAR:
3248 mono_array_set (info->values, gint16, j, read16 (p));
3252 mono_array_set (info->values, gint32, j, read32 (p));
3256 mono_array_set (info->values, gint64, j, read64 (p));
3259 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3266 BFLAGS_IgnoreCase = 1,
3267 BFLAGS_DeclaredOnly = 2,
3268 BFLAGS_Instance = 4,
3270 BFLAGS_Public = 0x10,
3271 BFLAGS_NonPublic = 0x20,
3272 BFLAGS_FlattenHierarchy = 0x40,
3273 BFLAGS_InvokeMethod = 0x100,
3274 BFLAGS_CreateInstance = 0x200,
3275 BFLAGS_GetField = 0x400,
3276 BFLAGS_SetField = 0x800,
3277 BFLAGS_GetProperty = 0x1000,
3278 BFLAGS_SetProperty = 0x2000,
3279 BFLAGS_ExactBinding = 0x10000,
3280 BFLAGS_SuppressChangeType = 0x20000,
3281 BFLAGS_OptionalParamBinding = 0x40000
3284 ICALL_EXPORT MonoReflectionField *
3285 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3288 MonoClass *startklass, *klass;
3290 MonoClassField *field;
3293 int (*compare_func) (const char *s1, const char *s2) = NULL;
3294 domain = ((MonoObject *)type)->vtable->domain;
3295 klass = startklass = mono_class_from_mono_type (type->type);
3298 mono_raise_exception (mono_get_exception_argument_null ("name"));
3299 if (type->type->byref)
3302 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3305 if (klass->exception_type != MONO_EXCEPTION_NONE)
3306 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3309 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3310 guint32 flags = mono_field_get_flags (field);
3313 if (mono_field_is_deleted_with_flags (field, flags))
3315 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3316 if (bflags & BFLAGS_Public)
3318 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3319 if (bflags & BFLAGS_NonPublic) {
3326 if (flags & FIELD_ATTRIBUTE_STATIC) {
3327 if (bflags & BFLAGS_Static)
3328 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3331 if (bflags & BFLAGS_Instance)
3338 utf8_name = mono_string_to_utf8 (name);
3340 if (compare_func (mono_field_get_name (field), utf8_name)) {
3346 return mono_field_get_object (domain, klass, field);
3348 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3354 ICALL_EXPORT MonoArray*
3355 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3358 MonoClass *startklass, *klass, *refklass;
3363 MonoClassField *field;
3364 MonoPtrArray tmp_array;
3366 MONO_ARCH_SAVE_REGS;
3368 domain = ((MonoObject *)type)->vtable->domain;
3369 if (type->type->byref)
3370 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3371 klass = startklass = mono_class_from_mono_type (type->type);
3372 refklass = mono_class_from_mono_type (reftype->type);
3374 mono_ptr_array_init (tmp_array, 2);
3377 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3378 mono_ptr_array_destroy (tmp_array);
3379 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3383 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3384 guint32 flags = mono_field_get_flags (field);
3386 if (mono_field_is_deleted_with_flags (field, flags))
3388 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3389 if (bflags & BFLAGS_Public)
3391 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3392 if (bflags & BFLAGS_NonPublic) {
3399 if (flags & FIELD_ATTRIBUTE_STATIC) {
3400 if (bflags & BFLAGS_Static)
3401 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3404 if (bflags & BFLAGS_Instance)
3410 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3411 mono_ptr_array_append (tmp_array, member);
3413 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3416 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3418 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3419 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3421 mono_ptr_array_destroy (tmp_array);
3427 method_nonpublic (MonoMethod* method, gboolean start_klass)
3429 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3430 case METHOD_ATTRIBUTE_ASSEM:
3431 return (start_klass || mono_defaults.generic_ilist_class);
3432 case METHOD_ATTRIBUTE_PRIVATE:
3434 case METHOD_ATTRIBUTE_PUBLIC:
3442 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3445 MonoClass *startklass;
3448 int len, match, nslots;
3449 /*FIXME, use MonoBitSet*/
3450 guint32 method_slots_default [8];
3451 guint32 *method_slots = NULL;
3452 int (*compare_func) (const char *s1, const char *s2) = NULL;
3454 array = g_ptr_array_new ();
3460 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3462 /* An optimization for calls made from Delegate:CreateDelegate () */
3463 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3464 method = mono_get_delegate_invoke (klass);
3465 if (mono_loader_get_last_error ())
3468 g_ptr_array_add (array, method);
3472 mono_class_setup_vtable (klass);
3473 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3476 if (is_generic_parameter (&klass->byval_arg))
3477 nslots = mono_class_get_vtable_size (klass->parent);
3479 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3480 if (nslots >= sizeof (method_slots_default) * 8) {
3481 method_slots = g_new0 (guint32, nslots / 32 + 1);
3483 method_slots = method_slots_default;
3484 memset (method_slots, 0, sizeof (method_slots_default));
3487 mono_class_setup_vtable (klass);
3488 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3492 while ((method = mono_class_get_methods (klass, &iter))) {
3494 if (method->slot != -1) {
3495 g_assert (method->slot < nslots);
3496 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3498 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3499 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3502 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3504 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3505 if (bflags & BFLAGS_Public)
3507 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3513 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3514 if (bflags & BFLAGS_Static)
3515 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3518 if (bflags & BFLAGS_Instance)
3526 if (compare_func (name, method->name))
3531 g_ptr_array_add (array, method);
3533 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3535 if (method_slots != method_slots_default)
3536 g_free (method_slots);
3541 if (method_slots != method_slots_default)
3542 g_free (method_slots);
3543 g_ptr_array_free (array, TRUE);
3545 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3546 *ex = mono_class_get_exception_for_failure (klass);
3548 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3549 mono_loader_clear_error ();
3554 ICALL_EXPORT MonoArray*
3555 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3557 static MonoClass *MethodInfo_array;
3560 MonoVTable *array_vtable;
3561 MonoException *ex = NULL;
3562 const char *mname = NULL;
3563 GPtrArray *method_array;
3564 MonoClass *klass, *refklass;
3567 if (!MethodInfo_array) {
3568 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3569 mono_memory_barrier ();
3570 MethodInfo_array = klass;
3573 klass = mono_class_from_mono_type (type->type);
3574 refklass = mono_class_from_mono_type (reftype->type);
3575 domain = ((MonoObject *)type)->vtable->domain;
3576 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3577 if (type->type->byref)
3578 return mono_array_new_specific (array_vtable, 0);
3581 mname = mono_string_to_utf8 (name);
3583 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3584 g_free ((char*)mname);
3586 mono_raise_exception (ex);
3588 res = mono_array_new_specific (array_vtable, method_array->len);
3591 for (i = 0; i < method_array->len; ++i) {
3592 MonoMethod *method = g_ptr_array_index (method_array, i);
3593 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3596 g_ptr_array_free (method_array, TRUE);
3600 ICALL_EXPORT MonoArray*
3601 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3604 static MonoClass *System_Reflection_ConstructorInfo;
3605 MonoClass *startklass, *klass, *refklass;
3610 gpointer iter = NULL;
3611 MonoPtrArray tmp_array;
3613 MONO_ARCH_SAVE_REGS;
3615 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3617 domain = ((MonoObject *)type)->vtable->domain;
3618 if (type->type->byref)
3619 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3620 klass = startklass = mono_class_from_mono_type (type->type);
3621 refklass = mono_class_from_mono_type (reftype->type);
3623 if (!System_Reflection_ConstructorInfo)
3624 System_Reflection_ConstructorInfo = mono_class_from_name (
3625 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3628 while ((method = mono_class_get_methods (klass, &iter))) {
3630 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3632 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3633 if (bflags & BFLAGS_Public)
3636 if (bflags & BFLAGS_NonPublic)
3642 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3643 if (bflags & BFLAGS_Static)
3644 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3647 if (bflags & BFLAGS_Instance)
3653 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3655 mono_ptr_array_append (tmp_array, member);
3658 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3660 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3661 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3663 mono_ptr_array_destroy (tmp_array);
3669 property_hash (gconstpointer data)
3671 MonoProperty *prop = (MonoProperty*)data;
3673 return g_str_hash (prop->name);
3677 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3679 // Properties are hide-by-name-and-signature
3680 if (!g_str_equal (prop1->name, prop2->name))
3683 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3685 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3691 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3696 return method_nonpublic (accessor, start_klass);
3699 ICALL_EXPORT MonoArray*
3700 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3704 static MonoClass *System_Reflection_PropertyInfo;
3705 MonoClass *startklass, *klass;
3711 gchar *propname = NULL;
3712 int (*compare_func) (const char *s1, const char *s2) = NULL;
3714 GHashTable *properties = NULL;
3715 MonoPtrArray tmp_array;
3717 MONO_ARCH_SAVE_REGS;
3719 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3721 if (!System_Reflection_PropertyInfo)
3722 System_Reflection_PropertyInfo = mono_class_from_name (
3723 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3725 domain = ((MonoObject *)type)->vtable->domain;
3726 if (type->type->byref)
3727 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3728 klass = startklass = mono_class_from_mono_type (type->type);
3731 propname = mono_string_to_utf8 (name);
3732 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3735 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3737 mono_class_setup_vtable (klass);
3738 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3742 while ((prop = mono_class_get_properties (klass, &iter))) {
3748 flags = method->flags;
3751 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3752 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3753 if (bflags & BFLAGS_Public)
3755 } else if (bflags & BFLAGS_NonPublic) {
3756 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3757 property_accessor_nonpublic(prop->set, startklass == klass)) {
3764 if (flags & METHOD_ATTRIBUTE_STATIC) {
3765 if (bflags & BFLAGS_Static)
3766 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3769 if (bflags & BFLAGS_Instance)
3778 if (compare_func (propname, prop->name))
3782 if (g_hash_table_lookup (properties, prop))
3785 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3787 g_hash_table_insert (properties, prop, prop);
3789 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3792 g_hash_table_destroy (properties);
3795 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3796 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3797 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3799 mono_ptr_array_destroy (tmp_array);
3805 g_hash_table_destroy (properties);
3808 mono_ptr_array_destroy (tmp_array);
3810 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3811 ex = mono_class_get_exception_for_failure (klass);
3813 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3814 mono_loader_clear_error ();
3816 mono_raise_exception (ex);
3820 ICALL_EXPORT MonoReflectionEvent *
3821 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3824 MonoClass *klass, *startklass;
3829 int (*compare_func) (const char *s1, const char *s2);
3831 MONO_ARCH_SAVE_REGS;
3833 event_name = mono_string_to_utf8 (name);
3834 if (type->type->byref)
3836 klass = startklass = mono_class_from_mono_type (type->type);
3837 domain = mono_object_domain (type);
3839 mono_class_init_or_throw (klass);
3841 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3843 if (klass->exception_type != MONO_EXCEPTION_NONE)
3844 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3847 while ((event = mono_class_get_events (klass, &iter))) {
3848 if (compare_func (event->name, event_name))
3851 method = event->add;
3853 method = event->remove;
3855 method = event->raise;
3857 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3858 if (!(bflags & BFLAGS_Public))
3861 if (!(bflags & BFLAGS_NonPublic))
3863 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3867 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3868 if (!(bflags & BFLAGS_Static))
3870 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3873 if (!(bflags & BFLAGS_Instance))
3877 if (!(bflags & BFLAGS_NonPublic))
3880 g_free (event_name);
3881 return mono_event_get_object (domain, startklass, event);
3884 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3887 g_free (event_name);
3892 event_hash (gconstpointer data)
3894 MonoEvent *event = (MonoEvent*)data;
3896 return g_str_hash (event->name);
3900 event_equal (MonoEvent *event1, MonoEvent *event2)
3902 // Events are hide-by-name
3903 return g_str_equal (event1->name, event2->name);
3906 ICALL_EXPORT MonoArray*
3907 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3911 static MonoClass *System_Reflection_EventInfo;
3912 MonoClass *startklass, *klass;
3918 GHashTable *events = NULL;
3919 MonoPtrArray tmp_array;
3921 MONO_ARCH_SAVE_REGS;
3923 mono_ptr_array_init (tmp_array, 4);
3925 if (!System_Reflection_EventInfo)
3926 System_Reflection_EventInfo = mono_class_from_name (
3927 mono_defaults.corlib, "System.Reflection", "EventInfo");
3929 domain = mono_object_domain (type);
3930 if (type->type->byref)
3931 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3932 klass = startklass = mono_class_from_mono_type (type->type);
3934 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3936 mono_class_setup_vtable (klass);
3937 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3941 while ((event = mono_class_get_events (klass, &iter))) {
3943 method = event->add;
3945 method = event->remove;
3947 method = event->raise;
3949 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3950 if (bflags & BFLAGS_Public)
3952 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3953 if (bflags & BFLAGS_NonPublic)
3958 if (bflags & BFLAGS_NonPublic)
3964 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3965 if (bflags & BFLAGS_Static)
3966 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3969 if (bflags & BFLAGS_Instance)
3974 if (bflags & BFLAGS_Instance)
3979 if (g_hash_table_lookup (events, event))
3982 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3984 g_hash_table_insert (events, event, event);
3986 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3989 g_hash_table_destroy (events);
3991 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3993 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3994 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3996 mono_ptr_array_destroy (tmp_array);
4001 mono_ptr_array_destroy (tmp_array);
4002 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4003 ex = mono_class_get_exception_for_failure (klass);
4005 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4006 mono_loader_clear_error ();
4008 mono_raise_exception (ex);
4012 ICALL_EXPORT MonoReflectionType *
4013 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4021 MONO_ARCH_SAVE_REGS;
4024 mono_raise_exception (mono_get_exception_argument_null ("name"));
4026 domain = ((MonoObject *)type)->vtable->domain;
4027 if (type->type->byref)
4029 klass = mono_class_from_mono_type (type->type);
4031 str = mono_string_to_utf8 (name);
4034 if (klass->exception_type != MONO_EXCEPTION_NONE)
4035 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4038 * If a nested type is generic, return its generic type definition.
4039 * Note that this means that the return value is essentially a
4040 * nested type of the generic type definition of @klass.
4042 * A note in MSDN claims that a generic type definition can have
4043 * nested types that aren't generic. In any case, the container of that
4044 * nested type would be the generic type definition.
4046 if (klass->generic_class)
4047 klass = klass->generic_class->container_class;
4050 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4052 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4053 if (bflags & BFLAGS_Public)
4056 if (bflags & BFLAGS_NonPublic)
4061 if (strcmp (nested->name, str) == 0){
4063 return mono_type_get_object (domain, &nested->byval_arg);
4066 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4072 ICALL_EXPORT MonoArray*
4073 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4082 MonoPtrArray tmp_array;
4084 MONO_ARCH_SAVE_REGS;
4086 domain = ((MonoObject *)type)->vtable->domain;
4087 if (type->type->byref)
4088 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4089 klass = mono_class_from_mono_type (type->type);
4092 * If a nested type is generic, return its generic type definition.
4093 * Note that this means that the return value is essentially the set
4094 * of nested types of the generic type definition of @klass.
4096 * A note in MSDN claims that a generic type definition can have
4097 * nested types that aren't generic. In any case, the container of that
4098 * nested type would be the generic type definition.
4100 if (klass->generic_class)
4101 klass = klass->generic_class->container_class;
4103 mono_ptr_array_init (tmp_array, 1);
4105 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4107 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4108 if (bflags & BFLAGS_Public)
4111 if (bflags & BFLAGS_NonPublic)
4116 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4117 mono_ptr_array_append (tmp_array, member);
4120 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4122 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4123 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4125 mono_ptr_array_destroy (tmp_array);
4130 ICALL_EXPORT MonoReflectionType*
4131 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4134 MonoType *type = NULL;
4135 MonoTypeNameParse info;
4136 gboolean type_resolve;
4138 MONO_ARCH_SAVE_REGS;
4140 /* On MS.NET, this does not fire a TypeResolve event */
4141 type_resolve = TRUE;
4142 str = mono_string_to_utf8 (name);
4143 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4144 if (!mono_reflection_parse_type (str, &info)) {
4146 mono_reflection_free_type_info (&info);
4147 if (throwOnError) /* uhm: this is a parse error, though... */
4148 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4149 /*g_print ("failed parse\n");*/
4153 if (info.assembly.name) {
4155 mono_reflection_free_type_info (&info);
4157 /* 1.0 and 2.0 throw different exceptions */
4158 if (mono_defaults.generic_ilist_class)
4159 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4161 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4166 if (module != NULL) {
4168 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4173 if (assembly->assembly->dynamic) {
4174 /* Enumerate all modules */
4175 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4179 if (abuilder->modules) {
4180 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4181 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4182 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4188 if (!type && abuilder->loaded_modules) {
4189 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4190 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4191 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4198 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4200 mono_reflection_free_type_info (&info);
4202 MonoException *e = NULL;
4205 e = mono_get_exception_type_load (name, NULL);
4207 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4208 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4210 mono_loader_clear_error ();
4213 mono_raise_exception (e);
4216 } else if (mono_loader_get_last_error ()) {
4218 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4219 mono_loader_clear_error ();
4222 if (type->type == MONO_TYPE_CLASS) {
4223 MonoClass *klass = mono_type_get_class (type);
4225 if (mono_security_enabled () && !klass->exception_type)
4226 /* Some security problems are detected during generic vtable construction */
4227 mono_class_setup_vtable (klass);
4229 /* need to report exceptions ? */
4230 if (throwOnError && klass->exception_type) {
4231 /* report SecurityException (or others) that occured when loading the assembly */
4232 MonoException *exc = mono_class_get_exception_for_failure (klass);
4233 mono_loader_clear_error ();
4234 mono_raise_exception (exc);
4235 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4240 /* g_print ("got it\n"); */
4241 return mono_type_get_object (mono_object_domain (assembly), type);
4245 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4248 gchar *shadow_ini_file;
4251 /* Check for shadow-copied assembly */
4252 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4253 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4255 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4256 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4262 g_free (shadow_ini_file);
4263 if (content != NULL) {
4266 *filename = content;
4273 ICALL_EXPORT MonoString *
4274 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4276 MonoDomain *domain = mono_object_domain (assembly);
4277 MonoAssembly *mass = assembly->assembly;
4278 MonoString *res = NULL;
4283 MONO_ARCH_SAVE_REGS;
4285 if (g_path_is_absolute (mass->image->name)) {
4286 absolute = g_strdup (mass->image->name);
4287 dirname = g_path_get_dirname (absolute);
4289 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4290 dirname = g_strdup (mass->basedir);
4293 replace_shadow_path (domain, dirname, &absolute);
4298 for (i = strlen (absolute) - 1; i >= 0; i--)
4299 if (absolute [i] == '\\')
4304 uri = g_filename_to_uri (absolute, NULL, NULL);
4306 const char *prepend = "file://";
4308 if (*absolute == '/' && *(absolute + 1) == '/') {
4311 prepend = "file:///";
4314 uri = g_strconcat (prepend, absolute, NULL);
4318 res = mono_string_new (domain, uri);
4325 ICALL_EXPORT MonoBoolean
4326 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4328 MonoAssembly *mass = assembly->assembly;
4330 MONO_ARCH_SAVE_REGS;
4332 return mass->in_gac;
4335 ICALL_EXPORT MonoReflectionAssembly*
4336 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4340 MonoImageOpenStatus status;
4342 MONO_ARCH_SAVE_REGS;
4344 name = mono_string_to_utf8 (mname);
4345 res = mono_assembly_load_with_partial_name (name, &status);
4351 return mono_assembly_get_object (mono_domain_get (), res);
4354 ICALL_EXPORT MonoString *
4355 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4357 MonoDomain *domain = mono_object_domain (assembly);
4360 MONO_ARCH_SAVE_REGS;
4362 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4367 ICALL_EXPORT MonoBoolean
4368 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4370 MONO_ARCH_SAVE_REGS;
4372 return assembly->assembly->ref_only;
4375 ICALL_EXPORT MonoString *
4376 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4378 MonoDomain *domain = mono_object_domain (assembly);
4380 MONO_ARCH_SAVE_REGS;
4382 return mono_string_new (domain, assembly->assembly->image->version);
4385 ICALL_EXPORT MonoReflectionMethod*
4386 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4388 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4390 MONO_ARCH_SAVE_REGS;
4394 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4397 ICALL_EXPORT MonoReflectionModule*
4398 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4400 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4403 ICALL_EXPORT MonoArray*
4404 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4406 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4407 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4411 MONO_ARCH_SAVE_REGS;
4413 for (i = 0; i < table->rows; ++i) {
4414 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4415 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4421 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4423 static MonoClass *System_Version = NULL;
4424 static MonoMethod *create_version = NULL;
4428 if (!System_Version) {
4429 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4430 g_assert (System_Version);
4433 if (!create_version) {
4434 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4435 create_version = mono_method_desc_search_in_class (desc, System_Version);
4436 g_assert (create_version);
4437 mono_method_desc_free (desc);
4443 args [3] = &revision;
4444 result = mono_object_new (domain, System_Version);
4445 mono_runtime_invoke (create_version, result, args, NULL);
4450 ICALL_EXPORT MonoArray*
4451 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4453 static MonoClass *System_Reflection_AssemblyName;
4455 MonoDomain *domain = mono_object_domain (assembly);
4457 static MonoMethod *create_culture = NULL;
4458 MonoImage *image = assembly->assembly->image;
4461 MONO_ARCH_SAVE_REGS;
4463 if (!System_Reflection_AssemblyName)
4464 System_Reflection_AssemblyName = mono_class_from_name (
4465 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4467 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4470 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4472 if (count > 0 && !create_culture) {
4473 MonoMethodDesc *desc = mono_method_desc_new (
4474 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4475 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4476 g_assert (create_culture);
4477 mono_method_desc_free (desc);
4480 for (i = 0; i < count; i++) {
4481 MonoReflectionAssemblyName *aname;
4482 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4484 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4486 aname = (MonoReflectionAssemblyName *) mono_object_new (
4487 domain, System_Reflection_AssemblyName);
4489 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4491 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4492 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4493 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4494 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4495 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4496 aname->versioncompat = 1; /* SameMachine (default) */
4497 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4498 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4500 if (create_culture) {
4502 MonoBoolean assembly_ref = 1;
4503 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4504 args [1] = &assembly_ref;
4505 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4508 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4509 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4510 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4512 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4513 /* public key token isn't copied - the class library will
4514 automatically generate it from the public key if required */
4515 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4516 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4518 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4519 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4522 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4525 /* note: this function doesn't return the codebase on purpose (i.e. it can
4526 be used under partial trust as path information isn't present). */
4528 mono_array_setref (result, i, aname);
4533 /* move this in some file in mono/util/ */
4535 g_concat_dir_and_file (const char *dir, const char *file)
4537 g_return_val_if_fail (dir != NULL, NULL);
4538 g_return_val_if_fail (file != NULL, NULL);
4541 * If the directory name doesn't have a / on the end, we need
4542 * to add one so we get a proper path to the file
4544 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4545 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4547 return g_strconcat (dir, file, NULL);
4551 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4553 char *n = mono_string_to_utf8 (name);
4554 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4556 guint32 cols [MONO_MANIFEST_SIZE];
4557 guint32 impl, file_idx;
4561 MONO_ARCH_SAVE_REGS;
4563 for (i = 0; i < table->rows; ++i) {
4564 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4565 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4566 if (strcmp (val, n) == 0)
4570 if (i == table->rows)
4573 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4576 * this code should only be called after obtaining the
4577 * ResourceInfo and handling the other cases.
4579 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4580 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4582 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4587 module = assembly->assembly->image;
4589 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4591 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4594 ICALL_EXPORT gboolean
4595 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4597 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4599 guint32 cols [MONO_MANIFEST_SIZE];
4600 guint32 file_cols [MONO_FILE_SIZE];
4604 MONO_ARCH_SAVE_REGS;
4606 n = mono_string_to_utf8 (name);
4607 for (i = 0; i < table->rows; ++i) {
4608 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4609 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4610 if (strcmp (val, n) == 0)
4614 if (i == table->rows)
4617 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4618 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4621 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4622 case MONO_IMPLEMENTATION_FILE:
4623 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4624 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4625 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4626 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4627 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4628 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4631 info->location = RESOURCE_LOCATION_EMBEDDED;
4634 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4635 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4636 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4637 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4638 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4639 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4641 mono_raise_exception (ex);
4643 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4645 /* Obtain info recursively */
4646 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4647 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4650 case MONO_IMPLEMENTATION_EXP_TYPE:
4651 g_assert_not_reached ();
4659 ICALL_EXPORT MonoObject*
4660 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4662 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4663 MonoArray *result = NULL;
4668 MONO_ARCH_SAVE_REGS;
4670 /* check hash if needed */
4672 n = mono_string_to_utf8 (name);
4673 for (i = 0; i < table->rows; ++i) {
4674 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4675 if (strcmp (val, n) == 0) {
4678 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4679 fn = mono_string_new (mono_object_domain (assembly), n);
4681 return (MonoObject*)fn;
4689 for (i = 0; i < table->rows; ++i) {
4690 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4694 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4697 for (i = 0; i < table->rows; ++i) {
4698 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4699 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4700 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4701 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4706 return (MonoObject*)result;
4709 ICALL_EXPORT MonoArray*
4710 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4712 MonoDomain *domain = mono_domain_get();
4715 int i, j, file_count = 0;
4716 MonoImage **modules;
4717 guint32 module_count, real_module_count;
4718 MonoTableInfo *table;
4719 guint32 cols [MONO_FILE_SIZE];
4720 MonoImage *image = assembly->assembly->image;
4722 g_assert (image != NULL);
4723 g_assert (!assembly->assembly->dynamic);
4725 table = &image->tables [MONO_TABLE_FILE];
4726 file_count = table->rows;
4728 modules = image->modules;
4729 module_count = image->module_count;
4731 real_module_count = 0;
4732 for (i = 0; i < module_count; ++i)
4734 real_module_count ++;
4736 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4737 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4739 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4741 for (i = 0; i < module_count; ++i)
4743 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4747 for (i = 0; i < file_count; ++i, ++j) {
4748 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4749 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4750 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4752 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4754 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4755 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4757 mono_array_setref (res, j, mono_module_get_object (domain, m));
4764 ICALL_EXPORT MonoReflectionMethod*
4765 ves_icall_GetCurrentMethod (void)
4767 MonoMethod *m = mono_method_get_last_managed ();
4769 while (m->is_inflated)
4770 m = ((MonoMethodInflated*)m)->declaring;
4772 return mono_method_get_object (mono_domain_get (), m, NULL);
4777 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4780 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4781 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4782 //method is inflated, we should inflate it on the other class
4783 MonoGenericContext ctx;
4784 ctx.method_inst = inflated->context.method_inst;
4785 ctx.class_inst = inflated->context.class_inst;
4786 if (klass->generic_class)
4787 ctx.class_inst = klass->generic_class->context.class_inst;
4788 else if (klass->generic_container)
4789 ctx.class_inst = klass->generic_container->context.class_inst;
4790 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4793 mono_class_setup_methods (method->klass);
4794 if (method->klass->exception_type)
4796 for (i = 0; i < method->klass->method.count; ++i) {
4797 if (method->klass->methods [i] == method) {
4802 mono_class_setup_methods (klass);
4803 if (klass->exception_type)
4805 g_assert (offset >= 0 && offset < klass->method.count);
4806 return klass->methods [offset];
4809 ICALL_EXPORT MonoReflectionMethod*
4810 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4814 klass = mono_class_from_mono_type (type);
4815 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4817 if (method->klass != klass) {
4818 method = mono_method_get_equivalent_method (method, klass);
4823 klass = method->klass;
4824 return mono_method_get_object (mono_domain_get (), method, klass);
4827 ICALL_EXPORT MonoReflectionMethod*
4828 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4830 return mono_method_get_object (mono_domain_get (), method, NULL);
4833 ICALL_EXPORT MonoReflectionMethodBody*
4834 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4836 return mono_method_body_get_object (mono_domain_get (), method);
4839 ICALL_EXPORT MonoReflectionAssembly*
4840 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4842 MonoMethod *dest = NULL;
4844 MONO_ARCH_SAVE_REGS;
4846 mono_stack_walk_no_il (get_executing, &dest);
4848 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4852 ICALL_EXPORT MonoReflectionAssembly*
4853 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4855 MonoDomain* domain = mono_domain_get ();
4857 MONO_ARCH_SAVE_REGS;
4859 if (!domain->entry_assembly)
4862 return mono_assembly_get_object (domain, domain->entry_assembly);
4865 ICALL_EXPORT MonoReflectionAssembly*
4866 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4871 MONO_ARCH_SAVE_REGS;
4874 mono_stack_walk_no_il (get_executing, &dest);
4876 mono_stack_walk_no_il (get_caller, &dest);
4879 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4882 ICALL_EXPORT MonoString *
4883 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4884 gboolean assembly_qualified)
4886 MonoDomain *domain = mono_object_domain (object);
4887 MonoTypeNameFormat format;
4892 format = assembly_qualified ?
4893 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4894 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4896 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4898 name = mono_type_get_name_full (object->type, format);
4902 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4907 res = mono_string_new (domain, name);
4914 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4916 MonoClass *klass = mono_class_from_mono_type (this->type);
4917 mono_class_init_or_throw (klass);
4918 return mono_security_core_clr_class_level (klass);
4922 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4924 static MonoMethod *create_culture = NULL;
4927 const char *pkey_ptr;
4929 MonoBoolean assembly_ref = 0;
4931 MONO_ARCH_SAVE_REGS;
4933 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4934 aname->major = name->major;
4935 aname->minor = name->minor;
4936 aname->build = name->build;
4937 aname->flags = name->flags;
4938 aname->revision = name->revision;
4939 aname->hashalg = name->hash_alg;
4940 aname->versioncompat = 1; /* SameMachine (default) */
4941 aname->processor_architecture = name->arch;
4943 if (by_default_version)
4944 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4947 if (absolute != NULL && *absolute != '\0') {
4948 const gchar *prepend = "file://";
4951 codebase = g_strdup (absolute);
4956 for (i = strlen (codebase) - 1; i >= 0; i--)
4957 if (codebase [i] == '\\')
4960 if (*codebase == '/' && *(codebase + 1) == '/') {
4963 prepend = "file:///";
4967 result = g_strconcat (prepend, codebase, NULL);
4973 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4977 if (!create_culture) {
4978 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4979 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4980 g_assert (create_culture);
4981 mono_method_desc_free (desc);
4984 if (name->culture) {
4985 args [0] = mono_string_new (domain, name->culture);
4986 args [1] = &assembly_ref;
4987 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4990 if (name->public_key) {
4991 pkey_ptr = (char*)name->public_key;
4992 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4994 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4995 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4996 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4997 } else if (default_publickey) {
4998 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4999 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5002 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5003 if (name->public_key_token [0]) {
5007 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5008 p = mono_array_addr (aname->keyToken, char, 0);
5010 for (i = 0, j = 0; i < 8; i++) {
5011 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5012 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5015 } else if (default_token) {
5016 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5020 ICALL_EXPORT MonoString *
5021 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5023 MonoDomain *domain = mono_object_domain (assembly);
5024 MonoAssembly *mass = assembly->assembly;
5028 name = mono_stringify_assembly_name (&mass->aname);
5029 res = mono_string_new (domain, name);
5036 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5039 MonoAssembly *mass = assembly->assembly;
5041 MONO_ARCH_SAVE_REGS;
5043 if (g_path_is_absolute (mass->image->name)) {
5044 fill_reflection_assembly_name (mono_object_domain (assembly),
5045 aname, &mass->aname, mass->image->name, TRUE,
5049 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5051 fill_reflection_assembly_name (mono_object_domain (assembly),
5052 aname, &mass->aname, absolute, TRUE, TRUE,
5059 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5062 MonoImageOpenStatus status = MONO_IMAGE_OK;
5065 MonoAssemblyName name;
5068 MONO_ARCH_SAVE_REGS;
5070 filename = mono_string_to_utf8 (fname);
5072 dirname = g_path_get_dirname (filename);
5073 replace_shadow_path (mono_domain_get (), dirname, &filename);
5076 image = mono_image_open (filename, &status);
5082 if (status == MONO_IMAGE_IMAGE_INVALID)
5083 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5085 exc = mono_get_exception_file_not_found2 (NULL, fname);
5086 mono_raise_exception (exc);
5089 res = mono_assembly_fill_assembly_name (image, &name);
5091 mono_image_close (image);
5093 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5096 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5100 mono_image_close (image);
5103 ICALL_EXPORT MonoBoolean
5104 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5105 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5107 MonoBoolean result = FALSE;
5108 MonoDeclSecurityEntry entry;
5110 /* SecurityAction.RequestMinimum */
5111 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5112 *minimum = entry.blob;
5113 *minLength = entry.size;
5116 /* SecurityAction.RequestOptional */
5117 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5118 *optional = entry.blob;
5119 *optLength = entry.size;
5122 /* SecurityAction.RequestRefuse */
5123 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5124 *refused = entry.blob;
5125 *refLength = entry.size;
5133 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5137 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5139 guint32 attrs, visibility;
5141 /* we start the count from 1 because we skip the special type <Module> */
5144 for (i = 1; i < tdef->rows; ++i) {
5145 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5146 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5147 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5151 count = tdef->rows - 1;
5153 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5154 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5156 for (i = 1; i < tdef->rows; ++i) {
5157 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5158 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5159 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5160 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5162 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5164 MonoLoaderError *error;
5167 error = mono_loader_get_last_error ();
5168 g_assert (error != NULL);
5170 ex = mono_loader_error_prepare_exception (error);
5171 mono_array_setref (*exceptions, count, ex);
5173 if (mono_loader_get_last_error ())
5174 mono_loader_clear_error ();
5182 ICALL_EXPORT MonoArray*
5183 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5185 MonoArray *res = NULL;
5186 MonoArray *exceptions = NULL;
5187 MonoImage *image = NULL;
5188 MonoTableInfo *table = NULL;
5191 int i, len, ex_count;
5193 MONO_ARCH_SAVE_REGS;
5195 domain = mono_object_domain (assembly);
5197 g_assert (!assembly->assembly->dynamic);
5198 image = assembly->assembly->image;
5199 table = &image->tables [MONO_TABLE_FILE];
5200 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5202 /* Append data from all modules in the assembly */
5203 for (i = 0; i < table->rows; ++i) {
5204 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5205 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5208 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5209 /* Append the new types to the end of the array */
5210 if (mono_array_length (res2) > 0) {
5212 MonoArray *res3, *ex3;
5214 len1 = mono_array_length (res);
5215 len2 = mono_array_length (res2);
5217 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5218 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5219 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5222 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5223 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5224 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5231 /* the ReflectionTypeLoadException must have all the types (Types property),
5232 * NULL replacing types which throws an exception. The LoaderException must
5233 * contain all exceptions for NULL items.
5236 len = mono_array_length (res);
5239 for (i = 0; i < len; i++) {
5240 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5244 klass = mono_type_get_class (t->type);
5245 if ((klass != NULL) && klass->exception_type) {
5246 /* keep the class in the list */
5247 list = g_list_append (list, klass);
5248 /* and replace Type with NULL */
5249 mono_array_setref (res, i, NULL);
5256 if (list || ex_count) {
5258 MonoException *exc = NULL;
5259 MonoArray *exl = NULL;
5260 int j, length = g_list_length (list) + ex_count;
5262 mono_loader_clear_error ();
5264 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5265 /* Types for which mono_class_get () succeeded */
5266 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5267 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5268 mono_array_setref (exl, i, exc);
5270 /* Types for which it don't */
5271 for (j = 0; j < mono_array_length (exceptions); ++j) {
5272 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5274 g_assert (i < length);
5275 mono_array_setref (exl, i, exc);
5282 exc = mono_get_exception_reflection_type_load (res, exl);
5283 mono_loader_clear_error ();
5284 mono_raise_exception (exc);
5290 ICALL_EXPORT gboolean
5291 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5293 MonoAssemblyName aname;
5294 MonoDomain *domain = mono_object_domain (name);
5296 gboolean is_version_defined;
5297 gboolean is_token_defined;
5299 aname.public_key = NULL;
5300 val = mono_string_to_utf8 (assname);
5301 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5302 g_free ((guint8*) aname.public_key);
5307 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5308 FALSE, is_token_defined);
5310 mono_assembly_name_free (&aname);
5311 g_free ((guint8*) aname.public_key);
5317 ICALL_EXPORT MonoReflectionType*
5318 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5320 MonoDomain *domain = mono_object_domain (module);
5323 MONO_ARCH_SAVE_REGS;
5325 g_assert (module->image);
5327 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5328 /* These images do not have a global type */
5331 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5332 return mono_type_get_object (domain, &klass->byval_arg);
5336 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5338 /*if (module->image)
5339 mono_image_close (module->image);*/
5342 ICALL_EXPORT MonoString*
5343 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5345 MonoDomain *domain = mono_object_domain (module);
5347 MONO_ARCH_SAVE_REGS;
5349 g_assert (module->image);
5350 return mono_string_new (domain, module->image->guid);
5353 ICALL_EXPORT gpointer
5354 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5357 if (module->image && module->image->is_module_handle)
5358 return module->image->raw_data;
5361 return (gpointer) (-1);
5365 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5367 if (image->dynamic) {
5368 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5369 *pe_kind = dyn->pe_kind;
5370 *machine = dyn->machine;
5373 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5374 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5379 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5381 return (image->md_version_major << 16) | (image->md_version_minor);
5384 ICALL_EXPORT MonoArray*
5385 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5387 MonoArray *exceptions;
5390 MONO_ARCH_SAVE_REGS;
5393 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5395 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5396 for (i = 0; i < mono_array_length (exceptions); ++i) {
5397 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5399 mono_raise_exception (ex);
5406 mono_memberref_is_method (MonoImage *image, guint32 token)
5408 if (!image->dynamic) {
5409 guint32 cols [MONO_MEMBERREF_SIZE];
5411 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5412 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5413 mono_metadata_decode_blob_size (sig, &sig);
5414 return (*sig != 0x6);
5416 MonoClass *handle_class;
5418 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5421 return mono_defaults.methodhandle_class == handle_class;
5426 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5429 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5430 mono_array_addr (type_args, MonoType*, 0));
5432 context->class_inst = NULL;
5434 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5435 mono_array_addr (method_args, MonoType*, 0));
5437 context->method_inst = NULL;
5440 ICALL_EXPORT MonoType*
5441 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5444 int table = mono_metadata_token_table (token);
5445 int index = mono_metadata_token_index (token);
5446 MonoGenericContext context;
5448 *error = ResolveTokenError_Other;
5450 /* Validate token */
5451 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5452 (table != MONO_TABLE_TYPESPEC)) {
5453 *error = ResolveTokenError_BadTable;
5457 if (image->dynamic) {
5458 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5459 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5460 return klass ? &klass->byval_arg : NULL;
5463 init_generic_context_from_args (&context, type_args, method_args);
5464 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5465 return klass ? &klass->byval_arg : NULL;
5468 if ((index <= 0) || (index > image->tables [table].rows)) {
5469 *error = ResolveTokenError_OutOfRange;
5473 init_generic_context_from_args (&context, type_args, method_args);
5474 klass = mono_class_get_full (image, token, &context);
5476 if (mono_loader_get_last_error ())
5477 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5480 return &klass->byval_arg;
5485 ICALL_EXPORT MonoMethod*
5486 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5488 int table = mono_metadata_token_table (token);
5489 int index = mono_metadata_token_index (token);
5490 MonoGenericContext context;
5493 *error = ResolveTokenError_Other;
5495 /* Validate token */
5496 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5497 (table != MONO_TABLE_MEMBERREF)) {
5498 *error = ResolveTokenError_BadTable;
5502 if (image->dynamic) {
5503 if (table == MONO_TABLE_METHOD)
5504 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5506 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5507 *error = ResolveTokenError_BadTable;
5511 init_generic_context_from_args (&context, type_args, method_args);
5512 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5515 if ((index <= 0) || (index > image->tables [table].rows)) {
5516 *error = ResolveTokenError_OutOfRange;
5519 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5520 *error = ResolveTokenError_BadTable;
5524 init_generic_context_from_args (&context, type_args, method_args);
5525 method = mono_get_method_full (image, token, NULL, &context);
5527 if (mono_loader_get_last_error ())
5528 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5533 ICALL_EXPORT MonoString*
5534 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5536 int index = mono_metadata_token_index (token);
5538 *error = ResolveTokenError_Other;
5540 /* Validate token */
5541 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5542 *error = ResolveTokenError_BadTable;
5547 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5549 if ((index <= 0) || (index >= image->heap_us.size)) {
5550 *error = ResolveTokenError_OutOfRange;
5554 /* FIXME: What to do if the index points into the middle of a string ? */
5556 return mono_ldstr (mono_domain_get (), image, index);
5559 ICALL_EXPORT MonoClassField*
5560 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5563 int table = mono_metadata_token_table (token);
5564 int index = mono_metadata_token_index (token);
5565 MonoGenericContext context;
5566 MonoClassField *field;
5568 *error = ResolveTokenError_Other;
5570 /* Validate token */
5571 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5572 *error = ResolveTokenError_BadTable;
5576 if (image->dynamic) {
5577 if (table == MONO_TABLE_FIELD)
5578 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5580 if (mono_memberref_is_method (image, token)) {
5581 *error = ResolveTokenError_BadTable;
5585 init_generic_context_from_args (&context, type_args, method_args);
5586 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5589 if ((index <= 0) || (index > image->tables [table].rows)) {
5590 *error = ResolveTokenError_OutOfRange;
5593 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5594 *error = ResolveTokenError_BadTable;
5598 init_generic_context_from_args (&context, type_args, method_args);
5599 field = mono_field_from_token (image, token, &klass, &context);
5601 if (mono_loader_get_last_error ())
5602 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5608 ICALL_EXPORT MonoObject*
5609 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5611 int table = mono_metadata_token_table (token);
5613 *error = ResolveTokenError_Other;
5616 case MONO_TABLE_TYPEDEF:
5617 case MONO_TABLE_TYPEREF:
5618 case MONO_TABLE_TYPESPEC: {
5619 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5621 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5625 case MONO_TABLE_METHOD:
5626 case MONO_TABLE_METHODSPEC: {
5627 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5629 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5633 case MONO_TABLE_FIELD: {
5634 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5636 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5640 case MONO_TABLE_MEMBERREF:
5641 if (mono_memberref_is_method (image, token)) {
5642 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5644 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5649 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5651 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5658 *error = ResolveTokenError_BadTable;
5664 ICALL_EXPORT MonoArray*
5665 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5667 int table = mono_metadata_token_table (token);
5668 int idx = mono_metadata_token_index (token);
5669 MonoTableInfo *tables = image->tables;
5674 *error = ResolveTokenError_OutOfRange;
5676 /* FIXME: Support other tables ? */
5677 if (table != MONO_TABLE_STANDALONESIG)
5683 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5686 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5688 ptr = mono_metadata_blob_heap (image, sig);
5689 len = mono_metadata_decode_blob_size (ptr, &ptr);
5691 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5692 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5696 ICALL_EXPORT MonoReflectionType*
5697 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5700 int isbyref = 0, rank;
5701 char *str = mono_string_to_utf8 (smodifiers);
5704 MONO_ARCH_SAVE_REGS;
5706 klass = mono_class_from_mono_type (tb->type.type);
5708 /* logic taken from mono_reflection_parse_type(): keep in sync */
5712 if (isbyref) { /* only one level allowed by the spec */
5719 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5722 klass = mono_ptr_class_get (&klass->byval_arg);
5723 mono_class_init (klass);
5734 else if (*p != '*') { /* '*' means unknown lower bound */
5745 klass = mono_array_class_get (klass, rank);
5746 mono_class_init (klass);
5753 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5756 ICALL_EXPORT MonoBoolean
5757 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5762 MONO_ARCH_SAVE_REGS;
5765 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5771 check_for_invalid_type (MonoClass *klass)
5775 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5778 name = mono_type_get_full_name (klass);
5779 str = mono_string_new (mono_domain_get (), name);
5781 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5784 ICALL_EXPORT MonoReflectionType *
5785 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5787 MonoClass *klass, *aklass;
5789 MONO_ARCH_SAVE_REGS;
5791 klass = mono_class_from_mono_type (type->type);
5792 check_for_invalid_type (klass);
5794 if (rank == 0) //single dimentional array
5795 aklass = mono_array_class_get (klass, 1);
5797 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5799 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5802 ICALL_EXPORT MonoReflectionType *
5803 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5807 MONO_ARCH_SAVE_REGS;
5809 klass = mono_class_from_mono_type (type->type);
5810 mono_class_init_or_throw (klass);
5811 check_for_invalid_type (klass);
5813 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5816 ICALL_EXPORT MonoReflectionType *
5817 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5819 MonoClass *klass, *pklass;
5821 klass = mono_class_from_mono_type (type->type);
5822 mono_class_init_or_throw (klass);
5823 check_for_invalid_type (klass);
5825 pklass = mono_ptr_class_get (type->type);
5827 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5830 ICALL_EXPORT MonoObject *
5831 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5832 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5834 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5835 MonoObject *delegate;
5837 MonoMethod *method = info->method;
5839 MONO_ARCH_SAVE_REGS;
5841 mono_class_init_or_throw (delegate_class);
5843 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5845 if (mono_security_core_clr_enabled ()) {
5846 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5850 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5852 if (method->dynamic) {
5853 /* Creating a trampoline would leak memory */
5854 func = mono_compile_method (method);
5856 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5857 method = mono_object_get_virtual_method (target, method);
5858 func = mono_create_ftnptr (mono_domain_get (),
5859 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5862 mono_delegate_ctor_with_method (delegate, target, func, method);
5868 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5870 /* Reset the invoke impl to the default one */
5871 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5875 * Magic number to convert a time which is relative to
5876 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5878 #define EPOCH_ADJUST ((guint64)62135596800LL)
5881 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5883 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5886 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5888 convert_to_absolute_date(SYSTEMTIME *date)
5890 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5891 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5892 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5893 /* from the calendar FAQ */
5894 int a = (14 - date->wMonth) / 12;
5895 int y = date->wYear - a;
5896 int m = date->wMonth + 12 * a - 2;
5897 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5899 /* d is now the day of the week for the first of the month (0 == Sunday) */
5901 int day_of_week = date->wDayOfWeek;
5903 /* set day_in_month to the first day in the month which falls on day_of_week */
5904 int day_in_month = 1 + (day_of_week - d);
5905 if (day_in_month <= 0)
5908 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5909 date->wDay = day_in_month + (date->wDay - 1) * 7;
5910 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5917 * Return's the offset from GMT of a local time.
5919 * tm is a local time
5920 * t is the same local time as seconds.
5923 gmt_offset(struct tm *tm, time_t t)
5925 #if defined (HAVE_TM_GMTOFF)
5926 return tm->tm_gmtoff;
5931 g.tm_isdst = tm->tm_isdst;
5933 return (int)difftime(t, t2);
5938 * This is heavily based on zdump.c from glibc 2.2.
5940 * * data[0]: start of daylight saving time (in DateTime ticks).
5941 * * data[1]: end of daylight saving time (in DateTime ticks).
5942 * * data[2]: utcoffset (in TimeSpan ticks).
5943 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5944 * * name[0]: name of this timezone when not daylight saving.
5945 * * name[1]: name of this timezone when daylight saving.
5947 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5948 * the class library allows years between 1 and 9999.
5950 * Returns true on success and zero on failure.
5952 ICALL_EXPORT guint32
5953 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5956 MonoDomain *domain = mono_domain_get ();
5957 struct tm start, tt;
5960 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5961 int day, transitioned;
5964 gmtoff_st = gmtoff_ds = transitioned = 0;
5966 MONO_ARCH_SAVE_REGS;
5968 MONO_CHECK_ARG_NULL (data);
5969 MONO_CHECK_ARG_NULL (names);
5971 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5972 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5975 * no info is better than crashing: we'll need our own tz data
5976 * to make this work properly, anyway. The range is probably
5977 * reduced to 1970 .. 2037 because that is what mktime is
5978 * guaranteed to support (we get into an infinite loop
5982 memset (&start, 0, sizeof (start));
5985 start.tm_year = year-1900;
5987 t = mktime (&start);
5989 if ((year < 1970) || (year > 2037) || (t == -1)) {
5991 tt = *localtime (&t);
5992 strftime (tzone, sizeof (tzone), "%Z", &tt);
5993 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5994 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5998 gmtoff = gmt_offset (&start, t);
6000 /* For each day of the year, calculate the tm_gmtoff. */
6001 for (day = 0; day < 365 && transitioned < 2; day++) {
6004 tt = *localtime (&t);
6006 gmtoff_after = gmt_offset(&tt, t);
6008 /* Daylight saving starts or ends here. */
6009 if (gmtoff_after != gmtoff) {
6013 /* Try to find the exact hour when daylight saving starts/ends. */
6017 tt1 = *localtime (&t1);
6018 } while (gmt_offset (&tt1, t1) != gmtoff);
6020 /* Try to find the exact minute when daylight saving starts/ends. */
6023 tt1 = *localtime (&t1);
6024 } while (gmt_offset (&tt1, t1) == gmtoff);
6026 strftime (tzone, sizeof (tzone), "%Z", &tt);
6028 /* Write data, if we're already in daylight saving, we're done. */
6030 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6031 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6032 if (gmtoff_ds == 0) {
6034 gmtoff_ds = gmtoff_after;
6041 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6042 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6043 if (gmtoff_ds == 0) {
6044 gmtoff_st = gmtoff_after;
6050 /* This is only set once when we enter daylight saving. */
6052 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6053 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6055 gmtoff = gmt_offset (&tt, t);
6059 if (transitioned < 2) {
6060 strftime (tzone, sizeof (tzone), "%Z", &tt);
6061 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6062 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6063 mono_array_set ((*data), gint64, 0, 0);
6064 mono_array_set ((*data), gint64, 1, 0);
6065 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6066 mono_array_set ((*data), gint64, 3, 0);
6071 MonoDomain *domain = mono_domain_get ();
6072 TIME_ZONE_INFORMATION tz_info;
6077 tz_id = GetTimeZoneInformation (&tz_info);
6078 if (tz_id == TIME_ZONE_ID_INVALID)
6081 MONO_CHECK_ARG_NULL (data);
6082 MONO_CHECK_ARG_NULL (names);
6084 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6085 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6087 for (i = 0; i < 32; ++i)
6088 if (!tz_info.DaylightName [i])
6090 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6091 for (i = 0; i < 32; ++i)
6092 if (!tz_info.StandardName [i])
6094 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6096 if ((year <= 1601) || (year > 30827)) {
6098 * According to MSDN, the MS time functions can't handle dates outside
6104 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6105 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6106 tz_info.StandardDate.wYear = year;
6107 convert_to_absolute_date(&tz_info.StandardDate);
6108 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6113 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6114 tz_info.DaylightDate.wYear = year;
6115 convert_to_absolute_date(&tz_info.DaylightDate);
6116 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6121 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6123 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6124 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6132 static inline gint32
6133 mono_array_get_byte_length (MonoArray *array)
6139 klass = array->obj.vtable->klass;
6141 if (array->bounds == NULL)
6142 length = array->max_length;
6145 for (i = 0; i < klass->rank; ++ i)
6146 length *= array->bounds [i].length;
6149 switch (klass->element_class->byval_arg.type) {
6152 case MONO_TYPE_BOOLEAN:
6156 case MONO_TYPE_CHAR:
6164 return length * sizeof (gpointer);
6175 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6177 MONO_ARCH_SAVE_REGS;
6179 return mono_array_get_byte_length (array);
6183 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6185 MONO_ARCH_SAVE_REGS;
6187 return mono_array_get (array, gint8, idx);
6191 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6193 MONO_ARCH_SAVE_REGS;
6195 mono_array_set (array, gint8, idx, value);
6198 ICALL_EXPORT MonoBoolean
6199 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6201 guint8 *src_buf, *dest_buf;
6203 MONO_ARCH_SAVE_REGS;
6205 /* This is called directly from the class libraries without going through the managed wrapper */
6206 MONO_CHECK_ARG_NULL (src);
6207 MONO_CHECK_ARG_NULL (dest);
6209 /* watch out for integer overflow */
6210 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6213 src_buf = (guint8 *)src->vector + src_offset;
6214 dest_buf = (guint8 *)dest->vector + dest_offset;
6217 memcpy (dest_buf, src_buf, count);
6219 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6224 #ifndef DISABLE_REMOTING
6225 ICALL_EXPORT MonoObject *
6226 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6228 MonoDomain *domain = mono_object_domain (this);
6230 MonoRealProxy *rp = ((MonoRealProxy *)this);
6231 MonoTransparentProxy *tp;
6235 MONO_ARCH_SAVE_REGS;
6237 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6238 tp = (MonoTransparentProxy*) res;
6240 MONO_OBJECT_SETREF (tp, rp, rp);
6241 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6242 klass = mono_class_from_mono_type (type);
6244 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6245 tp->remote_class = mono_remote_class (domain, class_name, klass);
6247 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6251 ICALL_EXPORT MonoReflectionType *
6252 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6254 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6258 /* System.Environment */
6261 ves_icall_System_Environment_get_UserName (void)
6263 MONO_ARCH_SAVE_REGS;
6265 /* using glib is more portable */
6266 return mono_string_new (mono_domain_get (), g_get_user_name ());
6270 ICALL_EXPORT MonoString *
6271 ves_icall_System_Environment_get_MachineName (void)
6273 #if defined (HOST_WIN32)
6278 len = MAX_COMPUTERNAME_LENGTH + 1;
6279 buf = g_new (gunichar2, len);
6282 if (GetComputerName (buf, (PDWORD) &len))
6283 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6287 #elif !defined(DISABLE_SOCKETS)
6291 if (gethostname (buf, sizeof (buf)) == 0)
6292 result = mono_string_new (mono_domain_get (), buf);
6298 return mono_string_new (mono_domain_get (), "mono");
6303 ves_icall_System_Environment_get_Platform (void)
6305 #if defined (TARGET_WIN32)
6308 #elif defined(__MACH__)
6311 // Notice that the value is hidden from user code, and only exposed
6312 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6313 // define and making assumptions based on Unix/128/4 values before there
6314 // was a MacOS define. Lots of code would assume that not-Unix meant
6315 // Windows, but in this case, it would be OSX.
6324 ICALL_EXPORT MonoString *
6325 ves_icall_System_Environment_get_NewLine (void)
6327 MONO_ARCH_SAVE_REGS;
6329 #if defined (HOST_WIN32)
6330 return mono_string_new (mono_domain_get (), "\r\n");
6332 return mono_string_new (mono_domain_get (), "\n");
6336 ICALL_EXPORT MonoString *
6337 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6342 MONO_ARCH_SAVE_REGS;
6347 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6348 value = g_getenv (utf8_name);
6355 return mono_string_new (mono_domain_get (), value);
6359 * There is no standard way to get at environ.
6362 #ifndef __MINGW32_VERSION
6363 #if defined(__APPLE__) && !defined (__arm__)
6364 /* Apple defines this in crt_externs.h but doesn't provide that header for
6365 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6366 * in fact exist on all implementations (so far)
6368 gchar ***_NSGetEnviron(void);
6369 #define environ (*_NSGetEnviron())
6377 ICALL_EXPORT MonoArray *
6378 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6389 env_strings = GetEnvironmentStrings();
6392 env_string = env_strings;
6393 while (*env_string != '\0') {
6394 /* weird case that MS seems to skip */
6395 if (*env_string != '=')
6397 while (*env_string != '\0')
6403 domain = mono_domain_get ();
6404 names = mono_array_new (domain, mono_defaults.string_class, n);
6408 env_string = env_strings;
6409 while (*env_string != '\0') {
6410 /* weird case that MS seems to skip */
6411 if (*env_string != '=') {
6412 equal_str = wcschr(env_string, '=');
6413 g_assert(equal_str);
6414 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6415 mono_array_setref (names, n, str);
6418 while (*env_string != '\0')
6423 FreeEnvironmentStrings (env_strings);
6435 MONO_ARCH_SAVE_REGS;
6438 for (e = environ; *e != 0; ++ e)
6441 domain = mono_domain_get ();
6442 names = mono_array_new (domain, mono_defaults.string_class, n);
6445 for (e = environ; *e != 0; ++ e) {
6446 parts = g_strsplit (*e, "=", 2);
6448 str = mono_string_new (domain, *parts);
6449 mono_array_setref (names, n, str);
6462 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6464 #if !GLIB_CHECK_VERSION(2,4,0)
6465 #define g_setenv(a,b,c) setenv(a,b,c)
6466 #define g_unsetenv(a) unsetenv(a)
6470 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6473 gunichar2 *utf16_name, *utf16_value;
6475 gchar *utf8_name, *utf8_value;
6479 MONO_ARCH_SAVE_REGS;
6482 utf16_name = mono_string_to_utf16 (name);
6483 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6484 SetEnvironmentVariable (utf16_name, NULL);
6485 g_free (utf16_name);
6489 utf16_value = mono_string_to_utf16 (value);
6491 SetEnvironmentVariable (utf16_name, utf16_value);
6493 g_free (utf16_name);
6494 g_free (utf16_value);
6496 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6498 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6499 g_unsetenv (utf8_name);
6504 utf8_value = mono_string_to_utf8_checked (value, &error);
6505 if (!mono_error_ok (&error)) {
6507 mono_error_raise_exception (&error);
6509 g_setenv (utf8_name, utf8_value, TRUE);
6512 g_free (utf8_value);
6517 ves_icall_System_Environment_Exit (int result)
6519 MONO_ARCH_SAVE_REGS;
6521 mono_environment_exitcode_set (result);
6523 /* FIXME: There are some cleanup hangs that should be worked out, but
6524 * if the program is going to exit, everything will be cleaned up when
6525 * NaCl exits anyway.
6527 #ifndef __native_client__
6528 if (!mono_runtime_try_shutdown ())
6529 mono_thread_exit ();
6531 /* Suspend all managed threads since the runtime is going away */
6532 mono_thread_suspend_all_other_threads ();
6534 mono_runtime_quit ();
6537 /* we may need to do some cleanup here... */
6541 ICALL_EXPORT MonoString*
6542 ves_icall_System_Environment_GetGacPath (void)
6544 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6547 ICALL_EXPORT MonoString*
6548 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6550 #if defined (HOST_WIN32)
6551 #ifndef CSIDL_FLAG_CREATE
6552 #define CSIDL_FLAG_CREATE 0x8000
6555 WCHAR path [MAX_PATH];
6556 /* Create directory if no existing */
6557 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6561 return mono_string_new_utf16 (mono_domain_get (), path, len);
6564 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6566 return mono_string_new (mono_domain_get (), "");
6569 ICALL_EXPORT MonoArray *
6570 ves_icall_System_Environment_GetLogicalDrives (void)
6572 gunichar2 buf [256], *ptr, *dname;
6574 guint initial_size = 127, size = 128;
6577 MonoString *drivestr;
6578 MonoDomain *domain = mono_domain_get ();
6581 MONO_ARCH_SAVE_REGS;
6586 while (size > initial_size) {
6587 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6588 if (size > initial_size) {
6591 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6592 initial_size = size;
6606 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6611 while (*u16) { u16++; len ++; }
6612 drivestr = mono_string_new_utf16 (domain, dname, len);
6613 mono_array_setref (result, ndrives++, drivestr);
6623 ICALL_EXPORT MonoString *
6624 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6626 gunichar2 volume_name [MAX_PATH + 1];
6628 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6630 return mono_string_from_utf16 (volume_name);
6633 ICALL_EXPORT MonoString *
6634 ves_icall_System_Environment_InternalGetHome (void)
6636 MONO_ARCH_SAVE_REGS;
6638 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6641 static const char *encodings [] = {
6643 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6644 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6645 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6647 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6648 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6649 "x_unicode_2_0_utf_7",
6651 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6652 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6654 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6657 "unicodefffe", "utf_16be",
6664 * Returns the internal codepage, if the value of "int_code_page" is
6665 * 1 at entry, and we can not compute a suitable code page number,
6666 * returns the code page as a string
6668 ICALL_EXPORT MonoString*
6669 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6674 char *codepage = NULL;
6676 int want_name = *int_code_page;
6679 *int_code_page = -1;
6680 MONO_ARCH_SAVE_REGS;
6682 g_get_charset (&cset);
6683 c = codepage = strdup (cset);
6684 for (c = codepage; *c; c++){
6685 if (isascii (*c) && isalpha (*c))
6690 /* g_print ("charset: %s\n", cset); */
6692 /* handle some common aliases */
6695 for (i = 0; p != 0; ){
6696 if ((gssize) p < 7){
6698 p = encodings [++i];
6701 if (strcmp (p, codepage) == 0){
6702 *int_code_page = code;
6705 p = encodings [++i];
6708 if (strstr (codepage, "utf_8") != NULL)
6709 *int_code_page |= 0x10000000;
6712 if (want_name && *int_code_page == -1)
6713 return mono_string_new (mono_domain_get (), cset);
6718 ICALL_EXPORT MonoBoolean
6719 ves_icall_System_Environment_get_HasShutdownStarted (void)
6721 if (mono_runtime_is_shutting_down ())
6724 if (mono_domain_is_unloading (mono_domain_get ()))
6731 ves_icall_System_Environment_BroadcastSettingChange (void)
6734 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6739 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6740 MonoReflectionMethod *method,
6741 MonoArray *out_args)
6743 MONO_ARCH_SAVE_REGS;
6745 mono_message_init (mono_object_domain (this), this, method, out_args);
6748 #ifndef DISABLE_REMOTING
6749 ICALL_EXPORT MonoBoolean
6750 ves_icall_IsTransparentProxy (MonoObject *proxy)
6752 MONO_ARCH_SAVE_REGS;
6757 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6763 ICALL_EXPORT MonoReflectionMethod *
6764 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6765 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6769 MonoMethod **vtable;
6770 MonoMethod *res = NULL;
6772 MONO_CHECK_ARG_NULL (rtype);
6773 MONO_CHECK_ARG_NULL (rmethod);
6775 method = rmethod->method;
6776 klass = mono_class_from_mono_type (rtype->type);
6777 mono_class_init_or_throw (klass);
6779 if (MONO_CLASS_IS_INTERFACE (klass))
6782 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6785 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6786 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6792 mono_class_setup_vtable (klass);
6793 vtable = klass->vtable;
6795 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6796 gboolean variance_used = FALSE;
6797 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6798 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6800 res = vtable [offs + method->slot];
6802 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6805 if (method->slot != -1)
6806 res = vtable [method->slot];
6812 return mono_method_get_object (mono_domain_get (), res, NULL);
6816 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6821 MONO_ARCH_SAVE_REGS;
6823 klass = mono_class_from_mono_type (type->type);
6824 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6826 mono_vtable_set_is_remote (vtable, enable);
6829 #else /* DISABLE_REMOTING */
6832 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6834 g_assert_not_reached ();
6839 ICALL_EXPORT MonoObject *
6840 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6845 MONO_ARCH_SAVE_REGS;
6847 domain = mono_object_domain (type);
6848 klass = mono_class_from_mono_type (type->type);
6849 mono_class_init_or_throw (klass);
6851 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6852 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6854 if (klass->rank >= 1) {
6855 g_assert (klass->rank == 1);
6856 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6858 /* Bypass remoting object creation check */
6859 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6863 ICALL_EXPORT MonoString *
6864 ves_icall_System_IO_get_temp_path (void)
6866 MONO_ARCH_SAVE_REGS;
6868 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6871 #ifndef PLATFORM_NO_DRIVEINFO
6872 ICALL_EXPORT MonoBoolean
6873 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6874 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6878 ULARGE_INTEGER wapi_free_bytes_avail;
6879 ULARGE_INTEGER wapi_total_number_of_bytes;
6880 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6882 MONO_ARCH_SAVE_REGS;
6884 *error = ERROR_SUCCESS;
6885 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6886 &wapi_total_number_of_free_bytes);
6889 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6890 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6891 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6893 *free_bytes_avail = 0;
6894 *total_number_of_bytes = 0;
6895 *total_number_of_free_bytes = 0;
6896 *error = GetLastError ();
6902 ICALL_EXPORT guint32
6903 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6905 MONO_ARCH_SAVE_REGS;
6907 return GetDriveType (mono_string_chars (root_path_name));
6911 ICALL_EXPORT gpointer
6912 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6914 MONO_ARCH_SAVE_REGS;
6916 return mono_compile_method (method);
6919 ICALL_EXPORT MonoString *
6920 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6925 MONO_ARCH_SAVE_REGS;
6927 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6929 #if defined (HOST_WIN32)
6930 /* Avoid mixing '/' and '\\' */
6933 for (i = strlen (path) - 1; i >= 0; i--)
6934 if (path [i] == '/')
6938 mcpath = mono_string_new (mono_domain_get (), path);
6945 get_bundled_app_config (void)
6947 const gchar *app_config;
6950 gchar *config_file_name, *config_file_path;
6954 MONO_ARCH_SAVE_REGS;
6956 domain = mono_domain_get ();
6957 file = domain->setup->configuration_file;
6961 // Retrieve config file and remove the extension
6962 config_file_name = mono_string_to_utf8 (file);
6963 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6964 if (!config_file_path)
6965 config_file_path = config_file_name;
6966 len = strlen (config_file_path) - strlen (".config");
6967 module = g_malloc0 (len + 1);
6968 memcpy (module, config_file_path, len);
6969 // Get the config file from the module name
6970 app_config = mono_config_string_for_assembly_file (module);
6973 if (config_file_name != config_file_path)
6974 g_free (config_file_name);
6975 g_free (config_file_path);
6980 return mono_string_new (mono_domain_get (), app_config);
6984 get_bundled_machine_config (void)
6986 const gchar *machine_config;
6988 MONO_ARCH_SAVE_REGS;
6990 machine_config = mono_get_machine_config ();
6992 if (!machine_config)
6995 return mono_string_new (mono_domain_get (), machine_config);
6998 ICALL_EXPORT MonoString *
6999 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7004 MONO_ARCH_SAVE_REGS;
7006 path = g_path_get_dirname (mono_get_config_dir ());
7008 #if defined (HOST_WIN32)
7009 /* Avoid mixing '/' and '\\' */
7012 for (i = strlen (path) - 1; i >= 0; i--)
7013 if (path [i] == '/')
7017 ipath = mono_string_new (mono_domain_get (), path);
7023 ICALL_EXPORT gboolean
7024 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7026 MonoPEResourceDataEntry *entry;
7029 MONO_ARCH_SAVE_REGS;
7031 if (!assembly || !result || !size)
7036 image = assembly->assembly->image;
7037 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7041 *result = mono_image_rva_map (image, entry->rde_data_offset);
7046 *size = entry->rde_size;
7051 ICALL_EXPORT MonoBoolean
7052 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7054 return mono_is_debugger_attached ();
7057 ICALL_EXPORT MonoBoolean
7058 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7060 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7061 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7067 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7069 if (mono_get_runtime_callbacks ()->debug_log)
7070 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7074 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7076 #if defined (HOST_WIN32)
7077 OutputDebugString (mono_string_chars (message));
7079 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7083 /* Only used for value types */
7084 ICALL_EXPORT MonoObject *
7085 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7090 MONO_ARCH_SAVE_REGS;
7092 domain = mono_object_domain (type);
7093 klass = mono_class_from_mono_type (type->type);
7094 mono_class_init_or_throw (klass);
7096 if (mono_class_is_nullable (klass))
7097 /* No arguments -> null */
7100 return mono_object_new (domain, klass);
7103 ICALL_EXPORT MonoReflectionMethod *
7104 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7106 MonoClass *klass, *parent;
7107 MonoMethod *method = m->method;
7108 MonoMethod *result = NULL;
7111 MONO_ARCH_SAVE_REGS;
7113 if (method->klass == NULL)
7116 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7117 MONO_CLASS_IS_INTERFACE (method->klass) ||
7118 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7121 slot = mono_method_get_vtable_slot (method);
7125 klass = method->klass;
7126 if (klass->generic_class)
7127 klass = klass->generic_class->container_class;
7130 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7131 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7132 mono_class_setup_vtable (parent);
7133 if (parent->vtable_size <= slot)
7138 klass = klass->parent;
7143 if (klass == method->klass)
7146 /*This is possible if definition == FALSE.
7147 * Do it here to be really sure we don't read invalid memory.
7149 if (slot >= klass->vtable_size)
7152 mono_class_setup_vtable (klass);
7154 result = klass->vtable [slot];
7155 if (result == NULL) {
7156 /* It is an abstract method */
7157 gpointer iter = NULL;
7158 while ((result = mono_class_get_methods (klass, &iter)))
7159 if (result->slot == slot)
7166 return mono_method_get_object (mono_domain_get (), result, NULL);
7169 ICALL_EXPORT MonoString*
7170 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7172 MonoMethod *method = m->method;
7174 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7179 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7181 MONO_ARCH_SAVE_REGS;
7183 iter->sig = *(MonoMethodSignature**)argsp;
7185 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7186 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7189 /* FIXME: it's not documented what start is exactly... */
7193 iter->args = argsp + sizeof (gpointer);
7195 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7197 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7200 ICALL_EXPORT MonoTypedRef
7201 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7203 guint32 i, arg_size;
7206 MONO_ARCH_SAVE_REGS;
7208 i = iter->sig->sentinelpos + iter->next_arg;
7210 g_assert (i < iter->sig->param_count);
7212 res.type = iter->sig->params [i];
7213 res.klass = mono_class_from_mono_type (res.type);
7214 arg_size = mono_type_stack_size (res.type, &align);
7215 #if defined(__arm__) || defined(__mips__)
7216 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7218 res.value = iter->args;
7219 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7220 /* Values are stored as 8 byte register sized objects, but 'value'
7221 * is dereferenced as a pointer in other routines.
7223 res.value = (char*)res.value + 4;
7225 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7226 if (arg_size <= sizeof (gpointer)) {
7228 int padding = arg_size - mono_type_size (res.type, &dummy);
7229 res.value = (guint8*)res.value + padding;
7232 iter->args = (char*)iter->args + arg_size;
7235 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7240 ICALL_EXPORT MonoTypedRef
7241 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7243 guint32 i, arg_size;
7246 MONO_ARCH_SAVE_REGS;
7248 i = iter->sig->sentinelpos + iter->next_arg;
7250 g_assert (i < iter->sig->param_count);
7252 while (i < iter->sig->param_count) {
7253 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7255 res.type = iter->sig->params [i];
7256 res.klass = mono_class_from_mono_type (res.type);
7257 /* FIXME: endianess issue... */
7258 arg_size = mono_type_stack_size (res.type, &align);
7259 #if defined(__arm__) || defined(__mips__)
7260 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7262 res.value = iter->args;
7263 iter->args = (char*)iter->args + arg_size;
7265 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7268 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7276 ICALL_EXPORT MonoType*
7277 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7280 MONO_ARCH_SAVE_REGS;
7282 i = iter->sig->sentinelpos + iter->next_arg;
7284 g_assert (i < iter->sig->param_count);
7286 return iter->sig->params [i];
7289 ICALL_EXPORT MonoObject*
7290 mono_TypedReference_ToObject (MonoTypedRef tref)
7292 MONO_ARCH_SAVE_REGS;
7294 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7295 MonoObject** objp = tref.value;
7299 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7302 ICALL_EXPORT MonoObject*
7303 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7305 MONO_ARCH_SAVE_REGS;
7307 if (MONO_TYPE_IS_REFERENCE (type)) {
7308 MonoObject** objp = value;
7312 return mono_value_box (mono_domain_get (), klass, value);
7316 prelink_method (MonoMethod *method)
7318 const char *exc_class, *exc_arg;
7319 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7321 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7323 mono_raise_exception(
7324 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7326 /* create the wrapper, too? */
7330 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7332 MONO_ARCH_SAVE_REGS;
7333 prelink_method (method->method);
7337 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7339 MonoClass *klass = mono_class_from_mono_type (type->type);
7341 gpointer iter = NULL;
7342 MONO_ARCH_SAVE_REGS;
7344 mono_class_init_or_throw (klass);
7346 while ((m = mono_class_get_methods (klass, &iter)))
7350 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7352 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7353 gint32 const **exponents,
7354 gunichar2 const **digitLowerTable,
7355 gunichar2 const **digitUpperTable,
7356 gint64 const **tenPowersList,
7357 gint32 const **decHexDigits)
7359 *mantissas = Formatter_MantissaBitsTable;
7360 *exponents = Formatter_TensExponentTable;
7361 *digitLowerTable = Formatter_DigitLowerTable;
7362 *digitUpperTable = Formatter_DigitUpperTable;
7363 *tenPowersList = Formatter_TenPowersList;
7364 *decHexDigits = Formatter_DecHexDigits;
7368 get_category_data (int version,
7369 guint8 const **category_data,
7370 guint16 const **category_astral_index)
7372 *category_astral_index = NULL;
7374 #ifndef DISABLE_NET_4_0
7376 *category_data = CategoryData_v4;
7377 #ifndef DISABLE_ASTRAL
7378 *category_astral_index = CategoryData_v4_astral_index;
7384 *category_data = CategoryData_v2;
7385 #ifndef DISABLE_ASTRAL
7386 *category_astral_index = CategoryData_v2_astral_index;
7390 /* These parameters are "readonly" in corlib/System/Char.cs */
7392 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7393 guint8 const **category_data,
7394 guint16 const **category_astral_index,
7395 guint8 const **numeric_data,
7396 gdouble const **numeric_data_values,
7397 guint16 const **to_lower_data_low,
7398 guint16 const **to_lower_data_high,
7399 guint16 const **to_upper_data_low,
7400 guint16 const **to_upper_data_high)
7402 get_category_data (category_data_version, category_data, category_astral_index);
7403 *numeric_data = NumericData;
7404 *numeric_data_values = NumericDataValues;
7405 *to_lower_data_low = ToLowerDataLow;
7406 *to_lower_data_high = ToLowerDataHigh;
7407 *to_upper_data_low = ToUpperDataLow;
7408 *to_upper_data_high = ToUpperDataHigh;
7412 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7414 return method->method->token;
7418 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7419 * and avoid useless allocations.
7422 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7426 for (i = 0; i < type->num_mods; ++i) {
7427 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7432 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7434 for (i = 0; i < type->num_mods; ++i) {
7435 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7436 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7437 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7444 ICALL_EXPORT MonoArray*
7445 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7447 MonoType *type = param->ClassImpl->type;
7448 MonoClass *member_class = mono_object_class (param->MemberImpl);
7449 MonoMethod *method = NULL;
7452 MonoMethodSignature *sig;
7454 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7455 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7456 method = rmethod->method;
7457 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7458 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7459 if (!(method = prop->property->get))
7460 method = prop->property->set;
7463 char *type_name = mono_type_get_full_name (member_class);
7464 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7465 MonoException *ex = mono_get_exception_not_supported (msg);
7468 mono_raise_exception (ex);
7471 image = method->klass->image;
7472 pos = param->PositionImpl;
7473 sig = mono_method_signature (method);
7477 type = sig->params [pos];
7479 return type_array_from_modifiers (image, type, optional);
7483 get_property_type (MonoProperty *prop)
7485 MonoMethodSignature *sig;
7487 sig = mono_method_signature (prop->get);
7489 } else if (prop->set) {
7490 sig = mono_method_signature (prop->set);
7491 return sig->params [sig->param_count - 1];
7496 ICALL_EXPORT MonoArray*
7497 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7499 MonoType *type = get_property_type (property->property);
7500 MonoImage *image = property->klass->image;
7504 return type_array_from_modifiers (image, type, optional);
7508 *Construct a MonoType suited to be used to decode a constant blob object.
7510 * @type is the target type which will be constructed
7511 * @blob_type is the blob type, for example, that comes from the constant table
7512 * @real_type is the expected constructed type.
7515 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7517 type->type = blob_type;
7518 type->data.klass = NULL;
7519 if (blob_type == MONO_TYPE_CLASS)
7520 type->data.klass = mono_defaults.object_class;
7521 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7522 /* For enums, we need to use the base type */
7523 type->type = MONO_TYPE_VALUETYPE;
7524 type->data.klass = mono_class_from_mono_type (real_type);
7526 type->data.klass = mono_class_from_mono_type (real_type);
7529 ICALL_EXPORT MonoObject*
7530 property_info_get_default_value (MonoReflectionProperty *property)
7533 MonoProperty *prop = property->property;
7534 MonoType *type = get_property_type (prop);
7535 MonoDomain *domain = mono_object_domain (property);
7536 MonoTypeEnum def_type;
7537 const char *def_value;
7540 mono_class_init (prop->parent);
7542 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7543 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7545 def_value = mono_class_get_property_default_value (prop, &def_type);
7547 mono_type_from_blob_type (&blob_type, def_type, type);
7548 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7553 ICALL_EXPORT MonoBoolean
7554 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7556 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7557 MonoCustomAttrInfo *cinfo;
7560 mono_class_init_or_throw (attr_class);
7562 cinfo = mono_reflection_get_custom_attrs_info (obj);
7565 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7567 mono_custom_attrs_free (cinfo);
7571 ICALL_EXPORT MonoArray*
7572 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7574 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7579 mono_class_init_or_throw (attr_class);
7581 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7582 mono_error_raise_exception (&error);
7584 if (mono_loader_get_last_error ()) {
7585 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7586 g_assert_not_reached ();
7594 ICALL_EXPORT MonoString*
7595 ves_icall_Mono_Runtime_GetDisplayName (void)
7598 MonoString *display_name;
7600 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7601 display_name = mono_string_new (mono_domain_get (), info);
7603 return display_name;
7606 ICALL_EXPORT MonoString*
7607 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7609 MonoString *message;
7613 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7614 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7617 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7619 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7627 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7628 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7629 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7630 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7631 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7632 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7633 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7634 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7638 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7643 gunichar2 last, prev_last, prev2_last;
7650 int havePadding = 0;
7652 last = prev_last = 0, prev2_last = 0;
7653 for (i = 0; i < ilength; i++) {
7655 if (c >= sizeof (dbase64)) {
7656 exc = mono_exception_from_name_msg (mono_get_corlib (),
7657 "System", "FormatException",
7658 "Invalid character found.");
7659 mono_raise_exception (exc);
7660 } else if (isspace (c)) {
7662 } else if (havePadding && c != '=') {
7663 exc = mono_exception_from_name_msg (mono_get_corlib (),
7664 "System", "FormatException",
7665 "Invalid character found.");
7666 mono_raise_exception (exc);
7668 if (c == '=') havePadding = 1;
7669 prev2_last = prev_last;
7675 olength = ilength - ignored;
7677 if (allowWhitespaceOnly && olength == 0) {
7678 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7681 if ((olength & 3) != 0 || olength <= 0) {
7682 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7683 "FormatException", "Invalid length.");
7684 mono_raise_exception (exc);
7687 if (prev2_last == '=') {
7688 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7689 mono_raise_exception (exc);
7692 olength = (olength * 3) / 4;
7696 if (prev_last == '=')
7699 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7700 res_ptr = mono_array_addr (result, guchar, 0);
7701 for (i = 0; i < ilength; ) {
7704 for (k = 0; k < 4 && i < ilength;) {
7710 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7711 exc = mono_exception_from_name_msg (mono_get_corlib (),
7712 "System", "FormatException",
7713 "Invalid character found.");
7714 mono_raise_exception (exc);
7719 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7721 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7723 *res_ptr++ = (b [2] << 6) | b [3];
7725 while (i < ilength && isspace (start [i]))
7732 ICALL_EXPORT MonoArray *
7733 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7735 MONO_ARCH_SAVE_REGS;
7737 return base64_to_byte_array (mono_string_chars (str),
7738 mono_string_length (str), allowWhitespaceOnly);
7741 ICALL_EXPORT MonoArray *
7742 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7744 MONO_ARCH_SAVE_REGS;
7746 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7750 #ifndef DISABLE_ICALL_TABLES
7752 #define ICALL_TYPE(id,name,first)
7753 #define ICALL(id,name,func) Icall_ ## id,
7756 #include "metadata/icall-def.h"
7762 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7763 #define ICALL(id,name,func)
7765 #include "metadata/icall-def.h"
7771 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7772 #define ICALL(id,name,func)
7774 guint16 first_icall;
7777 static const IcallTypeDesc
7778 icall_type_descs [] = {
7779 #include "metadata/icall-def.h"
7783 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7786 #define ICALL_TYPE(id,name,first)
7789 #ifdef HAVE_ARRAY_ELEM_INIT
7790 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7791 #define MSGSTRFIELD1(line) str##line
7793 static const struct msgstrtn_t {
7794 #define ICALL(id,name,func)
7796 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7797 #include "metadata/icall-def.h"
7799 } icall_type_names_str = {
7800 #define ICALL_TYPE(id,name,first) (name),
7801 #include "metadata/icall-def.h"
7804 static const guint16 icall_type_names_idx [] = {
7805 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7806 #include "metadata/icall-def.h"
7809 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7811 static const struct msgstr_t {
7813 #define ICALL_TYPE(id,name,first)
7814 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7815 #include "metadata/icall-def.h"
7817 } icall_names_str = {
7818 #define ICALL(id,name,func) (name),
7819 #include "metadata/icall-def.h"
7822 static const guint16 icall_names_idx [] = {
7823 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7824 #include "metadata/icall-def.h"
7827 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7833 #define ICALL_TYPE(id,name,first) name,
7834 #define ICALL(id,name,func)
7835 static const char* const
7836 icall_type_names [] = {
7837 #include "metadata/icall-def.h"
7841 #define icall_type_name_get(id) (icall_type_names [(id)])
7845 #define ICALL_TYPE(id,name,first)
7846 #define ICALL(id,name,func) name,
7847 static const char* const
7849 #include "metadata/icall-def.h"
7852 #define icall_name_get(id) icall_names [(id)]
7854 #endif /* !HAVE_ARRAY_ELEM_INIT */
7858 #define ICALL_TYPE(id,name,first)
7859 #define ICALL(id,name,func) func,
7860 static const gconstpointer
7861 icall_functions [] = {
7862 #include "metadata/icall-def.h"
7866 #ifdef ENABLE_ICALL_SYMBOL_MAP
7869 #define ICALL_TYPE(id,name,first)
7870 #define ICALL(id,name,func) #func,
7871 static const gconstpointer
7872 icall_symbols [] = {
7873 #include "metadata/icall-def.h"
7878 #endif /* DISABLE_ICALL_TABLES */
7880 static mono_mutex_t icall_mutex;
7881 static GHashTable *icall_hash = NULL;
7882 static GHashTable *jit_icall_hash_name = NULL;
7883 static GHashTable *jit_icall_hash_addr = NULL;
7886 mono_icall_init (void)
7888 #ifndef DISABLE_ICALL_TABLES
7891 /* check that tables are sorted: disable in release */
7894 const char *prev_class = NULL;
7895 const char *prev_method;
7897 for (i = 0; i < Icall_type_num; ++i) {
7898 const IcallTypeDesc *desc;
7901 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7902 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7903 prev_class = icall_type_name_get (i);
7904 desc = &icall_type_descs [i];
7905 num_icalls = icall_desc_num_icalls (desc);
7906 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7907 for (j = 0; j < num_icalls; ++j) {
7908 const char *methodn = icall_name_get (desc->first_icall + j);
7909 if (prev_method && strcmp (prev_method, methodn) >= 0)
7910 g_print ("method %s should come before method %s\n", methodn, prev_method);
7911 prev_method = methodn;
7917 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7918 mono_mutex_init (&icall_mutex);
7922 mono_icall_lock (void)
7924 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7928 mono_icall_unlock (void)
7930 mono_locks_mutex_release (&icall_mutex, IcallLock);
7934 mono_icall_cleanup (void)
7936 g_hash_table_destroy (icall_hash);
7937 g_hash_table_destroy (jit_icall_hash_name);
7938 g_hash_table_destroy (jit_icall_hash_addr);
7939 mono_mutex_destroy (&icall_mutex);
7943 mono_add_internal_call (const char *name, gconstpointer method)
7947 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7949 mono_icall_unlock ();
7952 #ifndef DISABLE_ICALL_TABLES
7954 #ifdef HAVE_ARRAY_ELEM_INIT
7956 compare_method_imap (const void *key, const void *elem)
7958 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7959 return strcmp (key, method_name);
7963 find_method_icall (const IcallTypeDesc *imap, const char *name)
7965 const guint16 *nameslot = mono_binary_search (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7968 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7972 compare_class_imap (const void *key, const void *elem)
7974 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7975 return strcmp (key, class_name);
7978 static const IcallTypeDesc*
7979 find_class_icalls (const char *name)
7981 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7984 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7987 #else /* HAVE_ARRAY_ELEM_INIT */
7990 compare_method_imap (const void *key, const void *elem)
7992 const char** method_name = (const char**)elem;
7993 return strcmp (key, *method_name);
7997 find_method_icall (const IcallTypeDesc *imap, const char *name)
7999 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8002 return (gpointer)icall_functions [(nameslot - icall_names)];
8006 compare_class_imap (const void *key, const void *elem)
8008 const char** class_name = (const char**)elem;
8009 return strcmp (key, *class_name);
8012 static const IcallTypeDesc*
8013 find_class_icalls (const char *name)
8015 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8018 return &icall_type_descs [nameslot - icall_type_names];
8021 #endif /* HAVE_ARRAY_ELEM_INIT */
8023 #endif /* DISABLE_ICALL_TABLES */
8026 * we should probably export this as an helper (handle nested types).
8027 * Returns the number of chars written in buf.
8030 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8032 int nspacelen, cnamelen;
8033 nspacelen = strlen (klass->name_space);
8034 cnamelen = strlen (klass->name);
8035 if (nspacelen + cnamelen + 2 > bufsize)
8038 memcpy (buf, klass->name_space, nspacelen);
8039 buf [nspacelen ++] = '.';
8041 memcpy (buf + nspacelen, klass->name, cnamelen);
8042 buf [nspacelen + cnamelen] = 0;
8043 return nspacelen + cnamelen;
8046 #ifdef DISABLE_ICALL_TABLES
8048 no_icall_table (void)
8050 g_assert_not_reached ();
8055 mono_lookup_internal_call (MonoMethod *method)
8060 int typelen = 0, mlen, siglen;
8062 #ifndef DISABLE_ICALL_TABLES
8063 const IcallTypeDesc *imap = NULL;
8066 g_assert (method != NULL);
8068 if (method->is_inflated)
8069 method = ((MonoMethodInflated *) method)->declaring;
8071 if (method->klass->nested_in) {
8072 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8076 mname [pos++] = '/';
8079 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8085 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8090 #ifndef DISABLE_ICALL_TABLES
8091 imap = find_class_icalls (mname);
8094 mname [typelen] = ':';
8095 mname [typelen + 1] = ':';
8097 mlen = strlen (method->name);
8098 memcpy (mname + typelen + 2, method->name, mlen);
8099 sigstart = mname + typelen + 2 + mlen;
8102 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8103 siglen = strlen (tmpsig);
8104 if (typelen + mlen + siglen + 6 > sizeof (mname))
8107 memcpy (sigstart + 1, tmpsig, siglen);
8108 sigstart [siglen + 1] = ')';
8109 sigstart [siglen + 2] = 0;
8114 res = g_hash_table_lookup (icall_hash, mname);
8116 mono_icall_unlock ();;
8119 /* try without signature */
8121 res = g_hash_table_lookup (icall_hash, mname);
8123 mono_icall_unlock ();
8127 #ifdef DISABLE_ICALL_TABLES
8128 mono_icall_unlock ();
8129 /* Fail only when the result is actually used */
8130 /* mono_marshal_get_native_wrapper () depends on this */
8131 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8132 return ves_icall_System_String_ctor_RedirectToCreateString;
8134 return no_icall_table;
8136 /* it wasn't found in the static call tables */
8138 mono_icall_unlock ();
8141 res = find_method_icall (imap, sigstart - mlen);
8143 mono_icall_unlock ();
8146 /* try _with_ signature */
8148 res = find_method_icall (imap, sigstart - mlen);
8150 mono_icall_unlock ();
8154 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8155 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8156 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8157 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8158 g_print ("Do not report this as a bug unless you're sure you have updated correctly:\nyou probably have a broken mono install.\n");
8159 g_print ("If you see other errors or faults after this message they are probably related\n");
8160 g_print ("and you need to fix your mono install first.\n");
8162 mono_icall_unlock ();
8168 #ifdef ENABLE_ICALL_SYMBOL_MAP
8170 func_cmp (gconstpointer key, gconstpointer p)
8172 return (gsize)key - (gsize)*(gsize*)p;
8177 * mono_lookup_icall_symbol:
8179 * Given the icall METHOD, returns its C symbol.
8182 mono_lookup_icall_symbol (MonoMethod *m)
8184 #ifdef DISABLE_ICALL_TABLES
8185 g_assert_not_reached ();
8188 #ifdef ENABLE_ICALL_SYMBOL_MAP
8192 static gconstpointer *functions_sorted;
8193 static const char**symbols_sorted;
8194 static gboolean inited;
8199 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8200 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8201 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8202 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8203 /* Bubble sort the two arrays */
8207 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8208 if (functions_sorted [i] > functions_sorted [i + 1]) {
8211 tmp = functions_sorted [i];
8212 functions_sorted [i] = functions_sorted [i + 1];
8213 functions_sorted [i + 1] = tmp;
8214 tmp = symbols_sorted [i];
8215 symbols_sorted [i] = symbols_sorted [i + 1];
8216 symbols_sorted [i + 1] = tmp;
8223 func = mono_lookup_internal_call (m);
8226 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8230 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8232 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8233 g_assert_not_reached ();
8240 type_from_typename (char *typename)
8242 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8244 if (!strcmp (typename, "int"))
8245 klass = mono_defaults.int_class;
8246 else if (!strcmp (typename, "ptr"))
8247 klass = mono_defaults.int_class;
8248 else if (!strcmp (typename, "void"))
8249 klass = mono_defaults.void_class;
8250 else if (!strcmp (typename, "int32"))
8251 klass = mono_defaults.int32_class;
8252 else if (!strcmp (typename, "uint32"))
8253 klass = mono_defaults.uint32_class;
8254 else if (!strcmp (typename, "int8"))
8255 klass = mono_defaults.sbyte_class;
8256 else if (!strcmp (typename, "uint8"))
8257 klass = mono_defaults.byte_class;
8258 else if (!strcmp (typename, "int16"))
8259 klass = mono_defaults.int16_class;
8260 else if (!strcmp (typename, "uint16"))
8261 klass = mono_defaults.uint16_class;
8262 else if (!strcmp (typename, "long"))
8263 klass = mono_defaults.int64_class;
8264 else if (!strcmp (typename, "ulong"))
8265 klass = mono_defaults.uint64_class;
8266 else if (!strcmp (typename, "float"))
8267 klass = mono_defaults.single_class;
8268 else if (!strcmp (typename, "double"))
8269 klass = mono_defaults.double_class;
8270 else if (!strcmp (typename, "object"))
8271 klass = mono_defaults.object_class;
8272 else if (!strcmp (typename, "obj"))
8273 klass = mono_defaults.object_class;
8274 else if (!strcmp (typename, "string"))
8275 klass = mono_defaults.string_class;
8276 else if (!strcmp (typename, "bool"))
8277 klass = mono_defaults.boolean_class;
8278 else if (!strcmp (typename, "boolean"))
8279 klass = mono_defaults.boolean_class;
8281 g_error ("%s", typename);
8282 g_assert_not_reached ();
8284 return &klass->byval_arg;
8288 * LOCKING: Take the corlib image lock.
8290 MonoMethodSignature*
8291 mono_create_icall_signature (const char *sigstr)
8296 MonoMethodSignature *res, *res2;
8297 MonoImage *corlib = mono_defaults.corlib;
8299 mono_image_lock (corlib);
8300 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8301 mono_image_unlock (corlib);
8306 parts = g_strsplit (sigstr, " ", 256);
8315 res = mono_metadata_signature_alloc (corlib, len - 1);
8320 * Under windows, the default pinvoke calling convention is STDCALL but
8323 res->call_convention = MONO_CALL_C;
8326 res->ret = type_from_typename (parts [0]);
8327 for (i = 1; i < len; ++i) {
8328 res->params [i - 1] = type_from_typename (parts [i]);
8333 mono_image_lock (corlib);
8334 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8336 res = res2; /*Value is allocated in the image pool*/
8338 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8339 mono_image_unlock (corlib);
8345 mono_find_jit_icall_by_name (const char *name)
8347 MonoJitICallInfo *info;
8348 g_assert (jit_icall_hash_name);
8351 info = g_hash_table_lookup (jit_icall_hash_name, name);
8352 mono_icall_unlock ();
8357 mono_find_jit_icall_by_addr (gconstpointer addr)
8359 MonoJitICallInfo *info;
8360 g_assert (jit_icall_hash_addr);
8363 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8364 mono_icall_unlock ();
8370 * mono_get_jit_icall_info:
8372 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8373 * caller should access it while holding the icall lock.
8376 mono_get_jit_icall_info (void)
8378 return jit_icall_hash_name;
8382 * mono_lookup_jit_icall_symbol:
8384 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8387 mono_lookup_jit_icall_symbol (const char *name)
8389 MonoJitICallInfo *info;
8390 const char *res = NULL;
8393 info = g_hash_table_lookup (jit_icall_hash_name, name);
8395 res = info->c_symbol;
8396 mono_icall_unlock ();
8401 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8404 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8405 mono_icall_unlock ();
8409 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8411 MonoJitICallInfo *info;
8418 if (!jit_icall_hash_name) {
8419 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8420 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8423 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8424 g_warning ("jit icall already defined \"%s\"\n", name);
8425 g_assert_not_reached ();
8428 info = g_new0 (MonoJitICallInfo, 1);
8433 info->c_symbol = c_symbol;
8436 info->wrapper = func;
8438 info->wrapper = NULL;
8441 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8442 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8444 mono_icall_unlock ();
8449 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8451 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);