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 */
934 current = (guint8 *)&stack_addr;
935 if (current > stack_addr) {
936 if ((current - stack_addr) < min_size)
939 if (current - (stack_addr - stack_size) < min_size)
945 ICALL_EXPORT MonoObject *
946 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
950 return mono_object_clone (this);
954 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
957 MonoObject **values = NULL;
961 MonoClassField* field;
966 klass = mono_object_class (this);
968 if (mono_class_num_fields (klass) == 0)
969 return mono_object_hash (this);
972 * Compute the starting value of the hashcode for fields of primitive
973 * types, and return the remaining fields in an array to the managed side.
974 * This way, we can avoid costly reflection operations in managed code.
977 while ((field = mono_class_get_fields (klass, &iter))) {
978 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
980 if (mono_field_is_deleted (field))
982 /* FIXME: Add more types */
983 switch (field->type->type) {
985 result ^= *(gint32*)((guint8*)this + field->offset);
987 case MONO_TYPE_STRING: {
989 s = *(MonoString**)((guint8*)this + field->offset);
991 result ^= mono_string_hash (s);
996 values = g_newa (MonoObject*, mono_class_num_fields (klass));
997 o = mono_field_get_value_object (mono_object_domain (this), field, this);
998 values [count++] = o;
1004 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1005 for (i = 0; i < count; ++i)
1006 mono_array_setref (*fields, i, values [i]);
1013 ICALL_EXPORT MonoBoolean
1014 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1017 MonoObject **values = NULL;
1019 MonoClassField* field;
1023 MONO_ARCH_SAVE_REGS;
1025 MONO_CHECK_ARG_NULL (that);
1027 if (this->vtable != that->vtable)
1030 klass = mono_object_class (this);
1032 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1033 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1036 * Do the comparison for fields of primitive type and return a result if
1037 * possible. Otherwise, return the remaining fields in an array to the
1038 * managed side. This way, we can avoid costly reflection operations in
1043 while ((field = mono_class_get_fields (klass, &iter))) {
1044 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1046 if (mono_field_is_deleted (field))
1048 /* FIXME: Add more types */
1049 switch (field->type->type) {
1052 case MONO_TYPE_BOOLEAN:
1053 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1058 case MONO_TYPE_CHAR:
1059 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1064 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1069 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1073 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1077 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1082 case MONO_TYPE_STRING: {
1083 MonoString *s1, *s2;
1084 guint32 s1len, s2len;
1085 s1 = *(MonoString**)((guint8*)this + field->offset);
1086 s2 = *(MonoString**)((guint8*)that + field->offset);
1089 if ((s1 == NULL) || (s2 == NULL))
1091 s1len = mono_string_length (s1);
1092 s2len = mono_string_length (s2);
1096 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1102 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1103 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1104 values [count++] = o;
1105 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1106 values [count++] = o;
1109 if (klass->enumtype)
1110 /* enums only have one non-static field */
1116 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1117 for (i = 0; i < count; ++i)
1118 mono_array_setref_fast (*fields, i, values [i]);
1125 ICALL_EXPORT MonoReflectionType *
1126 ves_icall_System_Object_GetType (MonoObject *obj)
1128 MONO_ARCH_SAVE_REGS;
1130 #ifndef DISABLE_REMOTING
1131 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1132 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1135 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1139 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1141 MONO_ARCH_SAVE_REGS;
1143 mtype->type = &obj->vtable->klass->byval_arg;
1144 g_assert (mtype->type->type);
1148 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1150 MONO_ARCH_SAVE_REGS;
1152 MONO_CHECK_ARG_NULL (obj);
1154 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1158 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1159 MonoReflectionMethod *method,
1160 MonoArray *opt_param_types)
1162 MONO_ARCH_SAVE_REGS;
1164 MONO_CHECK_ARG_NULL (method);
1166 return mono_image_create_method_token (
1167 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1171 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1173 MONO_ARCH_SAVE_REGS;
1175 mono_image_create_pefile (mb, file);
1179 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1181 MONO_ARCH_SAVE_REGS;
1183 mono_image_build_metadata (mb);
1187 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1189 MONO_ARCH_SAVE_REGS;
1191 mono_image_register_token (mb->dynamic_image, token, obj);
1195 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1197 MonoMethod **dest = data;
1199 /* skip unmanaged frames */
1215 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1217 MonoMethod **dest = data;
1219 /* skip unmanaged frames */
1224 if (!strcmp (m->klass->name_space, "System.Reflection"))
1233 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1235 MonoMethod **dest = data;
1237 /* skip unmanaged frames */
1241 if (m->wrapper_type != MONO_WRAPPER_NONE)
1244 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1258 static MonoReflectionType *
1259 type_from_name (const char *str, MonoBoolean ignoreCase)
1261 MonoType *type = NULL;
1262 MonoAssembly *assembly = NULL;
1263 MonoTypeNameParse info;
1264 char *temp_str = g_strdup (str);
1265 gboolean type_resolve = FALSE;
1267 MONO_ARCH_SAVE_REGS;
1269 /* mono_reflection_parse_type() mangles the string */
1270 if (!mono_reflection_parse_type (temp_str, &info)) {
1271 mono_reflection_free_type_info (&info);
1276 if (info.assembly.name) {
1277 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1279 MonoMethod *m = mono_method_get_last_managed ();
1280 MonoMethod *dest = m;
1282 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1287 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1288 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1289 * to crash. This only seems to happen in some strange remoting
1290 * scenarios and I was unable to figure out what's happening there.
1291 * Dec 10, 2005 - Martin.
1295 assembly = dest->klass->image->assembly;
1296 type_resolve = TRUE;
1298 g_warning (G_STRLOC);
1303 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1304 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1307 if (!info.assembly.name && !type) /* try mscorlib */
1308 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1310 if (assembly && !type && type_resolve) {
1311 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1312 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1315 mono_reflection_free_type_info (&info);
1321 return mono_type_get_object (mono_domain_get (), type);
1325 MonoReflectionType *
1326 mono_type_get (const char *str)
1328 char *copy = g_strdup (str);
1329 MonoReflectionType *type = type_from_name (copy, FALSE);
1336 ICALL_EXPORT MonoReflectionType*
1337 ves_icall_type_from_name (MonoString *name,
1338 MonoBoolean throwOnError,
1339 MonoBoolean ignoreCase)
1341 char *str = mono_string_to_utf8 (name);
1342 MonoReflectionType *type;
1344 type = type_from_name (str, ignoreCase);
1347 MonoException *e = NULL;
1350 e = mono_get_exception_type_load (name, NULL);
1352 mono_loader_clear_error ();
1354 mono_raise_exception (e);
1361 ICALL_EXPORT MonoReflectionType*
1362 ves_icall_type_from_handle (MonoType *handle)
1364 MonoDomain *domain = mono_domain_get ();
1366 MONO_ARCH_SAVE_REGS;
1368 return mono_type_get_object (domain, handle);
1371 ICALL_EXPORT MonoBoolean
1372 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1374 MONO_ARCH_SAVE_REGS;
1376 if (c && type->type && c->type)
1377 return mono_metadata_type_equal (type->type, c->type);
1379 return (type == c) ? TRUE : FALSE;
1382 /* System.TypeCode */
1401 TYPECODE_STRING = 18
1404 ICALL_EXPORT guint32
1405 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1407 int t = type->type->type;
1409 MONO_ARCH_SAVE_REGS;
1411 if (type->type->byref)
1412 return TYPECODE_OBJECT;
1416 case MONO_TYPE_VOID:
1417 return TYPECODE_OBJECT;
1418 case MONO_TYPE_BOOLEAN:
1419 return TYPECODE_BOOLEAN;
1421 return TYPECODE_BYTE;
1423 return TYPECODE_SBYTE;
1425 return TYPECODE_UINT16;
1427 return TYPECODE_INT16;
1428 case MONO_TYPE_CHAR:
1429 return TYPECODE_CHAR;
1433 return TYPECODE_OBJECT;
1435 return TYPECODE_UINT32;
1437 return TYPECODE_INT32;
1439 return TYPECODE_UINT64;
1441 return TYPECODE_INT64;
1443 return TYPECODE_SINGLE;
1445 return TYPECODE_DOUBLE;
1446 case MONO_TYPE_VALUETYPE: {
1447 MonoClass *klass = type->type->data.klass;
1449 if (klass->enumtype) {
1450 t = mono_class_enum_basetype (klass)->type;
1452 } else if (mono_is_corlib_image (klass->image)) {
1453 if (strcmp (klass->name_space, "System") == 0) {
1454 if (strcmp (klass->name, "Decimal") == 0)
1455 return TYPECODE_DECIMAL;
1456 else if (strcmp (klass->name, "DateTime") == 0)
1457 return TYPECODE_DATETIME;
1460 return TYPECODE_OBJECT;
1462 case MONO_TYPE_STRING:
1463 return TYPECODE_STRING;
1464 case MONO_TYPE_SZARRAY:
1465 case MONO_TYPE_ARRAY:
1466 case MONO_TYPE_OBJECT:
1468 case MONO_TYPE_MVAR:
1469 case MONO_TYPE_TYPEDBYREF:
1470 return TYPECODE_OBJECT;
1471 case MONO_TYPE_CLASS:
1473 MonoClass *klass = type->type->data.klass;
1474 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1475 if (strcmp (klass->name, "DBNull") == 0)
1476 return TYPECODE_DBNULL;
1479 return TYPECODE_OBJECT;
1480 case MONO_TYPE_GENERICINST:
1481 return TYPECODE_OBJECT;
1483 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1488 ICALL_EXPORT guint32
1489 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1495 MONO_ARCH_SAVE_REGS;
1497 g_assert (type != NULL);
1499 domain = ((MonoObject *)type)->vtable->domain;
1501 if (!c) /* FIXME: dont know what do do here */
1504 klass = mono_class_from_mono_type (type->type);
1505 klassc = mono_class_from_mono_type (c->type);
1507 /* Interface check requires a more complex setup so we
1508 * only do for them. Otherwise we simply avoid mono_class_init.
1510 if (check_interfaces) {
1511 mono_class_init_or_throw (klass);
1512 mono_class_init_or_throw (klassc);
1513 } else if (!klass->supertypes || !klassc->supertypes) {
1514 mono_class_setup_supertypes (klass);
1515 mono_class_setup_supertypes (klassc);
1518 if (type->type->byref)
1519 return klassc == mono_defaults.object_class;
1521 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1525 mono_type_is_primitive (MonoType *type)
1527 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1528 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1532 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1534 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1535 return mono_class_enum_basetype (type->data.klass);
1536 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1537 return mono_class_enum_basetype (type->data.generic_class->container_class);
1541 ICALL_EXPORT guint32
1542 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1548 MONO_ARCH_SAVE_REGS;
1550 g_assert (type != NULL);
1552 domain = ((MonoObject *)type)->vtable->domain;
1554 klass = mono_class_from_mono_type (type->type);
1555 klassc = mono_class_from_mono_type (c->type);
1557 mono_class_init_or_throw (klass);
1558 mono_class_init_or_throw (klassc);
1560 if (type->type->byref ^ c->type->byref)
1563 if (type->type->byref) {
1564 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1565 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1567 klass = mono_class_from_mono_type (t);
1568 klassc = mono_class_from_mono_type (ot);
1570 if (mono_type_is_primitive (t)) {
1571 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1572 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1573 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1574 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1575 return t->type == ot->type;
1577 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1580 if (klass->valuetype)
1581 return klass == klassc;
1582 return klass->valuetype == klassc->valuetype;
1585 return mono_class_is_assignable_from (klass, klassc);
1588 ICALL_EXPORT guint32
1589 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1591 MonoClass *klass = mono_class_from_mono_type (type->type);
1592 mono_class_init_or_throw (klass);
1593 return mono_object_isinst (obj, klass) != NULL;
1596 ICALL_EXPORT guint32
1597 ves_icall_get_attributes (MonoReflectionType *type)
1599 MonoClass *klass = mono_class_from_mono_type (type->type);
1600 return klass->flags;
1603 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1604 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1606 MonoClass *klass = field->field->parent;
1607 MonoMarshalType *info;
1610 if (klass->generic_container ||
1611 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1614 info = mono_marshal_load_type_info (klass);
1616 for (i = 0; i < info->num_fields; ++i) {
1617 if (info->fields [i].field == field->field) {
1618 if (!info->fields [i].mspec)
1621 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1628 ICALL_EXPORT MonoReflectionField*
1629 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1631 gboolean found = FALSE;
1638 klass = handle->parent;
1640 klass = mono_class_from_mono_type (type);
1642 /* Check that the field belongs to the class */
1643 for (k = klass; k; k = k->parent) {
1644 if (k == handle->parent) {
1651 /* The managed code will throw the exception */
1655 return mono_field_get_object (mono_domain_get (), klass, handle);
1658 ICALL_EXPORT MonoArray*
1659 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1662 MonoType *type = mono_field_get_type_checked (field->field, &error);
1663 if (!mono_error_ok (&error))
1664 mono_error_raise_exception (&error);
1666 return type_array_from_modifiers (field->field->parent->image, type, optional);
1670 vell_icall_get_method_attributes (MonoMethod *method)
1672 return method->flags;
1676 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1679 MonoDomain *domain = mono_domain_get ();
1680 MonoMethodSignature* sig;
1681 MONO_ARCH_SAVE_REGS;
1683 sig = mono_method_signature_checked (method, &error);
1684 if (!mono_error_ok (&error))
1685 mono_error_raise_exception (&error);
1688 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1689 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1690 info->attrs = method->flags;
1691 info->implattrs = method->iflags;
1692 if (sig->call_convention == MONO_CALL_DEFAULT)
1693 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1695 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1700 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1703 ICALL_EXPORT MonoArray*
1704 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1706 MonoDomain *domain = mono_domain_get ();
1708 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1711 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1712 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1714 MonoDomain *domain = mono_domain_get ();
1715 MonoReflectionMarshalAsAttribute* res = NULL;
1716 MonoMarshalSpec **mspecs;
1719 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1720 mono_method_get_marshal_info (method, mspecs);
1723 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1725 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1727 mono_metadata_free_marshal_spec (mspecs [i]);
1734 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1736 MonoClass *parent = field->field->parent;
1737 if (!parent->size_inited)
1738 mono_class_init (parent);
1740 return field->field->offset - sizeof (MonoObject);
1743 ICALL_EXPORT MonoReflectionType*
1744 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1747 MONO_ARCH_SAVE_REGS;
1749 parent = declaring? field->field->parent: field->klass;
1751 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1754 ICALL_EXPORT MonoObject *
1755 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1757 MonoClass *fklass = field->klass;
1758 MonoClassField *cf = field->field;
1759 MonoDomain *domain = mono_object_domain (field);
1761 if (fklass->image->assembly->ref_only)
1762 mono_raise_exception (mono_get_exception_invalid_operation (
1763 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1765 if (mono_security_core_clr_enabled ())
1766 mono_security_core_clr_ensure_reflection_access_field (cf);
1768 return mono_field_get_value_object (domain, cf, obj);
1772 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1775 MonoClassField *cf = field->field;
1779 MONO_ARCH_SAVE_REGS;
1781 if (field->klass->image->assembly->ref_only)
1782 mono_raise_exception (mono_get_exception_invalid_operation (
1783 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1785 if (mono_security_core_clr_enabled ())
1786 mono_security_core_clr_ensure_reflection_access_field (cf);
1788 type = mono_field_get_type_checked (cf, &error);
1789 if (!mono_error_ok (&error))
1790 mono_error_raise_exception (&error);
1792 v = (gchar *) value;
1794 switch (type->type) {
1797 case MONO_TYPE_BOOLEAN:
1800 case MONO_TYPE_CHAR:
1809 case MONO_TYPE_VALUETYPE:
1812 v += sizeof (MonoObject);
1814 case MONO_TYPE_STRING:
1815 case MONO_TYPE_OBJECT:
1816 case MONO_TYPE_CLASS:
1817 case MONO_TYPE_ARRAY:
1818 case MONO_TYPE_SZARRAY:
1821 case MONO_TYPE_GENERICINST: {
1822 MonoGenericClass *gclass = type->data.generic_class;
1823 g_assert (!gclass->context.class_inst->is_open);
1825 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1826 MonoClass *nklass = mono_class_from_mono_type (type);
1827 MonoObject *nullable;
1830 * Convert the boxed vtype into a Nullable structure.
1831 * This is complicated by the fact that Nullables have
1832 * a variable structure.
1834 nullable = mono_object_new (mono_domain_get (), nklass);
1836 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1838 v = mono_object_unbox (nullable);
1841 if (gclass->container_class->valuetype && (v != NULL))
1842 v += sizeof (MonoObject);
1846 g_error ("type 0x%x not handled in "
1847 "ves_icall_FieldInfo_SetValueInternal", type->type);
1852 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1853 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1854 if (!vtable->initialized)
1855 mono_runtime_class_init (vtable);
1856 mono_field_static_set_value (vtable, cf, v);
1858 mono_field_set_value (obj, cf, v);
1862 ICALL_EXPORT MonoObject *
1863 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1865 MonoObject *o = NULL;
1866 MonoClassField *field = this->field;
1868 MonoDomain *domain = mono_object_domain (this);
1870 MonoTypeEnum def_type;
1871 const char *def_value;
1875 MONO_ARCH_SAVE_REGS;
1877 mono_class_init (field->parent);
1879 t = mono_field_get_type_checked (field, &error);
1880 if (!mono_error_ok (&error))
1881 mono_error_raise_exception (&error);
1883 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1884 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1886 if (field->parent->image->dynamic) {
1888 g_assert_not_reached ();
1891 def_value = mono_class_get_field_default_value (field, &def_type);
1892 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1893 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1895 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1899 case MONO_TYPE_BOOLEAN:
1902 case MONO_TYPE_CHAR:
1910 case MONO_TYPE_R8: {
1913 /* boxed value type */
1914 t = g_new0 (MonoType, 1);
1916 klass = mono_class_from_mono_type (t);
1918 o = mono_object_new (domain, klass);
1919 v = ((gchar *) o) + sizeof (MonoObject);
1920 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1923 case MONO_TYPE_STRING:
1924 case MONO_TYPE_CLASS:
1925 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1928 g_assert_not_reached ();
1934 ICALL_EXPORT MonoReflectionType*
1935 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1938 MonoClassField *field = ref_field->field;
1939 MonoType *type = mono_field_get_type_checked (field, &error);
1940 if (!mono_error_ok (&error))
1941 mono_error_raise_exception (&error);
1942 return mono_type_get_object (mono_object_domain (ref_field), type);
1945 ICALL_EXPORT MonoReflectionType*
1946 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1948 MonoMethod *method = rmethod->method.method;
1950 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1953 /* From MonoProperty.cs */
1955 PInfo_Attributes = 1,
1956 PInfo_GetMethod = 1 << 1,
1957 PInfo_SetMethod = 1 << 2,
1958 PInfo_ReflectedType = 1 << 3,
1959 PInfo_DeclaringType = 1 << 4,
1964 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1966 MonoDomain *domain = mono_object_domain (property);
1968 MONO_ARCH_SAVE_REGS;
1970 if ((req_info & PInfo_ReflectedType) != 0)
1971 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1972 if ((req_info & PInfo_DeclaringType) != 0)
1973 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1975 if ((req_info & PInfo_Name) != 0)
1976 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1978 if ((req_info & PInfo_Attributes) != 0)
1979 info->attrs = property->property->attrs;
1981 if ((req_info & PInfo_GetMethod) != 0)
1982 MONO_STRUCT_SETREF (info, get, property->property->get ?
1983 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1985 if ((req_info & PInfo_SetMethod) != 0)
1986 MONO_STRUCT_SETREF (info, set, property->property->set ?
1987 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1989 * There may be other methods defined for properties, though, it seems they are not exposed
1990 * in the reflection API
1995 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1997 MonoDomain *domain = mono_object_domain (event);
1999 MONO_ARCH_SAVE_REGS;
2001 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2002 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2004 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2005 info->attrs = event->event->attrs;
2006 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2007 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2008 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2010 #ifndef MONO_SMALL_CONFIG
2011 if (event->event->other) {
2013 while (event->event->other [n])
2015 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2017 for (i = 0; i < n; i++)
2018 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2024 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2029 mono_class_setup_interfaces (klass, error);
2030 if (!mono_error_ok (error))
2033 for (i = 0; i < klass->interface_count; i++) {
2034 ic = klass->interfaces [i];
2035 g_hash_table_insert (ifaces, ic, ic);
2037 collect_interfaces (ic, ifaces, error);
2038 if (!mono_error_ok (error))
2044 MonoArray *iface_array;
2045 MonoGenericContext *context;
2049 } FillIfaceArrayData;
2052 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2054 FillIfaceArrayData *data = user_data;
2055 MonoClass *ic = key;
2056 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2058 if (!mono_error_ok (data->error))
2061 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2062 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2063 if (!mono_error_ok (data->error))
2067 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2070 mono_metadata_free_type (inflated);
2073 ICALL_EXPORT MonoArray*
2074 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2077 MonoClass *class = mono_class_from_mono_type (type->type);
2079 FillIfaceArrayData data = { 0 };
2082 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2084 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2085 data.context = mono_class_get_context (class);
2086 class = class->generic_class->container_class;
2089 for (parent = class; parent; parent = parent->parent) {
2090 mono_class_setup_interfaces (parent, &error);
2091 if (!mono_error_ok (&error))
2093 collect_interfaces (parent, iface_hash, &error);
2094 if (!mono_error_ok (&error))
2098 data.error = &error;
2099 data.domain = mono_object_domain (type);
2101 len = g_hash_table_size (iface_hash);
2103 g_hash_table_destroy (iface_hash);
2104 if (!data.domain->empty_types)
2105 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2106 return data.domain->empty_types;
2109 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2110 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2111 if (!mono_error_ok (&error))
2114 g_hash_table_destroy (iface_hash);
2115 return data.iface_array;
2118 g_hash_table_destroy (iface_hash);
2119 mono_error_raise_exception (&error);
2124 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2126 gboolean variance_used;
2127 MonoClass *class = mono_class_from_mono_type (type->type);
2128 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2129 MonoReflectionMethod *member;
2132 int i = 0, len, ioffset;
2135 MONO_ARCH_SAVE_REGS;
2136 mono_class_init_or_throw (class);
2137 mono_class_init_or_throw (iclass);
2139 mono_class_setup_vtable (class);
2141 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2145 len = mono_class_num_methods (iclass);
2146 domain = mono_object_domain (type);
2147 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2148 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2150 while ((method = mono_class_get_methods (iclass, &iter))) {
2151 member = mono_method_get_object (domain, method, iclass);
2152 mono_array_setref (*methods, i, member);
2153 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2154 mono_array_setref (*targets, i, member);
2161 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2163 MonoClass *klass = mono_class_from_mono_type (type->type);
2164 mono_class_init_or_throw (klass);
2166 if (klass->image->dynamic) {
2167 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2168 *packing = tb->packing_size;
2169 *size = tb->class_size;
2171 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2175 ICALL_EXPORT MonoReflectionType*
2176 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2180 MONO_ARCH_SAVE_REGS;
2182 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2183 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2185 class = mono_class_from_mono_type (type->type);
2186 mono_class_init_or_throw (class);
2188 // GetElementType should only return a type for:
2189 // Array Pointer PassedByRef
2190 if (type->type->byref)
2191 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2192 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2193 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2194 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2195 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2200 ICALL_EXPORT MonoReflectionType*
2201 ves_icall_get_type_parent (MonoReflectionType *type)
2203 MonoClass *class = mono_class_from_mono_type (type->type);
2204 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2207 ICALL_EXPORT MonoBoolean
2208 ves_icall_type_ispointer (MonoReflectionType *type)
2210 MONO_ARCH_SAVE_REGS;
2212 return type->type->type == MONO_TYPE_PTR;
2215 ICALL_EXPORT MonoBoolean
2216 ves_icall_type_isprimitive (MonoReflectionType *type)
2218 MONO_ARCH_SAVE_REGS;
2220 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)));
2223 ICALL_EXPORT MonoBoolean
2224 ves_icall_type_isbyref (MonoReflectionType *type)
2226 MONO_ARCH_SAVE_REGS;
2228 return type->type->byref;
2231 ICALL_EXPORT MonoBoolean
2232 ves_icall_type_iscomobject (MonoReflectionType *type)
2234 MonoClass *klass = mono_class_from_mono_type (type->type);
2235 mono_class_init_or_throw (klass);
2237 return mono_class_is_com_object (klass);
2240 ICALL_EXPORT MonoReflectionModule*
2241 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2243 MonoClass *class = mono_class_from_mono_type (type->type);
2244 return mono_module_get_object (mono_object_domain (type), class->image);
2247 ICALL_EXPORT MonoReflectionAssembly*
2248 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2250 MonoDomain *domain = mono_domain_get ();
2251 MonoClass *class = mono_class_from_mono_type (type->type);
2252 return mono_assembly_get_object (domain, class->image->assembly);
2255 ICALL_EXPORT MonoReflectionType*
2256 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2258 MonoDomain *domain = mono_domain_get ();
2261 MONO_ARCH_SAVE_REGS;
2263 if (type->type->byref)
2265 if (type->type->type == MONO_TYPE_VAR)
2266 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2267 else if (type->type->type == MONO_TYPE_MVAR)
2268 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2270 class = mono_class_from_mono_type (type->type)->nested_in;
2272 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2275 ICALL_EXPORT MonoString*
2276 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2278 MonoDomain *domain = mono_domain_get ();
2279 MonoClass *class = mono_class_from_mono_type (type->type);
2281 if (type->type->byref) {
2282 char *n = g_strdup_printf ("%s&", class->name);
2283 MonoString *res = mono_string_new (domain, n);
2289 return mono_string_new (domain, class->name);
2293 ICALL_EXPORT MonoString*
2294 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2296 MonoDomain *domain = mono_domain_get ();
2297 MonoClass *class = mono_class_from_mono_type (type->type);
2299 while (class->nested_in)
2300 class = class->nested_in;
2302 if (class->name_space [0] == '\0')
2305 return mono_string_new (domain, class->name_space);
2309 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2313 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2314 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2316 class = mono_class_from_mono_type (type->type);
2321 ICALL_EXPORT MonoArray*
2322 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2325 MonoClass *klass, *pklass;
2326 MonoDomain *domain = mono_object_domain (type);
2327 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2329 MONO_ARCH_SAVE_REGS;
2331 klass = mono_class_from_mono_type (type->type);
2333 if (klass->generic_container) {
2334 MonoGenericContainer *container = klass->generic_container;
2335 res = mono_array_new_specific (array_vtable, container->type_argc);
2336 for (i = 0; i < container->type_argc; ++i) {
2337 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2338 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2340 } else if (klass->generic_class) {
2341 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2342 res = mono_array_new_specific (array_vtable, inst->type_argc);
2343 for (i = 0; i < inst->type_argc; ++i)
2344 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2346 res = mono_array_new_specific (array_vtable, 0);
2351 ICALL_EXPORT gboolean
2352 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2355 MONO_ARCH_SAVE_REGS;
2357 if (!IS_MONOTYPE (type))
2360 if (type->type->byref)
2363 klass = mono_class_from_mono_type (type->type);
2364 return klass->generic_container != NULL;
2367 ICALL_EXPORT MonoReflectionType*
2368 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2371 MONO_ARCH_SAVE_REGS;
2373 if (type->type->byref)
2376 klass = mono_class_from_mono_type (type->type);
2378 if (klass->generic_container) {
2379 return type; /* check this one */
2381 if (klass->generic_class) {
2382 MonoClass *generic_class = klass->generic_class->container_class;
2385 tb = mono_class_get_ref_info (generic_class);
2387 if (generic_class->wastypebuilder && tb)
2390 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2395 ICALL_EXPORT MonoReflectionType*
2396 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2399 MonoType *geninst, **types;
2402 g_assert (IS_MONOTYPE (type));
2403 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2405 count = mono_array_length (type_array);
2406 types = g_new0 (MonoType *, count);
2408 for (i = 0; i < count; i++) {
2409 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2410 types [i] = t->type;
2413 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2418 class = mono_class_from_mono_type (geninst);
2420 /*we might inflate to the GTD*/
2421 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2422 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2424 return mono_type_get_object (mono_object_domain (type), geninst);
2427 ICALL_EXPORT gboolean
2428 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2431 MONO_ARCH_SAVE_REGS;
2433 if (type->type->byref)
2436 klass = mono_class_from_mono_type (type->type);
2438 return klass->generic_class != NULL;
2441 ICALL_EXPORT gboolean
2442 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2445 MONO_ARCH_SAVE_REGS;
2447 if (!IS_MONOTYPE (type))
2450 if (type->type->byref)
2453 klass = mono_class_from_mono_type (type->type);
2454 return klass->generic_class != NULL || klass->generic_container != NULL;
2458 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2460 MONO_ARCH_SAVE_REGS;
2462 if (!IS_MONOTYPE (type))
2465 if (is_generic_parameter (type->type))
2466 return mono_type_get_generic_param_num (type->type);
2470 ICALL_EXPORT GenericParameterAttributes
2471 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2473 MONO_ARCH_SAVE_REGS;
2475 g_assert (IS_MONOTYPE (type));
2476 g_assert (is_generic_parameter (type->type));
2477 return mono_generic_param_info (type->type->data.generic_param)->flags;
2480 ICALL_EXPORT MonoArray *
2481 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2483 MonoGenericParamInfo *param_info;
2489 MONO_ARCH_SAVE_REGS;
2491 g_assert (IS_MONOTYPE (type));
2493 domain = mono_object_domain (type);
2494 param_info = mono_generic_param_info (type->type->data.generic_param);
2495 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2498 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2499 for (i = 0; i < count; i++)
2500 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2506 ICALL_EXPORT MonoBoolean
2507 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2509 MONO_ARCH_SAVE_REGS;
2510 return is_generic_parameter (type->type);
2513 ICALL_EXPORT MonoBoolean
2514 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2516 MONO_ARCH_SAVE_REGS;
2517 return is_generic_parameter (tb->type.type);
2521 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2522 MonoReflectionType *t)
2524 enumtype->type = t->type;
2527 ICALL_EXPORT MonoReflectionMethod*
2528 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2529 MonoReflectionMethod* generic)
2536 MONO_ARCH_SAVE_REGS;
2538 domain = ((MonoObject *)type)->vtable->domain;
2540 klass = mono_class_from_mono_type (type->type);
2541 mono_class_init_or_throw (klass);
2544 while ((method = mono_class_get_methods (klass, &iter))) {
2545 if (method->token == generic->method->token)
2546 return mono_method_get_object (domain, method, klass);
2554 ICALL_EXPORT MonoReflectionMethod *
2555 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2558 MonoType *type = ref_type->type;
2560 MONO_ARCH_SAVE_REGS;
2562 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2563 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2564 if (type->type == MONO_TYPE_VAR)
2567 method = mono_type_get_generic_param_owner (type)->owner.method;
2569 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2572 ICALL_EXPORT MonoReflectionDllImportAttribute*
2573 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2575 static MonoClass *DllImportAttributeClass = NULL;
2576 MonoDomain *domain = mono_domain_get ();
2577 MonoReflectionDllImportAttribute *attr;
2578 MonoImage *image = method->klass->image;
2579 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2580 MonoTableInfo *tables = image->tables;
2581 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2582 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2583 guint32 im_cols [MONO_IMPLMAP_SIZE];
2584 guint32 scope_token;
2585 const char *import = NULL;
2586 const char *scope = NULL;
2589 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2592 if (!DllImportAttributeClass) {
2593 DllImportAttributeClass =
2594 mono_class_from_name (mono_defaults.corlib,
2595 "System.Runtime.InteropServices", "DllImportAttribute");
2596 g_assert (DllImportAttributeClass);
2599 if (method->klass->image->dynamic) {
2600 MonoReflectionMethodAux *method_aux =
2601 g_hash_table_lookup (
2602 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2604 import = method_aux->dllentry;
2605 scope = method_aux->dll;
2608 if (!import || !scope) {
2609 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2614 if (piinfo->implmap_idx) {
2615 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2617 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2618 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2619 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2620 scope = mono_metadata_string_heap (image, scope_token);
2623 flags = piinfo->piflags;
2625 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2627 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2628 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2629 attr->call_conv = (flags & 0x700) >> 8;
2630 attr->charset = ((flags & 0x6) >> 1) + 1;
2631 if (attr->charset == 1)
2633 attr->exact_spelling = (flags & 0x1) != 0;
2634 attr->set_last_error = (flags & 0x40) != 0;
2635 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2636 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2637 attr->preserve_sig = FALSE;
2642 ICALL_EXPORT MonoReflectionMethod *
2643 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2645 MonoMethodInflated *imethod;
2648 MONO_ARCH_SAVE_REGS;
2650 if (method->method->is_generic)
2653 if (!method->method->is_inflated)
2656 imethod = (MonoMethodInflated *) method->method;
2658 result = imethod->declaring;
2659 /* Not a generic method. */
2660 if (!result->is_generic)
2663 if (method->method->klass->image->dynamic) {
2664 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2665 MonoReflectionMethod *res;
2668 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2669 * the dynamic case as well ?
2671 mono_image_lock ((MonoImage*)image);
2672 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2673 mono_image_unlock ((MonoImage*)image);
2679 if (imethod->context.class_inst) {
2680 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2681 /*Generic methods gets the context of the GTD.*/
2682 if (mono_class_get_context (klass))
2683 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2686 return mono_method_get_object (mono_object_domain (method), result, NULL);
2689 ICALL_EXPORT gboolean
2690 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2692 MONO_ARCH_SAVE_REGS;
2694 return mono_method_signature (method->method)->generic_param_count != 0;
2697 ICALL_EXPORT gboolean
2698 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2700 MONO_ARCH_SAVE_REGS;
2702 return method->method->is_generic;
2705 ICALL_EXPORT MonoArray*
2706 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2711 MONO_ARCH_SAVE_REGS;
2713 domain = mono_object_domain (method);
2715 if (method->method->is_inflated) {
2716 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2719 count = inst->type_argc;
2720 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2722 for (i = 0; i < count; i++)
2723 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2729 count = mono_method_signature (method->method)->generic_param_count;
2730 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2732 for (i = 0; i < count; i++) {
2733 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2734 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2735 MonoClass *pklass = mono_class_from_generic_parameter (
2736 param, method->method->klass->image, TRUE);
2737 mono_array_setref (res, i,
2738 mono_type_get_object (domain, &pklass->byval_arg));
2744 ICALL_EXPORT MonoObject *
2745 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2748 * Invoke from reflection is supposed to always be a virtual call (the API
2749 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2750 * greater flexibility.
2752 MonoMethod *m = method->method;
2753 MonoMethodSignature *sig = mono_method_signature (m);
2758 MONO_ARCH_SAVE_REGS;
2762 if (mono_security_core_clr_enabled ())
2763 mono_security_core_clr_ensure_reflection_access_method (m);
2765 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2766 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2767 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2772 if (!mono_object_isinst (this, m->klass)) {
2773 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2774 char *target_name = mono_type_get_full_name (m->klass);
2775 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2776 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2778 g_free (target_name);
2782 m = mono_object_get_virtual_method (this, m);
2783 /* must pass the pointer to the value for valuetype methods */
2784 if (m->klass->valuetype)
2785 obj = mono_object_unbox (this);
2786 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2787 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2792 if (sig->ret->byref) {
2793 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"));
2797 pcount = params? mono_array_length (params): 0;
2798 if (pcount != sig->param_count) {
2799 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2803 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2804 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."));
2808 image = m->klass->image;
2809 if (image->assembly->ref_only) {
2810 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."));
2814 if (image->dynamic && !((MonoDynamicImage*)image)->run) {
2815 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2819 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2822 intptr_t *lower_bounds;
2823 pcount = mono_array_length (params);
2824 lengths = alloca (sizeof (uintptr_t) * pcount);
2825 /* Note: the synthetized array .ctors have int32 as argument type */
2826 for (i = 0; i < pcount; ++i)
2827 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2829 if (m->klass->rank == pcount) {
2830 /* Only lengths provided. */
2831 lower_bounds = NULL;
2833 g_assert (pcount == (m->klass->rank * 2));
2834 /* lower bounds are first. */
2835 lower_bounds = (intptr_t*)lengths;
2836 lengths += m->klass->rank;
2839 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2841 return mono_runtime_invoke_array (m, obj, params, NULL);
2844 #ifndef DISABLE_REMOTING
2845 ICALL_EXPORT MonoObject *
2846 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2848 MonoDomain *domain = mono_object_domain (method);
2849 MonoMethod *m = method->method;
2850 MonoMethodSignature *sig = mono_method_signature (m);
2851 MonoArray *out_args;
2853 int i, j, outarg_count = 0;
2855 MONO_ARCH_SAVE_REGS;
2857 if (m->klass == mono_defaults.object_class) {
2859 if (!strcmp (m->name, "FieldGetter")) {
2860 MonoClass *k = this->vtable->klass;
2864 /* If this is a proxy, then it must be a CBO */
2865 if (k == mono_defaults.transparent_proxy_class) {
2866 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2867 this = tp->rp->unwrapped_server;
2869 k = this->vtable->klass;
2872 name = mono_array_get (params, MonoString *, 1);
2873 str = mono_string_to_utf8 (name);
2876 MonoClassField* field = mono_class_get_field_from_name (k, str);
2878 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2879 if (field_klass->valuetype)
2880 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2882 result = *((gpointer *)((char *)this + field->offset));
2884 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2885 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2886 mono_array_setref (out_args, 0, result);
2894 g_assert_not_reached ();
2896 } else if (!strcmp (m->name, "FieldSetter")) {
2897 MonoClass *k = this->vtable->klass;
2903 /* If this is a proxy, then it must be a CBO */
2904 if (k == mono_defaults.transparent_proxy_class) {
2905 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2906 this = tp->rp->unwrapped_server;
2908 k = this->vtable->klass;
2911 name = mono_array_get (params, MonoString *, 1);
2912 str = mono_string_to_utf8 (name);
2915 MonoClassField* field = mono_class_get_field_from_name (k, str);
2917 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2918 MonoObject *val = mono_array_get (params, gpointer, 2);
2920 if (field_klass->valuetype) {
2921 size = mono_type_size (field->type, &align);
2922 g_assert (size == mono_class_value_size (field_klass, NULL));
2923 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2925 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2928 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2929 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2939 g_assert_not_reached ();
2944 for (i = 0; i < mono_array_length (params); i++) {
2945 if (sig->params [i]->byref)
2949 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2951 /* handle constructors only for objects already allocated */
2952 if (!strcmp (method->method->name, ".ctor"))
2955 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2956 g_assert (!method->method->klass->valuetype);
2957 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2959 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2960 if (sig->params [i]->byref) {
2962 arg = mono_array_get (params, gpointer, i);
2963 mono_array_setref (out_args, j, arg);
2968 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2975 read_enum_value (char *mem, int type)
2979 return *(guint8*)mem;
2981 return *(gint8*)mem;
2983 return *(guint16*)mem;
2985 return *(gint16*)mem;
2987 return *(guint32*)mem;
2989 return *(gint32*)mem;
2991 return *(guint64*)mem;
2993 return *(gint64*)mem;
2995 g_assert_not_reached ();
3001 write_enum_value (char *mem, int type, guint64 value)
3005 case MONO_TYPE_I1: {
3006 guint8 *p = (guint8*)mem;
3011 case MONO_TYPE_I2: {
3012 guint16 *p = (void*)mem;
3017 case MONO_TYPE_I4: {
3018 guint32 *p = (void*)mem;
3023 case MONO_TYPE_I8: {
3024 guint64 *p = (void*)mem;
3029 g_assert_not_reached ();
3034 ICALL_EXPORT MonoObject *
3035 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3038 MonoClass *enumc, *objc;
3043 MONO_ARCH_SAVE_REGS;
3045 MONO_CHECK_ARG_NULL (enumType);
3046 MONO_CHECK_ARG_NULL (value);
3048 domain = mono_object_domain (enumType);
3049 enumc = mono_class_from_mono_type (enumType->type);
3051 mono_class_init_or_throw (enumc);
3053 objc = value->vtable->klass;
3055 if (!enumc->enumtype)
3056 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3057 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3058 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."));
3060 etype = mono_class_enum_basetype (enumc);
3062 /* MS throws this for typebuilders */
3063 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3065 res = mono_object_new (domain, enumc);
3066 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3067 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3072 ICALL_EXPORT MonoObject *
3073 ves_icall_System_Enum_get_value (MonoObject *this)
3081 MONO_ARCH_SAVE_REGS;
3086 g_assert (this->vtable->klass->enumtype);
3088 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3089 res = mono_object_new (mono_object_domain (this), enumc);
3090 dst = (char *)res + sizeof (MonoObject);
3091 src = (char *)this + sizeof (MonoObject);
3092 size = mono_class_value_size (enumc, NULL);
3094 memcpy (dst, src, size);
3099 ICALL_EXPORT MonoReflectionType *
3100 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3105 MONO_ARCH_SAVE_REGS;
3107 klass = mono_class_from_mono_type (type->type);
3108 mono_class_init_or_throw (klass);
3110 etype = mono_class_enum_basetype (klass);
3112 /* MS throws this for typebuilders */
3113 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3115 return mono_type_get_object (mono_object_domain (type), etype);
3119 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3121 gpointer tdata = (char *)this + sizeof (MonoObject);
3122 gpointer odata = (char *)other + sizeof (MonoObject);
3123 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3124 g_assert (basetype);
3126 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3127 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3128 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3131 return me > other ? 1 : -1; \
3134 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3135 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3136 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3139 return me - other; \
3142 switch (basetype->type) {
3144 COMPARE_ENUM_VALUES (guint8);
3146 COMPARE_ENUM_VALUES (gint8);
3147 case MONO_TYPE_CHAR:
3149 COMPARE_ENUM_VALUES_RANGE (guint16);
3151 COMPARE_ENUM_VALUES (gint16);
3153 COMPARE_ENUM_VALUES (guint32);
3155 COMPARE_ENUM_VALUES (gint32);
3157 COMPARE_ENUM_VALUES (guint64);
3159 COMPARE_ENUM_VALUES (gint64);
3161 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3163 #undef COMPARE_ENUM_VALUES_RANGE
3164 #undef COMPARE_ENUM_VALUES
3169 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3171 gpointer data = (char *)this + sizeof (MonoObject);
3172 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3173 g_assert (basetype);
3175 switch (basetype->type) {
3177 return *((gint8*)data);
3179 return *((guint8*)data);
3180 case MONO_TYPE_CHAR:
3182 return *((guint16*)data);
3185 return *((gint16*)data);
3187 return *((guint32*)data);
3189 return *((gint32*)data);
3191 case MONO_TYPE_I8: {
3192 gint64 value = *((gint64*)data);
3193 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3196 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3202 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3204 MonoDomain *domain = mono_object_domain (type);
3205 MonoClass *enumc = mono_class_from_mono_type (type->type);
3206 guint j = 0, nvalues, crow;
3208 MonoClassField *field;
3210 MONO_ARCH_SAVE_REGS;
3212 mono_class_init_or_throw (enumc);
3214 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3215 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3216 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3217 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3221 while ((field = mono_class_get_fields (enumc, &iter))) {
3224 MonoTypeEnum def_type;
3226 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3228 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3230 if (mono_field_is_deleted (field))
3232 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3234 p = mono_class_get_field_default_value (field, &def_type);
3235 len = mono_metadata_decode_blob_size (p, &p);
3236 switch (mono_class_enum_basetype (enumc)->type) {
3239 mono_array_set (info->values, gchar, j, *p);
3241 case MONO_TYPE_CHAR:
3244 mono_array_set (info->values, gint16, j, read16 (p));
3248 mono_array_set (info->values, gint32, j, read32 (p));
3252 mono_array_set (info->values, gint64, j, read64 (p));
3255 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3262 BFLAGS_IgnoreCase = 1,
3263 BFLAGS_DeclaredOnly = 2,
3264 BFLAGS_Instance = 4,
3266 BFLAGS_Public = 0x10,
3267 BFLAGS_NonPublic = 0x20,
3268 BFLAGS_FlattenHierarchy = 0x40,
3269 BFLAGS_InvokeMethod = 0x100,
3270 BFLAGS_CreateInstance = 0x200,
3271 BFLAGS_GetField = 0x400,
3272 BFLAGS_SetField = 0x800,
3273 BFLAGS_GetProperty = 0x1000,
3274 BFLAGS_SetProperty = 0x2000,
3275 BFLAGS_ExactBinding = 0x10000,
3276 BFLAGS_SuppressChangeType = 0x20000,
3277 BFLAGS_OptionalParamBinding = 0x40000
3280 ICALL_EXPORT MonoReflectionField *
3281 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3284 MonoClass *startklass, *klass;
3286 MonoClassField *field;
3289 int (*compare_func) (const char *s1, const char *s2) = NULL;
3290 domain = ((MonoObject *)type)->vtable->domain;
3291 klass = startklass = mono_class_from_mono_type (type->type);
3294 mono_raise_exception (mono_get_exception_argument_null ("name"));
3295 if (type->type->byref)
3298 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3301 if (klass->exception_type != MONO_EXCEPTION_NONE)
3302 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3305 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3306 guint32 flags = mono_field_get_flags (field);
3309 if (mono_field_is_deleted_with_flags (field, flags))
3311 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3312 if (bflags & BFLAGS_Public)
3314 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3315 if (bflags & BFLAGS_NonPublic) {
3322 if (flags & FIELD_ATTRIBUTE_STATIC) {
3323 if (bflags & BFLAGS_Static)
3324 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3327 if (bflags & BFLAGS_Instance)
3334 utf8_name = mono_string_to_utf8 (name);
3336 if (compare_func (mono_field_get_name (field), utf8_name)) {
3342 return mono_field_get_object (domain, klass, field);
3344 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3350 ICALL_EXPORT MonoArray*
3351 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3354 MonoClass *startklass, *klass, *refklass;
3359 MonoClassField *field;
3360 MonoPtrArray tmp_array;
3362 MONO_ARCH_SAVE_REGS;
3364 domain = ((MonoObject *)type)->vtable->domain;
3365 if (type->type->byref)
3366 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3367 klass = startklass = mono_class_from_mono_type (type->type);
3368 refklass = mono_class_from_mono_type (reftype->type);
3370 mono_ptr_array_init (tmp_array, 2);
3373 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3374 mono_ptr_array_destroy (tmp_array);
3375 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3379 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3380 guint32 flags = mono_field_get_flags (field);
3382 if (mono_field_is_deleted_with_flags (field, flags))
3384 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3385 if (bflags & BFLAGS_Public)
3387 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3388 if (bflags & BFLAGS_NonPublic) {
3395 if (flags & FIELD_ATTRIBUTE_STATIC) {
3396 if (bflags & BFLAGS_Static)
3397 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3400 if (bflags & BFLAGS_Instance)
3406 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3407 mono_ptr_array_append (tmp_array, member);
3409 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3412 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3414 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3415 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3417 mono_ptr_array_destroy (tmp_array);
3423 method_nonpublic (MonoMethod* method, gboolean start_klass)
3425 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3426 case METHOD_ATTRIBUTE_ASSEM:
3427 return (start_klass || mono_defaults.generic_ilist_class);
3428 case METHOD_ATTRIBUTE_PRIVATE:
3430 case METHOD_ATTRIBUTE_PUBLIC:
3438 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3441 MonoClass *startklass;
3444 int len, match, nslots;
3445 /*FIXME, use MonoBitSet*/
3446 guint32 method_slots_default [8];
3447 guint32 *method_slots = NULL;
3448 int (*compare_func) (const char *s1, const char *s2) = NULL;
3450 array = g_ptr_array_new ();
3456 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3458 /* An optimization for calls made from Delegate:CreateDelegate () */
3459 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3460 method = mono_get_delegate_invoke (klass);
3461 if (mono_loader_get_last_error ())
3464 g_ptr_array_add (array, method);
3468 mono_class_setup_vtable (klass);
3469 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3472 if (is_generic_parameter (&klass->byval_arg))
3473 nslots = mono_class_get_vtable_size (klass->parent);
3475 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3476 if (nslots >= sizeof (method_slots_default) * 8) {
3477 method_slots = g_new0 (guint32, nslots / 32 + 1);
3479 method_slots = method_slots_default;
3480 memset (method_slots, 0, sizeof (method_slots_default));
3483 mono_class_setup_vtable (klass);
3484 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3488 while ((method = mono_class_get_methods (klass, &iter))) {
3490 if (method->slot != -1) {
3491 g_assert (method->slot < nslots);
3492 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3494 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3495 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3498 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3500 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3501 if (bflags & BFLAGS_Public)
3503 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3509 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3510 if (bflags & BFLAGS_Static)
3511 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3514 if (bflags & BFLAGS_Instance)
3522 if (compare_func (name, method->name))
3527 g_ptr_array_add (array, method);
3529 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3531 if (method_slots != method_slots_default)
3532 g_free (method_slots);
3537 if (method_slots != method_slots_default)
3538 g_free (method_slots);
3539 g_ptr_array_free (array, TRUE);
3541 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3542 *ex = mono_class_get_exception_for_failure (klass);
3544 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3545 mono_loader_clear_error ();
3550 ICALL_EXPORT MonoArray*
3551 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3553 static MonoClass *MethodInfo_array;
3556 MonoVTable *array_vtable;
3557 MonoException *ex = NULL;
3558 const char *mname = NULL;
3559 GPtrArray *method_array;
3560 MonoClass *klass, *refklass;
3563 if (!MethodInfo_array) {
3564 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3565 mono_memory_barrier ();
3566 MethodInfo_array = klass;
3569 klass = mono_class_from_mono_type (type->type);
3570 refklass = mono_class_from_mono_type (reftype->type);
3571 domain = ((MonoObject *)type)->vtable->domain;
3572 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3573 if (type->type->byref)
3574 return mono_array_new_specific (array_vtable, 0);
3577 mname = mono_string_to_utf8 (name);
3579 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3580 g_free ((char*)mname);
3582 mono_raise_exception (ex);
3584 res = mono_array_new_specific (array_vtable, method_array->len);
3587 for (i = 0; i < method_array->len; ++i) {
3588 MonoMethod *method = g_ptr_array_index (method_array, i);
3589 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3592 g_ptr_array_free (method_array, TRUE);
3596 ICALL_EXPORT MonoArray*
3597 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3600 static MonoClass *System_Reflection_ConstructorInfo;
3601 MonoClass *startklass, *klass, *refklass;
3606 gpointer iter = NULL;
3607 MonoPtrArray tmp_array;
3609 MONO_ARCH_SAVE_REGS;
3611 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3613 domain = ((MonoObject *)type)->vtable->domain;
3614 if (type->type->byref)
3615 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3616 klass = startklass = mono_class_from_mono_type (type->type);
3617 refklass = mono_class_from_mono_type (reftype->type);
3619 if (!System_Reflection_ConstructorInfo)
3620 System_Reflection_ConstructorInfo = mono_class_from_name (
3621 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3624 while ((method = mono_class_get_methods (klass, &iter))) {
3626 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3628 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3629 if (bflags & BFLAGS_Public)
3632 if (bflags & BFLAGS_NonPublic)
3638 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3639 if (bflags & BFLAGS_Static)
3640 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3643 if (bflags & BFLAGS_Instance)
3649 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3651 mono_ptr_array_append (tmp_array, member);
3654 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3656 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3657 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3659 mono_ptr_array_destroy (tmp_array);
3665 property_hash (gconstpointer data)
3667 MonoProperty *prop = (MonoProperty*)data;
3669 return g_str_hash (prop->name);
3673 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3675 // Properties are hide-by-name-and-signature
3676 if (!g_str_equal (prop1->name, prop2->name))
3679 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3681 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3687 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3692 return method_nonpublic (accessor, start_klass);
3695 ICALL_EXPORT MonoArray*
3696 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3700 static MonoClass *System_Reflection_PropertyInfo;
3701 MonoClass *startklass, *klass;
3707 gchar *propname = NULL;
3708 int (*compare_func) (const char *s1, const char *s2) = NULL;
3710 GHashTable *properties = NULL;
3711 MonoPtrArray tmp_array;
3713 MONO_ARCH_SAVE_REGS;
3715 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3717 if (!System_Reflection_PropertyInfo)
3718 System_Reflection_PropertyInfo = mono_class_from_name (
3719 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3721 domain = ((MonoObject *)type)->vtable->domain;
3722 if (type->type->byref)
3723 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3724 klass = startklass = mono_class_from_mono_type (type->type);
3727 propname = mono_string_to_utf8 (name);
3728 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3731 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3733 mono_class_setup_vtable (klass);
3734 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3738 while ((prop = mono_class_get_properties (klass, &iter))) {
3744 flags = method->flags;
3747 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3748 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3749 if (bflags & BFLAGS_Public)
3751 } else if (bflags & BFLAGS_NonPublic) {
3752 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3753 property_accessor_nonpublic(prop->set, startklass == klass)) {
3760 if (flags & METHOD_ATTRIBUTE_STATIC) {
3761 if (bflags & BFLAGS_Static)
3762 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3765 if (bflags & BFLAGS_Instance)
3774 if (compare_func (propname, prop->name))
3778 if (g_hash_table_lookup (properties, prop))
3781 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3783 g_hash_table_insert (properties, prop, prop);
3785 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3788 g_hash_table_destroy (properties);
3791 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3792 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3793 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3795 mono_ptr_array_destroy (tmp_array);
3801 g_hash_table_destroy (properties);
3804 mono_ptr_array_destroy (tmp_array);
3806 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3807 ex = mono_class_get_exception_for_failure (klass);
3809 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3810 mono_loader_clear_error ();
3812 mono_raise_exception (ex);
3816 ICALL_EXPORT MonoReflectionEvent *
3817 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3820 MonoClass *klass, *startklass;
3825 int (*compare_func) (const char *s1, const char *s2);
3827 MONO_ARCH_SAVE_REGS;
3829 event_name = mono_string_to_utf8 (name);
3830 if (type->type->byref)
3832 klass = startklass = mono_class_from_mono_type (type->type);
3833 domain = mono_object_domain (type);
3835 mono_class_init_or_throw (klass);
3837 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3839 if (klass->exception_type != MONO_EXCEPTION_NONE)
3840 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3843 while ((event = mono_class_get_events (klass, &iter))) {
3844 if (compare_func (event->name, event_name))
3847 method = event->add;
3849 method = event->remove;
3851 method = event->raise;
3853 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3854 if (!(bflags & BFLAGS_Public))
3857 if (!(bflags & BFLAGS_NonPublic))
3859 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3863 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3864 if (!(bflags & BFLAGS_Static))
3866 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3869 if (!(bflags & BFLAGS_Instance))
3873 if (!(bflags & BFLAGS_NonPublic))
3876 g_free (event_name);
3877 return mono_event_get_object (domain, startklass, event);
3880 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3883 g_free (event_name);
3887 ICALL_EXPORT MonoArray*
3888 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3892 static MonoClass *System_Reflection_EventInfo;
3893 MonoClass *startklass, *klass;
3900 MonoPtrArray tmp_array;
3902 MONO_ARCH_SAVE_REGS;
3904 mono_ptr_array_init (tmp_array, 4);
3906 if (!System_Reflection_EventInfo)
3907 System_Reflection_EventInfo = mono_class_from_name (
3908 mono_defaults.corlib, "System.Reflection", "EventInfo");
3910 domain = mono_object_domain (type);
3911 if (type->type->byref)
3912 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3913 klass = startklass = mono_class_from_mono_type (type->type);
3916 mono_class_setup_vtable (klass);
3917 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3921 while ((event = mono_class_get_events (klass, &iter))) {
3923 method = event->add;
3925 method = event->remove;
3927 method = event->raise;
3929 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3930 if (bflags & BFLAGS_Public)
3932 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3933 if (bflags & BFLAGS_NonPublic)
3938 if (bflags & BFLAGS_NonPublic)
3944 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3945 if (bflags & BFLAGS_Static)
3946 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3949 if (bflags & BFLAGS_Instance)
3954 if (bflags & BFLAGS_Instance)
3958 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3960 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3963 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3965 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3966 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3968 mono_ptr_array_destroy (tmp_array);
3973 mono_ptr_array_destroy (tmp_array);
3974 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3975 ex = mono_class_get_exception_for_failure (klass);
3977 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3978 mono_loader_clear_error ();
3980 mono_raise_exception (ex);
3984 ICALL_EXPORT MonoReflectionType *
3985 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3993 MONO_ARCH_SAVE_REGS;
3996 mono_raise_exception (mono_get_exception_argument_null ("name"));
3998 domain = ((MonoObject *)type)->vtable->domain;
3999 if (type->type->byref)
4001 klass = mono_class_from_mono_type (type->type);
4003 str = mono_string_to_utf8 (name);
4006 if (klass->exception_type != MONO_EXCEPTION_NONE)
4007 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4010 * If a nested type is generic, return its generic type definition.
4011 * Note that this means that the return value is essentially a
4012 * nested type of the generic type definition of @klass.
4014 * A note in MSDN claims that a generic type definition can have
4015 * nested types that aren't generic. In any case, the container of that
4016 * nested type would be the generic type definition.
4018 if (klass->generic_class)
4019 klass = klass->generic_class->container_class;
4022 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4024 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4025 if (bflags & BFLAGS_Public)
4028 if (bflags & BFLAGS_NonPublic)
4033 if (strcmp (nested->name, str) == 0){
4035 return mono_type_get_object (domain, &nested->byval_arg);
4038 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4044 ICALL_EXPORT MonoArray*
4045 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4054 MonoPtrArray tmp_array;
4056 MONO_ARCH_SAVE_REGS;
4058 domain = ((MonoObject *)type)->vtable->domain;
4059 if (type->type->byref)
4060 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4061 klass = mono_class_from_mono_type (type->type);
4064 * If a nested type is generic, return its generic type definition.
4065 * Note that this means that the return value is essentially the set
4066 * of nested types of the generic type definition of @klass.
4068 * A note in MSDN claims that a generic type definition can have
4069 * nested types that aren't generic. In any case, the container of that
4070 * nested type would be the generic type definition.
4072 if (klass->generic_class)
4073 klass = klass->generic_class->container_class;
4075 mono_ptr_array_init (tmp_array, 1);
4077 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4079 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4080 if (bflags & BFLAGS_Public)
4083 if (bflags & BFLAGS_NonPublic)
4088 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4089 mono_ptr_array_append (tmp_array, member);
4092 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4094 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4095 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4097 mono_ptr_array_destroy (tmp_array);
4102 ICALL_EXPORT MonoReflectionType*
4103 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4106 MonoType *type = NULL;
4107 MonoTypeNameParse info;
4108 gboolean type_resolve;
4110 MONO_ARCH_SAVE_REGS;
4112 /* On MS.NET, this does not fire a TypeResolve event */
4113 type_resolve = TRUE;
4114 str = mono_string_to_utf8 (name);
4115 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4116 if (!mono_reflection_parse_type (str, &info)) {
4118 mono_reflection_free_type_info (&info);
4119 if (throwOnError) /* uhm: this is a parse error, though... */
4120 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4121 /*g_print ("failed parse\n");*/
4125 if (info.assembly.name) {
4127 mono_reflection_free_type_info (&info);
4129 /* 1.0 and 2.0 throw different exceptions */
4130 if (mono_defaults.generic_ilist_class)
4131 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4133 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4138 if (module != NULL) {
4140 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4145 if (assembly->assembly->dynamic) {
4146 /* Enumerate all modules */
4147 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4151 if (abuilder->modules) {
4152 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4153 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4154 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4160 if (!type && abuilder->loaded_modules) {
4161 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4162 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4163 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4170 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4172 mono_reflection_free_type_info (&info);
4174 MonoException *e = NULL;
4177 e = mono_get_exception_type_load (name, NULL);
4179 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4180 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4182 mono_loader_clear_error ();
4185 mono_raise_exception (e);
4188 } else if (mono_loader_get_last_error ()) {
4190 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4191 mono_loader_clear_error ();
4194 if (type->type == MONO_TYPE_CLASS) {
4195 MonoClass *klass = mono_type_get_class (type);
4197 if (mono_security_enabled () && !klass->exception_type)
4198 /* Some security problems are detected during generic vtable construction */
4199 mono_class_setup_vtable (klass);
4201 /* need to report exceptions ? */
4202 if (throwOnError && klass->exception_type) {
4203 /* report SecurityException (or others) that occured when loading the assembly */
4204 MonoException *exc = mono_class_get_exception_for_failure (klass);
4205 mono_loader_clear_error ();
4206 mono_raise_exception (exc);
4207 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4212 /* g_print ("got it\n"); */
4213 return mono_type_get_object (mono_object_domain (assembly), type);
4217 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4220 gchar *shadow_ini_file;
4223 /* Check for shadow-copied assembly */
4224 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4225 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4227 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4228 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4234 g_free (shadow_ini_file);
4235 if (content != NULL) {
4238 *filename = content;
4245 ICALL_EXPORT MonoString *
4246 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4248 MonoDomain *domain = mono_object_domain (assembly);
4249 MonoAssembly *mass = assembly->assembly;
4250 MonoString *res = NULL;
4255 MONO_ARCH_SAVE_REGS;
4257 if (g_path_is_absolute (mass->image->name)) {
4258 absolute = g_strdup (mass->image->name);
4259 dirname = g_path_get_dirname (absolute);
4261 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4262 dirname = g_strdup (mass->basedir);
4265 replace_shadow_path (domain, dirname, &absolute);
4270 for (i = strlen (absolute) - 1; i >= 0; i--)
4271 if (absolute [i] == '\\')
4276 uri = g_filename_to_uri (absolute, NULL, NULL);
4278 const char *prepend = "file://";
4280 if (*absolute == '/' && *(absolute + 1) == '/') {
4283 prepend = "file:///";
4286 uri = g_strconcat (prepend, absolute, NULL);
4290 res = mono_string_new (domain, uri);
4297 ICALL_EXPORT MonoBoolean
4298 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4300 MonoAssembly *mass = assembly->assembly;
4302 MONO_ARCH_SAVE_REGS;
4304 return mass->in_gac;
4307 ICALL_EXPORT MonoReflectionAssembly*
4308 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4312 MonoImageOpenStatus status;
4314 MONO_ARCH_SAVE_REGS;
4316 name = mono_string_to_utf8 (mname);
4317 res = mono_assembly_load_with_partial_name (name, &status);
4323 return mono_assembly_get_object (mono_domain_get (), res);
4326 ICALL_EXPORT MonoString *
4327 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4329 MonoDomain *domain = mono_object_domain (assembly);
4332 MONO_ARCH_SAVE_REGS;
4334 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4339 ICALL_EXPORT MonoBoolean
4340 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4342 MONO_ARCH_SAVE_REGS;
4344 return assembly->assembly->ref_only;
4347 ICALL_EXPORT MonoString *
4348 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4350 MonoDomain *domain = mono_object_domain (assembly);
4352 MONO_ARCH_SAVE_REGS;
4354 return mono_string_new (domain, assembly->assembly->image->version);
4357 ICALL_EXPORT MonoReflectionMethod*
4358 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4360 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4362 MONO_ARCH_SAVE_REGS;
4366 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4369 ICALL_EXPORT MonoReflectionModule*
4370 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4372 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4375 ICALL_EXPORT MonoArray*
4376 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4378 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4379 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4383 MONO_ARCH_SAVE_REGS;
4385 for (i = 0; i < table->rows; ++i) {
4386 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4387 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4393 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4395 static MonoClass *System_Version = NULL;
4396 static MonoMethod *create_version = NULL;
4400 if (!System_Version) {
4401 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4402 g_assert (System_Version);
4405 if (!create_version) {
4406 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4407 create_version = mono_method_desc_search_in_class (desc, System_Version);
4408 g_assert (create_version);
4409 mono_method_desc_free (desc);
4415 args [3] = &revision;
4416 result = mono_object_new (domain, System_Version);
4417 mono_runtime_invoke (create_version, result, args, NULL);
4422 ICALL_EXPORT MonoArray*
4423 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4425 static MonoClass *System_Reflection_AssemblyName;
4427 MonoDomain *domain = mono_object_domain (assembly);
4429 static MonoMethod *create_culture = NULL;
4430 MonoImage *image = assembly->assembly->image;
4433 MONO_ARCH_SAVE_REGS;
4435 if (!System_Reflection_AssemblyName)
4436 System_Reflection_AssemblyName = mono_class_from_name (
4437 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4439 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4442 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4444 if (count > 0 && !create_culture) {
4445 MonoMethodDesc *desc = mono_method_desc_new (
4446 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4447 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4448 g_assert (create_culture);
4449 mono_method_desc_free (desc);
4452 for (i = 0; i < count; i++) {
4453 MonoReflectionAssemblyName *aname;
4454 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4456 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4458 aname = (MonoReflectionAssemblyName *) mono_object_new (
4459 domain, System_Reflection_AssemblyName);
4461 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4463 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4464 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4465 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4466 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4467 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4468 aname->versioncompat = 1; /* SameMachine (default) */
4469 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4470 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4472 if (create_culture) {
4474 MonoBoolean assembly_ref = 1;
4475 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4476 args [1] = &assembly_ref;
4477 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4480 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4481 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4482 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4484 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4485 /* public key token isn't copied - the class library will
4486 automatically generate it from the public key if required */
4487 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4488 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4490 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4491 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4494 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4497 /* note: this function doesn't return the codebase on purpose (i.e. it can
4498 be used under partial trust as path information isn't present). */
4500 mono_array_setref (result, i, aname);
4505 /* move this in some file in mono/util/ */
4507 g_concat_dir_and_file (const char *dir, const char *file)
4509 g_return_val_if_fail (dir != NULL, NULL);
4510 g_return_val_if_fail (file != NULL, NULL);
4513 * If the directory name doesn't have a / on the end, we need
4514 * to add one so we get a proper path to the file
4516 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4517 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4519 return g_strconcat (dir, file, NULL);
4523 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4525 char *n = mono_string_to_utf8 (name);
4526 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4528 guint32 cols [MONO_MANIFEST_SIZE];
4529 guint32 impl, file_idx;
4533 MONO_ARCH_SAVE_REGS;
4535 for (i = 0; i < table->rows; ++i) {
4536 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4537 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4538 if (strcmp (val, n) == 0)
4542 if (i == table->rows)
4545 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4548 * this code should only be called after obtaining the
4549 * ResourceInfo and handling the other cases.
4551 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4552 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4554 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4559 module = assembly->assembly->image;
4561 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4563 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4566 ICALL_EXPORT gboolean
4567 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4569 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4571 guint32 cols [MONO_MANIFEST_SIZE];
4572 guint32 file_cols [MONO_FILE_SIZE];
4576 MONO_ARCH_SAVE_REGS;
4578 n = mono_string_to_utf8 (name);
4579 for (i = 0; i < table->rows; ++i) {
4580 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4581 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4582 if (strcmp (val, n) == 0)
4586 if (i == table->rows)
4589 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4590 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4593 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4594 case MONO_IMPLEMENTATION_FILE:
4595 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4596 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4597 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4598 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4599 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4600 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4603 info->location = RESOURCE_LOCATION_EMBEDDED;
4606 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4607 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4608 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4609 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4610 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4611 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4613 mono_raise_exception (ex);
4615 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4617 /* Obtain info recursively */
4618 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4619 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4622 case MONO_IMPLEMENTATION_EXP_TYPE:
4623 g_assert_not_reached ();
4631 ICALL_EXPORT MonoObject*
4632 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4634 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4635 MonoArray *result = NULL;
4640 MONO_ARCH_SAVE_REGS;
4642 /* check hash if needed */
4644 n = mono_string_to_utf8 (name);
4645 for (i = 0; i < table->rows; ++i) {
4646 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4647 if (strcmp (val, n) == 0) {
4650 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4651 fn = mono_string_new (mono_object_domain (assembly), n);
4653 return (MonoObject*)fn;
4661 for (i = 0; i < table->rows; ++i) {
4662 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4666 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4669 for (i = 0; i < table->rows; ++i) {
4670 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4671 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4672 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4673 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4678 return (MonoObject*)result;
4681 ICALL_EXPORT MonoArray*
4682 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4684 MonoDomain *domain = mono_domain_get();
4687 int i, j, file_count = 0;
4688 MonoImage **modules;
4689 guint32 module_count, real_module_count;
4690 MonoTableInfo *table;
4691 guint32 cols [MONO_FILE_SIZE];
4692 MonoImage *image = assembly->assembly->image;
4694 g_assert (image != NULL);
4695 g_assert (!assembly->assembly->dynamic);
4697 table = &image->tables [MONO_TABLE_FILE];
4698 file_count = table->rows;
4700 modules = image->modules;
4701 module_count = image->module_count;
4703 real_module_count = 0;
4704 for (i = 0; i < module_count; ++i)
4706 real_module_count ++;
4708 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4709 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4711 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4713 for (i = 0; i < module_count; ++i)
4715 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4719 for (i = 0; i < file_count; ++i, ++j) {
4720 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4721 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4722 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4724 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4726 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4727 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4729 mono_array_setref (res, j, mono_module_get_object (domain, m));
4736 ICALL_EXPORT MonoReflectionMethod*
4737 ves_icall_GetCurrentMethod (void)
4739 MonoMethod *m = mono_method_get_last_managed ();
4741 while (m->is_inflated)
4742 m = ((MonoMethodInflated*)m)->declaring;
4744 return mono_method_get_object (mono_domain_get (), m, NULL);
4749 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4752 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4753 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4754 //method is inflated, we should inflate it on the other class
4755 MonoGenericContext ctx;
4756 ctx.method_inst = inflated->context.method_inst;
4757 ctx.class_inst = inflated->context.class_inst;
4758 if (klass->generic_class)
4759 ctx.class_inst = klass->generic_class->context.class_inst;
4760 else if (klass->generic_container)
4761 ctx.class_inst = klass->generic_container->context.class_inst;
4762 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4765 mono_class_setup_methods (method->klass);
4766 if (method->klass->exception_type)
4768 for (i = 0; i < method->klass->method.count; ++i) {
4769 if (method->klass->methods [i] == method) {
4774 mono_class_setup_methods (klass);
4775 if (klass->exception_type)
4777 g_assert (offset >= 0 && offset < klass->method.count);
4778 return klass->methods [offset];
4781 ICALL_EXPORT MonoReflectionMethod*
4782 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4786 klass = mono_class_from_mono_type (type);
4787 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4789 if (method->klass != klass) {
4790 method = mono_method_get_equivalent_method (method, klass);
4795 klass = method->klass;
4796 return mono_method_get_object (mono_domain_get (), method, klass);
4799 ICALL_EXPORT MonoReflectionMethod*
4800 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4802 return mono_method_get_object (mono_domain_get (), method, NULL);
4805 ICALL_EXPORT MonoReflectionMethodBody*
4806 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4808 return mono_method_body_get_object (mono_domain_get (), method);
4811 ICALL_EXPORT MonoReflectionAssembly*
4812 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4814 MonoMethod *dest = NULL;
4816 MONO_ARCH_SAVE_REGS;
4818 mono_stack_walk_no_il (get_executing, &dest);
4820 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4824 ICALL_EXPORT MonoReflectionAssembly*
4825 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4827 MonoDomain* domain = mono_domain_get ();
4829 MONO_ARCH_SAVE_REGS;
4831 if (!domain->entry_assembly)
4834 return mono_assembly_get_object (domain, domain->entry_assembly);
4837 ICALL_EXPORT MonoReflectionAssembly*
4838 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4843 MONO_ARCH_SAVE_REGS;
4846 mono_stack_walk_no_il (get_executing, &dest);
4848 mono_stack_walk_no_il (get_caller, &dest);
4851 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4854 ICALL_EXPORT MonoString *
4855 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4856 gboolean assembly_qualified)
4858 MonoDomain *domain = mono_object_domain (object);
4859 MonoTypeNameFormat format;
4864 format = assembly_qualified ?
4865 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4866 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4868 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4870 name = mono_type_get_name_full (object->type, format);
4874 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4879 res = mono_string_new (domain, name);
4886 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4888 MonoClass *klass = mono_class_from_mono_type (this->type);
4889 mono_class_init_or_throw (klass);
4890 return mono_security_core_clr_class_level (klass);
4894 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4896 static MonoMethod *create_culture = NULL;
4899 const char *pkey_ptr;
4901 MonoBoolean assembly_ref = 0;
4903 MONO_ARCH_SAVE_REGS;
4905 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4906 aname->major = name->major;
4907 aname->minor = name->minor;
4908 aname->build = name->build;
4909 aname->flags = name->flags;
4910 aname->revision = name->revision;
4911 aname->hashalg = name->hash_alg;
4912 aname->versioncompat = 1; /* SameMachine (default) */
4913 aname->processor_architecture = name->arch;
4915 if (by_default_version)
4916 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4919 if (absolute != NULL && *absolute != '\0') {
4920 const gchar *prepend = "file://";
4923 codebase = g_strdup (absolute);
4928 for (i = strlen (codebase) - 1; i >= 0; i--)
4929 if (codebase [i] == '\\')
4932 if (*codebase == '/' && *(codebase + 1) == '/') {
4935 prepend = "file:///";
4939 result = g_strconcat (prepend, codebase, NULL);
4945 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4949 if (!create_culture) {
4950 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4951 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4952 g_assert (create_culture);
4953 mono_method_desc_free (desc);
4956 if (name->culture) {
4957 args [0] = mono_string_new (domain, name->culture);
4958 args [1] = &assembly_ref;
4959 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4962 if (name->public_key) {
4963 pkey_ptr = (char*)name->public_key;
4964 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4966 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4967 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4968 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4969 } else if (default_publickey) {
4970 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4971 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4974 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4975 if (name->public_key_token [0]) {
4979 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4980 p = mono_array_addr (aname->keyToken, char, 0);
4982 for (i = 0, j = 0; i < 8; i++) {
4983 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4984 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4987 } else if (default_token) {
4988 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4992 ICALL_EXPORT MonoString *
4993 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4995 MonoDomain *domain = mono_object_domain (assembly);
4996 MonoAssembly *mass = assembly->assembly;
5000 name = mono_stringify_assembly_name (&mass->aname);
5001 res = mono_string_new (domain, name);
5008 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5011 MonoAssembly *mass = assembly->assembly;
5013 MONO_ARCH_SAVE_REGS;
5015 if (g_path_is_absolute (mass->image->name)) {
5016 fill_reflection_assembly_name (mono_object_domain (assembly),
5017 aname, &mass->aname, mass->image->name, TRUE,
5021 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5023 fill_reflection_assembly_name (mono_object_domain (assembly),
5024 aname, &mass->aname, absolute, TRUE, TRUE,
5031 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5034 MonoImageOpenStatus status = MONO_IMAGE_OK;
5037 MonoAssemblyName name;
5040 MONO_ARCH_SAVE_REGS;
5042 filename = mono_string_to_utf8 (fname);
5044 dirname = g_path_get_dirname (filename);
5045 replace_shadow_path (mono_domain_get (), dirname, &filename);
5048 image = mono_image_open (filename, &status);
5054 if (status == MONO_IMAGE_IMAGE_INVALID)
5055 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5057 exc = mono_get_exception_file_not_found2 (NULL, fname);
5058 mono_raise_exception (exc);
5061 res = mono_assembly_fill_assembly_name (image, &name);
5063 mono_image_close (image);
5065 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5068 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5072 mono_image_close (image);
5075 ICALL_EXPORT MonoBoolean
5076 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5077 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5079 MonoBoolean result = FALSE;
5080 MonoDeclSecurityEntry entry;
5082 /* SecurityAction.RequestMinimum */
5083 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5084 *minimum = entry.blob;
5085 *minLength = entry.size;
5088 /* SecurityAction.RequestOptional */
5089 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5090 *optional = entry.blob;
5091 *optLength = entry.size;
5094 /* SecurityAction.RequestRefuse */
5095 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5096 *refused = entry.blob;
5097 *refLength = entry.size;
5105 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5109 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5111 guint32 attrs, visibility;
5113 /* we start the count from 1 because we skip the special type <Module> */
5116 for (i = 1; i < tdef->rows; ++i) {
5117 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5118 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5119 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5123 count = tdef->rows - 1;
5125 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5126 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5128 for (i = 1; i < tdef->rows; ++i) {
5129 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5130 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5131 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5132 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5134 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5136 MonoLoaderError *error;
5139 error = mono_loader_get_last_error ();
5140 g_assert (error != NULL);
5142 ex = mono_loader_error_prepare_exception (error);
5143 mono_array_setref (*exceptions, count, ex);
5145 if (mono_loader_get_last_error ())
5146 mono_loader_clear_error ();
5154 ICALL_EXPORT MonoArray*
5155 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5157 MonoArray *res = NULL;
5158 MonoArray *exceptions = NULL;
5159 MonoImage *image = NULL;
5160 MonoTableInfo *table = NULL;
5163 int i, len, ex_count;
5165 MONO_ARCH_SAVE_REGS;
5167 domain = mono_object_domain (assembly);
5169 g_assert (!assembly->assembly->dynamic);
5170 image = assembly->assembly->image;
5171 table = &image->tables [MONO_TABLE_FILE];
5172 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5174 /* Append data from all modules in the assembly */
5175 for (i = 0; i < table->rows; ++i) {
5176 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5177 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5180 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5181 /* Append the new types to the end of the array */
5182 if (mono_array_length (res2) > 0) {
5184 MonoArray *res3, *ex3;
5186 len1 = mono_array_length (res);
5187 len2 = mono_array_length (res2);
5189 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5190 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5191 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5194 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5195 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5196 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5203 /* the ReflectionTypeLoadException must have all the types (Types property),
5204 * NULL replacing types which throws an exception. The LoaderException must
5205 * contain all exceptions for NULL items.
5208 len = mono_array_length (res);
5211 for (i = 0; i < len; i++) {
5212 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5216 klass = mono_type_get_class (t->type);
5217 if ((klass != NULL) && klass->exception_type) {
5218 /* keep the class in the list */
5219 list = g_list_append (list, klass);
5220 /* and replace Type with NULL */
5221 mono_array_setref (res, i, NULL);
5228 if (list || ex_count) {
5230 MonoException *exc = NULL;
5231 MonoArray *exl = NULL;
5232 int j, length = g_list_length (list) + ex_count;
5234 mono_loader_clear_error ();
5236 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5237 /* Types for which mono_class_get () succeeded */
5238 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5239 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5240 mono_array_setref (exl, i, exc);
5242 /* Types for which it don't */
5243 for (j = 0; j < mono_array_length (exceptions); ++j) {
5244 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5246 g_assert (i < length);
5247 mono_array_setref (exl, i, exc);
5254 exc = mono_get_exception_reflection_type_load (res, exl);
5255 mono_loader_clear_error ();
5256 mono_raise_exception (exc);
5262 ICALL_EXPORT gboolean
5263 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5265 MonoAssemblyName aname;
5266 MonoDomain *domain = mono_object_domain (name);
5268 gboolean is_version_defined;
5269 gboolean is_token_defined;
5271 aname.public_key = NULL;
5272 val = mono_string_to_utf8 (assname);
5273 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5274 g_free ((guint8*) aname.public_key);
5279 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5280 FALSE, is_token_defined);
5282 mono_assembly_name_free (&aname);
5283 g_free ((guint8*) aname.public_key);
5289 ICALL_EXPORT MonoReflectionType*
5290 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5292 MonoDomain *domain = mono_object_domain (module);
5295 MONO_ARCH_SAVE_REGS;
5297 g_assert (module->image);
5299 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5300 /* These images do not have a global type */
5303 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5304 return mono_type_get_object (domain, &klass->byval_arg);
5308 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5310 /*if (module->image)
5311 mono_image_close (module->image);*/
5314 ICALL_EXPORT MonoString*
5315 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5317 MonoDomain *domain = mono_object_domain (module);
5319 MONO_ARCH_SAVE_REGS;
5321 g_assert (module->image);
5322 return mono_string_new (domain, module->image->guid);
5325 ICALL_EXPORT gpointer
5326 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5329 if (module->image && module->image->is_module_handle)
5330 return module->image->raw_data;
5333 return (gpointer) (-1);
5337 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5339 if (image->dynamic) {
5340 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5341 *pe_kind = dyn->pe_kind;
5342 *machine = dyn->machine;
5345 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5346 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5351 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5353 return (image->md_version_major << 16) | (image->md_version_minor);
5356 ICALL_EXPORT MonoArray*
5357 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5359 MonoArray *exceptions;
5362 MONO_ARCH_SAVE_REGS;
5365 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5367 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5368 for (i = 0; i < mono_array_length (exceptions); ++i) {
5369 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5371 mono_raise_exception (ex);
5378 mono_memberref_is_method (MonoImage *image, guint32 token)
5380 if (!image->dynamic) {
5381 guint32 cols [MONO_MEMBERREF_SIZE];
5383 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5384 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5385 mono_metadata_decode_blob_size (sig, &sig);
5386 return (*sig != 0x6);
5388 MonoClass *handle_class;
5390 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5393 return mono_defaults.methodhandle_class == handle_class;
5398 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5401 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5402 mono_array_addr (type_args, MonoType*, 0));
5404 context->class_inst = NULL;
5406 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5407 mono_array_addr (method_args, MonoType*, 0));
5409 context->method_inst = NULL;
5412 ICALL_EXPORT MonoType*
5413 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5416 int table = mono_metadata_token_table (token);
5417 int index = mono_metadata_token_index (token);
5418 MonoGenericContext context;
5420 *error = ResolveTokenError_Other;
5422 /* Validate token */
5423 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5424 (table != MONO_TABLE_TYPESPEC)) {
5425 *error = ResolveTokenError_BadTable;
5429 if (image->dynamic) {
5430 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5431 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5432 return klass ? &klass->byval_arg : NULL;
5435 init_generic_context_from_args (&context, type_args, method_args);
5436 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5437 return klass ? &klass->byval_arg : NULL;
5440 if ((index <= 0) || (index > image->tables [table].rows)) {
5441 *error = ResolveTokenError_OutOfRange;
5445 init_generic_context_from_args (&context, type_args, method_args);
5446 klass = mono_class_get_full (image, token, &context);
5448 if (mono_loader_get_last_error ())
5449 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5452 return &klass->byval_arg;
5457 ICALL_EXPORT MonoMethod*
5458 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5460 int table = mono_metadata_token_table (token);
5461 int index = mono_metadata_token_index (token);
5462 MonoGenericContext context;
5465 *error = ResolveTokenError_Other;
5467 /* Validate token */
5468 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5469 (table != MONO_TABLE_MEMBERREF)) {
5470 *error = ResolveTokenError_BadTable;
5474 if (image->dynamic) {
5475 if (table == MONO_TABLE_METHOD)
5476 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5478 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5479 *error = ResolveTokenError_BadTable;
5483 init_generic_context_from_args (&context, type_args, method_args);
5484 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5487 if ((index <= 0) || (index > image->tables [table].rows)) {
5488 *error = ResolveTokenError_OutOfRange;
5491 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5492 *error = ResolveTokenError_BadTable;
5496 init_generic_context_from_args (&context, type_args, method_args);
5497 method = mono_get_method_full (image, token, NULL, &context);
5499 if (mono_loader_get_last_error ())
5500 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5505 ICALL_EXPORT MonoString*
5506 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5508 int index = mono_metadata_token_index (token);
5510 *error = ResolveTokenError_Other;
5512 /* Validate token */
5513 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5514 *error = ResolveTokenError_BadTable;
5519 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5521 if ((index <= 0) || (index >= image->heap_us.size)) {
5522 *error = ResolveTokenError_OutOfRange;
5526 /* FIXME: What to do if the index points into the middle of a string ? */
5528 return mono_ldstr (mono_domain_get (), image, index);
5531 ICALL_EXPORT MonoClassField*
5532 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5535 int table = mono_metadata_token_table (token);
5536 int index = mono_metadata_token_index (token);
5537 MonoGenericContext context;
5538 MonoClassField *field;
5540 *error = ResolveTokenError_Other;
5542 /* Validate token */
5543 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5544 *error = ResolveTokenError_BadTable;
5548 if (image->dynamic) {
5549 if (table == MONO_TABLE_FIELD)
5550 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5552 if (mono_memberref_is_method (image, token)) {
5553 *error = ResolveTokenError_BadTable;
5557 init_generic_context_from_args (&context, type_args, method_args);
5558 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5561 if ((index <= 0) || (index > image->tables [table].rows)) {
5562 *error = ResolveTokenError_OutOfRange;
5565 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5566 *error = ResolveTokenError_BadTable;
5570 init_generic_context_from_args (&context, type_args, method_args);
5571 field = mono_field_from_token (image, token, &klass, &context);
5573 if (mono_loader_get_last_error ())
5574 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5580 ICALL_EXPORT MonoObject*
5581 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5583 int table = mono_metadata_token_table (token);
5585 *error = ResolveTokenError_Other;
5588 case MONO_TABLE_TYPEDEF:
5589 case MONO_TABLE_TYPEREF:
5590 case MONO_TABLE_TYPESPEC: {
5591 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5593 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5597 case MONO_TABLE_METHOD:
5598 case MONO_TABLE_METHODSPEC: {
5599 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5601 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5605 case MONO_TABLE_FIELD: {
5606 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5608 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5612 case MONO_TABLE_MEMBERREF:
5613 if (mono_memberref_is_method (image, token)) {
5614 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5616 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5621 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5623 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5630 *error = ResolveTokenError_BadTable;
5636 ICALL_EXPORT MonoArray*
5637 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5639 int table = mono_metadata_token_table (token);
5640 int idx = mono_metadata_token_index (token);
5641 MonoTableInfo *tables = image->tables;
5646 *error = ResolveTokenError_OutOfRange;
5648 /* FIXME: Support other tables ? */
5649 if (table != MONO_TABLE_STANDALONESIG)
5655 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5658 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5660 ptr = mono_metadata_blob_heap (image, sig);
5661 len = mono_metadata_decode_blob_size (ptr, &ptr);
5663 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5664 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5668 ICALL_EXPORT MonoReflectionType*
5669 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5672 int isbyref = 0, rank;
5673 char *str = mono_string_to_utf8 (smodifiers);
5676 MONO_ARCH_SAVE_REGS;
5678 klass = mono_class_from_mono_type (tb->type.type);
5680 /* logic taken from mono_reflection_parse_type(): keep in sync */
5684 if (isbyref) { /* only one level allowed by the spec */
5691 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5694 klass = mono_ptr_class_get (&klass->byval_arg);
5695 mono_class_init (klass);
5706 else if (*p != '*') { /* '*' means unknown lower bound */
5717 klass = mono_array_class_get (klass, rank);
5718 mono_class_init (klass);
5725 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5728 ICALL_EXPORT MonoBoolean
5729 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5734 MONO_ARCH_SAVE_REGS;
5737 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5743 check_for_invalid_type (MonoClass *klass)
5747 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5750 name = mono_type_get_full_name (klass);
5751 str = mono_string_new (mono_domain_get (), name);
5753 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5756 ICALL_EXPORT MonoReflectionType *
5757 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5759 MonoClass *klass, *aklass;
5761 MONO_ARCH_SAVE_REGS;
5763 klass = mono_class_from_mono_type (type->type);
5764 check_for_invalid_type (klass);
5766 if (rank == 0) //single dimentional array
5767 aklass = mono_array_class_get (klass, 1);
5769 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5771 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5774 ICALL_EXPORT MonoReflectionType *
5775 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5779 MONO_ARCH_SAVE_REGS;
5781 klass = mono_class_from_mono_type (type->type);
5782 mono_class_init_or_throw (klass);
5783 check_for_invalid_type (klass);
5785 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5788 ICALL_EXPORT MonoReflectionType *
5789 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5791 MonoClass *klass, *pklass;
5793 klass = mono_class_from_mono_type (type->type);
5794 mono_class_init_or_throw (klass);
5795 check_for_invalid_type (klass);
5797 pklass = mono_ptr_class_get (type->type);
5799 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5802 ICALL_EXPORT MonoObject *
5803 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5804 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5806 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5807 MonoObject *delegate;
5809 MonoMethod *method = info->method;
5811 MONO_ARCH_SAVE_REGS;
5813 mono_class_init_or_throw (delegate_class);
5815 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5817 if (mono_security_core_clr_enabled ()) {
5818 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5822 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5824 if (method->dynamic) {
5825 /* Creating a trampoline would leak memory */
5826 func = mono_compile_method (method);
5828 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5829 method = mono_object_get_virtual_method (target, method);
5830 func = mono_create_ftnptr (mono_domain_get (),
5831 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5834 mono_delegate_ctor_with_method (delegate, target, func, method);
5840 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5842 /* Reset the invoke impl to the default one */
5843 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5847 * Magic number to convert a time which is relative to
5848 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5850 #define EPOCH_ADJUST ((guint64)62135596800LL)
5853 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5855 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5858 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5860 convert_to_absolute_date(SYSTEMTIME *date)
5862 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5863 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5864 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5865 /* from the calendar FAQ */
5866 int a = (14 - date->wMonth) / 12;
5867 int y = date->wYear - a;
5868 int m = date->wMonth + 12 * a - 2;
5869 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5871 /* d is now the day of the week for the first of the month (0 == Sunday) */
5873 int day_of_week = date->wDayOfWeek;
5875 /* set day_in_month to the first day in the month which falls on day_of_week */
5876 int day_in_month = 1 + (day_of_week - d);
5877 if (day_in_month <= 0)
5880 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5881 date->wDay = day_in_month + (date->wDay - 1) * 7;
5882 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5889 * Return's the offset from GMT of a local time.
5891 * tm is a local time
5892 * t is the same local time as seconds.
5895 gmt_offset(struct tm *tm, time_t t)
5897 #if defined (HAVE_TM_GMTOFF)
5898 return tm->tm_gmtoff;
5903 g.tm_isdst = tm->tm_isdst;
5905 return (int)difftime(t, t2);
5910 * This is heavily based on zdump.c from glibc 2.2.
5912 * * data[0]: start of daylight saving time (in DateTime ticks).
5913 * * data[1]: end of daylight saving time (in DateTime ticks).
5914 * * data[2]: utcoffset (in TimeSpan ticks).
5915 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5916 * * name[0]: name of this timezone when not daylight saving.
5917 * * name[1]: name of this timezone when daylight saving.
5919 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5920 * the class library allows years between 1 and 9999.
5922 * Returns true on success and zero on failure.
5924 ICALL_EXPORT guint32
5925 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5928 MonoDomain *domain = mono_domain_get ();
5929 struct tm start, tt;
5932 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5933 int day, transitioned;
5936 gmtoff_st = gmtoff_ds = transitioned = 0;
5938 MONO_ARCH_SAVE_REGS;
5940 MONO_CHECK_ARG_NULL (data);
5941 MONO_CHECK_ARG_NULL (names);
5943 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5944 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5947 * no info is better than crashing: we'll need our own tz data
5948 * to make this work properly, anyway. The range is probably
5949 * reduced to 1970 .. 2037 because that is what mktime is
5950 * guaranteed to support (we get into an infinite loop
5954 memset (&start, 0, sizeof (start));
5957 start.tm_year = year-1900;
5959 t = mktime (&start);
5961 if ((year < 1970) || (year > 2037) || (t == -1)) {
5963 tt = *localtime (&t);
5964 strftime (tzone, sizeof (tzone), "%Z", &tt);
5965 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5966 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5970 gmtoff = gmt_offset (&start, t);
5972 /* For each day of the year, calculate the tm_gmtoff. */
5973 for (day = 0; day < 365 && transitioned < 2; day++) {
5976 tt = *localtime (&t);
5978 gmtoff_after = gmt_offset(&tt, t);
5980 /* Daylight saving starts or ends here. */
5981 if (gmtoff_after != gmtoff) {
5985 /* Try to find the exact hour when daylight saving starts/ends. */
5989 tt1 = *localtime (&t1);
5990 } while (gmt_offset (&tt1, t1) != gmtoff);
5992 /* Try to find the exact minute when daylight saving starts/ends. */
5995 tt1 = *localtime (&t1);
5996 } while (gmt_offset (&tt1, t1) == gmtoff);
5998 strftime (tzone, sizeof (tzone), "%Z", &tt);
6000 /* Write data, if we're already in daylight saving, we're done. */
6002 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6003 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6004 if (gmtoff_ds == 0) {
6006 gmtoff_ds = gmtoff_after;
6013 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6014 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6015 if (gmtoff_ds == 0) {
6016 gmtoff_st = gmtoff_after;
6022 /* This is only set once when we enter daylight saving. */
6024 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6025 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6027 gmtoff = gmt_offset (&tt, t);
6031 if (transitioned < 2) {
6032 strftime (tzone, sizeof (tzone), "%Z", &tt);
6033 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6034 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6035 mono_array_set ((*data), gint64, 0, 0);
6036 mono_array_set ((*data), gint64, 1, 0);
6037 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6038 mono_array_set ((*data), gint64, 3, 0);
6043 MonoDomain *domain = mono_domain_get ();
6044 TIME_ZONE_INFORMATION tz_info;
6049 tz_id = GetTimeZoneInformation (&tz_info);
6050 if (tz_id == TIME_ZONE_ID_INVALID)
6053 MONO_CHECK_ARG_NULL (data);
6054 MONO_CHECK_ARG_NULL (names);
6056 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6057 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6059 for (i = 0; i < 32; ++i)
6060 if (!tz_info.DaylightName [i])
6062 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6063 for (i = 0; i < 32; ++i)
6064 if (!tz_info.StandardName [i])
6066 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6068 if ((year <= 1601) || (year > 30827)) {
6070 * According to MSDN, the MS time functions can't handle dates outside
6076 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6077 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6078 tz_info.StandardDate.wYear = year;
6079 convert_to_absolute_date(&tz_info.StandardDate);
6080 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6085 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6086 tz_info.DaylightDate.wYear = year;
6087 convert_to_absolute_date(&tz_info.DaylightDate);
6088 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6093 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6095 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6096 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6102 ICALL_EXPORT gpointer
6103 ves_icall_System_Object_obj_address (MonoObject *this)
6105 MONO_ARCH_SAVE_REGS;
6112 static inline gint32
6113 mono_array_get_byte_length (MonoArray *array)
6119 klass = array->obj.vtable->klass;
6121 if (array->bounds == NULL)
6122 length = array->max_length;
6125 for (i = 0; i < klass->rank; ++ i)
6126 length *= array->bounds [i].length;
6129 switch (klass->element_class->byval_arg.type) {
6132 case MONO_TYPE_BOOLEAN:
6136 case MONO_TYPE_CHAR:
6144 return length * sizeof (gpointer);
6155 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6157 MONO_ARCH_SAVE_REGS;
6159 return mono_array_get_byte_length (array);
6163 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6165 MONO_ARCH_SAVE_REGS;
6167 return mono_array_get (array, gint8, idx);
6171 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6173 MONO_ARCH_SAVE_REGS;
6175 mono_array_set (array, gint8, idx, value);
6178 ICALL_EXPORT MonoBoolean
6179 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6181 guint8 *src_buf, *dest_buf;
6183 MONO_ARCH_SAVE_REGS;
6185 /* This is called directly from the class libraries without going through the managed wrapper */
6186 MONO_CHECK_ARG_NULL (src);
6187 MONO_CHECK_ARG_NULL (dest);
6189 /* watch out for integer overflow */
6190 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6193 src_buf = (guint8 *)src->vector + src_offset;
6194 dest_buf = (guint8 *)dest->vector + dest_offset;
6197 memcpy (dest_buf, src_buf, count);
6199 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6204 #ifndef DISABLE_REMOTING
6205 ICALL_EXPORT MonoObject *
6206 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6208 MonoDomain *domain = mono_object_domain (this);
6210 MonoRealProxy *rp = ((MonoRealProxy *)this);
6211 MonoTransparentProxy *tp;
6215 MONO_ARCH_SAVE_REGS;
6217 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6218 tp = (MonoTransparentProxy*) res;
6220 MONO_OBJECT_SETREF (tp, rp, rp);
6221 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6222 klass = mono_class_from_mono_type (type);
6224 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6225 tp->remote_class = mono_remote_class (domain, class_name, klass);
6227 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6231 ICALL_EXPORT MonoReflectionType *
6232 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6234 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6238 /* System.Environment */
6241 ves_icall_System_Environment_get_UserName (void)
6243 MONO_ARCH_SAVE_REGS;
6245 /* using glib is more portable */
6246 return mono_string_new (mono_domain_get (), g_get_user_name ());
6250 ICALL_EXPORT MonoString *
6251 ves_icall_System_Environment_get_MachineName (void)
6253 #if defined (HOST_WIN32)
6258 len = MAX_COMPUTERNAME_LENGTH + 1;
6259 buf = g_new (gunichar2, len);
6262 if (GetComputerName (buf, (PDWORD) &len))
6263 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6267 #elif !defined(DISABLE_SOCKETS)
6271 if (gethostname (buf, sizeof (buf)) == 0)
6272 result = mono_string_new (mono_domain_get (), buf);
6278 return mono_string_new (mono_domain_get (), "mono");
6283 ves_icall_System_Environment_get_Platform (void)
6285 #if defined (TARGET_WIN32)
6288 #elif defined(__MACH__)
6291 // Notice that the value is hidden from user code, and only exposed
6292 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6293 // define and making assumptions based on Unix/128/4 values before there
6294 // was a MacOS define. Lots of code would assume that not-Unix meant
6295 // Windows, but in this case, it would be OSX.
6304 ICALL_EXPORT MonoString *
6305 ves_icall_System_Environment_get_NewLine (void)
6307 MONO_ARCH_SAVE_REGS;
6309 #if defined (HOST_WIN32)
6310 return mono_string_new (mono_domain_get (), "\r\n");
6312 return mono_string_new (mono_domain_get (), "\n");
6316 ICALL_EXPORT MonoString *
6317 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6322 MONO_ARCH_SAVE_REGS;
6327 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6328 value = g_getenv (utf8_name);
6335 return mono_string_new (mono_domain_get (), value);
6339 * There is no standard way to get at environ.
6342 #ifndef __MINGW32_VERSION
6343 #if defined(__APPLE__) && !defined (__arm__)
6344 /* Apple defines this in crt_externs.h but doesn't provide that header for
6345 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6346 * in fact exist on all implementations (so far)
6348 gchar ***_NSGetEnviron(void);
6349 #define environ (*_NSGetEnviron())
6357 ICALL_EXPORT MonoArray *
6358 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6369 env_strings = GetEnvironmentStrings();
6372 env_string = env_strings;
6373 while (*env_string != '\0') {
6374 /* weird case that MS seems to skip */
6375 if (*env_string != '=')
6377 while (*env_string != '\0')
6383 domain = mono_domain_get ();
6384 names = mono_array_new (domain, mono_defaults.string_class, n);
6388 env_string = env_strings;
6389 while (*env_string != '\0') {
6390 /* weird case that MS seems to skip */
6391 if (*env_string != '=') {
6392 equal_str = wcschr(env_string, '=');
6393 g_assert(equal_str);
6394 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6395 mono_array_setref (names, n, str);
6398 while (*env_string != '\0')
6403 FreeEnvironmentStrings (env_strings);
6415 MONO_ARCH_SAVE_REGS;
6418 for (e = environ; *e != 0; ++ e)
6421 domain = mono_domain_get ();
6422 names = mono_array_new (domain, mono_defaults.string_class, n);
6425 for (e = environ; *e != 0; ++ e) {
6426 parts = g_strsplit (*e, "=", 2);
6428 str = mono_string_new (domain, *parts);
6429 mono_array_setref (names, n, str);
6442 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6444 #if !GLIB_CHECK_VERSION(2,4,0)
6445 #define g_setenv(a,b,c) setenv(a,b,c)
6446 #define g_unsetenv(a) unsetenv(a)
6450 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6455 gunichar2 *utf16_name, *utf16_value;
6457 gchar *utf8_name, *utf8_value;
6460 MONO_ARCH_SAVE_REGS;
6463 utf16_name = mono_string_to_utf16 (name);
6464 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6465 SetEnvironmentVariable (utf16_name, NULL);
6466 g_free (utf16_name);
6470 utf16_value = mono_string_to_utf16 (value);
6472 SetEnvironmentVariable (utf16_name, utf16_value);
6474 g_free (utf16_name);
6475 g_free (utf16_value);
6477 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6479 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6480 g_unsetenv (utf8_name);
6485 utf8_value = mono_string_to_utf8_checked (value, &error);
6486 if (!mono_error_ok (&error)) {
6488 mono_error_raise_exception (&error);
6490 g_setenv (utf8_name, utf8_value, TRUE);
6493 g_free (utf8_value);
6498 ves_icall_System_Environment_Exit (int result)
6500 MONO_ARCH_SAVE_REGS;
6502 mono_environment_exitcode_set (result);
6504 /* FIXME: There are some cleanup hangs that should be worked out, but
6505 * if the program is going to exit, everything will be cleaned up when
6506 * NaCl exits anyway.
6508 #ifndef __native_client__
6509 if (!mono_runtime_try_shutdown ())
6510 mono_thread_exit ();
6512 /* Suspend all managed threads since the runtime is going away */
6513 mono_thread_suspend_all_other_threads ();
6515 mono_runtime_quit ();
6518 /* we may need to do some cleanup here... */
6522 ICALL_EXPORT MonoString*
6523 ves_icall_System_Environment_GetGacPath (void)
6525 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6528 ICALL_EXPORT MonoString*
6529 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6531 #if defined (HOST_WIN32)
6532 #ifndef CSIDL_FLAG_CREATE
6533 #define CSIDL_FLAG_CREATE 0x8000
6536 WCHAR path [MAX_PATH];
6537 /* Create directory if no existing */
6538 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6542 return mono_string_new_utf16 (mono_domain_get (), path, len);
6545 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6547 return mono_string_new (mono_domain_get (), "");
6550 ICALL_EXPORT MonoArray *
6551 ves_icall_System_Environment_GetLogicalDrives (void)
6553 gunichar2 buf [256], *ptr, *dname;
6555 guint initial_size = 127, size = 128;
6558 MonoString *drivestr;
6559 MonoDomain *domain = mono_domain_get ();
6562 MONO_ARCH_SAVE_REGS;
6567 while (size > initial_size) {
6568 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6569 if (size > initial_size) {
6572 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6573 initial_size = size;
6587 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6592 while (*u16) { u16++; len ++; }
6593 drivestr = mono_string_new_utf16 (domain, dname, len);
6594 mono_array_setref (result, ndrives++, drivestr);
6604 ICALL_EXPORT MonoString *
6605 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6607 gunichar2 volume_name [MAX_PATH + 1];
6609 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6611 return mono_string_from_utf16 (volume_name);
6614 ICALL_EXPORT MonoString *
6615 ves_icall_System_Environment_InternalGetHome (void)
6617 MONO_ARCH_SAVE_REGS;
6619 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6622 static const char *encodings [] = {
6624 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6625 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6626 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6628 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6629 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6630 "x_unicode_2_0_utf_7",
6632 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6633 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6635 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6638 "unicodefffe", "utf_16be",
6645 * Returns the internal codepage, if the value of "int_code_page" is
6646 * 1 at entry, and we can not compute a suitable code page number,
6647 * returns the code page as a string
6649 ICALL_EXPORT MonoString*
6650 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6655 char *codepage = NULL;
6657 int want_name = *int_code_page;
6660 *int_code_page = -1;
6661 MONO_ARCH_SAVE_REGS;
6663 g_get_charset (&cset);
6664 c = codepage = strdup (cset);
6665 for (c = codepage; *c; c++){
6666 if (isascii (*c) && isalpha (*c))
6671 /* g_print ("charset: %s\n", cset); */
6673 /* handle some common aliases */
6676 for (i = 0; p != 0; ){
6677 if ((gssize) p < 7){
6679 p = encodings [++i];
6682 if (strcmp (p, codepage) == 0){
6683 *int_code_page = code;
6686 p = encodings [++i];
6689 if (strstr (codepage, "utf_8") != NULL)
6690 *int_code_page |= 0x10000000;
6693 if (want_name && *int_code_page == -1)
6694 return mono_string_new (mono_domain_get (), cset);
6699 ICALL_EXPORT MonoBoolean
6700 ves_icall_System_Environment_get_HasShutdownStarted (void)
6702 if (mono_runtime_is_shutting_down ())
6705 if (mono_domain_is_unloading (mono_domain_get ()))
6712 ves_icall_System_Environment_BroadcastSettingChange (void)
6715 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6720 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6721 MonoReflectionMethod *method,
6722 MonoArray *out_args)
6724 MONO_ARCH_SAVE_REGS;
6726 mono_message_init (mono_object_domain (this), this, method, out_args);
6729 #ifndef DISABLE_REMOTING
6730 ICALL_EXPORT MonoBoolean
6731 ves_icall_IsTransparentProxy (MonoObject *proxy)
6733 MONO_ARCH_SAVE_REGS;
6738 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6744 ICALL_EXPORT MonoReflectionMethod *
6745 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6746 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6750 MonoMethod **vtable;
6751 MonoMethod *res = NULL;
6753 MONO_CHECK_ARG_NULL (rtype);
6754 MONO_CHECK_ARG_NULL (rmethod);
6756 method = rmethod->method;
6757 klass = mono_class_from_mono_type (rtype->type);
6758 mono_class_init_or_throw (klass);
6760 if (MONO_CLASS_IS_INTERFACE (klass))
6763 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6766 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6767 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6773 mono_class_setup_vtable (klass);
6774 vtable = klass->vtable;
6776 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6777 gboolean variance_used = FALSE;
6778 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6779 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6781 res = vtable [offs + method->slot];
6783 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6786 if (method->slot != -1)
6787 res = vtable [method->slot];
6793 return mono_method_get_object (mono_domain_get (), res, NULL);
6797 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6802 MONO_ARCH_SAVE_REGS;
6804 klass = mono_class_from_mono_type (type->type);
6805 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6807 mono_vtable_set_is_remote (vtable, enable);
6810 #else /* DISABLE_REMOTING */
6813 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6815 g_assert_not_reached ();
6820 ICALL_EXPORT MonoObject *
6821 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6826 MONO_ARCH_SAVE_REGS;
6828 domain = mono_object_domain (type);
6829 klass = mono_class_from_mono_type (type->type);
6830 mono_class_init_or_throw (klass);
6832 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6833 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6835 if (klass->rank >= 1) {
6836 g_assert (klass->rank == 1);
6837 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6839 /* Bypass remoting object creation check */
6840 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6844 ICALL_EXPORT MonoString *
6845 ves_icall_System_IO_get_temp_path (void)
6847 MONO_ARCH_SAVE_REGS;
6849 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6852 #ifndef PLATFORM_NO_DRIVEINFO
6853 ICALL_EXPORT MonoBoolean
6854 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6855 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6859 ULARGE_INTEGER wapi_free_bytes_avail;
6860 ULARGE_INTEGER wapi_total_number_of_bytes;
6861 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6863 MONO_ARCH_SAVE_REGS;
6865 *error = ERROR_SUCCESS;
6866 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6867 &wapi_total_number_of_free_bytes);
6870 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6871 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6872 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6874 *free_bytes_avail = 0;
6875 *total_number_of_bytes = 0;
6876 *total_number_of_free_bytes = 0;
6877 *error = GetLastError ();
6883 ICALL_EXPORT guint32
6884 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6886 MONO_ARCH_SAVE_REGS;
6888 return GetDriveType (mono_string_chars (root_path_name));
6892 ICALL_EXPORT gpointer
6893 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6895 MONO_ARCH_SAVE_REGS;
6897 return mono_compile_method (method);
6900 ICALL_EXPORT MonoString *
6901 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6906 MONO_ARCH_SAVE_REGS;
6908 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6910 #if defined (HOST_WIN32)
6911 /* Avoid mixing '/' and '\\' */
6914 for (i = strlen (path) - 1; i >= 0; i--)
6915 if (path [i] == '/')
6919 mcpath = mono_string_new (mono_domain_get (), path);
6926 get_bundled_app_config (void)
6928 const gchar *app_config;
6931 gchar *config_file_name, *config_file_path;
6935 MONO_ARCH_SAVE_REGS;
6937 domain = mono_domain_get ();
6938 file = domain->setup->configuration_file;
6942 // Retrieve config file and remove the extension
6943 config_file_name = mono_string_to_utf8 (file);
6944 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6945 if (!config_file_path)
6946 config_file_path = config_file_name;
6947 len = strlen (config_file_path) - strlen (".config");
6948 module = g_malloc0 (len + 1);
6949 memcpy (module, config_file_path, len);
6950 // Get the config file from the module name
6951 app_config = mono_config_string_for_assembly_file (module);
6954 if (config_file_name != config_file_path)
6955 g_free (config_file_name);
6956 g_free (config_file_path);
6961 return mono_string_new (mono_domain_get (), app_config);
6965 get_bundled_machine_config (void)
6967 const gchar *machine_config;
6969 MONO_ARCH_SAVE_REGS;
6971 machine_config = mono_get_machine_config ();
6973 if (!machine_config)
6976 return mono_string_new (mono_domain_get (), machine_config);
6979 ICALL_EXPORT MonoString *
6980 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6985 MONO_ARCH_SAVE_REGS;
6987 path = g_path_get_dirname (mono_get_config_dir ());
6989 #if defined (HOST_WIN32)
6990 /* Avoid mixing '/' and '\\' */
6993 for (i = strlen (path) - 1; i >= 0; i--)
6994 if (path [i] == '/')
6998 ipath = mono_string_new (mono_domain_get (), path);
7004 ICALL_EXPORT gboolean
7005 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7007 MonoPEResourceDataEntry *entry;
7010 MONO_ARCH_SAVE_REGS;
7012 if (!assembly || !result || !size)
7017 image = assembly->assembly->image;
7018 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7022 *result = mono_image_rva_map (image, entry->rde_data_offset);
7027 *size = entry->rde_size;
7032 ICALL_EXPORT MonoBoolean
7033 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7035 return mono_is_debugger_attached ();
7038 ICALL_EXPORT MonoBoolean
7039 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7041 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7042 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7048 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7050 if (mono_get_runtime_callbacks ()->debug_log)
7051 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7055 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7057 #if defined (HOST_WIN32)
7058 OutputDebugString (mono_string_chars (message));
7060 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7064 /* Only used for value types */
7065 ICALL_EXPORT MonoObject *
7066 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7071 MONO_ARCH_SAVE_REGS;
7073 domain = mono_object_domain (type);
7074 klass = mono_class_from_mono_type (type->type);
7075 mono_class_init_or_throw (klass);
7077 if (mono_class_is_nullable (klass))
7078 /* No arguments -> null */
7081 return mono_object_new (domain, klass);
7084 ICALL_EXPORT MonoReflectionMethod *
7085 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7087 MonoClass *klass, *parent;
7088 MonoMethod *method = m->method;
7089 MonoMethod *result = NULL;
7092 MONO_ARCH_SAVE_REGS;
7094 if (method->klass == NULL)
7097 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7098 MONO_CLASS_IS_INTERFACE (method->klass) ||
7099 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7102 slot = mono_method_get_vtable_slot (method);
7106 klass = method->klass;
7107 if (klass->generic_class)
7108 klass = klass->generic_class->container_class;
7111 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7112 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7113 mono_class_setup_vtable (parent);
7114 if (parent->vtable_size <= slot)
7119 klass = klass->parent;
7124 if (klass == method->klass)
7127 /*This is possible if definition == FALSE.
7128 * Do it here to be really sure we don't read invalid memory.
7130 if (slot >= klass->vtable_size)
7133 mono_class_setup_vtable (klass);
7135 result = klass->vtable [slot];
7136 if (result == NULL) {
7137 /* It is an abstract method */
7138 gpointer iter = NULL;
7139 while ((result = mono_class_get_methods (klass, &iter)))
7140 if (result->slot == slot)
7147 return mono_method_get_object (mono_domain_get (), result, NULL);
7150 ICALL_EXPORT MonoString*
7151 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7153 MonoMethod *method = m->method;
7155 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7160 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7162 MONO_ARCH_SAVE_REGS;
7164 iter->sig = *(MonoMethodSignature**)argsp;
7166 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7167 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7170 /* FIXME: it's not documented what start is exactly... */
7174 iter->args = argsp + sizeof (gpointer);
7176 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7178 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7181 ICALL_EXPORT MonoTypedRef
7182 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7184 guint32 i, arg_size;
7187 MONO_ARCH_SAVE_REGS;
7189 i = iter->sig->sentinelpos + iter->next_arg;
7191 g_assert (i < iter->sig->param_count);
7193 res.type = iter->sig->params [i];
7194 res.klass = mono_class_from_mono_type (res.type);
7195 arg_size = mono_type_stack_size (res.type, &align);
7196 #if defined(__arm__) || defined(__mips__)
7197 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7199 res.value = iter->args;
7200 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7201 /* Values are stored as 8 byte register sized objects, but 'value'
7202 * is dereferenced as a pointer in other routines.
7204 res.value = (char*)res.value + 4;
7206 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7207 if (arg_size <= sizeof (gpointer)) {
7209 int padding = arg_size - mono_type_size (res.type, &dummy);
7210 res.value = (guint8*)res.value + padding;
7213 iter->args = (char*)iter->args + arg_size;
7216 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7221 ICALL_EXPORT MonoTypedRef
7222 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7224 guint32 i, arg_size;
7227 MONO_ARCH_SAVE_REGS;
7229 i = iter->sig->sentinelpos + iter->next_arg;
7231 g_assert (i < iter->sig->param_count);
7233 while (i < iter->sig->param_count) {
7234 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7236 res.type = iter->sig->params [i];
7237 res.klass = mono_class_from_mono_type (res.type);
7238 /* FIXME: endianess issue... */
7239 arg_size = mono_type_stack_size (res.type, &align);
7240 #if defined(__arm__) || defined(__mips__)
7241 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7243 res.value = iter->args;
7244 iter->args = (char*)iter->args + arg_size;
7246 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7249 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7257 ICALL_EXPORT MonoType*
7258 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7261 MONO_ARCH_SAVE_REGS;
7263 i = iter->sig->sentinelpos + iter->next_arg;
7265 g_assert (i < iter->sig->param_count);
7267 return iter->sig->params [i];
7270 ICALL_EXPORT MonoObject*
7271 mono_TypedReference_ToObject (MonoTypedRef tref)
7273 MONO_ARCH_SAVE_REGS;
7275 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7276 MonoObject** objp = tref.value;
7280 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7283 ICALL_EXPORT MonoObject*
7284 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7286 MONO_ARCH_SAVE_REGS;
7288 if (MONO_TYPE_IS_REFERENCE (type)) {
7289 MonoObject** objp = value;
7293 return mono_value_box (mono_domain_get (), klass, value);
7297 prelink_method (MonoMethod *method)
7299 const char *exc_class, *exc_arg;
7300 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7302 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7304 mono_raise_exception(
7305 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7307 /* create the wrapper, too? */
7311 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7313 MONO_ARCH_SAVE_REGS;
7314 prelink_method (method->method);
7318 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7320 MonoClass *klass = mono_class_from_mono_type (type->type);
7322 gpointer iter = NULL;
7323 MONO_ARCH_SAVE_REGS;
7325 mono_class_init_or_throw (klass);
7327 while ((m = mono_class_get_methods (klass, &iter)))
7331 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7333 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7334 gint32 const **exponents,
7335 gunichar2 const **digitLowerTable,
7336 gunichar2 const **digitUpperTable,
7337 gint64 const **tenPowersList,
7338 gint32 const **decHexDigits)
7340 *mantissas = Formatter_MantissaBitsTable;
7341 *exponents = Formatter_TensExponentTable;
7342 *digitLowerTable = Formatter_DigitLowerTable;
7343 *digitUpperTable = Formatter_DigitUpperTable;
7344 *tenPowersList = Formatter_TenPowersList;
7345 *decHexDigits = Formatter_DecHexDigits;
7349 get_category_data (int version,
7350 guint8 const **category_data,
7351 guint16 const **category_astral_index)
7353 *category_astral_index = NULL;
7355 #ifndef DISABLE_NET_4_0
7357 *category_data = CategoryData_v4;
7358 #ifndef DISABLE_ASTRAL
7359 *category_astral_index = CategoryData_v4_astral_index;
7365 *category_data = CategoryData_v2;
7366 #ifndef DISABLE_ASTRAL
7367 *category_astral_index = CategoryData_v2_astral_index;
7371 /* These parameters are "readonly" in corlib/System/Char.cs */
7373 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7374 guint8 const **category_data,
7375 guint16 const **category_astral_index,
7376 guint8 const **numeric_data,
7377 gdouble const **numeric_data_values,
7378 guint16 const **to_lower_data_low,
7379 guint16 const **to_lower_data_high,
7380 guint16 const **to_upper_data_low,
7381 guint16 const **to_upper_data_high)
7383 get_category_data (category_data_version, category_data, category_astral_index);
7384 *numeric_data = NumericData;
7385 *numeric_data_values = NumericDataValues;
7386 *to_lower_data_low = ToLowerDataLow;
7387 *to_lower_data_high = ToLowerDataHigh;
7388 *to_upper_data_low = ToUpperDataLow;
7389 *to_upper_data_high = ToUpperDataHigh;
7393 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7395 return method->method->token;
7399 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7400 * and avoid useless allocations.
7403 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7407 for (i = 0; i < type->num_mods; ++i) {
7408 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7413 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7415 for (i = 0; i < type->num_mods; ++i) {
7416 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7417 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7418 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7425 ICALL_EXPORT MonoArray*
7426 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7428 MonoType *type = param->ClassImpl->type;
7429 MonoClass *member_class = mono_object_class (param->MemberImpl);
7430 MonoMethod *method = NULL;
7433 MonoMethodSignature *sig;
7435 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7436 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7437 method = rmethod->method;
7438 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7439 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7440 if (!(method = prop->property->get))
7441 method = prop->property->set;
7444 char *type_name = mono_type_get_full_name (member_class);
7445 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7446 MonoException *ex = mono_get_exception_not_supported (msg);
7449 mono_raise_exception (ex);
7452 image = method->klass->image;
7453 pos = param->PositionImpl;
7454 sig = mono_method_signature (method);
7458 type = sig->params [pos];
7460 return type_array_from_modifiers (image, type, optional);
7464 get_property_type (MonoProperty *prop)
7466 MonoMethodSignature *sig;
7468 sig = mono_method_signature (prop->get);
7470 } else if (prop->set) {
7471 sig = mono_method_signature (prop->set);
7472 return sig->params [sig->param_count - 1];
7477 ICALL_EXPORT MonoArray*
7478 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7480 MonoType *type = get_property_type (property->property);
7481 MonoImage *image = property->klass->image;
7485 return type_array_from_modifiers (image, type, optional);
7489 *Construct a MonoType suited to be used to decode a constant blob object.
7491 * @type is the target type which will be constructed
7492 * @blob_type is the blob type, for example, that comes from the constant table
7493 * @real_type is the expected constructed type.
7496 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7498 type->type = blob_type;
7499 type->data.klass = NULL;
7500 if (blob_type == MONO_TYPE_CLASS)
7501 type->data.klass = mono_defaults.object_class;
7502 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7503 /* For enums, we need to use the base type */
7504 type->type = MONO_TYPE_VALUETYPE;
7505 type->data.klass = mono_class_from_mono_type (real_type);
7507 type->data.klass = mono_class_from_mono_type (real_type);
7510 ICALL_EXPORT MonoObject*
7511 property_info_get_default_value (MonoReflectionProperty *property)
7514 MonoProperty *prop = property->property;
7515 MonoType *type = get_property_type (prop);
7516 MonoDomain *domain = mono_object_domain (property);
7517 MonoTypeEnum def_type;
7518 const char *def_value;
7521 mono_class_init (prop->parent);
7523 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7524 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7526 def_value = mono_class_get_property_default_value (prop, &def_type);
7528 mono_type_from_blob_type (&blob_type, def_type, type);
7529 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7534 ICALL_EXPORT MonoBoolean
7535 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7537 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7538 MonoCustomAttrInfo *cinfo;
7541 mono_class_init_or_throw (attr_class);
7543 cinfo = mono_reflection_get_custom_attrs_info (obj);
7546 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7548 mono_custom_attrs_free (cinfo);
7552 ICALL_EXPORT MonoArray*
7553 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7555 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7560 mono_class_init_or_throw (attr_class);
7562 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7563 if (!mono_error_ok (&error))
7564 mono_error_raise_exception (&error);
7565 if (mono_loader_get_last_error ()) {
7566 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7567 g_assert_not_reached ();
7575 ICALL_EXPORT MonoString*
7576 ves_icall_Mono_Runtime_GetDisplayName (void)
7579 MonoString *display_name;
7581 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7582 display_name = mono_string_new (mono_domain_get (), info);
7584 return display_name;
7587 ICALL_EXPORT MonoString*
7588 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7590 MonoString *message;
7594 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7595 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7598 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7600 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7608 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7609 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7610 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7611 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7612 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7613 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7614 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7615 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7619 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7624 gunichar2 last, prev_last, prev2_last;
7631 int havePadding = 0;
7633 last = prev_last = 0, prev2_last = 0;
7634 for (i = 0; i < ilength; i++) {
7636 if (c >= sizeof (dbase64)) {
7637 exc = mono_exception_from_name_msg (mono_get_corlib (),
7638 "System", "FormatException",
7639 "Invalid character found.");
7640 mono_raise_exception (exc);
7641 } else if (isspace (c)) {
7643 } else if (havePadding && c != '=') {
7644 exc = mono_exception_from_name_msg (mono_get_corlib (),
7645 "System", "FormatException",
7646 "Invalid character found.");
7647 mono_raise_exception (exc);
7649 if (c == '=') havePadding = 1;
7650 prev2_last = prev_last;
7656 olength = ilength - ignored;
7658 if (allowWhitespaceOnly && olength == 0) {
7659 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7662 if ((olength & 3) != 0 || olength <= 0) {
7663 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7664 "FormatException", "Invalid length.");
7665 mono_raise_exception (exc);
7668 if (prev2_last == '=') {
7669 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7670 mono_raise_exception (exc);
7673 olength = (olength * 3) / 4;
7677 if (prev_last == '=')
7680 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7681 res_ptr = mono_array_addr (result, guchar, 0);
7682 for (i = 0; i < ilength; ) {
7685 for (k = 0; k < 4 && i < ilength;) {
7691 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7692 exc = mono_exception_from_name_msg (mono_get_corlib (),
7693 "System", "FormatException",
7694 "Invalid character found.");
7695 mono_raise_exception (exc);
7700 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7702 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7704 *res_ptr++ = (b [2] << 6) | b [3];
7706 while (i < ilength && isspace (start [i]))
7713 ICALL_EXPORT MonoArray *
7714 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7716 MONO_ARCH_SAVE_REGS;
7718 return base64_to_byte_array (mono_string_chars (str),
7719 mono_string_length (str), allowWhitespaceOnly);
7722 ICALL_EXPORT MonoArray *
7723 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7725 MONO_ARCH_SAVE_REGS;
7727 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7731 #ifndef DISABLE_ICALL_TABLES
7733 #define ICALL_TYPE(id,name,first)
7734 #define ICALL(id,name,func) Icall_ ## id,
7737 #include "metadata/icall-def.h"
7743 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7744 #define ICALL(id,name,func)
7746 #include "metadata/icall-def.h"
7752 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7753 #define ICALL(id,name,func)
7755 guint16 first_icall;
7758 static const IcallTypeDesc
7759 icall_type_descs [] = {
7760 #include "metadata/icall-def.h"
7764 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7767 #define ICALL_TYPE(id,name,first)
7770 #ifdef HAVE_ARRAY_ELEM_INIT
7771 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7772 #define MSGSTRFIELD1(line) str##line
7774 static const struct msgstrtn_t {
7775 #define ICALL(id,name,func)
7777 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7778 #include "metadata/icall-def.h"
7780 } icall_type_names_str = {
7781 #define ICALL_TYPE(id,name,first) (name),
7782 #include "metadata/icall-def.h"
7785 static const guint16 icall_type_names_idx [] = {
7786 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7787 #include "metadata/icall-def.h"
7790 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7792 static const struct msgstr_t {
7794 #define ICALL_TYPE(id,name,first)
7795 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7796 #include "metadata/icall-def.h"
7798 } icall_names_str = {
7799 #define ICALL(id,name,func) (name),
7800 #include "metadata/icall-def.h"
7803 static const guint16 icall_names_idx [] = {
7804 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7805 #include "metadata/icall-def.h"
7808 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7814 #define ICALL_TYPE(id,name,first) name,
7815 #define ICALL(id,name,func)
7816 static const char* const
7817 icall_type_names [] = {
7818 #include "metadata/icall-def.h"
7822 #define icall_type_name_get(id) (icall_type_names [(id)])
7826 #define ICALL_TYPE(id,name,first)
7827 #define ICALL(id,name,func) name,
7828 static const char* const
7830 #include "metadata/icall-def.h"
7833 #define icall_name_get(id) icall_names [(id)]
7835 #endif /* !HAVE_ARRAY_ELEM_INIT */
7839 #define ICALL_TYPE(id,name,first)
7840 #define ICALL(id,name,func) func,
7841 static const gconstpointer
7842 icall_functions [] = {
7843 #include "metadata/icall-def.h"
7847 #ifdef ENABLE_ICALL_SYMBOL_MAP
7850 #define ICALL_TYPE(id,name,first)
7851 #define ICALL(id,name,func) #func,
7852 static const gconstpointer
7853 icall_symbols [] = {
7854 #include "metadata/icall-def.h"
7859 #endif /* DISABLE_ICALL_TABLES */
7861 static mono_mutex_t icall_mutex;
7862 static GHashTable *icall_hash = NULL;
7863 static GHashTable *jit_icall_hash_name = NULL;
7864 static GHashTable *jit_icall_hash_addr = NULL;
7867 mono_icall_init (void)
7869 #ifndef DISABLE_ICALL_TABLES
7872 /* check that tables are sorted: disable in release */
7875 const char *prev_class = NULL;
7876 const char *prev_method;
7878 for (i = 0; i < Icall_type_num; ++i) {
7879 const IcallTypeDesc *desc;
7882 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7883 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7884 prev_class = icall_type_name_get (i);
7885 desc = &icall_type_descs [i];
7886 num_icalls = icall_desc_num_icalls (desc);
7887 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7888 for (j = 0; j < num_icalls; ++j) {
7889 const char *methodn = icall_name_get (desc->first_icall + j);
7890 if (prev_method && strcmp (prev_method, methodn) >= 0)
7891 g_print ("method %s should come before method %s\n", methodn, prev_method);
7892 prev_method = methodn;
7898 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7899 mono_mutex_init (&icall_mutex);
7903 mono_icall_lock (void)
7905 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7909 mono_icall_unlock (void)
7911 mono_locks_mutex_release (&icall_mutex, IcallLock);
7915 mono_icall_cleanup (void)
7917 g_hash_table_destroy (icall_hash);
7918 g_hash_table_destroy (jit_icall_hash_name);
7919 g_hash_table_destroy (jit_icall_hash_addr);
7920 mono_mutex_destroy (&icall_mutex);
7924 mono_add_internal_call (const char *name, gconstpointer method)
7928 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7930 mono_icall_unlock ();
7933 #ifndef DISABLE_ICALL_TABLES
7935 #ifdef HAVE_ARRAY_ELEM_INIT
7937 compare_method_imap (const void *key, const void *elem)
7939 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7940 return strcmp (key, method_name);
7944 find_method_icall (const IcallTypeDesc *imap, const char *name)
7946 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);
7949 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7953 compare_class_imap (const void *key, const void *elem)
7955 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7956 return strcmp (key, class_name);
7959 static const IcallTypeDesc*
7960 find_class_icalls (const char *name)
7962 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7965 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7968 #else /* HAVE_ARRAY_ELEM_INIT */
7971 compare_method_imap (const void *key, const void *elem)
7973 const char** method_name = (const char**)elem;
7974 return strcmp (key, *method_name);
7978 find_method_icall (const IcallTypeDesc *imap, const char *name)
7980 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7983 return (gpointer)icall_functions [(nameslot - icall_names)];
7987 compare_class_imap (const void *key, const void *elem)
7989 const char** class_name = (const char**)elem;
7990 return strcmp (key, *class_name);
7993 static const IcallTypeDesc*
7994 find_class_icalls (const char *name)
7996 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7999 return &icall_type_descs [nameslot - icall_type_names];
8002 #endif /* HAVE_ARRAY_ELEM_INIT */
8004 #endif /* DISABLE_ICALL_TABLES */
8007 * we should probably export this as an helper (handle nested types).
8008 * Returns the number of chars written in buf.
8011 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8013 int nspacelen, cnamelen;
8014 nspacelen = strlen (klass->name_space);
8015 cnamelen = strlen (klass->name);
8016 if (nspacelen + cnamelen + 2 > bufsize)
8019 memcpy (buf, klass->name_space, nspacelen);
8020 buf [nspacelen ++] = '.';
8022 memcpy (buf + nspacelen, klass->name, cnamelen);
8023 buf [nspacelen + cnamelen] = 0;
8024 return nspacelen + cnamelen;
8027 #ifdef DISABLE_ICALL_TABLES
8029 no_icall_table (void)
8031 g_assert_not_reached ();
8036 mono_lookup_internal_call (MonoMethod *method)
8041 int typelen = 0, mlen, siglen;
8043 #ifndef DISABLE_ICALL_TABLES
8044 const IcallTypeDesc *imap = NULL;
8047 g_assert (method != NULL);
8049 if (method->is_inflated)
8050 method = ((MonoMethodInflated *) method)->declaring;
8052 if (method->klass->nested_in) {
8053 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8057 mname [pos++] = '/';
8060 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8066 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8071 #ifndef DISABLE_ICALL_TABLES
8072 imap = find_class_icalls (mname);
8075 mname [typelen] = ':';
8076 mname [typelen + 1] = ':';
8078 mlen = strlen (method->name);
8079 memcpy (mname + typelen + 2, method->name, mlen);
8080 sigstart = mname + typelen + 2 + mlen;
8083 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8084 siglen = strlen (tmpsig);
8085 if (typelen + mlen + siglen + 6 > sizeof (mname))
8088 memcpy (sigstart + 1, tmpsig, siglen);
8089 sigstart [siglen + 1] = ')';
8090 sigstart [siglen + 2] = 0;
8095 res = g_hash_table_lookup (icall_hash, mname);
8097 mono_icall_unlock ();;
8100 /* try without signature */
8102 res = g_hash_table_lookup (icall_hash, mname);
8104 mono_icall_unlock ();
8108 #ifdef DISABLE_ICALL_TABLES
8109 mono_icall_unlock ();
8110 /* Fail only when the result is actually used */
8111 /* mono_marshal_get_native_wrapper () depends on this */
8112 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8113 return ves_icall_System_String_ctor_RedirectToCreateString;
8115 return no_icall_table;
8117 /* it wasn't found in the static call tables */
8119 mono_icall_unlock ();
8122 res = find_method_icall (imap, sigstart - mlen);
8124 mono_icall_unlock ();
8127 /* try _with_ signature */
8129 res = find_method_icall (imap, sigstart - mlen);
8131 mono_icall_unlock ();
8135 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8136 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8137 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8138 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8139 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");
8140 g_print ("If you see other errors or faults after this message they are probably related\n");
8141 g_print ("and you need to fix your mono install first.\n");
8143 mono_icall_unlock ();
8149 #ifdef ENABLE_ICALL_SYMBOL_MAP
8151 func_cmp (gconstpointer key, gconstpointer p)
8153 return (gsize)key - (gsize)*(gsize*)p;
8158 * mono_lookup_icall_symbol:
8160 * Given the icall METHOD, returns its C symbol.
8163 mono_lookup_icall_symbol (MonoMethod *m)
8165 #ifdef DISABLE_ICALL_TABLES
8166 g_assert_not_reached ();
8169 #ifdef ENABLE_ICALL_SYMBOL_MAP
8173 static gconstpointer *functions_sorted;
8174 static const char**symbols_sorted;
8175 static gboolean inited;
8180 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8181 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8182 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8183 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8184 /* Bubble sort the two arrays */
8188 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8189 if (functions_sorted [i] > functions_sorted [i + 1]) {
8192 tmp = functions_sorted [i];
8193 functions_sorted [i] = functions_sorted [i + 1];
8194 functions_sorted [i + 1] = tmp;
8195 tmp = symbols_sorted [i];
8196 symbols_sorted [i] = symbols_sorted [i + 1];
8197 symbols_sorted [i + 1] = tmp;
8204 func = mono_lookup_internal_call (m);
8207 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8211 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8213 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8214 g_assert_not_reached ();
8221 type_from_typename (char *typename)
8223 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8225 if (!strcmp (typename, "int"))
8226 klass = mono_defaults.int_class;
8227 else if (!strcmp (typename, "ptr"))
8228 klass = mono_defaults.int_class;
8229 else if (!strcmp (typename, "void"))
8230 klass = mono_defaults.void_class;
8231 else if (!strcmp (typename, "int32"))
8232 klass = mono_defaults.int32_class;
8233 else if (!strcmp (typename, "uint32"))
8234 klass = mono_defaults.uint32_class;
8235 else if (!strcmp (typename, "int8"))
8236 klass = mono_defaults.sbyte_class;
8237 else if (!strcmp (typename, "uint8"))
8238 klass = mono_defaults.byte_class;
8239 else if (!strcmp (typename, "int16"))
8240 klass = mono_defaults.int16_class;
8241 else if (!strcmp (typename, "uint16"))
8242 klass = mono_defaults.uint16_class;
8243 else if (!strcmp (typename, "long"))
8244 klass = mono_defaults.int64_class;
8245 else if (!strcmp (typename, "ulong"))
8246 klass = mono_defaults.uint64_class;
8247 else if (!strcmp (typename, "float"))
8248 klass = mono_defaults.single_class;
8249 else if (!strcmp (typename, "double"))
8250 klass = mono_defaults.double_class;
8251 else if (!strcmp (typename, "object"))
8252 klass = mono_defaults.object_class;
8253 else if (!strcmp (typename, "obj"))
8254 klass = mono_defaults.object_class;
8255 else if (!strcmp (typename, "string"))
8256 klass = mono_defaults.string_class;
8257 else if (!strcmp (typename, "bool"))
8258 klass = mono_defaults.boolean_class;
8259 else if (!strcmp (typename, "boolean"))
8260 klass = mono_defaults.boolean_class;
8262 g_error ("%s", typename);
8263 g_assert_not_reached ();
8265 return &klass->byval_arg;
8269 * LOCKING: Take the corlib image lock.
8271 MonoMethodSignature*
8272 mono_create_icall_signature (const char *sigstr)
8277 MonoMethodSignature *res, *res2;
8278 MonoImage *corlib = mono_defaults.corlib;
8280 mono_image_lock (corlib);
8281 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8282 mono_image_unlock (corlib);
8287 parts = g_strsplit (sigstr, " ", 256);
8296 res = mono_metadata_signature_alloc (corlib, len - 1);
8301 * Under windows, the default pinvoke calling convention is STDCALL but
8304 res->call_convention = MONO_CALL_C;
8307 res->ret = type_from_typename (parts [0]);
8308 for (i = 1; i < len; ++i) {
8309 res->params [i - 1] = type_from_typename (parts [i]);
8314 mono_image_lock (corlib);
8315 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8317 res = res2; /*Value is allocated in the image pool*/
8319 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8320 mono_image_unlock (corlib);
8326 mono_find_jit_icall_by_name (const char *name)
8328 MonoJitICallInfo *info;
8329 g_assert (jit_icall_hash_name);
8332 info = g_hash_table_lookup (jit_icall_hash_name, name);
8333 mono_icall_unlock ();
8338 mono_find_jit_icall_by_addr (gconstpointer addr)
8340 MonoJitICallInfo *info;
8341 g_assert (jit_icall_hash_addr);
8344 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8345 mono_icall_unlock ();
8351 * mono_get_jit_icall_info:
8353 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8354 * caller should access it while holding the icall lock.
8357 mono_get_jit_icall_info (void)
8359 return jit_icall_hash_name;
8363 * mono_lookup_jit_icall_symbol:
8365 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8368 mono_lookup_jit_icall_symbol (const char *name)
8370 MonoJitICallInfo *info;
8371 const char *res = NULL;
8374 info = g_hash_table_lookup (jit_icall_hash_name, name);
8376 res = info->c_symbol;
8377 mono_icall_unlock ();
8382 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8385 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8386 mono_icall_unlock ();
8390 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8392 MonoJitICallInfo *info;
8399 if (!jit_icall_hash_name) {
8400 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8401 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8404 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8405 g_warning ("jit icall already defined \"%s\"\n", name);
8406 g_assert_not_reached ();
8409 info = g_new0 (MonoJitICallInfo, 1);
8414 info->c_symbol = c_symbol;
8417 info->wrapper = func;
8419 info->wrapper = NULL;
8422 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8423 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8425 mono_icall_unlock ();
8430 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8432 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);