5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
22 #ifdef HAVE_SYS_TIME_H
28 #if defined (HOST_WIN32)
31 #if defined (HAVE_WCHAR_H)
35 #include "mono/utils/mono-membar.h"
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/threads.h>
38 #include <mono/metadata/threads-types.h>
39 #include <mono/metadata/threadpool.h>
40 #include <mono/metadata/monitor.h>
41 #include <mono/metadata/reflection.h>
42 #include <mono/metadata/assembly.h>
43 #include <mono/metadata/tabledefs.h>
44 #include <mono/metadata/exception.h>
45 #include <mono/metadata/file-io.h>
46 #include <mono/metadata/console-io.h>
47 #include <mono/metadata/socket-io.h>
48 #include <mono/metadata/mono-endian.h>
49 #include <mono/metadata/tokentype.h>
50 #include <mono/metadata/domain-internals.h>
51 #include <mono/metadata/metadata-internals.h>
52 #include <mono/metadata/class-internals.h>
53 #include <mono/metadata/marshal.h>
54 #include <mono/metadata/gc-internal.h>
55 #include <mono/metadata/mono-gc.h>
56 #include <mono/metadata/rand.h>
57 #include <mono/metadata/sysmath.h>
58 #include <mono/metadata/string-icalls.h>
59 #include <mono/metadata/debug-helpers.h>
60 #include <mono/metadata/process.h>
61 #include <mono/metadata/environment.h>
62 #include <mono/metadata/profiler-private.h>
63 #include <mono/metadata/locales.h>
64 #include <mono/metadata/filewatcher.h>
65 #include <mono/metadata/char-conversions.h>
66 #include <mono/metadata/security.h>
67 #include <mono/metadata/mono-config.h>
68 #include <mono/metadata/cil-coff.h>
69 #include <mono/metadata/number-formatter.h>
70 #include <mono/metadata/security-manager.h>
71 #include <mono/metadata/security-core-clr.h>
72 #include <mono/metadata/mono-perfcounters.h>
73 #include <mono/metadata/mono-debug.h>
74 #include <mono/metadata/mono-ptr-array.h>
75 #include <mono/metadata/verify-internals.h>
76 #include <mono/metadata/runtime.h>
77 #include <mono/io-layer/io-layer.h>
78 #include <mono/utils/strtod.h>
79 #include <mono/utils/monobitset.h>
80 #include <mono/utils/mono-time.h>
81 #include <mono/utils/mono-proclib.h>
82 #include <mono/utils/mono-string.h>
83 #include <mono/utils/mono-error-internals.h>
84 #include <mono/utils/mono-mmap.h>
85 #include <mono/utils/mono-io-portability.h>
86 #include <mono/utils/mono-digest.h>
87 #include <mono/utils/bsearch.h>
88 #include <mono/utils/mono-mutex.h>
90 #if defined (HOST_WIN32)
96 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
98 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
101 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
103 static inline MonoBoolean
104 is_generic_parameter (MonoType *type)
106 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
110 mono_class_init_or_throw (MonoClass *klass)
112 if (!mono_class_init (klass))
113 mono_raise_exception (mono_class_get_exception_for_failure (klass));
117 * We expect a pointer to a char, not a string
119 ICALL_EXPORT gboolean
120 mono_double_ParseImpl (char *ptr, double *result)
122 gchar *endptr = NULL;
129 *result = strtod (ptr, &endptr);
132 /* mono_strtod () is not thread-safe */
133 EnterCriticalSection (&mono_strtod_mutex);
134 *result = mono_strtod (ptr, &endptr);
135 LeaveCriticalSection (&mono_strtod_mutex);
139 if (!*ptr || (endptr && *endptr))
145 ICALL_EXPORT MonoObject *
146 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
155 ao = (MonoArray *)this;
156 ac = (MonoClass *)ao->obj.vtable->klass;
158 esize = mono_array_element_size (ac);
159 ea = (gpointer*)((char*)ao->vector + (pos * esize));
161 if (ac->element_class->valuetype)
162 return mono_value_box (this->vtable->domain, ac->element_class, ea);
167 ICALL_EXPORT MonoObject *
168 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
176 MONO_CHECK_ARG_NULL (idxs);
178 io = (MonoArray *)idxs;
179 ic = (MonoClass *)io->obj.vtable->klass;
181 ao = (MonoArray *)this;
182 ac = (MonoClass *)ao->obj.vtable->klass;
184 g_assert (ic->rank == 1);
185 if (io->bounds != NULL || io->max_length != ac->rank)
186 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
188 ind = (gint32 *)io->vector;
190 if (ao->bounds == NULL) {
191 if (*ind < 0 || *ind >= ao->max_length)
192 mono_raise_exception (mono_get_exception_index_out_of_range ());
194 return ves_icall_System_Array_GetValueImpl (this, *ind);
197 for (i = 0; i < ac->rank; i++)
198 if ((ind [i] < ao->bounds [i].lower_bound) ||
199 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
200 mono_raise_exception (mono_get_exception_index_out_of_range ());
202 pos = ind [0] - ao->bounds [0].lower_bound;
203 for (i = 1; i < ac->rank; i++)
204 pos = pos*ao->bounds [i].length + ind [i] -
205 ao->bounds [i].lower_bound;
207 return ves_icall_System_Array_GetValueImpl (this, pos);
211 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
213 MonoClass *ac, *vc, *ec;
225 vc = value->vtable->klass;
229 ac = this->obj.vtable->klass;
230 ec = ac->element_class;
232 esize = mono_array_element_size (ac);
233 ea = (gpointer*)((char*)this->vector + (pos * esize));
234 va = (gpointer*)((char*)value + sizeof (MonoObject));
236 if (mono_class_is_nullable (ec)) {
237 mono_nullable_init ((guint8*)ea, value, ec);
242 mono_gc_bzero (ea, esize);
246 #define NO_WIDENING_CONVERSION G_STMT_START{\
247 mono_raise_exception (mono_get_exception_argument ( \
248 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) \
253 mono_raise_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
257 #define INVALID_CAST G_STMT_START{ \
258 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
259 mono_raise_exception (mono_get_exception_invalid_cast ()); \
262 /* Check element (destination) type. */
263 switch (ec->byval_arg.type) {
264 case MONO_TYPE_STRING:
265 switch (vc->byval_arg.type) {
266 case MONO_TYPE_STRING:
272 case MONO_TYPE_BOOLEAN:
273 switch (vc->byval_arg.type) {
274 case MONO_TYPE_BOOLEAN:
287 NO_WIDENING_CONVERSION;
294 if (!ec->valuetype) {
295 if (!mono_object_isinst (value, ec))
297 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
301 if (mono_object_isinst (value, ec)) {
302 if (ec->has_references)
303 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
305 mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
312 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
314 et = ec->byval_arg.type;
315 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
316 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
318 vt = vc->byval_arg.type;
319 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
320 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
322 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
328 case MONO_TYPE_CHAR: \
329 CHECK_WIDENING_CONVERSION(0); \
330 *(etype *) ea = (etype) u64; \
332 /* You can't assign a signed value to an unsigned array. */ \
337 /* You can't assign a floating point number to an integer array. */ \
340 NO_WIDENING_CONVERSION; \
344 #define ASSIGN_SIGNED(etype) G_STMT_START{\
350 CHECK_WIDENING_CONVERSION(0); \
351 *(etype *) ea = (etype) i64; \
353 /* You can assign an unsigned value to a signed array if the array's */ \
354 /* element size is larger than the value size. */ \
359 case MONO_TYPE_CHAR: \
360 CHECK_WIDENING_CONVERSION(1); \
361 *(etype *) ea = (etype) u64; \
363 /* You can't assign a floating point number to an integer array. */ \
366 NO_WIDENING_CONVERSION; \
370 #define ASSIGN_REAL(etype) G_STMT_START{\
374 CHECK_WIDENING_CONVERSION(0); \
375 *(etype *) ea = (etype) r64; \
377 /* All integer values fit into a floating point array, so we don't */ \
378 /* need to CHECK_WIDENING_CONVERSION here. */ \
383 *(etype *) ea = (etype) i64; \
389 case MONO_TYPE_CHAR: \
390 *(etype *) ea = (etype) u64; \
397 u64 = *(guint8 *) va;
400 u64 = *(guint16 *) va;
403 u64 = *(guint32 *) va;
406 u64 = *(guint64 *) va;
412 i64 = *(gint16 *) va;
415 i64 = *(gint32 *) va;
418 i64 = *(gint64 *) va;
421 r64 = *(gfloat *) va;
424 r64 = *(gdouble *) va;
427 u64 = *(guint16 *) va;
429 case MONO_TYPE_BOOLEAN:
430 /* Boolean is only compatible with itself. */
443 NO_WIDENING_CONVERSION;
450 /* If we can't do a direct copy, let's try a widening conversion. */
453 ASSIGN_UNSIGNED (guint16);
455 ASSIGN_UNSIGNED (guint8);
457 ASSIGN_UNSIGNED (guint16);
459 ASSIGN_UNSIGNED (guint32);
461 ASSIGN_UNSIGNED (guint64);
463 ASSIGN_SIGNED (gint8);
465 ASSIGN_SIGNED (gint16);
467 ASSIGN_SIGNED (gint32);
469 ASSIGN_SIGNED (gint64);
471 ASSIGN_REAL (gfloat);
473 ASSIGN_REAL (gdouble);
477 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
481 #undef NO_WIDENING_CONVERSION
482 #undef CHECK_WIDENING_CONVERSION
483 #undef ASSIGN_UNSIGNED
489 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
497 MONO_CHECK_ARG_NULL (idxs);
499 ic = idxs->obj.vtable->klass;
500 ac = this->obj.vtable->klass;
502 g_assert (ic->rank == 1);
503 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
504 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
506 ind = (gint32 *)idxs->vector;
508 if (this->bounds == NULL) {
509 if (*ind < 0 || *ind >= this->max_length)
510 mono_raise_exception (mono_get_exception_index_out_of_range ());
512 ves_icall_System_Array_SetValueImpl (this, value, *ind);
516 for (i = 0; i < ac->rank; i++)
517 if ((ind [i] < this->bounds [i].lower_bound) ||
518 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
519 mono_raise_exception (mono_get_exception_index_out_of_range ());
521 pos = ind [0] - this->bounds [0].lower_bound;
522 for (i = 1; i < ac->rank; i++)
523 pos = pos * this->bounds [i].length + ind [i] -
524 this->bounds [i].lower_bound;
526 ves_icall_System_Array_SetValueImpl (this, value, pos);
529 ICALL_EXPORT MonoArray *
530 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
532 MonoClass *aklass, *klass;
535 gboolean bounded = FALSE;
539 MONO_CHECK_ARG_NULL (type);
540 MONO_CHECK_ARG_NULL (lengths);
542 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
544 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
546 for (i = 0; i < mono_array_length (lengths); i++)
547 if (mono_array_get (lengths, gint32, i) < 0)
548 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
550 klass = mono_class_from_mono_type (type->type);
551 mono_class_init_or_throw (klass);
553 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
554 /* vectors are not the same as one dimensional arrays with no-zero bounds */
559 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
561 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
562 for (i = 0; i < aklass->rank; ++i) {
563 sizes [i] = mono_array_get (lengths, guint32, i);
565 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
567 sizes [i + aklass->rank] = 0;
570 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
575 ICALL_EXPORT MonoArray *
576 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
578 MonoClass *aklass, *klass;
581 gboolean bounded = FALSE;
585 MONO_CHECK_ARG_NULL (type);
586 MONO_CHECK_ARG_NULL (lengths);
588 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
590 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
592 for (i = 0; i < mono_array_length (lengths); i++)
593 if ((mono_array_get (lengths, gint64, i) < 0) ||
594 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
595 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
597 klass = mono_class_from_mono_type (type->type);
598 mono_class_init_or_throw (klass);
600 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
601 /* vectors are not the same as one dimensional arrays with no-zero bounds */
606 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
608 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
609 for (i = 0; i < aklass->rank; ++i) {
610 sizes [i] = mono_array_get (lengths, guint64, i);
612 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
614 sizes [i + aklass->rank] = 0;
617 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
623 ves_icall_System_Array_GetRank (MonoObject *this)
627 return this->vtable->klass->rank;
631 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
633 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
638 if ((dimension < 0) || (dimension >= rank))
639 mono_raise_exception (mono_get_exception_index_out_of_range ());
641 if (this->bounds == NULL)
642 length = this->max_length;
644 length = this->bounds [dimension].length;
646 #ifdef MONO_BIG_ARRAYS
647 if (length > G_MAXINT32)
648 mono_raise_exception (mono_get_exception_overflow ());
654 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
656 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
660 if ((dimension < 0) || (dimension >= rank))
661 mono_raise_exception (mono_get_exception_index_out_of_range ());
663 if (this->bounds == NULL)
664 return this->max_length;
666 return this->bounds [dimension].length;
670 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
672 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
676 if ((dimension < 0) || (dimension >= rank))
677 mono_raise_exception (mono_get_exception_index_out_of_range ());
679 if (this->bounds == NULL)
682 return this->bounds [dimension].lower_bound;
686 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
688 int sz = mono_array_element_size (mono_object_class (arr));
689 mono_gc_bzero (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
692 ICALL_EXPORT gboolean
693 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
698 MonoVTable *src_vtable;
699 MonoVTable *dest_vtable;
700 MonoClass *src_class;
701 MonoClass *dest_class;
703 src_vtable = source->obj.vtable;
704 dest_vtable = dest->obj.vtable;
706 if (src_vtable->rank != dest_vtable->rank)
709 if (source->bounds || dest->bounds)
712 /* there's no integer overflow since mono_array_length returns an unsigned integer */
713 if ((dest_idx + length > mono_array_length_fast (dest)) ||
714 (source_idx + length > mono_array_length_fast (source)))
717 src_class = src_vtable->klass->element_class;
718 dest_class = dest_vtable->klass->element_class;
721 * Handle common cases.
724 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
725 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
727 if (src_class == mono_defaults.object_class && dest_class->valuetype)
730 /* Check if we're copying a char[] <==> (u)short[] */
731 if (src_class != dest_class) {
732 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
735 /* 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. */
736 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
740 if (dest_class->valuetype) {
741 element_size = mono_array_element_size (source->obj.vtable->klass);
742 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
743 if (dest_class->has_references) {
744 mono_value_copy_array (dest, dest_idx, source_addr, length);
746 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
747 mono_gc_memmove (dest_addr, source_addr, element_size * length);
750 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
757 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
766 ao = (MonoArray *)this;
767 ac = (MonoClass *)ao->obj.vtable->klass;
769 esize = mono_array_element_size (ac);
770 ea = (gpointer*)((char*)ao->vector + (pos * esize));
772 mono_gc_memmove (value, ea, esize);
776 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
785 ao = (MonoArray *)this;
786 ac = (MonoClass *)ao->obj.vtable->klass;
787 ec = ac->element_class;
789 esize = mono_array_element_size (ac);
790 ea = (gpointer*)((char*)ao->vector + (pos * esize));
792 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
793 g_assert (esize == sizeof (gpointer));
794 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
796 g_assert (ec->inited);
797 g_assert (esize == mono_class_value_size (ec, NULL));
798 if (ec->has_references)
799 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
801 mono_gc_memmove (ea, value, esize);
806 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
808 MonoClass *klass = array->obj.vtable->klass;
809 guint32 size = mono_array_element_size (klass);
810 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
812 const char *field_data;
814 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
815 MonoException *exc = mono_get_exception_argument("array",
816 "Cannot initialize array of non-primitive type.");
817 mono_raise_exception (exc);
820 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
821 MonoException *exc = mono_get_exception_argument("field_handle",
822 "Field doesn't have an RVA");
823 mono_raise_exception (exc);
826 size *= array->max_length;
827 field_data = mono_field_get_data (field_handle);
829 if (size > mono_type_size (field_handle->type, &align)) {
830 MonoException *exc = mono_get_exception_argument("field_handle",
831 "Field not large enough to fill array");
832 mono_raise_exception (exc);
835 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
837 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
838 guint ## n *src = (guint ## n *) field_data; \
839 guint ## n *end = (guint ## n *)((char*)src + size); \
841 for (; src < end; data++, src++) { \
842 *data = read ## n (src); \
846 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
848 switch (type->type) {
865 memcpy (mono_array_addr (array, char, 0), field_data, size);
869 memcpy (mono_array_addr (array, char, 0), field_data, size);
874 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
878 return offsetof (MonoString, chars);
881 ICALL_EXPORT MonoObject *
882 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
886 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
889 return mono_object_clone (obj);
893 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
898 MONO_CHECK_ARG_NULL (handle);
900 klass = mono_class_from_mono_type (handle);
901 MONO_CHECK_ARG (handle, klass);
903 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
905 /* This will call the type constructor */
906 mono_runtime_class_init (vtable);
910 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
914 mono_image_check_for_module_cctor (image);
915 if (image->has_module_cctor) {
916 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
917 /*It's fine to raise the exception here*/
918 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
922 ICALL_EXPORT MonoBoolean
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
928 /* later make this configurable and per-arch */
929 int min_size = 4096 * 4 * sizeof (void*);
930 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
931 /* if we have no info we are optimistic and assume there is enough room */
935 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
939 current = (guint8 *)&stack_addr;
940 if (current > stack_addr) {
941 if ((current - stack_addr) < min_size)
944 if (current - (stack_addr - stack_size) < min_size)
950 ICALL_EXPORT MonoObject *
951 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
955 return mono_object_clone (this);
959 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
962 MonoObject **values = NULL;
966 MonoClassField* field;
971 klass = mono_object_class (this);
973 if (mono_class_num_fields (klass) == 0)
974 return mono_object_hash (this);
977 * Compute the starting value of the hashcode for fields of primitive
978 * types, and return the remaining fields in an array to the managed side.
979 * This way, we can avoid costly reflection operations in managed code.
982 while ((field = mono_class_get_fields (klass, &iter))) {
983 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
985 if (mono_field_is_deleted (field))
987 /* FIXME: Add more types */
988 switch (field->type->type) {
990 result ^= *(gint32*)((guint8*)this + field->offset);
992 case MONO_TYPE_STRING: {
994 s = *(MonoString**)((guint8*)this + field->offset);
996 result ^= mono_string_hash (s);
1001 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1002 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1003 values [count++] = o;
1009 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1010 for (i = 0; i < count; ++i)
1011 mono_array_setref (*fields, i, values [i]);
1018 ICALL_EXPORT MonoBoolean
1019 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1022 MonoObject **values = NULL;
1024 MonoClassField* field;
1028 MONO_ARCH_SAVE_REGS;
1030 MONO_CHECK_ARG_NULL (that);
1032 if (this->vtable != that->vtable)
1035 klass = mono_object_class (this);
1037 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1038 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1041 * Do the comparison for fields of primitive type and return a result if
1042 * possible. Otherwise, return the remaining fields in an array to the
1043 * managed side. This way, we can avoid costly reflection operations in
1048 while ((field = mono_class_get_fields (klass, &iter))) {
1049 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1051 if (mono_field_is_deleted (field))
1053 /* FIXME: Add more types */
1054 switch (field->type->type) {
1057 case MONO_TYPE_BOOLEAN:
1058 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1063 case MONO_TYPE_CHAR:
1064 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1069 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1074 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1078 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1082 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1087 case MONO_TYPE_STRING: {
1088 MonoString *s1, *s2;
1089 guint32 s1len, s2len;
1090 s1 = *(MonoString**)((guint8*)this + field->offset);
1091 s2 = *(MonoString**)((guint8*)that + field->offset);
1094 if ((s1 == NULL) || (s2 == NULL))
1096 s1len = mono_string_length (s1);
1097 s2len = mono_string_length (s2);
1101 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1107 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1108 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1109 values [count++] = o;
1110 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1111 values [count++] = o;
1114 if (klass->enumtype)
1115 /* enums only have one non-static field */
1121 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1122 for (i = 0; i < count; ++i)
1123 mono_array_setref_fast (*fields, i, values [i]);
1130 ICALL_EXPORT MonoReflectionType *
1131 ves_icall_System_Object_GetType (MonoObject *obj)
1133 MONO_ARCH_SAVE_REGS;
1135 #ifndef DISABLE_REMOTING
1136 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1137 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1140 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1144 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1146 MONO_ARCH_SAVE_REGS;
1148 mtype->type = &obj->vtable->klass->byval_arg;
1149 g_assert (mtype->type->type);
1153 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1155 MONO_ARCH_SAVE_REGS;
1157 MONO_CHECK_ARG_NULL (obj);
1159 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1163 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1164 MonoReflectionMethod *method,
1165 MonoArray *opt_param_types)
1167 MONO_ARCH_SAVE_REGS;
1169 MONO_CHECK_ARG_NULL (method);
1171 return mono_image_create_method_token (
1172 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1176 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1178 MONO_ARCH_SAVE_REGS;
1180 mono_image_create_pefile (mb, file);
1184 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1186 MONO_ARCH_SAVE_REGS;
1188 mono_image_build_metadata (mb);
1192 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1194 MONO_ARCH_SAVE_REGS;
1196 mono_image_register_token (mb->dynamic_image, token, obj);
1200 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1202 MonoMethod **dest = data;
1204 /* skip unmanaged frames */
1220 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1222 MonoMethod **dest = data;
1224 /* skip unmanaged frames */
1229 if (!strcmp (m->klass->name_space, "System.Reflection"))
1238 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1240 MonoMethod **dest = data;
1242 /* skip unmanaged frames */
1246 if (m->wrapper_type != MONO_WRAPPER_NONE)
1249 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1263 static MonoReflectionType *
1264 type_from_name (const char *str, MonoBoolean ignoreCase)
1266 MonoType *type = NULL;
1267 MonoAssembly *assembly = NULL;
1268 MonoTypeNameParse info;
1269 char *temp_str = g_strdup (str);
1270 gboolean type_resolve = FALSE;
1272 MONO_ARCH_SAVE_REGS;
1274 /* mono_reflection_parse_type() mangles the string */
1275 if (!mono_reflection_parse_type (temp_str, &info)) {
1276 mono_reflection_free_type_info (&info);
1281 if (info.assembly.name) {
1282 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1284 MonoMethod *m = mono_method_get_last_managed ();
1285 MonoMethod *dest = m;
1287 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1292 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1293 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1294 * to crash. This only seems to happen in some strange remoting
1295 * scenarios and I was unable to figure out what's happening there.
1296 * Dec 10, 2005 - Martin.
1300 assembly = dest->klass->image->assembly;
1301 type_resolve = TRUE;
1303 g_warning (G_STRLOC);
1308 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1309 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1312 if (!info.assembly.name && !type) /* try mscorlib */
1313 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1315 if (assembly && !type && type_resolve) {
1316 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1317 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1320 mono_reflection_free_type_info (&info);
1326 return mono_type_get_object (mono_domain_get (), type);
1330 MonoReflectionType *
1331 mono_type_get (const char *str)
1333 char *copy = g_strdup (str);
1334 MonoReflectionType *type = type_from_name (copy, FALSE);
1341 ICALL_EXPORT MonoReflectionType*
1342 ves_icall_type_from_name (MonoString *name,
1343 MonoBoolean throwOnError,
1344 MonoBoolean ignoreCase)
1346 char *str = mono_string_to_utf8 (name);
1347 MonoReflectionType *type;
1349 type = type_from_name (str, ignoreCase);
1352 MonoException *e = NULL;
1355 e = mono_get_exception_type_load (name, NULL);
1357 mono_loader_clear_error ();
1359 mono_raise_exception (e);
1366 ICALL_EXPORT MonoReflectionType*
1367 ves_icall_type_from_handle (MonoType *handle)
1369 MonoDomain *domain = mono_domain_get ();
1371 MONO_ARCH_SAVE_REGS;
1373 return mono_type_get_object (domain, handle);
1376 ICALL_EXPORT MonoBoolean
1377 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1379 MONO_ARCH_SAVE_REGS;
1381 if (c && type->type && c->type)
1382 return mono_metadata_type_equal (type->type, c->type);
1384 return (type == c) ? TRUE : FALSE;
1387 /* System.TypeCode */
1406 TYPECODE_STRING = 18
1409 ICALL_EXPORT guint32
1410 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1412 int t = type->type->type;
1414 MONO_ARCH_SAVE_REGS;
1416 if (type->type->byref)
1417 return TYPECODE_OBJECT;
1421 case MONO_TYPE_VOID:
1422 return TYPECODE_OBJECT;
1423 case MONO_TYPE_BOOLEAN:
1424 return TYPECODE_BOOLEAN;
1426 return TYPECODE_BYTE;
1428 return TYPECODE_SBYTE;
1430 return TYPECODE_UINT16;
1432 return TYPECODE_INT16;
1433 case MONO_TYPE_CHAR:
1434 return TYPECODE_CHAR;
1438 return TYPECODE_OBJECT;
1440 return TYPECODE_UINT32;
1442 return TYPECODE_INT32;
1444 return TYPECODE_UINT64;
1446 return TYPECODE_INT64;
1448 return TYPECODE_SINGLE;
1450 return TYPECODE_DOUBLE;
1451 case MONO_TYPE_VALUETYPE: {
1452 MonoClass *klass = type->type->data.klass;
1454 if (klass->enumtype) {
1455 t = mono_class_enum_basetype (klass)->type;
1457 } else if (mono_is_corlib_image (klass->image)) {
1458 if (strcmp (klass->name_space, "System") == 0) {
1459 if (strcmp (klass->name, "Decimal") == 0)
1460 return TYPECODE_DECIMAL;
1461 else if (strcmp (klass->name, "DateTime") == 0)
1462 return TYPECODE_DATETIME;
1465 return TYPECODE_OBJECT;
1467 case MONO_TYPE_STRING:
1468 return TYPECODE_STRING;
1469 case MONO_TYPE_SZARRAY:
1470 case MONO_TYPE_ARRAY:
1471 case MONO_TYPE_OBJECT:
1473 case MONO_TYPE_MVAR:
1474 case MONO_TYPE_TYPEDBYREF:
1475 return TYPECODE_OBJECT;
1476 case MONO_TYPE_CLASS:
1478 MonoClass *klass = type->type->data.klass;
1479 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1480 if (strcmp (klass->name, "DBNull") == 0)
1481 return TYPECODE_DBNULL;
1484 return TYPECODE_OBJECT;
1485 case MONO_TYPE_GENERICINST:
1486 return TYPECODE_OBJECT;
1488 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1493 ICALL_EXPORT guint32
1494 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1500 MONO_ARCH_SAVE_REGS;
1502 g_assert (type != NULL);
1504 domain = ((MonoObject *)type)->vtable->domain;
1506 if (!c) /* FIXME: dont know what do do here */
1509 klass = mono_class_from_mono_type (type->type);
1510 klassc = mono_class_from_mono_type (c->type);
1512 /* Interface check requires a more complex setup so we
1513 * only do for them. Otherwise we simply avoid mono_class_init.
1515 if (check_interfaces) {
1516 mono_class_init_or_throw (klass);
1517 mono_class_init_or_throw (klassc);
1518 } else if (!klass->supertypes || !klassc->supertypes) {
1519 mono_class_setup_supertypes (klass);
1520 mono_class_setup_supertypes (klassc);
1523 if (type->type->byref)
1524 return klassc == mono_defaults.object_class;
1526 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1530 mono_type_is_primitive (MonoType *type)
1532 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1533 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1537 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1539 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1540 return mono_class_enum_basetype (type->data.klass);
1541 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1542 return mono_class_enum_basetype (type->data.generic_class->container_class);
1546 ICALL_EXPORT guint32
1547 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1553 MONO_ARCH_SAVE_REGS;
1555 g_assert (type != NULL);
1557 domain = ((MonoObject *)type)->vtable->domain;
1559 klass = mono_class_from_mono_type (type->type);
1560 klassc = mono_class_from_mono_type (c->type);
1562 mono_class_init_or_throw (klass);
1563 mono_class_init_or_throw (klassc);
1565 if (type->type->byref ^ c->type->byref)
1568 if (type->type->byref) {
1569 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1570 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1572 klass = mono_class_from_mono_type (t);
1573 klassc = mono_class_from_mono_type (ot);
1575 if (mono_type_is_primitive (t)) {
1576 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1577 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1578 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1579 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1580 return t->type == ot->type;
1582 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1585 if (klass->valuetype)
1586 return klass == klassc;
1587 return klass->valuetype == klassc->valuetype;
1590 return mono_class_is_assignable_from (klass, klassc);
1593 ICALL_EXPORT guint32
1594 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1596 MonoClass *klass = mono_class_from_mono_type (type->type);
1597 mono_class_init_or_throw (klass);
1598 return mono_object_isinst (obj, klass) != NULL;
1601 ICALL_EXPORT guint32
1602 ves_icall_get_attributes (MonoReflectionType *type)
1604 MonoClass *klass = mono_class_from_mono_type (type->type);
1605 return klass->flags;
1608 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1609 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1611 MonoClass *klass = field->field->parent;
1612 MonoMarshalType *info;
1615 if (klass->generic_container ||
1616 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1619 info = mono_marshal_load_type_info (klass);
1621 for (i = 0; i < info->num_fields; ++i) {
1622 if (info->fields [i].field == field->field) {
1623 if (!info->fields [i].mspec)
1626 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1633 ICALL_EXPORT MonoReflectionField*
1634 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1636 gboolean found = FALSE;
1643 klass = handle->parent;
1645 klass = mono_class_from_mono_type (type);
1647 /* Check that the field belongs to the class */
1648 for (k = klass; k; k = k->parent) {
1649 if (k == handle->parent) {
1656 /* The managed code will throw the exception */
1660 return mono_field_get_object (mono_domain_get (), klass, handle);
1663 ICALL_EXPORT MonoArray*
1664 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1667 MonoType *type = mono_field_get_type_checked (field->field, &error);
1668 if (!mono_error_ok (&error))
1669 mono_error_raise_exception (&error);
1671 return type_array_from_modifiers (field->field->parent->image, type, optional);
1675 vell_icall_get_method_attributes (MonoMethod *method)
1677 return method->flags;
1681 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1684 MonoDomain *domain = mono_domain_get ();
1685 MonoMethodSignature* sig;
1686 MONO_ARCH_SAVE_REGS;
1688 sig = mono_method_signature_checked (method, &error);
1689 if (!mono_error_ok (&error))
1690 mono_error_raise_exception (&error);
1693 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1694 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1695 info->attrs = method->flags;
1696 info->implattrs = method->iflags;
1697 if (sig->call_convention == MONO_CALL_DEFAULT)
1698 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1700 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1705 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1708 ICALL_EXPORT MonoArray*
1709 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1711 MonoDomain *domain = mono_domain_get ();
1713 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1716 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1717 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1719 MonoDomain *domain = mono_domain_get ();
1720 MonoReflectionMarshalAsAttribute* res = NULL;
1721 MonoMarshalSpec **mspecs;
1724 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1725 mono_method_get_marshal_info (method, mspecs);
1728 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1730 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1732 mono_metadata_free_marshal_spec (mspecs [i]);
1739 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1741 MonoClass *parent = field->field->parent;
1742 if (!parent->size_inited)
1743 mono_class_init (parent);
1745 return field->field->offset - sizeof (MonoObject);
1748 ICALL_EXPORT MonoReflectionType*
1749 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1752 MONO_ARCH_SAVE_REGS;
1754 parent = declaring? field->field->parent: field->klass;
1756 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1759 ICALL_EXPORT MonoObject *
1760 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1762 MonoClass *fklass = field->klass;
1763 MonoClassField *cf = field->field;
1764 MonoDomain *domain = mono_object_domain (field);
1766 if (fklass->image->assembly->ref_only)
1767 mono_raise_exception (mono_get_exception_invalid_operation (
1768 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1770 if (mono_security_core_clr_enabled ())
1771 mono_security_core_clr_ensure_reflection_access_field (cf);
1773 return mono_field_get_value_object (domain, cf, obj);
1777 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1780 MonoClassField *cf = field->field;
1784 MONO_ARCH_SAVE_REGS;
1786 if (field->klass->image->assembly->ref_only)
1787 mono_raise_exception (mono_get_exception_invalid_operation (
1788 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1790 if (mono_security_core_clr_enabled ())
1791 mono_security_core_clr_ensure_reflection_access_field (cf);
1793 type = mono_field_get_type_checked (cf, &error);
1794 if (!mono_error_ok (&error))
1795 mono_error_raise_exception (&error);
1797 v = (gchar *) value;
1799 switch (type->type) {
1802 case MONO_TYPE_BOOLEAN:
1805 case MONO_TYPE_CHAR:
1814 case MONO_TYPE_VALUETYPE:
1817 v += sizeof (MonoObject);
1819 case MONO_TYPE_STRING:
1820 case MONO_TYPE_OBJECT:
1821 case MONO_TYPE_CLASS:
1822 case MONO_TYPE_ARRAY:
1823 case MONO_TYPE_SZARRAY:
1826 case MONO_TYPE_GENERICINST: {
1827 MonoGenericClass *gclass = type->data.generic_class;
1828 g_assert (!gclass->context.class_inst->is_open);
1830 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1831 MonoClass *nklass = mono_class_from_mono_type (type);
1832 MonoObject *nullable;
1835 * Convert the boxed vtype into a Nullable structure.
1836 * This is complicated by the fact that Nullables have
1837 * a variable structure.
1839 nullable = mono_object_new (mono_domain_get (), nklass);
1841 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1843 v = mono_object_unbox (nullable);
1846 if (gclass->container_class->valuetype && (v != NULL))
1847 v += sizeof (MonoObject);
1851 g_error ("type 0x%x not handled in "
1852 "ves_icall_FieldInfo_SetValueInternal", type->type);
1857 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1858 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1859 if (!vtable->initialized)
1860 mono_runtime_class_init (vtable);
1861 mono_field_static_set_value (vtable, cf, v);
1863 mono_field_set_value (obj, cf, v);
1867 ICALL_EXPORT MonoObject *
1868 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1870 MonoObject *o = NULL;
1871 MonoClassField *field = this->field;
1873 MonoDomain *domain = mono_object_domain (this);
1875 MonoTypeEnum def_type;
1876 const char *def_value;
1880 MONO_ARCH_SAVE_REGS;
1882 mono_class_init (field->parent);
1884 t = mono_field_get_type_checked (field, &error);
1885 if (!mono_error_ok (&error))
1886 mono_error_raise_exception (&error);
1888 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1889 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1891 if (field->parent->image->dynamic) {
1893 g_assert_not_reached ();
1896 def_value = mono_class_get_field_default_value (field, &def_type);
1897 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1898 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1900 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1904 case MONO_TYPE_BOOLEAN:
1907 case MONO_TYPE_CHAR:
1915 case MONO_TYPE_R8: {
1918 /* boxed value type */
1919 t = g_new0 (MonoType, 1);
1921 klass = mono_class_from_mono_type (t);
1923 o = mono_object_new (domain, klass);
1924 v = ((gchar *) o) + sizeof (MonoObject);
1925 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1928 case MONO_TYPE_STRING:
1929 case MONO_TYPE_CLASS:
1930 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1933 g_assert_not_reached ();
1939 ICALL_EXPORT MonoReflectionType*
1940 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1943 MonoClassField *field = ref_field->field;
1944 MonoType *type = mono_field_get_type_checked (field, &error);
1945 if (!mono_error_ok (&error))
1946 mono_error_raise_exception (&error);
1947 return mono_type_get_object (mono_object_domain (ref_field), type);
1950 ICALL_EXPORT MonoReflectionType*
1951 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1953 MonoMethod *method = rmethod->method.method;
1955 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1958 /* From MonoProperty.cs */
1960 PInfo_Attributes = 1,
1961 PInfo_GetMethod = 1 << 1,
1962 PInfo_SetMethod = 1 << 2,
1963 PInfo_ReflectedType = 1 << 3,
1964 PInfo_DeclaringType = 1 << 4,
1969 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1971 MonoDomain *domain = mono_object_domain (property);
1973 MONO_ARCH_SAVE_REGS;
1975 if ((req_info & PInfo_ReflectedType) != 0)
1976 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1977 if ((req_info & PInfo_DeclaringType) != 0)
1978 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1980 if ((req_info & PInfo_Name) != 0)
1981 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1983 if ((req_info & PInfo_Attributes) != 0)
1984 info->attrs = property->property->attrs;
1986 if ((req_info & PInfo_GetMethod) != 0)
1987 MONO_STRUCT_SETREF (info, get, property->property->get ?
1988 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1990 if ((req_info & PInfo_SetMethod) != 0)
1991 MONO_STRUCT_SETREF (info, set, property->property->set ?
1992 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1994 * There may be other methods defined for properties, though, it seems they are not exposed
1995 * in the reflection API
2000 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2002 MonoDomain *domain = mono_object_domain (event);
2004 MONO_ARCH_SAVE_REGS;
2006 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2007 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2009 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2010 info->attrs = event->event->attrs;
2011 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2012 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2013 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2015 #ifndef MONO_SMALL_CONFIG
2016 if (event->event->other) {
2018 while (event->event->other [n])
2020 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2022 for (i = 0; i < n; i++)
2023 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2029 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2034 mono_class_setup_interfaces (klass, error);
2035 if (!mono_error_ok (error))
2038 for (i = 0; i < klass->interface_count; i++) {
2039 ic = klass->interfaces [i];
2040 g_hash_table_insert (ifaces, ic, ic);
2042 collect_interfaces (ic, ifaces, error);
2043 if (!mono_error_ok (error))
2049 MonoArray *iface_array;
2050 MonoGenericContext *context;
2054 } FillIfaceArrayData;
2057 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2059 FillIfaceArrayData *data = user_data;
2060 MonoClass *ic = key;
2061 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2063 if (!mono_error_ok (data->error))
2066 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2067 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2068 if (!mono_error_ok (data->error))
2072 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2075 mono_metadata_free_type (inflated);
2078 ICALL_EXPORT MonoArray*
2079 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2082 MonoClass *class = mono_class_from_mono_type (type->type);
2084 FillIfaceArrayData data = { 0 };
2087 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2089 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2090 data.context = mono_class_get_context (class);
2091 class = class->generic_class->container_class;
2094 for (parent = class; parent; parent = parent->parent) {
2095 mono_class_setup_interfaces (parent, &error);
2096 if (!mono_error_ok (&error))
2098 collect_interfaces (parent, iface_hash, &error);
2099 if (!mono_error_ok (&error))
2103 data.error = &error;
2104 data.domain = mono_object_domain (type);
2106 len = g_hash_table_size (iface_hash);
2108 g_hash_table_destroy (iface_hash);
2109 if (!data.domain->empty_types)
2110 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2111 return data.domain->empty_types;
2114 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2115 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2116 if (!mono_error_ok (&error))
2119 g_hash_table_destroy (iface_hash);
2120 return data.iface_array;
2123 g_hash_table_destroy (iface_hash);
2124 mono_error_raise_exception (&error);
2129 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2131 gboolean variance_used;
2132 MonoClass *class = mono_class_from_mono_type (type->type);
2133 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2134 MonoReflectionMethod *member;
2137 int i = 0, len, ioffset;
2140 MONO_ARCH_SAVE_REGS;
2141 mono_class_init_or_throw (class);
2142 mono_class_init_or_throw (iclass);
2144 mono_class_setup_vtable (class);
2146 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2150 len = mono_class_num_methods (iclass);
2151 domain = mono_object_domain (type);
2152 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2153 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2155 while ((method = mono_class_get_methods (iclass, &iter))) {
2156 member = mono_method_get_object (domain, method, iclass);
2157 mono_array_setref (*methods, i, member);
2158 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2159 mono_array_setref (*targets, i, member);
2166 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2168 MonoClass *klass = mono_class_from_mono_type (type->type);
2169 mono_class_init_or_throw (klass);
2171 if (klass->image->dynamic) {
2172 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2173 *packing = tb->packing_size;
2174 *size = tb->class_size;
2176 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2180 ICALL_EXPORT MonoReflectionType*
2181 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2185 MONO_ARCH_SAVE_REGS;
2187 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2188 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2190 class = mono_class_from_mono_type (type->type);
2191 mono_class_init_or_throw (class);
2193 // GetElementType should only return a type for:
2194 // Array Pointer PassedByRef
2195 if (type->type->byref)
2196 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2197 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2198 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2199 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2200 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2205 ICALL_EXPORT MonoReflectionType*
2206 ves_icall_get_type_parent (MonoReflectionType *type)
2208 MonoClass *class = mono_class_from_mono_type (type->type);
2209 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2212 ICALL_EXPORT MonoBoolean
2213 ves_icall_type_ispointer (MonoReflectionType *type)
2215 MONO_ARCH_SAVE_REGS;
2217 return type->type->type == MONO_TYPE_PTR;
2220 ICALL_EXPORT MonoBoolean
2221 ves_icall_type_isprimitive (MonoReflectionType *type)
2223 MONO_ARCH_SAVE_REGS;
2225 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)));
2228 ICALL_EXPORT MonoBoolean
2229 ves_icall_type_isbyref (MonoReflectionType *type)
2231 MONO_ARCH_SAVE_REGS;
2233 return type->type->byref;
2236 ICALL_EXPORT MonoBoolean
2237 ves_icall_type_iscomobject (MonoReflectionType *type)
2239 MonoClass *klass = mono_class_from_mono_type (type->type);
2240 mono_class_init_or_throw (klass);
2242 return mono_class_is_com_object (klass);
2245 ICALL_EXPORT MonoReflectionModule*
2246 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2248 MonoClass *class = mono_class_from_mono_type (type->type);
2249 return mono_module_get_object (mono_object_domain (type), class->image);
2252 ICALL_EXPORT MonoReflectionAssembly*
2253 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2255 MonoDomain *domain = mono_domain_get ();
2256 MonoClass *class = mono_class_from_mono_type (type->type);
2257 return mono_assembly_get_object (domain, class->image->assembly);
2260 ICALL_EXPORT MonoReflectionType*
2261 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2263 MonoDomain *domain = mono_domain_get ();
2266 MONO_ARCH_SAVE_REGS;
2268 if (type->type->byref)
2270 if (type->type->type == MONO_TYPE_VAR)
2271 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2272 else if (type->type->type == MONO_TYPE_MVAR)
2273 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2275 class = mono_class_from_mono_type (type->type)->nested_in;
2277 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2280 ICALL_EXPORT MonoString*
2281 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2283 MonoDomain *domain = mono_domain_get ();
2284 MonoClass *class = mono_class_from_mono_type (type->type);
2286 if (type->type->byref) {
2287 char *n = g_strdup_printf ("%s&", class->name);
2288 MonoString *res = mono_string_new (domain, n);
2294 return mono_string_new (domain, class->name);
2298 ICALL_EXPORT MonoString*
2299 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2301 MonoDomain *domain = mono_domain_get ();
2302 MonoClass *class = mono_class_from_mono_type (type->type);
2304 while (class->nested_in)
2305 class = class->nested_in;
2307 if (class->name_space [0] == '\0')
2310 return mono_string_new (domain, class->name_space);
2314 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2318 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2319 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2321 class = mono_class_from_mono_type (type->type);
2326 ICALL_EXPORT MonoArray*
2327 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2330 MonoClass *klass, *pklass;
2331 MonoDomain *domain = mono_object_domain (type);
2332 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2334 MONO_ARCH_SAVE_REGS;
2336 klass = mono_class_from_mono_type (type->type);
2338 if (klass->generic_container) {
2339 MonoGenericContainer *container = klass->generic_container;
2340 res = mono_array_new_specific (array_vtable, container->type_argc);
2341 for (i = 0; i < container->type_argc; ++i) {
2342 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2343 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2345 } else if (klass->generic_class) {
2346 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2347 res = mono_array_new_specific (array_vtable, inst->type_argc);
2348 for (i = 0; i < inst->type_argc; ++i)
2349 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2351 res = mono_array_new_specific (array_vtable, 0);
2356 ICALL_EXPORT gboolean
2357 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2360 MONO_ARCH_SAVE_REGS;
2362 if (!IS_MONOTYPE (type))
2365 if (type->type->byref)
2368 klass = mono_class_from_mono_type (type->type);
2369 return klass->generic_container != NULL;
2372 ICALL_EXPORT MonoReflectionType*
2373 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2376 MONO_ARCH_SAVE_REGS;
2378 if (type->type->byref)
2381 klass = mono_class_from_mono_type (type->type);
2383 if (klass->generic_container) {
2384 return type; /* check this one */
2386 if (klass->generic_class) {
2387 MonoClass *generic_class = klass->generic_class->container_class;
2390 tb = mono_class_get_ref_info (generic_class);
2392 if (generic_class->wastypebuilder && tb)
2395 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2400 ICALL_EXPORT MonoReflectionType*
2401 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2404 MonoType *geninst, **types;
2407 g_assert (IS_MONOTYPE (type));
2408 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2410 count = mono_array_length (type_array);
2411 types = g_new0 (MonoType *, count);
2413 for (i = 0; i < count; i++) {
2414 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2415 types [i] = t->type;
2418 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2423 class = mono_class_from_mono_type (geninst);
2425 /*we might inflate to the GTD*/
2426 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2427 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2429 return mono_type_get_object (mono_object_domain (type), geninst);
2432 ICALL_EXPORT gboolean
2433 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2436 MONO_ARCH_SAVE_REGS;
2438 if (type->type->byref)
2441 klass = mono_class_from_mono_type (type->type);
2443 return klass->generic_class != NULL;
2446 ICALL_EXPORT gboolean
2447 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2450 MONO_ARCH_SAVE_REGS;
2452 if (!IS_MONOTYPE (type))
2455 if (type->type->byref)
2458 klass = mono_class_from_mono_type (type->type);
2459 return klass->generic_class != NULL || klass->generic_container != NULL;
2463 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2465 MONO_ARCH_SAVE_REGS;
2467 if (!IS_MONOTYPE (type))
2470 if (is_generic_parameter (type->type))
2471 return mono_type_get_generic_param_num (type->type);
2475 ICALL_EXPORT GenericParameterAttributes
2476 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2478 MONO_ARCH_SAVE_REGS;
2480 g_assert (IS_MONOTYPE (type));
2481 g_assert (is_generic_parameter (type->type));
2482 return mono_generic_param_info (type->type->data.generic_param)->flags;
2485 ICALL_EXPORT MonoArray *
2486 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2488 MonoGenericParamInfo *param_info;
2494 MONO_ARCH_SAVE_REGS;
2496 g_assert (IS_MONOTYPE (type));
2498 domain = mono_object_domain (type);
2499 param_info = mono_generic_param_info (type->type->data.generic_param);
2500 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2503 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2504 for (i = 0; i < count; i++)
2505 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2511 ICALL_EXPORT MonoBoolean
2512 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2514 MONO_ARCH_SAVE_REGS;
2515 return is_generic_parameter (type->type);
2518 ICALL_EXPORT MonoBoolean
2519 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2521 MONO_ARCH_SAVE_REGS;
2522 return is_generic_parameter (tb->type.type);
2526 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2527 MonoReflectionType *t)
2529 enumtype->type = t->type;
2532 ICALL_EXPORT MonoReflectionMethod*
2533 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2534 MonoReflectionMethod* generic)
2541 MONO_ARCH_SAVE_REGS;
2543 domain = ((MonoObject *)type)->vtable->domain;
2545 klass = mono_class_from_mono_type (type->type);
2546 mono_class_init_or_throw (klass);
2549 while ((method = mono_class_get_methods (klass, &iter))) {
2550 if (method->token == generic->method->token)
2551 return mono_method_get_object (domain, method, klass);
2559 ICALL_EXPORT MonoReflectionMethod *
2560 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2563 MonoType *type = ref_type->type;
2565 MONO_ARCH_SAVE_REGS;
2567 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2568 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2569 if (type->type == MONO_TYPE_VAR)
2572 method = mono_type_get_generic_param_owner (type)->owner.method;
2574 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2577 ICALL_EXPORT MonoReflectionDllImportAttribute*
2578 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2580 static MonoClass *DllImportAttributeClass = NULL;
2581 MonoDomain *domain = mono_domain_get ();
2582 MonoReflectionDllImportAttribute *attr;
2583 MonoImage *image = method->klass->image;
2584 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2585 MonoTableInfo *tables = image->tables;
2586 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2587 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2588 guint32 im_cols [MONO_IMPLMAP_SIZE];
2589 guint32 scope_token;
2590 const char *import = NULL;
2591 const char *scope = NULL;
2594 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2597 if (!DllImportAttributeClass) {
2598 DllImportAttributeClass =
2599 mono_class_from_name (mono_defaults.corlib,
2600 "System.Runtime.InteropServices", "DllImportAttribute");
2601 g_assert (DllImportAttributeClass);
2604 if (method->klass->image->dynamic) {
2605 MonoReflectionMethodAux *method_aux =
2606 g_hash_table_lookup (
2607 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2609 import = method_aux->dllentry;
2610 scope = method_aux->dll;
2613 if (!import || !scope) {
2614 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2619 if (piinfo->implmap_idx) {
2620 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2622 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2623 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2624 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2625 scope = mono_metadata_string_heap (image, scope_token);
2628 flags = piinfo->piflags;
2630 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2632 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2633 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2634 attr->call_conv = (flags & 0x700) >> 8;
2635 attr->charset = ((flags & 0x6) >> 1) + 1;
2636 if (attr->charset == 1)
2638 attr->exact_spelling = (flags & 0x1) != 0;
2639 attr->set_last_error = (flags & 0x40) != 0;
2640 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2641 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2642 attr->preserve_sig = FALSE;
2647 ICALL_EXPORT MonoReflectionMethod *
2648 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2650 MonoMethodInflated *imethod;
2653 MONO_ARCH_SAVE_REGS;
2655 if (method->method->is_generic)
2658 if (!method->method->is_inflated)
2661 imethod = (MonoMethodInflated *) method->method;
2663 result = imethod->declaring;
2664 /* Not a generic method. */
2665 if (!result->is_generic)
2668 if (method->method->klass->image->dynamic) {
2669 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2670 MonoReflectionMethod *res;
2673 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2674 * the dynamic case as well ?
2676 mono_image_lock ((MonoImage*)image);
2677 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2678 mono_image_unlock ((MonoImage*)image);
2684 if (imethod->context.class_inst) {
2685 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2686 /*Generic methods gets the context of the GTD.*/
2687 if (mono_class_get_context (klass))
2688 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2691 return mono_method_get_object (mono_object_domain (method), result, NULL);
2694 ICALL_EXPORT gboolean
2695 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2697 MONO_ARCH_SAVE_REGS;
2699 return mono_method_signature (method->method)->generic_param_count != 0;
2702 ICALL_EXPORT gboolean
2703 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2705 MONO_ARCH_SAVE_REGS;
2707 return method->method->is_generic;
2710 ICALL_EXPORT MonoArray*
2711 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2716 MONO_ARCH_SAVE_REGS;
2718 domain = mono_object_domain (method);
2720 if (method->method->is_inflated) {
2721 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2724 count = inst->type_argc;
2725 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2727 for (i = 0; i < count; i++)
2728 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2734 count = mono_method_signature (method->method)->generic_param_count;
2735 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2737 for (i = 0; i < count; i++) {
2738 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2739 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2740 MonoClass *pklass = mono_class_from_generic_parameter (
2741 param, method->method->klass->image, TRUE);
2742 mono_array_setref (res, i,
2743 mono_type_get_object (domain, &pklass->byval_arg));
2749 ICALL_EXPORT MonoObject *
2750 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2753 * Invoke from reflection is supposed to always be a virtual call (the API
2754 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2755 * greater flexibility.
2757 MonoMethod *m = method->method;
2758 MonoMethodSignature *sig = mono_method_signature (m);
2763 MONO_ARCH_SAVE_REGS;
2767 if (mono_security_core_clr_enabled ())
2768 mono_security_core_clr_ensure_reflection_access_method (m);
2770 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2771 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2772 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2777 if (!mono_object_isinst (this, m->klass)) {
2778 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2779 char *target_name = mono_type_get_full_name (m->klass);
2780 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2781 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2783 g_free (target_name);
2787 m = mono_object_get_virtual_method (this, m);
2788 /* must pass the pointer to the value for valuetype methods */
2789 if (m->klass->valuetype)
2790 obj = mono_object_unbox (this);
2791 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2792 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2797 if (sig->ret->byref) {
2798 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"));
2802 pcount = params? mono_array_length (params): 0;
2803 if (pcount != sig->param_count) {
2804 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2808 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2809 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."));
2813 image = m->klass->image;
2814 if (image->assembly->ref_only) {
2815 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."));
2819 if (image->dynamic && !((MonoDynamicImage*)image)->run) {
2820 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2824 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2827 intptr_t *lower_bounds;
2828 pcount = mono_array_length (params);
2829 lengths = alloca (sizeof (uintptr_t) * pcount);
2830 /* Note: the synthetized array .ctors have int32 as argument type */
2831 for (i = 0; i < pcount; ++i)
2832 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2834 if (m->klass->rank == pcount) {
2835 /* Only lengths provided. */
2836 lower_bounds = NULL;
2838 g_assert (pcount == (m->klass->rank * 2));
2839 /* lower bounds are first. */
2840 lower_bounds = (intptr_t*)lengths;
2841 lengths += m->klass->rank;
2844 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2846 return mono_runtime_invoke_array (m, obj, params, NULL);
2849 #ifndef DISABLE_REMOTING
2850 ICALL_EXPORT MonoObject *
2851 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2853 MonoDomain *domain = mono_object_domain (method);
2854 MonoMethod *m = method->method;
2855 MonoMethodSignature *sig = mono_method_signature (m);
2856 MonoArray *out_args;
2858 int i, j, outarg_count = 0;
2860 MONO_ARCH_SAVE_REGS;
2862 if (m->klass == mono_defaults.object_class) {
2864 if (!strcmp (m->name, "FieldGetter")) {
2865 MonoClass *k = this->vtable->klass;
2869 /* If this is a proxy, then it must be a CBO */
2870 if (k == mono_defaults.transparent_proxy_class) {
2871 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2872 this = tp->rp->unwrapped_server;
2874 k = this->vtable->klass;
2877 name = mono_array_get (params, MonoString *, 1);
2878 str = mono_string_to_utf8 (name);
2881 MonoClassField* field = mono_class_get_field_from_name (k, str);
2883 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2884 if (field_klass->valuetype)
2885 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2887 result = *((gpointer *)((char *)this + field->offset));
2889 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2890 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2891 mono_array_setref (out_args, 0, result);
2899 g_assert_not_reached ();
2901 } else if (!strcmp (m->name, "FieldSetter")) {
2902 MonoClass *k = this->vtable->klass;
2908 /* If this is a proxy, then it must be a CBO */
2909 if (k == mono_defaults.transparent_proxy_class) {
2910 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2911 this = tp->rp->unwrapped_server;
2913 k = this->vtable->klass;
2916 name = mono_array_get (params, MonoString *, 1);
2917 str = mono_string_to_utf8 (name);
2920 MonoClassField* field = mono_class_get_field_from_name (k, str);
2922 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2923 MonoObject *val = mono_array_get (params, gpointer, 2);
2925 if (field_klass->valuetype) {
2926 size = mono_type_size (field->type, &align);
2927 g_assert (size == mono_class_value_size (field_klass, NULL));
2928 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2930 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2933 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2934 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2944 g_assert_not_reached ();
2949 for (i = 0; i < mono_array_length (params); i++) {
2950 if (sig->params [i]->byref)
2954 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2956 /* handle constructors only for objects already allocated */
2957 if (!strcmp (method->method->name, ".ctor"))
2960 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2961 g_assert (!method->method->klass->valuetype);
2962 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2964 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2965 if (sig->params [i]->byref) {
2967 arg = mono_array_get (params, gpointer, i);
2968 mono_array_setref (out_args, j, arg);
2973 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2980 read_enum_value (char *mem, int type)
2984 return *(guint8*)mem;
2986 return *(gint8*)mem;
2988 return *(guint16*)mem;
2990 return *(gint16*)mem;
2992 return *(guint32*)mem;
2994 return *(gint32*)mem;
2996 return *(guint64*)mem;
2998 return *(gint64*)mem;
3000 g_assert_not_reached ();
3006 write_enum_value (char *mem, int type, guint64 value)
3010 case MONO_TYPE_I1: {
3011 guint8 *p = (guint8*)mem;
3016 case MONO_TYPE_I2: {
3017 guint16 *p = (void*)mem;
3022 case MONO_TYPE_I4: {
3023 guint32 *p = (void*)mem;
3028 case MONO_TYPE_I8: {
3029 guint64 *p = (void*)mem;
3034 g_assert_not_reached ();
3039 ICALL_EXPORT MonoObject *
3040 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3043 MonoClass *enumc, *objc;
3048 MONO_ARCH_SAVE_REGS;
3050 MONO_CHECK_ARG_NULL (enumType);
3051 MONO_CHECK_ARG_NULL (value);
3053 domain = mono_object_domain (enumType);
3054 enumc = mono_class_from_mono_type (enumType->type);
3056 mono_class_init_or_throw (enumc);
3058 objc = value->vtable->klass;
3060 if (!enumc->enumtype)
3061 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3062 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3063 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."));
3065 etype = mono_class_enum_basetype (enumc);
3067 /* MS throws this for typebuilders */
3068 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3070 res = mono_object_new (domain, enumc);
3071 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3072 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3077 ICALL_EXPORT MonoObject *
3078 ves_icall_System_Enum_get_value (MonoObject *this)
3086 MONO_ARCH_SAVE_REGS;
3091 g_assert (this->vtable->klass->enumtype);
3093 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3094 res = mono_object_new (mono_object_domain (this), enumc);
3095 dst = (char *)res + sizeof (MonoObject);
3096 src = (char *)this + sizeof (MonoObject);
3097 size = mono_class_value_size (enumc, NULL);
3099 memcpy (dst, src, size);
3104 ICALL_EXPORT MonoReflectionType *
3105 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3110 MONO_ARCH_SAVE_REGS;
3112 klass = mono_class_from_mono_type (type->type);
3113 mono_class_init_or_throw (klass);
3115 etype = mono_class_enum_basetype (klass);
3117 /* MS throws this for typebuilders */
3118 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3120 return mono_type_get_object (mono_object_domain (type), etype);
3124 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3126 gpointer tdata = (char *)this + sizeof (MonoObject);
3127 gpointer odata = (char *)other + sizeof (MonoObject);
3128 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3129 g_assert (basetype);
3131 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3132 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3133 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3136 return me > other ? 1 : -1; \
3139 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3140 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3141 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3144 return me - other; \
3147 switch (basetype->type) {
3149 COMPARE_ENUM_VALUES (guint8);
3151 COMPARE_ENUM_VALUES (gint8);
3152 case MONO_TYPE_CHAR:
3154 COMPARE_ENUM_VALUES_RANGE (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_RANGE
3169 #undef COMPARE_ENUM_VALUES
3174 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3176 gpointer data = (char *)this + sizeof (MonoObject);
3177 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3178 g_assert (basetype);
3180 switch (basetype->type) {
3182 return *((gint8*)data);
3184 return *((guint8*)data);
3185 case MONO_TYPE_CHAR:
3187 return *((guint16*)data);
3190 return *((gint16*)data);
3192 return *((guint32*)data);
3194 return *((gint32*)data);
3196 case MONO_TYPE_I8: {
3197 gint64 value = *((gint64*)data);
3198 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3201 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3207 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3209 MonoDomain *domain = mono_object_domain (type);
3210 MonoClass *enumc = mono_class_from_mono_type (type->type);
3211 guint j = 0, nvalues, crow;
3213 MonoClassField *field;
3215 MONO_ARCH_SAVE_REGS;
3217 mono_class_init_or_throw (enumc);
3219 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3220 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3221 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3222 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3226 while ((field = mono_class_get_fields (enumc, &iter))) {
3229 MonoTypeEnum def_type;
3231 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3233 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3235 if (mono_field_is_deleted (field))
3237 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3239 p = mono_class_get_field_default_value (field, &def_type);
3240 len = mono_metadata_decode_blob_size (p, &p);
3241 switch (mono_class_enum_basetype (enumc)->type) {
3244 mono_array_set (info->values, gchar, j, *p);
3246 case MONO_TYPE_CHAR:
3249 mono_array_set (info->values, gint16, j, read16 (p));
3253 mono_array_set (info->values, gint32, j, read32 (p));
3257 mono_array_set (info->values, gint64, j, read64 (p));
3260 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3267 BFLAGS_IgnoreCase = 1,
3268 BFLAGS_DeclaredOnly = 2,
3269 BFLAGS_Instance = 4,
3271 BFLAGS_Public = 0x10,
3272 BFLAGS_NonPublic = 0x20,
3273 BFLAGS_FlattenHierarchy = 0x40,
3274 BFLAGS_InvokeMethod = 0x100,
3275 BFLAGS_CreateInstance = 0x200,
3276 BFLAGS_GetField = 0x400,
3277 BFLAGS_SetField = 0x800,
3278 BFLAGS_GetProperty = 0x1000,
3279 BFLAGS_SetProperty = 0x2000,
3280 BFLAGS_ExactBinding = 0x10000,
3281 BFLAGS_SuppressChangeType = 0x20000,
3282 BFLAGS_OptionalParamBinding = 0x40000
3285 ICALL_EXPORT MonoReflectionField *
3286 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3289 MonoClass *startklass, *klass;
3291 MonoClassField *field;
3294 int (*compare_func) (const char *s1, const char *s2) = NULL;
3295 domain = ((MonoObject *)type)->vtable->domain;
3296 klass = startklass = mono_class_from_mono_type (type->type);
3299 mono_raise_exception (mono_get_exception_argument_null ("name"));
3300 if (type->type->byref)
3303 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3306 if (klass->exception_type != MONO_EXCEPTION_NONE)
3307 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3310 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3311 guint32 flags = mono_field_get_flags (field);
3314 if (mono_field_is_deleted_with_flags (field, flags))
3316 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3317 if (bflags & BFLAGS_Public)
3319 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3320 if (bflags & BFLAGS_NonPublic) {
3327 if (flags & FIELD_ATTRIBUTE_STATIC) {
3328 if (bflags & BFLAGS_Static)
3329 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3332 if (bflags & BFLAGS_Instance)
3339 utf8_name = mono_string_to_utf8 (name);
3341 if (compare_func (mono_field_get_name (field), utf8_name)) {
3347 return mono_field_get_object (domain, klass, field);
3349 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3355 ICALL_EXPORT MonoArray*
3356 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3359 MonoClass *startklass, *klass, *refklass;
3364 MonoClassField *field;
3365 MonoPtrArray tmp_array;
3367 MONO_ARCH_SAVE_REGS;
3369 domain = ((MonoObject *)type)->vtable->domain;
3370 if (type->type->byref)
3371 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3372 klass = startklass = mono_class_from_mono_type (type->type);
3373 refklass = mono_class_from_mono_type (reftype->type);
3375 mono_ptr_array_init (tmp_array, 2);
3378 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3379 mono_ptr_array_destroy (tmp_array);
3380 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3384 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3385 guint32 flags = mono_field_get_flags (field);
3387 if (mono_field_is_deleted_with_flags (field, flags))
3389 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3390 if (bflags & BFLAGS_Public)
3392 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3393 if (bflags & BFLAGS_NonPublic) {
3400 if (flags & FIELD_ATTRIBUTE_STATIC) {
3401 if (bflags & BFLAGS_Static)
3402 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3405 if (bflags & BFLAGS_Instance)
3411 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3412 mono_ptr_array_append (tmp_array, member);
3414 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3417 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3419 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3420 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3422 mono_ptr_array_destroy (tmp_array);
3428 method_nonpublic (MonoMethod* method, gboolean start_klass)
3430 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3431 case METHOD_ATTRIBUTE_ASSEM:
3432 return (start_klass || mono_defaults.generic_ilist_class);
3433 case METHOD_ATTRIBUTE_PRIVATE:
3435 case METHOD_ATTRIBUTE_PUBLIC:
3443 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3446 MonoClass *startklass;
3449 int len, match, nslots;
3450 /*FIXME, use MonoBitSet*/
3451 guint32 method_slots_default [8];
3452 guint32 *method_slots = NULL;
3453 int (*compare_func) (const char *s1, const char *s2) = NULL;
3455 array = g_ptr_array_new ();
3461 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3463 /* An optimization for calls made from Delegate:CreateDelegate () */
3464 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3465 method = mono_get_delegate_invoke (klass);
3466 if (mono_loader_get_last_error ())
3469 g_ptr_array_add (array, method);
3473 mono_class_setup_vtable (klass);
3474 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3477 if (is_generic_parameter (&klass->byval_arg))
3478 nslots = mono_class_get_vtable_size (klass->parent);
3480 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3481 if (nslots >= sizeof (method_slots_default) * 8) {
3482 method_slots = g_new0 (guint32, nslots / 32 + 1);
3484 method_slots = method_slots_default;
3485 memset (method_slots, 0, sizeof (method_slots_default));
3488 mono_class_setup_vtable (klass);
3489 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3493 while ((method = mono_class_get_methods (klass, &iter))) {
3495 if (method->slot != -1) {
3496 g_assert (method->slot < nslots);
3497 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3499 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3500 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3503 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3505 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3506 if (bflags & BFLAGS_Public)
3508 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3514 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3515 if (bflags & BFLAGS_Static)
3516 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3519 if (bflags & BFLAGS_Instance)
3527 if (compare_func (name, method->name))
3532 g_ptr_array_add (array, method);
3534 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3536 if (method_slots != method_slots_default)
3537 g_free (method_slots);
3542 if (method_slots != method_slots_default)
3543 g_free (method_slots);
3544 g_ptr_array_free (array, TRUE);
3546 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3547 *ex = mono_class_get_exception_for_failure (klass);
3549 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3550 mono_loader_clear_error ();
3555 ICALL_EXPORT MonoArray*
3556 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3558 static MonoClass *MethodInfo_array;
3561 MonoVTable *array_vtable;
3562 MonoException *ex = NULL;
3563 const char *mname = NULL;
3564 GPtrArray *method_array;
3565 MonoClass *klass, *refklass;
3568 if (!MethodInfo_array) {
3569 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3570 mono_memory_barrier ();
3571 MethodInfo_array = klass;
3574 klass = mono_class_from_mono_type (type->type);
3575 refklass = mono_class_from_mono_type (reftype->type);
3576 domain = ((MonoObject *)type)->vtable->domain;
3577 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3578 if (type->type->byref)
3579 return mono_array_new_specific (array_vtable, 0);
3582 mname = mono_string_to_utf8 (name);
3584 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3585 g_free ((char*)mname);
3587 mono_raise_exception (ex);
3589 res = mono_array_new_specific (array_vtable, method_array->len);
3592 for (i = 0; i < method_array->len; ++i) {
3593 MonoMethod *method = g_ptr_array_index (method_array, i);
3594 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3597 g_ptr_array_free (method_array, TRUE);
3601 ICALL_EXPORT MonoArray*
3602 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3605 static MonoClass *System_Reflection_ConstructorInfo;
3606 MonoClass *startklass, *klass, *refklass;
3611 gpointer iter = NULL;
3612 MonoPtrArray tmp_array;
3614 MONO_ARCH_SAVE_REGS;
3616 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3618 domain = ((MonoObject *)type)->vtable->domain;
3619 if (type->type->byref)
3620 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3621 klass = startklass = mono_class_from_mono_type (type->type);
3622 refklass = mono_class_from_mono_type (reftype->type);
3624 if (!System_Reflection_ConstructorInfo)
3625 System_Reflection_ConstructorInfo = mono_class_from_name (
3626 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3629 while ((method = mono_class_get_methods (klass, &iter))) {
3631 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3633 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3634 if (bflags & BFLAGS_Public)
3637 if (bflags & BFLAGS_NonPublic)
3643 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3644 if (bflags & BFLAGS_Static)
3645 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3648 if (bflags & BFLAGS_Instance)
3654 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3656 mono_ptr_array_append (tmp_array, member);
3659 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3661 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3662 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3664 mono_ptr_array_destroy (tmp_array);
3670 property_hash (gconstpointer data)
3672 MonoProperty *prop = (MonoProperty*)data;
3674 return g_str_hash (prop->name);
3678 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3680 // Properties are hide-by-name-and-signature
3681 if (!g_str_equal (prop1->name, prop2->name))
3684 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3686 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3692 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3697 return method_nonpublic (accessor, start_klass);
3700 ICALL_EXPORT MonoArray*
3701 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3705 static MonoClass *System_Reflection_PropertyInfo;
3706 MonoClass *startklass, *klass;
3712 gchar *propname = NULL;
3713 int (*compare_func) (const char *s1, const char *s2) = NULL;
3715 GHashTable *properties = NULL;
3716 MonoPtrArray tmp_array;
3718 MONO_ARCH_SAVE_REGS;
3720 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3722 if (!System_Reflection_PropertyInfo)
3723 System_Reflection_PropertyInfo = mono_class_from_name (
3724 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3726 domain = ((MonoObject *)type)->vtable->domain;
3727 if (type->type->byref)
3728 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3729 klass = startklass = mono_class_from_mono_type (type->type);
3732 propname = mono_string_to_utf8 (name);
3733 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3736 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3738 mono_class_setup_vtable (klass);
3739 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3743 while ((prop = mono_class_get_properties (klass, &iter))) {
3749 flags = method->flags;
3752 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3753 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3754 if (bflags & BFLAGS_Public)
3756 } else if (bflags & BFLAGS_NonPublic) {
3757 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3758 property_accessor_nonpublic(prop->set, startklass == klass)) {
3765 if (flags & METHOD_ATTRIBUTE_STATIC) {
3766 if (bflags & BFLAGS_Static)
3767 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3770 if (bflags & BFLAGS_Instance)
3779 if (compare_func (propname, prop->name))
3783 if (g_hash_table_lookup (properties, prop))
3786 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3788 g_hash_table_insert (properties, prop, prop);
3790 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3793 g_hash_table_destroy (properties);
3796 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3797 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3798 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3800 mono_ptr_array_destroy (tmp_array);
3806 g_hash_table_destroy (properties);
3809 mono_ptr_array_destroy (tmp_array);
3811 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3812 ex = mono_class_get_exception_for_failure (klass);
3814 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3815 mono_loader_clear_error ();
3817 mono_raise_exception (ex);
3821 ICALL_EXPORT MonoReflectionEvent *
3822 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3825 MonoClass *klass, *startklass;
3830 int (*compare_func) (const char *s1, const char *s2);
3832 MONO_ARCH_SAVE_REGS;
3834 event_name = mono_string_to_utf8 (name);
3835 if (type->type->byref)
3837 klass = startklass = mono_class_from_mono_type (type->type);
3838 domain = mono_object_domain (type);
3840 mono_class_init_or_throw (klass);
3842 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3844 if (klass->exception_type != MONO_EXCEPTION_NONE)
3845 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3848 while ((event = mono_class_get_events (klass, &iter))) {
3849 if (compare_func (event->name, event_name))
3852 method = event->add;
3854 method = event->remove;
3856 method = event->raise;
3858 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3859 if (!(bflags & BFLAGS_Public))
3862 if (!(bflags & BFLAGS_NonPublic))
3864 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3868 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3869 if (!(bflags & BFLAGS_Static))
3871 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3874 if (!(bflags & BFLAGS_Instance))
3878 if (!(bflags & BFLAGS_NonPublic))
3881 g_free (event_name);
3882 return mono_event_get_object (domain, startklass, event);
3885 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3888 g_free (event_name);
3892 ICALL_EXPORT MonoArray*
3893 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3897 static MonoClass *System_Reflection_EventInfo;
3898 MonoClass *startklass, *klass;
3905 MonoPtrArray tmp_array;
3907 MONO_ARCH_SAVE_REGS;
3909 mono_ptr_array_init (tmp_array, 4);
3911 if (!System_Reflection_EventInfo)
3912 System_Reflection_EventInfo = mono_class_from_name (
3913 mono_defaults.corlib, "System.Reflection", "EventInfo");
3915 domain = mono_object_domain (type);
3916 if (type->type->byref)
3917 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3918 klass = startklass = mono_class_from_mono_type (type->type);
3921 mono_class_setup_vtable (klass);
3922 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3926 while ((event = mono_class_get_events (klass, &iter))) {
3928 method = event->add;
3930 method = event->remove;
3932 method = event->raise;
3934 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3935 if (bflags & BFLAGS_Public)
3937 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3938 if (bflags & BFLAGS_NonPublic)
3943 if (bflags & BFLAGS_NonPublic)
3949 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3950 if (bflags & BFLAGS_Static)
3951 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3954 if (bflags & BFLAGS_Instance)
3959 if (bflags & BFLAGS_Instance)
3963 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3965 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3968 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3970 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3971 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3973 mono_ptr_array_destroy (tmp_array);
3978 mono_ptr_array_destroy (tmp_array);
3979 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3980 ex = mono_class_get_exception_for_failure (klass);
3982 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3983 mono_loader_clear_error ();
3985 mono_raise_exception (ex);
3989 ICALL_EXPORT MonoReflectionType *
3990 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3998 MONO_ARCH_SAVE_REGS;
4001 mono_raise_exception (mono_get_exception_argument_null ("name"));
4003 domain = ((MonoObject *)type)->vtable->domain;
4004 if (type->type->byref)
4006 klass = mono_class_from_mono_type (type->type);
4008 str = mono_string_to_utf8 (name);
4011 if (klass->exception_type != MONO_EXCEPTION_NONE)
4012 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4015 * If a nested type is generic, return its generic type definition.
4016 * Note that this means that the return value is essentially a
4017 * nested type of the generic type definition of @klass.
4019 * A note in MSDN claims that a generic type definition can have
4020 * nested types that aren't generic. In any case, the container of that
4021 * nested type would be the generic type definition.
4023 if (klass->generic_class)
4024 klass = klass->generic_class->container_class;
4027 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4029 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4030 if (bflags & BFLAGS_Public)
4033 if (bflags & BFLAGS_NonPublic)
4038 if (strcmp (nested->name, str) == 0){
4040 return mono_type_get_object (domain, &nested->byval_arg);
4043 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4049 ICALL_EXPORT MonoArray*
4050 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4059 MonoPtrArray tmp_array;
4061 MONO_ARCH_SAVE_REGS;
4063 domain = ((MonoObject *)type)->vtable->domain;
4064 if (type->type->byref)
4065 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4066 klass = mono_class_from_mono_type (type->type);
4069 * If a nested type is generic, return its generic type definition.
4070 * Note that this means that the return value is essentially the set
4071 * of nested types of the generic type definition of @klass.
4073 * A note in MSDN claims that a generic type definition can have
4074 * nested types that aren't generic. In any case, the container of that
4075 * nested type would be the generic type definition.
4077 if (klass->generic_class)
4078 klass = klass->generic_class->container_class;
4080 mono_ptr_array_init (tmp_array, 1);
4082 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4084 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4085 if (bflags & BFLAGS_Public)
4088 if (bflags & BFLAGS_NonPublic)
4093 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4094 mono_ptr_array_append (tmp_array, member);
4097 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4099 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4100 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4102 mono_ptr_array_destroy (tmp_array);
4107 ICALL_EXPORT MonoReflectionType*
4108 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4111 MonoType *type = NULL;
4112 MonoTypeNameParse info;
4113 gboolean type_resolve;
4115 MONO_ARCH_SAVE_REGS;
4117 /* On MS.NET, this does not fire a TypeResolve event */
4118 type_resolve = TRUE;
4119 str = mono_string_to_utf8 (name);
4120 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4121 if (!mono_reflection_parse_type (str, &info)) {
4123 mono_reflection_free_type_info (&info);
4124 if (throwOnError) /* uhm: this is a parse error, though... */
4125 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4126 /*g_print ("failed parse\n");*/
4130 if (info.assembly.name) {
4132 mono_reflection_free_type_info (&info);
4134 /* 1.0 and 2.0 throw different exceptions */
4135 if (mono_defaults.generic_ilist_class)
4136 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4138 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4143 if (module != NULL) {
4145 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4150 if (assembly->assembly->dynamic) {
4151 /* Enumerate all modules */
4152 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4156 if (abuilder->modules) {
4157 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4158 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4159 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4165 if (!type && abuilder->loaded_modules) {
4166 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4167 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4168 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4175 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4177 mono_reflection_free_type_info (&info);
4179 MonoException *e = NULL;
4182 e = mono_get_exception_type_load (name, NULL);
4184 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4185 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4187 mono_loader_clear_error ();
4190 mono_raise_exception (e);
4193 } else if (mono_loader_get_last_error ()) {
4195 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4196 mono_loader_clear_error ();
4199 if (type->type == MONO_TYPE_CLASS) {
4200 MonoClass *klass = mono_type_get_class (type);
4202 if (mono_security_enabled () && !klass->exception_type)
4203 /* Some security problems are detected during generic vtable construction */
4204 mono_class_setup_vtable (klass);
4206 /* need to report exceptions ? */
4207 if (throwOnError && klass->exception_type) {
4208 /* report SecurityException (or others) that occured when loading the assembly */
4209 MonoException *exc = mono_class_get_exception_for_failure (klass);
4210 mono_loader_clear_error ();
4211 mono_raise_exception (exc);
4212 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4217 /* g_print ("got it\n"); */
4218 return mono_type_get_object (mono_object_domain (assembly), type);
4222 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4225 gchar *shadow_ini_file;
4228 /* Check for shadow-copied assembly */
4229 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4230 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4232 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4233 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4239 g_free (shadow_ini_file);
4240 if (content != NULL) {
4243 *filename = content;
4250 ICALL_EXPORT MonoString *
4251 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4253 MonoDomain *domain = mono_object_domain (assembly);
4254 MonoAssembly *mass = assembly->assembly;
4255 MonoString *res = NULL;
4260 MONO_ARCH_SAVE_REGS;
4262 if (g_path_is_absolute (mass->image->name)) {
4263 absolute = g_strdup (mass->image->name);
4264 dirname = g_path_get_dirname (absolute);
4266 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4267 dirname = g_strdup (mass->basedir);
4270 replace_shadow_path (domain, dirname, &absolute);
4275 for (i = strlen (absolute) - 1; i >= 0; i--)
4276 if (absolute [i] == '\\')
4281 uri = g_filename_to_uri (absolute, NULL, NULL);
4283 const char *prepend = "file://";
4285 if (*absolute == '/' && *(absolute + 1) == '/') {
4288 prepend = "file:///";
4291 uri = g_strconcat (prepend, absolute, NULL);
4295 res = mono_string_new (domain, uri);
4302 ICALL_EXPORT MonoBoolean
4303 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4305 MonoAssembly *mass = assembly->assembly;
4307 MONO_ARCH_SAVE_REGS;
4309 return mass->in_gac;
4312 ICALL_EXPORT MonoReflectionAssembly*
4313 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4317 MonoImageOpenStatus status;
4319 MONO_ARCH_SAVE_REGS;
4321 name = mono_string_to_utf8 (mname);
4322 res = mono_assembly_load_with_partial_name (name, &status);
4328 return mono_assembly_get_object (mono_domain_get (), res);
4331 ICALL_EXPORT MonoString *
4332 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4334 MonoDomain *domain = mono_object_domain (assembly);
4337 MONO_ARCH_SAVE_REGS;
4339 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4344 ICALL_EXPORT MonoBoolean
4345 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4347 MONO_ARCH_SAVE_REGS;
4349 return assembly->assembly->ref_only;
4352 ICALL_EXPORT MonoString *
4353 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4355 MonoDomain *domain = mono_object_domain (assembly);
4357 MONO_ARCH_SAVE_REGS;
4359 return mono_string_new (domain, assembly->assembly->image->version);
4362 ICALL_EXPORT MonoReflectionMethod*
4363 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4365 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4367 MONO_ARCH_SAVE_REGS;
4371 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4374 ICALL_EXPORT MonoReflectionModule*
4375 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4377 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4380 ICALL_EXPORT MonoArray*
4381 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4383 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4384 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4388 MONO_ARCH_SAVE_REGS;
4390 for (i = 0; i < table->rows; ++i) {
4391 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4392 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4398 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4400 static MonoClass *System_Version = NULL;
4401 static MonoMethod *create_version = NULL;
4405 if (!System_Version) {
4406 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4407 g_assert (System_Version);
4410 if (!create_version) {
4411 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4412 create_version = mono_method_desc_search_in_class (desc, System_Version);
4413 g_assert (create_version);
4414 mono_method_desc_free (desc);
4420 args [3] = &revision;
4421 result = mono_object_new (domain, System_Version);
4422 mono_runtime_invoke (create_version, result, args, NULL);
4427 ICALL_EXPORT MonoArray*
4428 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4430 static MonoClass *System_Reflection_AssemblyName;
4432 MonoDomain *domain = mono_object_domain (assembly);
4434 static MonoMethod *create_culture = NULL;
4435 MonoImage *image = assembly->assembly->image;
4438 MONO_ARCH_SAVE_REGS;
4440 if (!System_Reflection_AssemblyName)
4441 System_Reflection_AssemblyName = mono_class_from_name (
4442 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4444 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4447 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4449 if (count > 0 && !create_culture) {
4450 MonoMethodDesc *desc = mono_method_desc_new (
4451 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4452 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4453 g_assert (create_culture);
4454 mono_method_desc_free (desc);
4457 for (i = 0; i < count; i++) {
4458 MonoReflectionAssemblyName *aname;
4459 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4461 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4463 aname = (MonoReflectionAssemblyName *) mono_object_new (
4464 domain, System_Reflection_AssemblyName);
4466 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4468 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4469 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4470 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4471 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4472 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4473 aname->versioncompat = 1; /* SameMachine (default) */
4474 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4475 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4477 if (create_culture) {
4479 MonoBoolean assembly_ref = 1;
4480 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4481 args [1] = &assembly_ref;
4482 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4485 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4486 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4487 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4489 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4490 /* public key token isn't copied - the class library will
4491 automatically generate it from the public key if required */
4492 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4493 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4495 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4496 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4499 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4502 /* note: this function doesn't return the codebase on purpose (i.e. it can
4503 be used under partial trust as path information isn't present). */
4505 mono_array_setref (result, i, aname);
4510 /* move this in some file in mono/util/ */
4512 g_concat_dir_and_file (const char *dir, const char *file)
4514 g_return_val_if_fail (dir != NULL, NULL);
4515 g_return_val_if_fail (file != NULL, NULL);
4518 * If the directory name doesn't have a / on the end, we need
4519 * to add one so we get a proper path to the file
4521 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4522 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4524 return g_strconcat (dir, file, NULL);
4528 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4530 char *n = mono_string_to_utf8 (name);
4531 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4533 guint32 cols [MONO_MANIFEST_SIZE];
4534 guint32 impl, file_idx;
4538 MONO_ARCH_SAVE_REGS;
4540 for (i = 0; i < table->rows; ++i) {
4541 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4542 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4543 if (strcmp (val, n) == 0)
4547 if (i == table->rows)
4550 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4553 * this code should only be called after obtaining the
4554 * ResourceInfo and handling the other cases.
4556 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4557 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4559 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4564 module = assembly->assembly->image;
4566 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4568 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4571 ICALL_EXPORT gboolean
4572 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4574 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4576 guint32 cols [MONO_MANIFEST_SIZE];
4577 guint32 file_cols [MONO_FILE_SIZE];
4581 MONO_ARCH_SAVE_REGS;
4583 n = mono_string_to_utf8 (name);
4584 for (i = 0; i < table->rows; ++i) {
4585 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4586 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4587 if (strcmp (val, n) == 0)
4591 if (i == table->rows)
4594 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4595 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4598 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4599 case MONO_IMPLEMENTATION_FILE:
4600 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4601 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4602 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4603 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4604 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4605 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4608 info->location = RESOURCE_LOCATION_EMBEDDED;
4611 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4612 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4613 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4614 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4615 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4616 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4618 mono_raise_exception (ex);
4620 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4622 /* Obtain info recursively */
4623 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4624 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4627 case MONO_IMPLEMENTATION_EXP_TYPE:
4628 g_assert_not_reached ();
4636 ICALL_EXPORT MonoObject*
4637 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4639 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4640 MonoArray *result = NULL;
4645 MONO_ARCH_SAVE_REGS;
4647 /* check hash if needed */
4649 n = mono_string_to_utf8 (name);
4650 for (i = 0; i < table->rows; ++i) {
4651 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4652 if (strcmp (val, n) == 0) {
4655 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4656 fn = mono_string_new (mono_object_domain (assembly), n);
4658 return (MonoObject*)fn;
4666 for (i = 0; i < table->rows; ++i) {
4667 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4671 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4674 for (i = 0; i < table->rows; ++i) {
4675 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4676 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4677 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4678 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4683 return (MonoObject*)result;
4686 ICALL_EXPORT MonoArray*
4687 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4689 MonoDomain *domain = mono_domain_get();
4692 int i, j, file_count = 0;
4693 MonoImage **modules;
4694 guint32 module_count, real_module_count;
4695 MonoTableInfo *table;
4696 guint32 cols [MONO_FILE_SIZE];
4697 MonoImage *image = assembly->assembly->image;
4699 g_assert (image != NULL);
4700 g_assert (!assembly->assembly->dynamic);
4702 table = &image->tables [MONO_TABLE_FILE];
4703 file_count = table->rows;
4705 modules = image->modules;
4706 module_count = image->module_count;
4708 real_module_count = 0;
4709 for (i = 0; i < module_count; ++i)
4711 real_module_count ++;
4713 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4714 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4716 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4718 for (i = 0; i < module_count; ++i)
4720 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4724 for (i = 0; i < file_count; ++i, ++j) {
4725 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4726 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4727 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4729 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4731 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4732 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4734 mono_array_setref (res, j, mono_module_get_object (domain, m));
4741 ICALL_EXPORT MonoReflectionMethod*
4742 ves_icall_GetCurrentMethod (void)
4744 MonoMethod *m = mono_method_get_last_managed ();
4746 while (m->is_inflated)
4747 m = ((MonoMethodInflated*)m)->declaring;
4749 return mono_method_get_object (mono_domain_get (), m, NULL);
4754 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4757 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4758 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4759 //method is inflated, we should inflate it on the other class
4760 MonoGenericContext ctx;
4761 ctx.method_inst = inflated->context.method_inst;
4762 ctx.class_inst = inflated->context.class_inst;
4763 if (klass->generic_class)
4764 ctx.class_inst = klass->generic_class->context.class_inst;
4765 else if (klass->generic_container)
4766 ctx.class_inst = klass->generic_container->context.class_inst;
4767 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4770 mono_class_setup_methods (method->klass);
4771 if (method->klass->exception_type)
4773 for (i = 0; i < method->klass->method.count; ++i) {
4774 if (method->klass->methods [i] == method) {
4779 mono_class_setup_methods (klass);
4780 if (klass->exception_type)
4782 g_assert (offset >= 0 && offset < klass->method.count);
4783 return klass->methods [offset];
4786 ICALL_EXPORT MonoReflectionMethod*
4787 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4791 klass = mono_class_from_mono_type (type);
4792 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4794 if (method->klass != klass) {
4795 method = mono_method_get_equivalent_method (method, klass);
4800 klass = method->klass;
4801 return mono_method_get_object (mono_domain_get (), method, klass);
4804 ICALL_EXPORT MonoReflectionMethod*
4805 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4807 return mono_method_get_object (mono_domain_get (), method, NULL);
4810 ICALL_EXPORT MonoReflectionMethodBody*
4811 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4813 return mono_method_body_get_object (mono_domain_get (), method);
4816 ICALL_EXPORT MonoReflectionAssembly*
4817 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4819 MonoMethod *dest = NULL;
4821 MONO_ARCH_SAVE_REGS;
4823 mono_stack_walk_no_il (get_executing, &dest);
4825 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4829 ICALL_EXPORT MonoReflectionAssembly*
4830 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4832 MonoDomain* domain = mono_domain_get ();
4834 MONO_ARCH_SAVE_REGS;
4836 if (!domain->entry_assembly)
4839 return mono_assembly_get_object (domain, domain->entry_assembly);
4842 ICALL_EXPORT MonoReflectionAssembly*
4843 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4848 MONO_ARCH_SAVE_REGS;
4851 mono_stack_walk_no_il (get_executing, &dest);
4853 mono_stack_walk_no_il (get_caller, &dest);
4856 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4859 ICALL_EXPORT MonoString *
4860 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4861 gboolean assembly_qualified)
4863 MonoDomain *domain = mono_object_domain (object);
4864 MonoTypeNameFormat format;
4869 format = assembly_qualified ?
4870 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4871 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4873 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4875 name = mono_type_get_name_full (object->type, format);
4879 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4884 res = mono_string_new (domain, name);
4891 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4893 MonoClass *klass = mono_class_from_mono_type (this->type);
4894 mono_class_init_or_throw (klass);
4895 return mono_security_core_clr_class_level (klass);
4899 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4901 static MonoMethod *create_culture = NULL;
4904 const char *pkey_ptr;
4906 MonoBoolean assembly_ref = 0;
4908 MONO_ARCH_SAVE_REGS;
4910 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4911 aname->major = name->major;
4912 aname->minor = name->minor;
4913 aname->build = name->build;
4914 aname->flags = name->flags;
4915 aname->revision = name->revision;
4916 aname->hashalg = name->hash_alg;
4917 aname->versioncompat = 1; /* SameMachine (default) */
4918 aname->processor_architecture = name->arch;
4920 if (by_default_version)
4921 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4924 if (absolute != NULL && *absolute != '\0') {
4925 const gchar *prepend = "file://";
4928 codebase = g_strdup (absolute);
4933 for (i = strlen (codebase) - 1; i >= 0; i--)
4934 if (codebase [i] == '\\')
4937 if (*codebase == '/' && *(codebase + 1) == '/') {
4940 prepend = "file:///";
4944 result = g_strconcat (prepend, codebase, NULL);
4950 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4954 if (!create_culture) {
4955 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4956 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4957 g_assert (create_culture);
4958 mono_method_desc_free (desc);
4961 if (name->culture) {
4962 args [0] = mono_string_new (domain, name->culture);
4963 args [1] = &assembly_ref;
4964 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4967 if (name->public_key) {
4968 pkey_ptr = (char*)name->public_key;
4969 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4971 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4972 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4973 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4974 } else if (default_publickey) {
4975 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4976 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4979 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4980 if (name->public_key_token [0]) {
4984 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4985 p = mono_array_addr (aname->keyToken, char, 0);
4987 for (i = 0, j = 0; i < 8; i++) {
4988 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4989 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4992 } else if (default_token) {
4993 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4997 ICALL_EXPORT MonoString *
4998 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5000 MonoDomain *domain = mono_object_domain (assembly);
5001 MonoAssembly *mass = assembly->assembly;
5005 name = mono_stringify_assembly_name (&mass->aname);
5006 res = mono_string_new (domain, name);
5013 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5016 MonoAssembly *mass = assembly->assembly;
5018 MONO_ARCH_SAVE_REGS;
5020 if (g_path_is_absolute (mass->image->name)) {
5021 fill_reflection_assembly_name (mono_object_domain (assembly),
5022 aname, &mass->aname, mass->image->name, TRUE,
5026 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5028 fill_reflection_assembly_name (mono_object_domain (assembly),
5029 aname, &mass->aname, absolute, TRUE, TRUE,
5036 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5039 MonoImageOpenStatus status = MONO_IMAGE_OK;
5042 MonoAssemblyName name;
5045 MONO_ARCH_SAVE_REGS;
5047 filename = mono_string_to_utf8 (fname);
5049 dirname = g_path_get_dirname (filename);
5050 replace_shadow_path (mono_domain_get (), dirname, &filename);
5053 image = mono_image_open (filename, &status);
5059 if (status == MONO_IMAGE_IMAGE_INVALID)
5060 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5062 exc = mono_get_exception_file_not_found2 (NULL, fname);
5063 mono_raise_exception (exc);
5066 res = mono_assembly_fill_assembly_name (image, &name);
5068 mono_image_close (image);
5070 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5073 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5077 mono_image_close (image);
5080 ICALL_EXPORT MonoBoolean
5081 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5082 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5084 MonoBoolean result = FALSE;
5085 MonoDeclSecurityEntry entry;
5087 /* SecurityAction.RequestMinimum */
5088 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5089 *minimum = entry.blob;
5090 *minLength = entry.size;
5093 /* SecurityAction.RequestOptional */
5094 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5095 *optional = entry.blob;
5096 *optLength = entry.size;
5099 /* SecurityAction.RequestRefuse */
5100 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5101 *refused = entry.blob;
5102 *refLength = entry.size;
5110 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5114 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5116 guint32 attrs, visibility;
5118 /* we start the count from 1 because we skip the special type <Module> */
5121 for (i = 1; i < tdef->rows; ++i) {
5122 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5123 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5124 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5128 count = tdef->rows - 1;
5130 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5131 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5133 for (i = 1; i < tdef->rows; ++i) {
5134 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5135 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5136 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5137 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5139 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5141 MonoLoaderError *error;
5144 error = mono_loader_get_last_error ();
5145 g_assert (error != NULL);
5147 ex = mono_loader_error_prepare_exception (error);
5148 mono_array_setref (*exceptions, count, ex);
5150 if (mono_loader_get_last_error ())
5151 mono_loader_clear_error ();
5159 ICALL_EXPORT MonoArray*
5160 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5162 MonoArray *res = NULL;
5163 MonoArray *exceptions = NULL;
5164 MonoImage *image = NULL;
5165 MonoTableInfo *table = NULL;
5168 int i, len, ex_count;
5170 MONO_ARCH_SAVE_REGS;
5172 domain = mono_object_domain (assembly);
5174 g_assert (!assembly->assembly->dynamic);
5175 image = assembly->assembly->image;
5176 table = &image->tables [MONO_TABLE_FILE];
5177 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5179 /* Append data from all modules in the assembly */
5180 for (i = 0; i < table->rows; ++i) {
5181 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5182 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5185 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5186 /* Append the new types to the end of the array */
5187 if (mono_array_length (res2) > 0) {
5189 MonoArray *res3, *ex3;
5191 len1 = mono_array_length (res);
5192 len2 = mono_array_length (res2);
5194 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5195 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5196 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5199 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5200 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5201 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5208 /* the ReflectionTypeLoadException must have all the types (Types property),
5209 * NULL replacing types which throws an exception. The LoaderException must
5210 * contain all exceptions for NULL items.
5213 len = mono_array_length (res);
5216 for (i = 0; i < len; i++) {
5217 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5221 klass = mono_type_get_class (t->type);
5222 if ((klass != NULL) && klass->exception_type) {
5223 /* keep the class in the list */
5224 list = g_list_append (list, klass);
5225 /* and replace Type with NULL */
5226 mono_array_setref (res, i, NULL);
5233 if (list || ex_count) {
5235 MonoException *exc = NULL;
5236 MonoArray *exl = NULL;
5237 int j, length = g_list_length (list) + ex_count;
5239 mono_loader_clear_error ();
5241 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5242 /* Types for which mono_class_get () succeeded */
5243 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5244 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5245 mono_array_setref (exl, i, exc);
5247 /* Types for which it don't */
5248 for (j = 0; j < mono_array_length (exceptions); ++j) {
5249 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5251 g_assert (i < length);
5252 mono_array_setref (exl, i, exc);
5259 exc = mono_get_exception_reflection_type_load (res, exl);
5260 mono_loader_clear_error ();
5261 mono_raise_exception (exc);
5267 ICALL_EXPORT gboolean
5268 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5270 MonoAssemblyName aname;
5271 MonoDomain *domain = mono_object_domain (name);
5273 gboolean is_version_defined;
5274 gboolean is_token_defined;
5276 aname.public_key = NULL;
5277 val = mono_string_to_utf8 (assname);
5278 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5279 g_free ((guint8*) aname.public_key);
5284 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5285 FALSE, is_token_defined);
5287 mono_assembly_name_free (&aname);
5288 g_free ((guint8*) aname.public_key);
5294 ICALL_EXPORT MonoReflectionType*
5295 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5297 MonoDomain *domain = mono_object_domain (module);
5300 MONO_ARCH_SAVE_REGS;
5302 g_assert (module->image);
5304 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5305 /* These images do not have a global type */
5308 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5309 return mono_type_get_object (domain, &klass->byval_arg);
5313 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5315 /*if (module->image)
5316 mono_image_close (module->image);*/
5319 ICALL_EXPORT MonoString*
5320 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5322 MonoDomain *domain = mono_object_domain (module);
5324 MONO_ARCH_SAVE_REGS;
5326 g_assert (module->image);
5327 return mono_string_new (domain, module->image->guid);
5330 ICALL_EXPORT gpointer
5331 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5334 if (module->image && module->image->is_module_handle)
5335 return module->image->raw_data;
5338 return (gpointer) (-1);
5342 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5344 if (image->dynamic) {
5345 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5346 *pe_kind = dyn->pe_kind;
5347 *machine = dyn->machine;
5350 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5351 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5356 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5358 return (image->md_version_major << 16) | (image->md_version_minor);
5361 ICALL_EXPORT MonoArray*
5362 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5364 MonoArray *exceptions;
5367 MONO_ARCH_SAVE_REGS;
5370 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5372 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5373 for (i = 0; i < mono_array_length (exceptions); ++i) {
5374 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5376 mono_raise_exception (ex);
5383 mono_memberref_is_method (MonoImage *image, guint32 token)
5385 if (!image->dynamic) {
5386 guint32 cols [MONO_MEMBERREF_SIZE];
5388 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5389 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5390 mono_metadata_decode_blob_size (sig, &sig);
5391 return (*sig != 0x6);
5393 MonoClass *handle_class;
5395 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5398 return mono_defaults.methodhandle_class == handle_class;
5403 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5406 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5407 mono_array_addr (type_args, MonoType*, 0));
5409 context->class_inst = NULL;
5411 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5412 mono_array_addr (method_args, MonoType*, 0));
5414 context->method_inst = NULL;
5417 ICALL_EXPORT MonoType*
5418 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5421 int table = mono_metadata_token_table (token);
5422 int index = mono_metadata_token_index (token);
5423 MonoGenericContext context;
5425 *error = ResolveTokenError_Other;
5427 /* Validate token */
5428 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5429 (table != MONO_TABLE_TYPESPEC)) {
5430 *error = ResolveTokenError_BadTable;
5434 if (image->dynamic) {
5435 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5436 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5437 return klass ? &klass->byval_arg : NULL;
5440 init_generic_context_from_args (&context, type_args, method_args);
5441 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5442 return klass ? &klass->byval_arg : NULL;
5445 if ((index <= 0) || (index > image->tables [table].rows)) {
5446 *error = ResolveTokenError_OutOfRange;
5450 init_generic_context_from_args (&context, type_args, method_args);
5451 klass = mono_class_get_full (image, token, &context);
5453 if (mono_loader_get_last_error ())
5454 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5457 return &klass->byval_arg;
5462 ICALL_EXPORT MonoMethod*
5463 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5465 int table = mono_metadata_token_table (token);
5466 int index = mono_metadata_token_index (token);
5467 MonoGenericContext context;
5470 *error = ResolveTokenError_Other;
5472 /* Validate token */
5473 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5474 (table != MONO_TABLE_MEMBERREF)) {
5475 *error = ResolveTokenError_BadTable;
5479 if (image->dynamic) {
5480 if (table == MONO_TABLE_METHOD)
5481 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5483 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5484 *error = ResolveTokenError_BadTable;
5488 init_generic_context_from_args (&context, type_args, method_args);
5489 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5492 if ((index <= 0) || (index > image->tables [table].rows)) {
5493 *error = ResolveTokenError_OutOfRange;
5496 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5497 *error = ResolveTokenError_BadTable;
5501 init_generic_context_from_args (&context, type_args, method_args);
5502 method = mono_get_method_full (image, token, NULL, &context);
5504 if (mono_loader_get_last_error ())
5505 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5510 ICALL_EXPORT MonoString*
5511 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5513 int index = mono_metadata_token_index (token);
5515 *error = ResolveTokenError_Other;
5517 /* Validate token */
5518 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5519 *error = ResolveTokenError_BadTable;
5524 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5526 if ((index <= 0) || (index >= image->heap_us.size)) {
5527 *error = ResolveTokenError_OutOfRange;
5531 /* FIXME: What to do if the index points into the middle of a string ? */
5533 return mono_ldstr (mono_domain_get (), image, index);
5536 ICALL_EXPORT MonoClassField*
5537 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5540 int table = mono_metadata_token_table (token);
5541 int index = mono_metadata_token_index (token);
5542 MonoGenericContext context;
5543 MonoClassField *field;
5545 *error = ResolveTokenError_Other;
5547 /* Validate token */
5548 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5549 *error = ResolveTokenError_BadTable;
5553 if (image->dynamic) {
5554 if (table == MONO_TABLE_FIELD)
5555 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5557 if (mono_memberref_is_method (image, token)) {
5558 *error = ResolveTokenError_BadTable;
5562 init_generic_context_from_args (&context, type_args, method_args);
5563 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5566 if ((index <= 0) || (index > image->tables [table].rows)) {
5567 *error = ResolveTokenError_OutOfRange;
5570 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5571 *error = ResolveTokenError_BadTable;
5575 init_generic_context_from_args (&context, type_args, method_args);
5576 field = mono_field_from_token (image, token, &klass, &context);
5578 if (mono_loader_get_last_error ())
5579 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5585 ICALL_EXPORT MonoObject*
5586 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5588 int table = mono_metadata_token_table (token);
5590 *error = ResolveTokenError_Other;
5593 case MONO_TABLE_TYPEDEF:
5594 case MONO_TABLE_TYPEREF:
5595 case MONO_TABLE_TYPESPEC: {
5596 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5598 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5602 case MONO_TABLE_METHOD:
5603 case MONO_TABLE_METHODSPEC: {
5604 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5606 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5610 case MONO_TABLE_FIELD: {
5611 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5613 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5617 case MONO_TABLE_MEMBERREF:
5618 if (mono_memberref_is_method (image, token)) {
5619 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5621 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5626 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5628 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5635 *error = ResolveTokenError_BadTable;
5641 ICALL_EXPORT MonoArray*
5642 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5644 int table = mono_metadata_token_table (token);
5645 int idx = mono_metadata_token_index (token);
5646 MonoTableInfo *tables = image->tables;
5651 *error = ResolveTokenError_OutOfRange;
5653 /* FIXME: Support other tables ? */
5654 if (table != MONO_TABLE_STANDALONESIG)
5660 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5663 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5665 ptr = mono_metadata_blob_heap (image, sig);
5666 len = mono_metadata_decode_blob_size (ptr, &ptr);
5668 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5669 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5673 ICALL_EXPORT MonoReflectionType*
5674 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5677 int isbyref = 0, rank;
5678 char *str = mono_string_to_utf8 (smodifiers);
5681 MONO_ARCH_SAVE_REGS;
5683 klass = mono_class_from_mono_type (tb->type.type);
5685 /* logic taken from mono_reflection_parse_type(): keep in sync */
5689 if (isbyref) { /* only one level allowed by the spec */
5696 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5699 klass = mono_ptr_class_get (&klass->byval_arg);
5700 mono_class_init (klass);
5711 else if (*p != '*') { /* '*' means unknown lower bound */
5722 klass = mono_array_class_get (klass, rank);
5723 mono_class_init (klass);
5730 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5733 ICALL_EXPORT MonoBoolean
5734 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5739 MONO_ARCH_SAVE_REGS;
5742 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5748 check_for_invalid_type (MonoClass *klass)
5752 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5755 name = mono_type_get_full_name (klass);
5756 str = mono_string_new (mono_domain_get (), name);
5758 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5761 ICALL_EXPORT MonoReflectionType *
5762 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5764 MonoClass *klass, *aklass;
5766 MONO_ARCH_SAVE_REGS;
5768 klass = mono_class_from_mono_type (type->type);
5769 check_for_invalid_type (klass);
5771 if (rank == 0) //single dimentional array
5772 aklass = mono_array_class_get (klass, 1);
5774 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5776 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5779 ICALL_EXPORT MonoReflectionType *
5780 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5784 MONO_ARCH_SAVE_REGS;
5786 klass = mono_class_from_mono_type (type->type);
5787 mono_class_init_or_throw (klass);
5788 check_for_invalid_type (klass);
5790 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5793 ICALL_EXPORT MonoReflectionType *
5794 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5796 MonoClass *klass, *pklass;
5798 klass = mono_class_from_mono_type (type->type);
5799 mono_class_init_or_throw (klass);
5800 check_for_invalid_type (klass);
5802 pklass = mono_ptr_class_get (type->type);
5804 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5807 ICALL_EXPORT MonoObject *
5808 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5809 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5811 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5812 MonoObject *delegate;
5814 MonoMethod *method = info->method;
5816 MONO_ARCH_SAVE_REGS;
5818 mono_class_init_or_throw (delegate_class);
5820 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5822 if (mono_security_core_clr_enabled ()) {
5823 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5827 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5829 if (method->dynamic) {
5830 /* Creating a trampoline would leak memory */
5831 func = mono_compile_method (method);
5833 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5834 method = mono_object_get_virtual_method (target, method);
5835 func = mono_create_ftnptr (mono_domain_get (),
5836 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5839 mono_delegate_ctor_with_method (delegate, target, func, method);
5845 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5847 /* Reset the invoke impl to the default one */
5848 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5852 * Magic number to convert a time which is relative to
5853 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5855 #define EPOCH_ADJUST ((guint64)62135596800LL)
5858 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5860 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5863 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5865 convert_to_absolute_date(SYSTEMTIME *date)
5867 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5868 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5869 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5870 /* from the calendar FAQ */
5871 int a = (14 - date->wMonth) / 12;
5872 int y = date->wYear - a;
5873 int m = date->wMonth + 12 * a - 2;
5874 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5876 /* d is now the day of the week for the first of the month (0 == Sunday) */
5878 int day_of_week = date->wDayOfWeek;
5880 /* set day_in_month to the first day in the month which falls on day_of_week */
5881 int day_in_month = 1 + (day_of_week - d);
5882 if (day_in_month <= 0)
5885 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5886 date->wDay = day_in_month + (date->wDay - 1) * 7;
5887 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5894 * Return's the offset from GMT of a local time.
5896 * tm is a local time
5897 * t is the same local time as seconds.
5900 gmt_offset(struct tm *tm, time_t t)
5902 #if defined (HAVE_TM_GMTOFF)
5903 return tm->tm_gmtoff;
5908 g.tm_isdst = tm->tm_isdst;
5910 return (int)difftime(t, t2);
5915 * This is heavily based on zdump.c from glibc 2.2.
5917 * * data[0]: start of daylight saving time (in DateTime ticks).
5918 * * data[1]: end of daylight saving time (in DateTime ticks).
5919 * * data[2]: utcoffset (in TimeSpan ticks).
5920 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5921 * * name[0]: name of this timezone when not daylight saving.
5922 * * name[1]: name of this timezone when daylight saving.
5924 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5925 * the class library allows years between 1 and 9999.
5927 * Returns true on success and zero on failure.
5929 ICALL_EXPORT guint32
5930 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5933 MonoDomain *domain = mono_domain_get ();
5934 struct tm start, tt;
5937 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5938 int day, transitioned;
5941 gmtoff_st = gmtoff_ds = transitioned = 0;
5943 MONO_ARCH_SAVE_REGS;
5945 MONO_CHECK_ARG_NULL (data);
5946 MONO_CHECK_ARG_NULL (names);
5948 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5949 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5952 * no info is better than crashing: we'll need our own tz data
5953 * to make this work properly, anyway. The range is probably
5954 * reduced to 1970 .. 2037 because that is what mktime is
5955 * guaranteed to support (we get into an infinite loop
5959 memset (&start, 0, sizeof (start));
5962 start.tm_year = year-1900;
5964 t = mktime (&start);
5966 if ((year < 1970) || (year > 2037) || (t == -1)) {
5968 tt = *localtime (&t);
5969 strftime (tzone, sizeof (tzone), "%Z", &tt);
5970 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5971 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5975 gmtoff = gmt_offset (&start, t);
5977 /* For each day of the year, calculate the tm_gmtoff. */
5978 for (day = 0; day < 365 && transitioned < 2; day++) {
5981 tt = *localtime (&t);
5983 gmtoff_after = gmt_offset(&tt, t);
5985 /* Daylight saving starts or ends here. */
5986 if (gmtoff_after != gmtoff) {
5990 /* Try to find the exact hour when daylight saving starts/ends. */
5994 tt1 = *localtime (&t1);
5995 } while (gmt_offset (&tt1, t1) != gmtoff);
5997 /* Try to find the exact minute when daylight saving starts/ends. */
6000 tt1 = *localtime (&t1);
6001 } while (gmt_offset (&tt1, t1) == gmtoff);
6003 strftime (tzone, sizeof (tzone), "%Z", &tt);
6005 /* Write data, if we're already in daylight saving, we're done. */
6007 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6008 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6009 if (gmtoff_ds == 0) {
6011 gmtoff_ds = gmtoff_after;
6018 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6019 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6020 if (gmtoff_ds == 0) {
6021 gmtoff_st = gmtoff_after;
6027 /* This is only set once when we enter daylight saving. */
6029 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6030 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6032 gmtoff = gmt_offset (&tt, t);
6036 if (transitioned < 2) {
6037 strftime (tzone, sizeof (tzone), "%Z", &tt);
6038 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6039 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6040 mono_array_set ((*data), gint64, 0, 0);
6041 mono_array_set ((*data), gint64, 1, 0);
6042 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6043 mono_array_set ((*data), gint64, 3, 0);
6048 MonoDomain *domain = mono_domain_get ();
6049 TIME_ZONE_INFORMATION tz_info;
6054 tz_id = GetTimeZoneInformation (&tz_info);
6055 if (tz_id == TIME_ZONE_ID_INVALID)
6058 MONO_CHECK_ARG_NULL (data);
6059 MONO_CHECK_ARG_NULL (names);
6061 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6062 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6064 for (i = 0; i < 32; ++i)
6065 if (!tz_info.DaylightName [i])
6067 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6068 for (i = 0; i < 32; ++i)
6069 if (!tz_info.StandardName [i])
6071 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6073 if ((year <= 1601) || (year > 30827)) {
6075 * According to MSDN, the MS time functions can't handle dates outside
6081 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6082 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6083 tz_info.StandardDate.wYear = year;
6084 convert_to_absolute_date(&tz_info.StandardDate);
6085 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6090 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6091 tz_info.DaylightDate.wYear = year;
6092 convert_to_absolute_date(&tz_info.DaylightDate);
6093 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6098 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6100 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6101 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6107 ICALL_EXPORT gpointer
6108 ves_icall_System_Object_obj_address (MonoObject *this)
6110 MONO_ARCH_SAVE_REGS;
6117 static inline gint32
6118 mono_array_get_byte_length (MonoArray *array)
6124 klass = array->obj.vtable->klass;
6126 if (array->bounds == NULL)
6127 length = array->max_length;
6130 for (i = 0; i < klass->rank; ++ i)
6131 length *= array->bounds [i].length;
6134 switch (klass->element_class->byval_arg.type) {
6137 case MONO_TYPE_BOOLEAN:
6141 case MONO_TYPE_CHAR:
6149 return length * sizeof (gpointer);
6160 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6162 MONO_ARCH_SAVE_REGS;
6164 return mono_array_get_byte_length (array);
6168 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6170 MONO_ARCH_SAVE_REGS;
6172 return mono_array_get (array, gint8, idx);
6176 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6178 MONO_ARCH_SAVE_REGS;
6180 mono_array_set (array, gint8, idx, value);
6183 ICALL_EXPORT MonoBoolean
6184 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6186 guint8 *src_buf, *dest_buf;
6188 MONO_ARCH_SAVE_REGS;
6190 /* This is called directly from the class libraries without going through the managed wrapper */
6191 MONO_CHECK_ARG_NULL (src);
6192 MONO_CHECK_ARG_NULL (dest);
6194 /* watch out for integer overflow */
6195 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6198 src_buf = (guint8 *)src->vector + src_offset;
6199 dest_buf = (guint8 *)dest->vector + dest_offset;
6202 memcpy (dest_buf, src_buf, count);
6204 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6209 #ifndef DISABLE_REMOTING
6210 ICALL_EXPORT MonoObject *
6211 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6213 MonoDomain *domain = mono_object_domain (this);
6215 MonoRealProxy *rp = ((MonoRealProxy *)this);
6216 MonoTransparentProxy *tp;
6220 MONO_ARCH_SAVE_REGS;
6222 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6223 tp = (MonoTransparentProxy*) res;
6225 MONO_OBJECT_SETREF (tp, rp, rp);
6226 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6227 klass = mono_class_from_mono_type (type);
6229 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6230 tp->remote_class = mono_remote_class (domain, class_name, klass);
6232 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6236 ICALL_EXPORT MonoReflectionType *
6237 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6239 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6243 /* System.Environment */
6246 ves_icall_System_Environment_get_UserName (void)
6248 MONO_ARCH_SAVE_REGS;
6250 /* using glib is more portable */
6251 return mono_string_new (mono_domain_get (), g_get_user_name ());
6255 ICALL_EXPORT MonoString *
6256 ves_icall_System_Environment_get_MachineName (void)
6258 #if defined (HOST_WIN32)
6263 len = MAX_COMPUTERNAME_LENGTH + 1;
6264 buf = g_new (gunichar2, len);
6267 if (GetComputerName (buf, (PDWORD) &len))
6268 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6272 #elif !defined(DISABLE_SOCKETS)
6276 if (gethostname (buf, sizeof (buf)) == 0)
6277 result = mono_string_new (mono_domain_get (), buf);
6283 return mono_string_new (mono_domain_get (), "mono");
6288 ves_icall_System_Environment_get_Platform (void)
6290 #if defined (TARGET_WIN32)
6293 #elif defined(__MACH__)
6296 // Notice that the value is hidden from user code, and only exposed
6297 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6298 // define and making assumptions based on Unix/128/4 values before there
6299 // was a MacOS define. Lots of code would assume that not-Unix meant
6300 // Windows, but in this case, it would be OSX.
6309 ICALL_EXPORT MonoString *
6310 ves_icall_System_Environment_get_NewLine (void)
6312 MONO_ARCH_SAVE_REGS;
6314 #if defined (HOST_WIN32)
6315 return mono_string_new (mono_domain_get (), "\r\n");
6317 return mono_string_new (mono_domain_get (), "\n");
6321 ICALL_EXPORT MonoString *
6322 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6327 MONO_ARCH_SAVE_REGS;
6332 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6333 value = g_getenv (utf8_name);
6340 return mono_string_new (mono_domain_get (), value);
6344 * There is no standard way to get at environ.
6347 #ifndef __MINGW32_VERSION
6348 #if defined(__APPLE__) && !defined (__arm__)
6349 /* Apple defines this in crt_externs.h but doesn't provide that header for
6350 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6351 * in fact exist on all implementations (so far)
6353 gchar ***_NSGetEnviron(void);
6354 #define environ (*_NSGetEnviron())
6362 ICALL_EXPORT MonoArray *
6363 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6374 env_strings = GetEnvironmentStrings();
6377 env_string = env_strings;
6378 while (*env_string != '\0') {
6379 /* weird case that MS seems to skip */
6380 if (*env_string != '=')
6382 while (*env_string != '\0')
6388 domain = mono_domain_get ();
6389 names = mono_array_new (domain, mono_defaults.string_class, n);
6393 env_string = env_strings;
6394 while (*env_string != '\0') {
6395 /* weird case that MS seems to skip */
6396 if (*env_string != '=') {
6397 equal_str = wcschr(env_string, '=');
6398 g_assert(equal_str);
6399 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6400 mono_array_setref (names, n, str);
6403 while (*env_string != '\0')
6408 FreeEnvironmentStrings (env_strings);
6420 MONO_ARCH_SAVE_REGS;
6423 for (e = environ; *e != 0; ++ e)
6426 domain = mono_domain_get ();
6427 names = mono_array_new (domain, mono_defaults.string_class, n);
6430 for (e = environ; *e != 0; ++ e) {
6431 parts = g_strsplit (*e, "=", 2);
6433 str = mono_string_new (domain, *parts);
6434 mono_array_setref (names, n, str);
6447 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6449 #if !GLIB_CHECK_VERSION(2,4,0)
6450 #define g_setenv(a,b,c) setenv(a,b,c)
6451 #define g_unsetenv(a) unsetenv(a)
6455 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6460 gunichar2 *utf16_name, *utf16_value;
6462 gchar *utf8_name, *utf8_value;
6465 MONO_ARCH_SAVE_REGS;
6468 utf16_name = mono_string_to_utf16 (name);
6469 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6470 SetEnvironmentVariable (utf16_name, NULL);
6471 g_free (utf16_name);
6475 utf16_value = mono_string_to_utf16 (value);
6477 SetEnvironmentVariable (utf16_name, utf16_value);
6479 g_free (utf16_name);
6480 g_free (utf16_value);
6482 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6484 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6485 g_unsetenv (utf8_name);
6490 utf8_value = mono_string_to_utf8_checked (value, &error);
6491 if (!mono_error_ok (&error)) {
6493 mono_error_raise_exception (&error);
6495 g_setenv (utf8_name, utf8_value, TRUE);
6498 g_free (utf8_value);
6503 ves_icall_System_Environment_Exit (int result)
6505 MONO_ARCH_SAVE_REGS;
6507 mono_environment_exitcode_set (result);
6509 /* FIXME: There are some cleanup hangs that should be worked out, but
6510 * if the program is going to exit, everything will be cleaned up when
6511 * NaCl exits anyway.
6513 #ifndef __native_client__
6514 if (!mono_runtime_try_shutdown ())
6515 mono_thread_exit ();
6517 /* Suspend all managed threads since the runtime is going away */
6518 mono_thread_suspend_all_other_threads ();
6520 mono_runtime_quit ();
6523 /* we may need to do some cleanup here... */
6527 ICALL_EXPORT MonoString*
6528 ves_icall_System_Environment_GetGacPath (void)
6530 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6533 ICALL_EXPORT MonoString*
6534 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6536 #if defined (HOST_WIN32)
6537 #ifndef CSIDL_FLAG_CREATE
6538 #define CSIDL_FLAG_CREATE 0x8000
6541 WCHAR path [MAX_PATH];
6542 /* Create directory if no existing */
6543 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6547 return mono_string_new_utf16 (mono_domain_get (), path, len);
6550 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6552 return mono_string_new (mono_domain_get (), "");
6555 ICALL_EXPORT MonoArray *
6556 ves_icall_System_Environment_GetLogicalDrives (void)
6558 gunichar2 buf [256], *ptr, *dname;
6560 guint initial_size = 127, size = 128;
6563 MonoString *drivestr;
6564 MonoDomain *domain = mono_domain_get ();
6567 MONO_ARCH_SAVE_REGS;
6572 while (size > initial_size) {
6573 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6574 if (size > initial_size) {
6577 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6578 initial_size = size;
6592 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6597 while (*u16) { u16++; len ++; }
6598 drivestr = mono_string_new_utf16 (domain, dname, len);
6599 mono_array_setref (result, ndrives++, drivestr);
6609 ICALL_EXPORT MonoString *
6610 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6612 gunichar2 volume_name [MAX_PATH + 1];
6614 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6616 return mono_string_from_utf16 (volume_name);
6619 ICALL_EXPORT MonoString *
6620 ves_icall_System_Environment_InternalGetHome (void)
6622 MONO_ARCH_SAVE_REGS;
6624 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6627 static const char *encodings [] = {
6629 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6630 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6631 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6633 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6634 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6635 "x_unicode_2_0_utf_7",
6637 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6638 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6640 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6643 "unicodefffe", "utf_16be",
6650 * Returns the internal codepage, if the value of "int_code_page" is
6651 * 1 at entry, and we can not compute a suitable code page number,
6652 * returns the code page as a string
6654 ICALL_EXPORT MonoString*
6655 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6660 char *codepage = NULL;
6662 int want_name = *int_code_page;
6665 *int_code_page = -1;
6666 MONO_ARCH_SAVE_REGS;
6668 g_get_charset (&cset);
6669 c = codepage = strdup (cset);
6670 for (c = codepage; *c; c++){
6671 if (isascii (*c) && isalpha (*c))
6676 /* g_print ("charset: %s\n", cset); */
6678 /* handle some common aliases */
6681 for (i = 0; p != 0; ){
6682 if ((gssize) p < 7){
6684 p = encodings [++i];
6687 if (strcmp (p, codepage) == 0){
6688 *int_code_page = code;
6691 p = encodings [++i];
6694 if (strstr (codepage, "utf_8") != NULL)
6695 *int_code_page |= 0x10000000;
6698 if (want_name && *int_code_page == -1)
6699 return mono_string_new (mono_domain_get (), cset);
6704 ICALL_EXPORT MonoBoolean
6705 ves_icall_System_Environment_get_HasShutdownStarted (void)
6707 if (mono_runtime_is_shutting_down ())
6710 if (mono_domain_is_unloading (mono_domain_get ()))
6717 ves_icall_System_Environment_BroadcastSettingChange (void)
6720 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6725 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6726 MonoReflectionMethod *method,
6727 MonoArray *out_args)
6729 MONO_ARCH_SAVE_REGS;
6731 mono_message_init (mono_object_domain (this), this, method, out_args);
6734 #ifndef DISABLE_REMOTING
6735 ICALL_EXPORT MonoBoolean
6736 ves_icall_IsTransparentProxy (MonoObject *proxy)
6738 MONO_ARCH_SAVE_REGS;
6743 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6749 ICALL_EXPORT MonoReflectionMethod *
6750 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6751 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6755 MonoMethod **vtable;
6756 MonoMethod *res = NULL;
6758 MONO_CHECK_ARG_NULL (rtype);
6759 MONO_CHECK_ARG_NULL (rmethod);
6761 method = rmethod->method;
6762 klass = mono_class_from_mono_type (rtype->type);
6763 mono_class_init_or_throw (klass);
6765 if (MONO_CLASS_IS_INTERFACE (klass))
6768 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6771 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6772 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6778 mono_class_setup_vtable (klass);
6779 vtable = klass->vtable;
6781 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6782 gboolean variance_used = FALSE;
6783 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6784 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6786 res = vtable [offs + method->slot];
6788 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6791 if (method->slot != -1)
6792 res = vtable [method->slot];
6798 return mono_method_get_object (mono_domain_get (), res, NULL);
6802 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6807 MONO_ARCH_SAVE_REGS;
6809 klass = mono_class_from_mono_type (type->type);
6810 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6812 mono_vtable_set_is_remote (vtable, enable);
6815 #else /* DISABLE_REMOTING */
6818 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6820 g_assert_not_reached ();
6825 ICALL_EXPORT MonoObject *
6826 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6831 MONO_ARCH_SAVE_REGS;
6833 domain = mono_object_domain (type);
6834 klass = mono_class_from_mono_type (type->type);
6835 mono_class_init_or_throw (klass);
6837 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6838 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6840 if (klass->rank >= 1) {
6841 g_assert (klass->rank == 1);
6842 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6844 /* Bypass remoting object creation check */
6845 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6849 ICALL_EXPORT MonoString *
6850 ves_icall_System_IO_get_temp_path (void)
6852 MONO_ARCH_SAVE_REGS;
6854 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6857 #ifndef PLATFORM_NO_DRIVEINFO
6858 ICALL_EXPORT MonoBoolean
6859 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6860 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6864 ULARGE_INTEGER wapi_free_bytes_avail;
6865 ULARGE_INTEGER wapi_total_number_of_bytes;
6866 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6868 MONO_ARCH_SAVE_REGS;
6870 *error = ERROR_SUCCESS;
6871 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6872 &wapi_total_number_of_free_bytes);
6875 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6876 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6877 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6879 *free_bytes_avail = 0;
6880 *total_number_of_bytes = 0;
6881 *total_number_of_free_bytes = 0;
6882 *error = GetLastError ();
6888 ICALL_EXPORT guint32
6889 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6891 MONO_ARCH_SAVE_REGS;
6893 return GetDriveType (mono_string_chars (root_path_name));
6897 ICALL_EXPORT gpointer
6898 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6900 MONO_ARCH_SAVE_REGS;
6902 return mono_compile_method (method);
6905 ICALL_EXPORT MonoString *
6906 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6911 MONO_ARCH_SAVE_REGS;
6913 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6915 #if defined (HOST_WIN32)
6916 /* Avoid mixing '/' and '\\' */
6919 for (i = strlen (path) - 1; i >= 0; i--)
6920 if (path [i] == '/')
6924 mcpath = mono_string_new (mono_domain_get (), path);
6931 get_bundled_app_config (void)
6933 const gchar *app_config;
6936 gchar *config_file_name, *config_file_path;
6940 MONO_ARCH_SAVE_REGS;
6942 domain = mono_domain_get ();
6943 file = domain->setup->configuration_file;
6947 // Retrieve config file and remove the extension
6948 config_file_name = mono_string_to_utf8 (file);
6949 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6950 if (!config_file_path)
6951 config_file_path = config_file_name;
6952 len = strlen (config_file_path) - strlen (".config");
6953 module = g_malloc0 (len + 1);
6954 memcpy (module, config_file_path, len);
6955 // Get the config file from the module name
6956 app_config = mono_config_string_for_assembly_file (module);
6959 if (config_file_name != config_file_path)
6960 g_free (config_file_name);
6961 g_free (config_file_path);
6966 return mono_string_new (mono_domain_get (), app_config);
6970 get_bundled_machine_config (void)
6972 const gchar *machine_config;
6974 MONO_ARCH_SAVE_REGS;
6976 machine_config = mono_get_machine_config ();
6978 if (!machine_config)
6981 return mono_string_new (mono_domain_get (), machine_config);
6984 ICALL_EXPORT MonoString *
6985 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6990 MONO_ARCH_SAVE_REGS;
6992 path = g_path_get_dirname (mono_get_config_dir ());
6994 #if defined (HOST_WIN32)
6995 /* Avoid mixing '/' and '\\' */
6998 for (i = strlen (path) - 1; i >= 0; i--)
6999 if (path [i] == '/')
7003 ipath = mono_string_new (mono_domain_get (), path);
7009 ICALL_EXPORT gboolean
7010 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7012 MonoPEResourceDataEntry *entry;
7015 MONO_ARCH_SAVE_REGS;
7017 if (!assembly || !result || !size)
7022 image = assembly->assembly->image;
7023 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7027 *result = mono_image_rva_map (image, entry->rde_data_offset);
7032 *size = entry->rde_size;
7037 ICALL_EXPORT MonoBoolean
7038 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7040 return mono_is_debugger_attached ();
7043 ICALL_EXPORT MonoBoolean
7044 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7046 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7047 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7053 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7055 if (mono_get_runtime_callbacks ()->debug_log)
7056 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7060 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7062 #if defined (HOST_WIN32)
7063 OutputDebugString (mono_string_chars (message));
7065 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7069 /* Only used for value types */
7070 ICALL_EXPORT MonoObject *
7071 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7076 MONO_ARCH_SAVE_REGS;
7078 domain = mono_object_domain (type);
7079 klass = mono_class_from_mono_type (type->type);
7080 mono_class_init_or_throw (klass);
7082 if (mono_class_is_nullable (klass))
7083 /* No arguments -> null */
7086 return mono_object_new (domain, klass);
7089 ICALL_EXPORT MonoReflectionMethod *
7090 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7092 MonoClass *klass, *parent;
7093 MonoMethod *method = m->method;
7094 MonoMethod *result = NULL;
7097 MONO_ARCH_SAVE_REGS;
7099 if (method->klass == NULL)
7102 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7103 MONO_CLASS_IS_INTERFACE (method->klass) ||
7104 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7107 slot = mono_method_get_vtable_slot (method);
7111 klass = method->klass;
7112 if (klass->generic_class)
7113 klass = klass->generic_class->container_class;
7116 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7117 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7118 mono_class_setup_vtable (parent);
7119 if (parent->vtable_size <= slot)
7124 klass = klass->parent;
7129 if (klass == method->klass)
7132 /*This is possible if definition == FALSE.
7133 * Do it here to be really sure we don't read invalid memory.
7135 if (slot >= klass->vtable_size)
7138 mono_class_setup_vtable (klass);
7140 result = klass->vtable [slot];
7141 if (result == NULL) {
7142 /* It is an abstract method */
7143 gpointer iter = NULL;
7144 while ((result = mono_class_get_methods (klass, &iter)))
7145 if (result->slot == slot)
7152 return mono_method_get_object (mono_domain_get (), result, NULL);
7155 ICALL_EXPORT MonoString*
7156 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7158 MonoMethod *method = m->method;
7160 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7165 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7167 MONO_ARCH_SAVE_REGS;
7169 iter->sig = *(MonoMethodSignature**)argsp;
7171 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7172 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7175 /* FIXME: it's not documented what start is exactly... */
7179 iter->args = argsp + sizeof (gpointer);
7181 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7183 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7186 ICALL_EXPORT MonoTypedRef
7187 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7189 guint32 i, arg_size;
7192 MONO_ARCH_SAVE_REGS;
7194 i = iter->sig->sentinelpos + iter->next_arg;
7196 g_assert (i < iter->sig->param_count);
7198 res.type = iter->sig->params [i];
7199 res.klass = mono_class_from_mono_type (res.type);
7200 arg_size = mono_type_stack_size (res.type, &align);
7201 #if defined(__arm__) || defined(__mips__)
7202 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7204 res.value = iter->args;
7205 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7206 /* Values are stored as 8 byte register sized objects, but 'value'
7207 * is dereferenced as a pointer in other routines.
7209 res.value = (char*)res.value + 4;
7211 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7212 if (arg_size <= sizeof (gpointer)) {
7214 int padding = arg_size - mono_type_size (res.type, &dummy);
7215 res.value = (guint8*)res.value + padding;
7218 iter->args = (char*)iter->args + arg_size;
7221 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7226 ICALL_EXPORT MonoTypedRef
7227 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7229 guint32 i, arg_size;
7232 MONO_ARCH_SAVE_REGS;
7234 i = iter->sig->sentinelpos + iter->next_arg;
7236 g_assert (i < iter->sig->param_count);
7238 while (i < iter->sig->param_count) {
7239 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7241 res.type = iter->sig->params [i];
7242 res.klass = mono_class_from_mono_type (res.type);
7243 /* FIXME: endianess issue... */
7244 arg_size = mono_type_stack_size (res.type, &align);
7245 #if defined(__arm__) || defined(__mips__)
7246 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7248 res.value = iter->args;
7249 iter->args = (char*)iter->args + arg_size;
7251 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7254 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7262 ICALL_EXPORT MonoType*
7263 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7266 MONO_ARCH_SAVE_REGS;
7268 i = iter->sig->sentinelpos + iter->next_arg;
7270 g_assert (i < iter->sig->param_count);
7272 return iter->sig->params [i];
7275 ICALL_EXPORT MonoObject*
7276 mono_TypedReference_ToObject (MonoTypedRef tref)
7278 MONO_ARCH_SAVE_REGS;
7280 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7281 MonoObject** objp = tref.value;
7285 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7288 ICALL_EXPORT MonoObject*
7289 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7291 MONO_ARCH_SAVE_REGS;
7293 if (MONO_TYPE_IS_REFERENCE (type)) {
7294 MonoObject** objp = value;
7298 return mono_value_box (mono_domain_get (), klass, value);
7302 prelink_method (MonoMethod *method)
7304 const char *exc_class, *exc_arg;
7305 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7307 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7309 mono_raise_exception(
7310 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7312 /* create the wrapper, too? */
7316 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7318 MONO_ARCH_SAVE_REGS;
7319 prelink_method (method->method);
7323 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7325 MonoClass *klass = mono_class_from_mono_type (type->type);
7327 gpointer iter = NULL;
7328 MONO_ARCH_SAVE_REGS;
7330 mono_class_init_or_throw (klass);
7332 while ((m = mono_class_get_methods (klass, &iter)))
7336 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7338 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7339 gint32 const **exponents,
7340 gunichar2 const **digitLowerTable,
7341 gunichar2 const **digitUpperTable,
7342 gint64 const **tenPowersList,
7343 gint32 const **decHexDigits)
7345 *mantissas = Formatter_MantissaBitsTable;
7346 *exponents = Formatter_TensExponentTable;
7347 *digitLowerTable = Formatter_DigitLowerTable;
7348 *digitUpperTable = Formatter_DigitUpperTable;
7349 *tenPowersList = Formatter_TenPowersList;
7350 *decHexDigits = Formatter_DecHexDigits;
7354 get_category_data (int version,
7355 guint8 const **category_data,
7356 guint16 const **category_astral_index)
7358 *category_astral_index = NULL;
7360 #ifndef DISABLE_NET_4_0
7362 *category_data = CategoryData_v4;
7363 #ifndef DISABLE_ASTRAL
7364 *category_astral_index = CategoryData_v4_astral_index;
7370 *category_data = CategoryData_v2;
7371 #ifndef DISABLE_ASTRAL
7372 *category_astral_index = CategoryData_v2_astral_index;
7376 /* These parameters are "readonly" in corlib/System/Char.cs */
7378 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7379 guint8 const **category_data,
7380 guint16 const **category_astral_index,
7381 guint8 const **numeric_data,
7382 gdouble const **numeric_data_values,
7383 guint16 const **to_lower_data_low,
7384 guint16 const **to_lower_data_high,
7385 guint16 const **to_upper_data_low,
7386 guint16 const **to_upper_data_high)
7388 get_category_data (category_data_version, category_data, category_astral_index);
7389 *numeric_data = NumericData;
7390 *numeric_data_values = NumericDataValues;
7391 *to_lower_data_low = ToLowerDataLow;
7392 *to_lower_data_high = ToLowerDataHigh;
7393 *to_upper_data_low = ToUpperDataLow;
7394 *to_upper_data_high = ToUpperDataHigh;
7398 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7400 return method->method->token;
7404 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7405 * and avoid useless allocations.
7408 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7412 for (i = 0; i < type->num_mods; ++i) {
7413 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7418 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7420 for (i = 0; i < type->num_mods; ++i) {
7421 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7422 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7423 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7430 ICALL_EXPORT MonoArray*
7431 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7433 MonoType *type = param->ClassImpl->type;
7434 MonoClass *member_class = mono_object_class (param->MemberImpl);
7435 MonoMethod *method = NULL;
7438 MonoMethodSignature *sig;
7440 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7441 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7442 method = rmethod->method;
7443 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7444 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7445 if (!(method = prop->property->get))
7446 method = prop->property->set;
7449 char *type_name = mono_type_get_full_name (member_class);
7450 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7451 MonoException *ex = mono_get_exception_not_supported (msg);
7454 mono_raise_exception (ex);
7457 image = method->klass->image;
7458 pos = param->PositionImpl;
7459 sig = mono_method_signature (method);
7463 type = sig->params [pos];
7465 return type_array_from_modifiers (image, type, optional);
7469 get_property_type (MonoProperty *prop)
7471 MonoMethodSignature *sig;
7473 sig = mono_method_signature (prop->get);
7475 } else if (prop->set) {
7476 sig = mono_method_signature (prop->set);
7477 return sig->params [sig->param_count - 1];
7482 ICALL_EXPORT MonoArray*
7483 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7485 MonoType *type = get_property_type (property->property);
7486 MonoImage *image = property->klass->image;
7490 return type_array_from_modifiers (image, type, optional);
7494 *Construct a MonoType suited to be used to decode a constant blob object.
7496 * @type is the target type which will be constructed
7497 * @blob_type is the blob type, for example, that comes from the constant table
7498 * @real_type is the expected constructed type.
7501 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7503 type->type = blob_type;
7504 type->data.klass = NULL;
7505 if (blob_type == MONO_TYPE_CLASS)
7506 type->data.klass = mono_defaults.object_class;
7507 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7508 /* For enums, we need to use the base type */
7509 type->type = MONO_TYPE_VALUETYPE;
7510 type->data.klass = mono_class_from_mono_type (real_type);
7512 type->data.klass = mono_class_from_mono_type (real_type);
7515 ICALL_EXPORT MonoObject*
7516 property_info_get_default_value (MonoReflectionProperty *property)
7519 MonoProperty *prop = property->property;
7520 MonoType *type = get_property_type (prop);
7521 MonoDomain *domain = mono_object_domain (property);
7522 MonoTypeEnum def_type;
7523 const char *def_value;
7526 mono_class_init (prop->parent);
7528 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7529 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7531 def_value = mono_class_get_property_default_value (prop, &def_type);
7533 mono_type_from_blob_type (&blob_type, def_type, type);
7534 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7539 ICALL_EXPORT MonoBoolean
7540 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7542 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7543 MonoCustomAttrInfo *cinfo;
7546 mono_class_init_or_throw (attr_class);
7548 cinfo = mono_reflection_get_custom_attrs_info (obj);
7551 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7553 mono_custom_attrs_free (cinfo);
7557 ICALL_EXPORT MonoArray*
7558 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7560 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7565 mono_class_init_or_throw (attr_class);
7567 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7568 if (!mono_error_ok (&error))
7569 mono_error_raise_exception (&error);
7570 if (mono_loader_get_last_error ()) {
7571 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7572 g_assert_not_reached ();
7580 ICALL_EXPORT MonoString*
7581 ves_icall_Mono_Runtime_GetDisplayName (void)
7584 MonoString *display_name;
7586 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7587 display_name = mono_string_new (mono_domain_get (), info);
7589 return display_name;
7592 ICALL_EXPORT MonoString*
7593 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7595 MonoString *message;
7599 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7600 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7603 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7605 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7613 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7614 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7615 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7616 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7617 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7618 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7619 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7620 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7624 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7629 gunichar2 last, prev_last, prev2_last;
7636 int havePadding = 0;
7638 last = prev_last = 0, prev2_last = 0;
7639 for (i = 0; i < ilength; i++) {
7641 if (c >= sizeof (dbase64)) {
7642 exc = mono_exception_from_name_msg (mono_get_corlib (),
7643 "System", "FormatException",
7644 "Invalid character found.");
7645 mono_raise_exception (exc);
7646 } else if (isspace (c)) {
7648 } else if (havePadding && c != '=') {
7649 exc = mono_exception_from_name_msg (mono_get_corlib (),
7650 "System", "FormatException",
7651 "Invalid character found.");
7652 mono_raise_exception (exc);
7654 if (c == '=') havePadding = 1;
7655 prev2_last = prev_last;
7661 olength = ilength - ignored;
7663 if (allowWhitespaceOnly && olength == 0) {
7664 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7667 if ((olength & 3) != 0 || olength <= 0) {
7668 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7669 "FormatException", "Invalid length.");
7670 mono_raise_exception (exc);
7673 if (prev2_last == '=') {
7674 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7675 mono_raise_exception (exc);
7678 olength = (olength * 3) / 4;
7682 if (prev_last == '=')
7685 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7686 res_ptr = mono_array_addr (result, guchar, 0);
7687 for (i = 0; i < ilength; ) {
7690 for (k = 0; k < 4 && i < ilength;) {
7696 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7697 exc = mono_exception_from_name_msg (mono_get_corlib (),
7698 "System", "FormatException",
7699 "Invalid character found.");
7700 mono_raise_exception (exc);
7705 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7707 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7709 *res_ptr++ = (b [2] << 6) | b [3];
7711 while (i < ilength && isspace (start [i]))
7718 ICALL_EXPORT MonoArray *
7719 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7721 MONO_ARCH_SAVE_REGS;
7723 return base64_to_byte_array (mono_string_chars (str),
7724 mono_string_length (str), allowWhitespaceOnly);
7727 ICALL_EXPORT MonoArray *
7728 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7730 MONO_ARCH_SAVE_REGS;
7732 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7736 #ifndef DISABLE_ICALL_TABLES
7738 #define ICALL_TYPE(id,name,first)
7739 #define ICALL(id,name,func) Icall_ ## id,
7742 #include "metadata/icall-def.h"
7748 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7749 #define ICALL(id,name,func)
7751 #include "metadata/icall-def.h"
7757 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7758 #define ICALL(id,name,func)
7760 guint16 first_icall;
7763 static const IcallTypeDesc
7764 icall_type_descs [] = {
7765 #include "metadata/icall-def.h"
7769 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7772 #define ICALL_TYPE(id,name,first)
7775 #ifdef HAVE_ARRAY_ELEM_INIT
7776 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7777 #define MSGSTRFIELD1(line) str##line
7779 static const struct msgstrtn_t {
7780 #define ICALL(id,name,func)
7782 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7783 #include "metadata/icall-def.h"
7785 } icall_type_names_str = {
7786 #define ICALL_TYPE(id,name,first) (name),
7787 #include "metadata/icall-def.h"
7790 static const guint16 icall_type_names_idx [] = {
7791 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7792 #include "metadata/icall-def.h"
7795 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7797 static const struct msgstr_t {
7799 #define ICALL_TYPE(id,name,first)
7800 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7801 #include "metadata/icall-def.h"
7803 } icall_names_str = {
7804 #define ICALL(id,name,func) (name),
7805 #include "metadata/icall-def.h"
7808 static const guint16 icall_names_idx [] = {
7809 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7810 #include "metadata/icall-def.h"
7813 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7819 #define ICALL_TYPE(id,name,first) name,
7820 #define ICALL(id,name,func)
7821 static const char* const
7822 icall_type_names [] = {
7823 #include "metadata/icall-def.h"
7827 #define icall_type_name_get(id) (icall_type_names [(id)])
7831 #define ICALL_TYPE(id,name,first)
7832 #define ICALL(id,name,func) name,
7833 static const char* const
7835 #include "metadata/icall-def.h"
7838 #define icall_name_get(id) icall_names [(id)]
7840 #endif /* !HAVE_ARRAY_ELEM_INIT */
7844 #define ICALL_TYPE(id,name,first)
7845 #define ICALL(id,name,func) func,
7846 static const gconstpointer
7847 icall_functions [] = {
7848 #include "metadata/icall-def.h"
7852 #ifdef ENABLE_ICALL_SYMBOL_MAP
7855 #define ICALL_TYPE(id,name,first)
7856 #define ICALL(id,name,func) #func,
7857 static const gconstpointer
7858 icall_symbols [] = {
7859 #include "metadata/icall-def.h"
7864 #endif /* DISABLE_ICALL_TABLES */
7866 static mono_mutex_t icall_mutex;
7867 static GHashTable *icall_hash = NULL;
7868 static GHashTable *jit_icall_hash_name = NULL;
7869 static GHashTable *jit_icall_hash_addr = NULL;
7872 mono_icall_init (void)
7874 #ifndef DISABLE_ICALL_TABLES
7877 /* check that tables are sorted: disable in release */
7880 const char *prev_class = NULL;
7881 const char *prev_method;
7883 for (i = 0; i < Icall_type_num; ++i) {
7884 const IcallTypeDesc *desc;
7887 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7888 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7889 prev_class = icall_type_name_get (i);
7890 desc = &icall_type_descs [i];
7891 num_icalls = icall_desc_num_icalls (desc);
7892 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7893 for (j = 0; j < num_icalls; ++j) {
7894 const char *methodn = icall_name_get (desc->first_icall + j);
7895 if (prev_method && strcmp (prev_method, methodn) >= 0)
7896 g_print ("method %s should come before method %s\n", methodn, prev_method);
7897 prev_method = methodn;
7903 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7904 mono_mutex_init (&icall_mutex);
7908 mono_icall_lock (void)
7910 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7914 mono_icall_unlock (void)
7916 mono_locks_mutex_release (&icall_mutex, IcallLock);
7920 mono_icall_cleanup (void)
7922 g_hash_table_destroy (icall_hash);
7923 g_hash_table_destroy (jit_icall_hash_name);
7924 g_hash_table_destroy (jit_icall_hash_addr);
7925 mono_mutex_destroy (&icall_mutex);
7929 mono_add_internal_call (const char *name, gconstpointer method)
7933 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7935 mono_icall_unlock ();
7938 #ifndef DISABLE_ICALL_TABLES
7940 #ifdef HAVE_ARRAY_ELEM_INIT
7942 compare_method_imap (const void *key, const void *elem)
7944 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7945 return strcmp (key, method_name);
7949 find_method_icall (const IcallTypeDesc *imap, const char *name)
7951 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);
7954 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7958 compare_class_imap (const void *key, const void *elem)
7960 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7961 return strcmp (key, class_name);
7964 static const IcallTypeDesc*
7965 find_class_icalls (const char *name)
7967 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7970 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7973 #else /* HAVE_ARRAY_ELEM_INIT */
7976 compare_method_imap (const void *key, const void *elem)
7978 const char** method_name = (const char**)elem;
7979 return strcmp (key, *method_name);
7983 find_method_icall (const IcallTypeDesc *imap, const char *name)
7985 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7988 return (gpointer)icall_functions [(nameslot - icall_names)];
7992 compare_class_imap (const void *key, const void *elem)
7994 const char** class_name = (const char**)elem;
7995 return strcmp (key, *class_name);
7998 static const IcallTypeDesc*
7999 find_class_icalls (const char *name)
8001 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8004 return &icall_type_descs [nameslot - icall_type_names];
8007 #endif /* HAVE_ARRAY_ELEM_INIT */
8009 #endif /* DISABLE_ICALL_TABLES */
8012 * we should probably export this as an helper (handle nested types).
8013 * Returns the number of chars written in buf.
8016 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8018 int nspacelen, cnamelen;
8019 nspacelen = strlen (klass->name_space);
8020 cnamelen = strlen (klass->name);
8021 if (nspacelen + cnamelen + 2 > bufsize)
8024 memcpy (buf, klass->name_space, nspacelen);
8025 buf [nspacelen ++] = '.';
8027 memcpy (buf + nspacelen, klass->name, cnamelen);
8028 buf [nspacelen + cnamelen] = 0;
8029 return nspacelen + cnamelen;
8032 #ifdef DISABLE_ICALL_TABLES
8034 no_icall_table (void)
8036 g_assert_not_reached ();
8041 mono_lookup_internal_call (MonoMethod *method)
8046 int typelen = 0, mlen, siglen;
8048 #ifndef DISABLE_ICALL_TABLES
8049 const IcallTypeDesc *imap = NULL;
8052 g_assert (method != NULL);
8054 if (method->is_inflated)
8055 method = ((MonoMethodInflated *) method)->declaring;
8057 if (method->klass->nested_in) {
8058 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8062 mname [pos++] = '/';
8065 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8071 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8076 #ifndef DISABLE_ICALL_TABLES
8077 imap = find_class_icalls (mname);
8080 mname [typelen] = ':';
8081 mname [typelen + 1] = ':';
8083 mlen = strlen (method->name);
8084 memcpy (mname + typelen + 2, method->name, mlen);
8085 sigstart = mname + typelen + 2 + mlen;
8088 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8089 siglen = strlen (tmpsig);
8090 if (typelen + mlen + siglen + 6 > sizeof (mname))
8093 memcpy (sigstart + 1, tmpsig, siglen);
8094 sigstart [siglen + 1] = ')';
8095 sigstart [siglen + 2] = 0;
8100 res = g_hash_table_lookup (icall_hash, mname);
8102 mono_icall_unlock ();;
8105 /* try without signature */
8107 res = g_hash_table_lookup (icall_hash, mname);
8109 mono_icall_unlock ();
8113 #ifdef DISABLE_ICALL_TABLES
8114 mono_icall_unlock ();
8115 /* Fail only when the result is actually used */
8116 /* mono_marshal_get_native_wrapper () depends on this */
8117 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8118 return ves_icall_System_String_ctor_RedirectToCreateString;
8120 return no_icall_table;
8122 /* it wasn't found in the static call tables */
8124 mono_icall_unlock ();
8127 res = find_method_icall (imap, sigstart - mlen);
8129 mono_icall_unlock ();
8132 /* try _with_ signature */
8134 res = find_method_icall (imap, sigstart - mlen);
8136 mono_icall_unlock ();
8140 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8141 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8142 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8143 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8144 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");
8145 g_print ("If you see other errors or faults after this message they are probably related\n");
8146 g_print ("and you need to fix your mono install first.\n");
8148 mono_icall_unlock ();
8154 #ifdef ENABLE_ICALL_SYMBOL_MAP
8156 func_cmp (gconstpointer key, gconstpointer p)
8158 return (gsize)key - (gsize)*(gsize*)p;
8163 * mono_lookup_icall_symbol:
8165 * Given the icall METHOD, returns its C symbol.
8168 mono_lookup_icall_symbol (MonoMethod *m)
8170 #ifdef DISABLE_ICALL_TABLES
8171 g_assert_not_reached ();
8174 #ifdef ENABLE_ICALL_SYMBOL_MAP
8178 static gconstpointer *functions_sorted;
8179 static const char**symbols_sorted;
8180 static gboolean inited;
8185 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8186 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8187 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8188 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8189 /* Bubble sort the two arrays */
8193 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8194 if (functions_sorted [i] > functions_sorted [i + 1]) {
8197 tmp = functions_sorted [i];
8198 functions_sorted [i] = functions_sorted [i + 1];
8199 functions_sorted [i + 1] = tmp;
8200 tmp = symbols_sorted [i];
8201 symbols_sorted [i] = symbols_sorted [i + 1];
8202 symbols_sorted [i + 1] = tmp;
8209 func = mono_lookup_internal_call (m);
8212 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8216 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8218 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8219 g_assert_not_reached ();
8226 type_from_typename (char *typename)
8228 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8230 if (!strcmp (typename, "int"))
8231 klass = mono_defaults.int_class;
8232 else if (!strcmp (typename, "ptr"))
8233 klass = mono_defaults.int_class;
8234 else if (!strcmp (typename, "void"))
8235 klass = mono_defaults.void_class;
8236 else if (!strcmp (typename, "int32"))
8237 klass = mono_defaults.int32_class;
8238 else if (!strcmp (typename, "uint32"))
8239 klass = mono_defaults.uint32_class;
8240 else if (!strcmp (typename, "int8"))
8241 klass = mono_defaults.sbyte_class;
8242 else if (!strcmp (typename, "uint8"))
8243 klass = mono_defaults.byte_class;
8244 else if (!strcmp (typename, "int16"))
8245 klass = mono_defaults.int16_class;
8246 else if (!strcmp (typename, "uint16"))
8247 klass = mono_defaults.uint16_class;
8248 else if (!strcmp (typename, "long"))
8249 klass = mono_defaults.int64_class;
8250 else if (!strcmp (typename, "ulong"))
8251 klass = mono_defaults.uint64_class;
8252 else if (!strcmp (typename, "float"))
8253 klass = mono_defaults.single_class;
8254 else if (!strcmp (typename, "double"))
8255 klass = mono_defaults.double_class;
8256 else if (!strcmp (typename, "object"))
8257 klass = mono_defaults.object_class;
8258 else if (!strcmp (typename, "obj"))
8259 klass = mono_defaults.object_class;
8260 else if (!strcmp (typename, "string"))
8261 klass = mono_defaults.string_class;
8262 else if (!strcmp (typename, "bool"))
8263 klass = mono_defaults.boolean_class;
8264 else if (!strcmp (typename, "boolean"))
8265 klass = mono_defaults.boolean_class;
8267 g_error ("%s", typename);
8268 g_assert_not_reached ();
8270 return &klass->byval_arg;
8274 * LOCKING: Take the corlib image lock.
8276 MonoMethodSignature*
8277 mono_create_icall_signature (const char *sigstr)
8282 MonoMethodSignature *res, *res2;
8283 MonoImage *corlib = mono_defaults.corlib;
8285 mono_image_lock (corlib);
8286 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8287 mono_image_unlock (corlib);
8292 parts = g_strsplit (sigstr, " ", 256);
8301 res = mono_metadata_signature_alloc (corlib, len - 1);
8306 * Under windows, the default pinvoke calling convention is STDCALL but
8309 res->call_convention = MONO_CALL_C;
8312 res->ret = type_from_typename (parts [0]);
8313 for (i = 1; i < len; ++i) {
8314 res->params [i - 1] = type_from_typename (parts [i]);
8319 mono_image_lock (corlib);
8320 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8322 res = res2; /*Value is allocated in the image pool*/
8324 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8325 mono_image_unlock (corlib);
8331 mono_find_jit_icall_by_name (const char *name)
8333 MonoJitICallInfo *info;
8334 g_assert (jit_icall_hash_name);
8337 info = g_hash_table_lookup (jit_icall_hash_name, name);
8338 mono_icall_unlock ();
8343 mono_find_jit_icall_by_addr (gconstpointer addr)
8345 MonoJitICallInfo *info;
8346 g_assert (jit_icall_hash_addr);
8349 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8350 mono_icall_unlock ();
8356 * mono_get_jit_icall_info:
8358 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8359 * caller should access it while holding the icall lock.
8362 mono_get_jit_icall_info (void)
8364 return jit_icall_hash_name;
8368 * mono_lookup_jit_icall_symbol:
8370 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8373 mono_lookup_jit_icall_symbol (const char *name)
8375 MonoJitICallInfo *info;
8376 const char *res = NULL;
8379 info = g_hash_table_lookup (jit_icall_hash_name, name);
8381 res = info->c_symbol;
8382 mono_icall_unlock ();
8387 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8390 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8391 mono_icall_unlock ();
8395 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8397 MonoJitICallInfo *info;
8404 if (!jit_icall_hash_name) {
8405 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8406 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8409 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8410 g_warning ("jit icall already defined \"%s\"\n", name);
8411 g_assert_not_reached ();
8414 info = g_new0 (MonoJitICallInfo, 1);
8419 info->c_symbol = c_symbol;
8422 info->wrapper = func;
8424 info->wrapper = NULL;
8427 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8428 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8430 mono_icall_unlock ();
8435 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8437 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);