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>
88 #if defined (HOST_WIN32)
94 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
96 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
99 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
101 static inline MonoBoolean
102 is_generic_parameter (MonoType *type)
104 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
108 mono_class_init_or_throw (MonoClass *klass)
110 if (!mono_class_init (klass))
111 mono_raise_exception (mono_class_get_exception_for_failure (klass));
115 * We expect a pointer to a char, not a string
117 ICALL_EXPORT gboolean
118 mono_double_ParseImpl (char *ptr, double *result)
120 gchar *endptr = NULL;
127 *result = strtod (ptr, &endptr);
130 /* mono_strtod () is not thread-safe */
131 EnterCriticalSection (&mono_strtod_mutex);
132 *result = mono_strtod (ptr, &endptr);
133 LeaveCriticalSection (&mono_strtod_mutex);
137 if (!*ptr || (endptr && *endptr))
143 ICALL_EXPORT MonoObject *
144 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
153 ao = (MonoArray *)this;
154 ac = (MonoClass *)ao->obj.vtable->klass;
156 esize = mono_array_element_size (ac);
157 ea = (gpointer*)((char*)ao->vector + (pos * esize));
159 if (ac->element_class->valuetype)
160 return mono_value_box (this->vtable->domain, ac->element_class, ea);
165 ICALL_EXPORT MonoObject *
166 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
174 MONO_CHECK_ARG_NULL (idxs);
176 io = (MonoArray *)idxs;
177 ic = (MonoClass *)io->obj.vtable->klass;
179 ao = (MonoArray *)this;
180 ac = (MonoClass *)ao->obj.vtable->klass;
182 g_assert (ic->rank == 1);
183 if (io->bounds != NULL || io->max_length != ac->rank)
184 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
186 ind = (gint32 *)io->vector;
188 if (ao->bounds == NULL) {
189 if (*ind < 0 || *ind >= ao->max_length)
190 mono_raise_exception (mono_get_exception_index_out_of_range ());
192 return ves_icall_System_Array_GetValueImpl (this, *ind);
195 for (i = 0; i < ac->rank; i++)
196 if ((ind [i] < ao->bounds [i].lower_bound) ||
197 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
198 mono_raise_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - ao->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos*ao->bounds [i].length + ind [i] -
203 ao->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (this, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
211 MonoClass *ac, *vc, *ec;
223 vc = value->vtable->klass;
227 ac = this->obj.vtable->klass;
228 ec = ac->element_class;
230 esize = mono_array_element_size (ac);
231 ea = (gpointer*)((char*)this->vector + (pos * esize));
232 va = (gpointer*)((char*)value + sizeof (MonoObject));
234 if (mono_class_is_nullable (ec)) {
235 mono_nullable_init ((guint8*)ea, value, ec);
240 mono_gc_bzero (ea, esize);
244 #define NO_WIDENING_CONVERSION G_STMT_START{\
245 mono_raise_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
249 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
250 if (esize < vsize + (extra)) \
251 mono_raise_exception (mono_get_exception_argument ( \
252 "value", "not a widening conversion")); \
255 #define INVALID_CAST G_STMT_START{ \
256 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
257 mono_raise_exception (mono_get_exception_invalid_cast ()); \
260 /* Check element (destination) type. */
261 switch (ec->byval_arg.type) {
262 case MONO_TYPE_STRING:
263 switch (vc->byval_arg.type) {
264 case MONO_TYPE_STRING:
270 case MONO_TYPE_BOOLEAN:
271 switch (vc->byval_arg.type) {
272 case MONO_TYPE_BOOLEAN:
285 NO_WIDENING_CONVERSION;
292 if (!ec->valuetype) {
293 if (!mono_object_isinst (value, ec))
295 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
299 if (mono_object_isinst (value, ec)) {
300 if (ec->has_references)
301 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
303 mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
310 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
312 et = ec->byval_arg.type;
313 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
314 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
316 vt = vc->byval_arg.type;
317 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
318 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
320 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
326 case MONO_TYPE_CHAR: \
327 CHECK_WIDENING_CONVERSION(0); \
328 *(etype *) ea = (etype) u64; \
330 /* You can't assign a signed value to an unsigned array. */ \
335 /* You can't assign a floating point number to an integer array. */ \
338 NO_WIDENING_CONVERSION; \
342 #define ASSIGN_SIGNED(etype) G_STMT_START{\
348 CHECK_WIDENING_CONVERSION(0); \
349 *(etype *) ea = (etype) i64; \
351 /* You can assign an unsigned value to a signed array if the array's */ \
352 /* element size is larger than the value size. */ \
357 case MONO_TYPE_CHAR: \
358 CHECK_WIDENING_CONVERSION(1); \
359 *(etype *) ea = (etype) u64; \
361 /* You can't assign a floating point number to an integer array. */ \
364 NO_WIDENING_CONVERSION; \
368 #define ASSIGN_REAL(etype) G_STMT_START{\
372 CHECK_WIDENING_CONVERSION(0); \
373 *(etype *) ea = (etype) r64; \
375 /* All integer values fit into a floating point array, so we don't */ \
376 /* need to CHECK_WIDENING_CONVERSION here. */ \
381 *(etype *) ea = (etype) i64; \
387 case MONO_TYPE_CHAR: \
388 *(etype *) ea = (etype) u64; \
395 u64 = *(guint8 *) va;
398 u64 = *(guint16 *) va;
401 u64 = *(guint32 *) va;
404 u64 = *(guint64 *) va;
410 i64 = *(gint16 *) va;
413 i64 = *(gint32 *) va;
416 i64 = *(gint64 *) va;
419 r64 = *(gfloat *) va;
422 r64 = *(gdouble *) va;
425 u64 = *(guint16 *) va;
427 case MONO_TYPE_BOOLEAN:
428 /* Boolean is only compatible with itself. */
441 NO_WIDENING_CONVERSION;
448 /* If we can't do a direct copy, let's try a widening conversion. */
451 ASSIGN_UNSIGNED (guint16);
453 ASSIGN_UNSIGNED (guint8);
455 ASSIGN_UNSIGNED (guint16);
457 ASSIGN_UNSIGNED (guint32);
459 ASSIGN_UNSIGNED (guint64);
461 ASSIGN_SIGNED (gint8);
463 ASSIGN_SIGNED (gint16);
465 ASSIGN_SIGNED (gint32);
467 ASSIGN_SIGNED (gint64);
469 ASSIGN_REAL (gfloat);
471 ASSIGN_REAL (gdouble);
475 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
479 #undef NO_WIDENING_CONVERSION
480 #undef CHECK_WIDENING_CONVERSION
481 #undef ASSIGN_UNSIGNED
487 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
495 MONO_CHECK_ARG_NULL (idxs);
497 ic = idxs->obj.vtable->klass;
498 ac = this->obj.vtable->klass;
500 g_assert (ic->rank == 1);
501 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
502 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
504 ind = (gint32 *)idxs->vector;
506 if (this->bounds == NULL) {
507 if (*ind < 0 || *ind >= this->max_length)
508 mono_raise_exception (mono_get_exception_index_out_of_range ());
510 ves_icall_System_Array_SetValueImpl (this, value, *ind);
514 for (i = 0; i < ac->rank; i++)
515 if ((ind [i] < this->bounds [i].lower_bound) ||
516 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
517 mono_raise_exception (mono_get_exception_index_out_of_range ());
519 pos = ind [0] - this->bounds [0].lower_bound;
520 for (i = 1; i < ac->rank; i++)
521 pos = pos * this->bounds [i].length + ind [i] -
522 this->bounds [i].lower_bound;
524 ves_icall_System_Array_SetValueImpl (this, value, pos);
527 ICALL_EXPORT MonoArray *
528 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
530 MonoClass *aklass, *klass;
533 gboolean bounded = FALSE;
537 MONO_CHECK_ARG_NULL (type);
538 MONO_CHECK_ARG_NULL (lengths);
540 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
542 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
544 for (i = 0; i < mono_array_length (lengths); i++)
545 if (mono_array_get (lengths, gint32, i) < 0)
546 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
548 klass = mono_class_from_mono_type (type->type);
549 mono_class_init_or_throw (klass);
551 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
552 /* vectors are not the same as one dimensional arrays with no-zero bounds */
557 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
559 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
560 for (i = 0; i < aklass->rank; ++i) {
561 sizes [i] = mono_array_get (lengths, guint32, i);
563 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
565 sizes [i + aklass->rank] = 0;
568 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
573 ICALL_EXPORT MonoArray *
574 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
576 MonoClass *aklass, *klass;
579 gboolean bounded = FALSE;
583 MONO_CHECK_ARG_NULL (type);
584 MONO_CHECK_ARG_NULL (lengths);
586 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
588 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
590 for (i = 0; i < mono_array_length (lengths); i++)
591 if ((mono_array_get (lengths, gint64, i) < 0) ||
592 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
593 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
595 klass = mono_class_from_mono_type (type->type);
596 mono_class_init_or_throw (klass);
598 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
599 /* vectors are not the same as one dimensional arrays with no-zero bounds */
604 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
606 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
607 for (i = 0; i < aklass->rank; ++i) {
608 sizes [i] = mono_array_get (lengths, guint64, i);
610 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
612 sizes [i + aklass->rank] = 0;
615 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
621 ves_icall_System_Array_GetRank (MonoObject *this)
625 return this->vtable->klass->rank;
629 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
631 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
636 if ((dimension < 0) || (dimension >= rank))
637 mono_raise_exception (mono_get_exception_index_out_of_range ());
639 if (this->bounds == NULL)
640 length = this->max_length;
642 length = this->bounds [dimension].length;
644 #ifdef MONO_BIG_ARRAYS
645 if (length > G_MAXINT32)
646 mono_raise_exception (mono_get_exception_overflow ());
652 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
654 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank))
659 mono_raise_exception (mono_get_exception_index_out_of_range ());
661 if (this->bounds == NULL)
662 return this->max_length;
664 return this->bounds [dimension].length;
668 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
670 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
674 if ((dimension < 0) || (dimension >= rank))
675 mono_raise_exception (mono_get_exception_index_out_of_range ());
677 if (this->bounds == NULL)
680 return this->bounds [dimension].lower_bound;
684 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
686 int sz = mono_array_element_size (mono_object_class (arr));
687 mono_gc_bzero (mono_array_addr_with_size (arr, sz, idx), length * sz);
690 ICALL_EXPORT gboolean
691 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
696 MonoClass *src_class;
697 MonoClass *dest_class;
701 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
704 if (source->bounds || dest->bounds)
707 /* there's no integer overflow since mono_array_length returns an unsigned integer */
708 if ((dest_idx + length > mono_array_length (dest)) ||
709 (source_idx + length > mono_array_length (source)))
712 src_class = source->obj.vtable->klass->element_class;
713 dest_class = dest->obj.vtable->klass->element_class;
716 * Handle common cases.
719 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
720 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
721 // FIXME: This is racy
725 int has_refs = dest_class->has_references;
726 for (i = source_idx; i < source_idx + length; ++i) {
727 MonoObject *elem = mono_array_get (source, MonoObject*, i);
728 if (elem && !mono_object_isinst (elem, dest_class))
732 element_size = mono_array_element_size (dest->obj.vtable->klass);
733 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
734 for (i = 0; i < length; ++i) {
735 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
736 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
740 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
742 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
748 /* Check if we're copying a char[] <==> (u)short[] */
749 if (src_class != dest_class) {
750 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
753 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
755 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
756 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
757 // FIXME: This is racy
761 for (i = source_idx; i < source_idx + length; ++i) {
762 MonoObject *elem = mono_array_get (source, MonoObject*, i);
763 if (elem && !mono_object_isinst (elem, dest_class))
771 if (dest_class->valuetype) {
772 element_size = mono_array_element_size (source->obj.vtable->klass);
773 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
774 if (dest_class->has_references) {
775 mono_value_copy_array (dest, dest_idx, source_addr, length);
777 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
778 mono_gc_memmove (dest_addr, source_addr, element_size * length);
781 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
788 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
797 ao = (MonoArray *)this;
798 ac = (MonoClass *)ao->obj.vtable->klass;
800 esize = mono_array_element_size (ac);
801 ea = (gpointer*)((char*)ao->vector + (pos * esize));
803 mono_gc_memmove (value, ea, esize);
807 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
816 ao = (MonoArray *)this;
817 ac = (MonoClass *)ao->obj.vtable->klass;
818 ec = ac->element_class;
820 esize = mono_array_element_size (ac);
821 ea = (gpointer*)((char*)ao->vector + (pos * esize));
823 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
824 g_assert (esize == sizeof (gpointer));
825 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
827 g_assert (ec->inited);
828 g_assert (esize == mono_class_value_size (ec, NULL));
829 if (ec->has_references)
830 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
832 mono_gc_memmove (ea, value, esize);
837 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
839 MonoClass *klass = array->obj.vtable->klass;
840 guint32 size = mono_array_element_size (klass);
841 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
843 const char *field_data;
845 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
846 MonoException *exc = mono_get_exception_argument("array",
847 "Cannot initialize array of non-primitive type.");
848 mono_raise_exception (exc);
851 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
852 MonoException *exc = mono_get_exception_argument("field_handle",
853 "Field doesn't have an RVA");
854 mono_raise_exception (exc);
857 size *= array->max_length;
858 field_data = mono_field_get_data (field_handle);
860 if (size > mono_type_size (field_handle->type, &align)) {
861 MonoException *exc = mono_get_exception_argument("field_handle",
862 "Field not large enough to fill array");
863 mono_raise_exception (exc);
866 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
868 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
869 guint ## n *src = (guint ## n *) field_data; \
870 guint ## n *end = (guint ## n *)((char*)src + size); \
872 for (; src < end; data++, src++) { \
873 *data = read ## n (src); \
877 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
879 switch (type->type) {
896 memcpy (mono_array_addr (array, char, 0), field_data, size);
900 memcpy (mono_array_addr (array, char, 0), field_data, size);
905 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
909 return offsetof (MonoString, chars);
912 ICALL_EXPORT MonoObject *
913 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
917 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
920 return mono_object_clone (obj);
924 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
929 MONO_CHECK_ARG_NULL (handle);
931 klass = mono_class_from_mono_type (handle);
932 MONO_CHECK_ARG (handle, klass);
934 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
936 /* This will call the type constructor */
937 mono_runtime_class_init (vtable);
941 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
945 mono_image_check_for_module_cctor (image);
946 if (image->has_module_cctor) {
947 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
948 /*It's fine to raise the exception here*/
949 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
953 ICALL_EXPORT MonoBoolean
954 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
959 /* later make this configurable and per-arch */
960 int min_size = 4096 * 4 * sizeof (void*);
961 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
962 /* if we have no info we are optimistic and assume there is enough room */
965 current = (guint8 *)&stack_addr;
966 if (current > stack_addr) {
967 if ((current - stack_addr) < min_size)
970 if (current - (stack_addr - stack_size) < min_size)
976 ICALL_EXPORT MonoObject *
977 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
981 return mono_object_clone (this);
985 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
988 MonoObject **values = NULL;
992 MonoClassField* field;
997 klass = mono_object_class (this);
999 if (mono_class_num_fields (klass) == 0)
1000 return mono_object_hash (this);
1003 * Compute the starting value of the hashcode for fields of primitive
1004 * types, and return the remaining fields in an array to the managed side.
1005 * This way, we can avoid costly reflection operations in managed code.
1008 while ((field = mono_class_get_fields (klass, &iter))) {
1009 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1011 if (mono_field_is_deleted (field))
1013 /* FIXME: Add more types */
1014 switch (field->type->type) {
1016 result ^= *(gint32*)((guint8*)this + field->offset);
1018 case MONO_TYPE_STRING: {
1020 s = *(MonoString**)((guint8*)this + field->offset);
1022 result ^= mono_string_hash (s);
1027 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1028 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1029 values [count++] = o;
1035 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1036 for (i = 0; i < count; ++i)
1037 mono_array_setref (*fields, i, values [i]);
1044 ICALL_EXPORT MonoBoolean
1045 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1048 MonoObject **values = NULL;
1050 MonoClassField* field;
1054 MONO_ARCH_SAVE_REGS;
1056 MONO_CHECK_ARG_NULL (that);
1058 if (this->vtable != that->vtable)
1061 klass = mono_object_class (this);
1063 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1064 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1067 * Do the comparison for fields of primitive type and return a result if
1068 * possible. Otherwise, return the remaining fields in an array to the
1069 * managed side. This way, we can avoid costly reflection operations in
1074 while ((field = mono_class_get_fields (klass, &iter))) {
1075 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1077 if (mono_field_is_deleted (field))
1079 /* FIXME: Add more types */
1080 switch (field->type->type) {
1083 case MONO_TYPE_BOOLEAN:
1084 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1089 case MONO_TYPE_CHAR:
1090 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1095 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1100 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1104 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1108 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1113 case MONO_TYPE_STRING: {
1114 MonoString *s1, *s2;
1115 guint32 s1len, s2len;
1116 s1 = *(MonoString**)((guint8*)this + field->offset);
1117 s2 = *(MonoString**)((guint8*)that + field->offset);
1120 if ((s1 == NULL) || (s2 == NULL))
1122 s1len = mono_string_length (s1);
1123 s2len = mono_string_length (s2);
1127 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1133 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1134 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1135 values [count++] = o;
1136 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1137 values [count++] = o;
1140 if (klass->enumtype)
1141 /* enums only have one non-static field */
1147 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1148 for (i = 0; i < count; ++i)
1149 mono_array_setref (*fields, i, values [i]);
1156 ICALL_EXPORT MonoReflectionType *
1157 ves_icall_System_Object_GetType (MonoObject *obj)
1159 MONO_ARCH_SAVE_REGS;
1161 #ifndef DISABLE_REMOTING
1162 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1163 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1166 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1170 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1172 MONO_ARCH_SAVE_REGS;
1174 mtype->type = &obj->vtable->klass->byval_arg;
1175 g_assert (mtype->type->type);
1179 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1181 MONO_ARCH_SAVE_REGS;
1183 MONO_CHECK_ARG_NULL (obj);
1185 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1189 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1190 MonoReflectionMethod *method,
1191 MonoArray *opt_param_types)
1193 MONO_ARCH_SAVE_REGS;
1195 MONO_CHECK_ARG_NULL (method);
1197 return mono_image_create_method_token (
1198 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1202 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1204 MONO_ARCH_SAVE_REGS;
1206 mono_image_create_pefile (mb, file);
1210 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1212 MONO_ARCH_SAVE_REGS;
1214 mono_image_build_metadata (mb);
1218 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1220 MONO_ARCH_SAVE_REGS;
1222 mono_image_register_token (mb->dynamic_image, token, obj);
1226 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1228 MonoMethod **dest = data;
1230 /* skip unmanaged frames */
1246 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1248 MonoMethod **dest = data;
1250 /* skip unmanaged frames */
1255 if (!strcmp (m->klass->name_space, "System.Reflection"))
1264 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1266 MonoMethod **dest = data;
1268 /* skip unmanaged frames */
1272 if (m->wrapper_type != MONO_WRAPPER_NONE)
1275 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1289 static MonoReflectionType *
1290 type_from_name (const char *str, MonoBoolean ignoreCase)
1292 MonoType *type = NULL;
1293 MonoAssembly *assembly = NULL;
1294 MonoTypeNameParse info;
1295 char *temp_str = g_strdup (str);
1296 gboolean type_resolve = FALSE;
1298 MONO_ARCH_SAVE_REGS;
1300 /* mono_reflection_parse_type() mangles the string */
1301 if (!mono_reflection_parse_type (temp_str, &info)) {
1302 mono_reflection_free_type_info (&info);
1307 if (info.assembly.name) {
1308 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1310 MonoMethod *m = mono_method_get_last_managed ();
1311 MonoMethod *dest = m;
1313 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1318 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1319 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1320 * to crash. This only seems to happen in some strange remoting
1321 * scenarios and I was unable to figure out what's happening there.
1322 * Dec 10, 2005 - Martin.
1326 assembly = dest->klass->image->assembly;
1327 type_resolve = TRUE;
1329 g_warning (G_STRLOC);
1334 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1335 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1338 if (!info.assembly.name && !type) /* try mscorlib */
1339 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1341 if (assembly && !type && type_resolve) {
1342 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1343 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1346 mono_reflection_free_type_info (&info);
1352 return mono_type_get_object (mono_domain_get (), type);
1356 MonoReflectionType *
1357 mono_type_get (const char *str)
1359 char *copy = g_strdup (str);
1360 MonoReflectionType *type = type_from_name (copy, FALSE);
1367 ICALL_EXPORT MonoReflectionType*
1368 ves_icall_type_from_name (MonoString *name,
1369 MonoBoolean throwOnError,
1370 MonoBoolean ignoreCase)
1372 char *str = mono_string_to_utf8 (name);
1373 MonoReflectionType *type;
1375 type = type_from_name (str, ignoreCase);
1378 MonoException *e = NULL;
1381 e = mono_get_exception_type_load (name, NULL);
1383 mono_loader_clear_error ();
1385 mono_raise_exception (e);
1392 ICALL_EXPORT MonoReflectionType*
1393 ves_icall_type_from_handle (MonoType *handle)
1395 MonoDomain *domain = mono_domain_get ();
1397 MONO_ARCH_SAVE_REGS;
1399 return mono_type_get_object (domain, handle);
1402 ICALL_EXPORT MonoBoolean
1403 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1405 MONO_ARCH_SAVE_REGS;
1407 if (c && type->type && c->type)
1408 return mono_metadata_type_equal (type->type, c->type);
1410 return (type == c) ? TRUE : FALSE;
1413 /* System.TypeCode */
1432 TYPECODE_STRING = 18
1435 ICALL_EXPORT guint32
1436 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1438 int t = type->type->type;
1440 MONO_ARCH_SAVE_REGS;
1442 if (type->type->byref)
1443 return TYPECODE_OBJECT;
1447 case MONO_TYPE_VOID:
1448 return TYPECODE_OBJECT;
1449 case MONO_TYPE_BOOLEAN:
1450 return TYPECODE_BOOLEAN;
1452 return TYPECODE_BYTE;
1454 return TYPECODE_SBYTE;
1456 return TYPECODE_UINT16;
1458 return TYPECODE_INT16;
1459 case MONO_TYPE_CHAR:
1460 return TYPECODE_CHAR;
1464 return TYPECODE_OBJECT;
1466 return TYPECODE_UINT32;
1468 return TYPECODE_INT32;
1470 return TYPECODE_UINT64;
1472 return TYPECODE_INT64;
1474 return TYPECODE_SINGLE;
1476 return TYPECODE_DOUBLE;
1477 case MONO_TYPE_VALUETYPE: {
1478 MonoClass *klass = type->type->data.klass;
1480 if (klass->enumtype) {
1481 t = mono_class_enum_basetype (klass)->type;
1483 } else if (mono_is_corlib_image (klass->image)) {
1484 if (strcmp (klass->name_space, "System") == 0) {
1485 if (strcmp (klass->name, "Decimal") == 0)
1486 return TYPECODE_DECIMAL;
1487 else if (strcmp (klass->name, "DateTime") == 0)
1488 return TYPECODE_DATETIME;
1491 return TYPECODE_OBJECT;
1493 case MONO_TYPE_STRING:
1494 return TYPECODE_STRING;
1495 case MONO_TYPE_SZARRAY:
1496 case MONO_TYPE_ARRAY:
1497 case MONO_TYPE_OBJECT:
1499 case MONO_TYPE_MVAR:
1500 case MONO_TYPE_TYPEDBYREF:
1501 return TYPECODE_OBJECT;
1502 case MONO_TYPE_CLASS:
1504 MonoClass *klass = type->type->data.klass;
1505 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1506 if (strcmp (klass->name, "DBNull") == 0)
1507 return TYPECODE_DBNULL;
1510 return TYPECODE_OBJECT;
1511 case MONO_TYPE_GENERICINST:
1512 return TYPECODE_OBJECT;
1514 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1519 ICALL_EXPORT guint32
1520 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1526 MONO_ARCH_SAVE_REGS;
1528 g_assert (type != NULL);
1530 domain = ((MonoObject *)type)->vtable->domain;
1532 if (!c) /* FIXME: dont know what do do here */
1535 klass = mono_class_from_mono_type (type->type);
1536 klassc = mono_class_from_mono_type (c->type);
1538 /* Interface check requires a more complex setup so we
1539 * only do for them. Otherwise we simply avoid mono_class_init.
1541 if (check_interfaces) {
1542 mono_class_init_or_throw (klass);
1543 mono_class_init_or_throw (klassc);
1544 } else if (!klass->supertypes || !klassc->supertypes) {
1545 mono_loader_lock ();
1546 mono_class_setup_supertypes (klass);
1547 mono_class_setup_supertypes (klassc);
1548 mono_loader_unlock ();
1551 if (type->type->byref)
1552 return klassc == mono_defaults.object_class;
1554 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1558 mono_type_is_primitive (MonoType *type)
1560 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1561 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1565 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1567 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1568 return mono_class_enum_basetype (type->data.klass);
1569 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1570 return mono_class_enum_basetype (type->data.generic_class->container_class);
1574 ICALL_EXPORT guint32
1575 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1581 MONO_ARCH_SAVE_REGS;
1583 g_assert (type != NULL);
1585 domain = ((MonoObject *)type)->vtable->domain;
1587 klass = mono_class_from_mono_type (type->type);
1588 klassc = mono_class_from_mono_type (c->type);
1590 mono_class_init_or_throw (klass);
1591 mono_class_init_or_throw (klassc);
1593 if (type->type->byref ^ c->type->byref)
1596 if (type->type->byref) {
1597 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1598 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1600 klass = mono_class_from_mono_type (t);
1601 klassc = mono_class_from_mono_type (ot);
1603 if (mono_type_is_primitive (t)) {
1604 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1605 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1606 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1607 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1608 return t->type == ot->type;
1610 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1613 if (klass->valuetype)
1614 return klass == klassc;
1615 return klass->valuetype == klassc->valuetype;
1618 return mono_class_is_assignable_from (klass, klassc);
1621 ICALL_EXPORT guint32
1622 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1624 MonoClass *klass = mono_class_from_mono_type (type->type);
1625 mono_class_init_or_throw (klass);
1626 return mono_object_isinst (obj, klass) != NULL;
1629 ICALL_EXPORT guint32
1630 ves_icall_get_attributes (MonoReflectionType *type)
1632 MonoClass *klass = mono_class_from_mono_type (type->type);
1633 return klass->flags;
1636 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1637 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1639 MonoClass *klass = field->field->parent;
1640 MonoMarshalType *info;
1643 if (klass->generic_container ||
1644 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1647 info = mono_marshal_load_type_info (klass);
1649 for (i = 0; i < info->num_fields; ++i) {
1650 if (info->fields [i].field == field->field) {
1651 if (!info->fields [i].mspec)
1654 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1661 ICALL_EXPORT MonoReflectionField*
1662 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1664 gboolean found = FALSE;
1671 klass = handle->parent;
1673 klass = mono_class_from_mono_type (type);
1675 /* Check that the field belongs to the class */
1676 for (k = klass; k; k = k->parent) {
1677 if (k == handle->parent) {
1684 /* The managed code will throw the exception */
1688 return mono_field_get_object (mono_domain_get (), klass, handle);
1691 ICALL_EXPORT MonoArray*
1692 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1695 MonoType *type = mono_field_get_type_checked (field->field, &error);
1696 if (!mono_error_ok (&error))
1697 mono_error_raise_exception (&error);
1699 return type_array_from_modifiers (field->field->parent->image, type, optional);
1703 vell_icall_get_method_attributes (MonoMethod *method)
1705 return method->flags;
1709 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1712 MonoDomain *domain = mono_domain_get ();
1713 MonoMethodSignature* sig;
1714 MONO_ARCH_SAVE_REGS;
1716 sig = mono_method_signature_checked (method, &error);
1717 if (!mono_error_ok (&error))
1718 mono_error_raise_exception (&error);
1721 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1722 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1723 info->attrs = method->flags;
1724 info->implattrs = method->iflags;
1725 if (sig->call_convention == MONO_CALL_DEFAULT)
1726 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1728 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1733 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1736 ICALL_EXPORT MonoArray*
1737 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1739 MonoDomain *domain = mono_domain_get ();
1741 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1744 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1745 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1747 MonoDomain *domain = mono_domain_get ();
1748 MonoReflectionMarshalAsAttribute* res = NULL;
1749 MonoMarshalSpec **mspecs;
1752 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1753 mono_method_get_marshal_info (method, mspecs);
1756 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1758 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1760 mono_metadata_free_marshal_spec (mspecs [i]);
1767 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1769 MonoClass *parent = field->field->parent;
1770 if (!parent->size_inited)
1771 mono_class_init (parent);
1773 return field->field->offset - sizeof (MonoObject);
1776 ICALL_EXPORT MonoReflectionType*
1777 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1780 MONO_ARCH_SAVE_REGS;
1782 parent = declaring? field->field->parent: field->klass;
1784 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1787 ICALL_EXPORT MonoObject *
1788 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1790 MonoClass *fklass = field->klass;
1791 MonoClassField *cf = field->field;
1792 MonoDomain *domain = mono_object_domain (field);
1794 if (fklass->image->assembly->ref_only)
1795 mono_raise_exception (mono_get_exception_invalid_operation (
1796 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1798 if (mono_security_core_clr_enabled ())
1799 mono_security_core_clr_ensure_reflection_access_field (cf);
1801 return mono_field_get_value_object (domain, cf, obj);
1805 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1808 MonoClassField *cf = field->field;
1812 MONO_ARCH_SAVE_REGS;
1814 if (field->klass->image->assembly->ref_only)
1815 mono_raise_exception (mono_get_exception_invalid_operation (
1816 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1818 if (mono_security_core_clr_enabled ())
1819 mono_security_core_clr_ensure_reflection_access_field (cf);
1821 type = mono_field_get_type_checked (cf, &error);
1822 if (!mono_error_ok (&error))
1823 mono_error_raise_exception (&error);
1825 v = (gchar *) value;
1827 switch (type->type) {
1830 case MONO_TYPE_BOOLEAN:
1833 case MONO_TYPE_CHAR:
1842 case MONO_TYPE_VALUETYPE:
1845 v += sizeof (MonoObject);
1847 case MONO_TYPE_STRING:
1848 case MONO_TYPE_OBJECT:
1849 case MONO_TYPE_CLASS:
1850 case MONO_TYPE_ARRAY:
1851 case MONO_TYPE_SZARRAY:
1854 case MONO_TYPE_GENERICINST: {
1855 MonoGenericClass *gclass = type->data.generic_class;
1856 g_assert (!gclass->context.class_inst->is_open);
1858 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1859 MonoClass *nklass = mono_class_from_mono_type (type);
1860 MonoObject *nullable;
1863 * Convert the boxed vtype into a Nullable structure.
1864 * This is complicated by the fact that Nullables have
1865 * a variable structure.
1867 nullable = mono_object_new (mono_domain_get (), nklass);
1869 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1871 v = mono_object_unbox (nullable);
1874 if (gclass->container_class->valuetype && (v != NULL))
1875 v += sizeof (MonoObject);
1879 g_error ("type 0x%x not handled in "
1880 "ves_icall_FieldInfo_SetValueInternal", type->type);
1885 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1886 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1887 if (!vtable->initialized)
1888 mono_runtime_class_init (vtable);
1889 mono_field_static_set_value (vtable, cf, v);
1891 mono_field_set_value (obj, cf, v);
1895 ICALL_EXPORT MonoObject *
1896 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1898 MonoObject *o = NULL;
1899 MonoClassField *field = this->field;
1901 MonoDomain *domain = mono_object_domain (this);
1903 MonoTypeEnum def_type;
1904 const char *def_value;
1908 MONO_ARCH_SAVE_REGS;
1910 mono_class_init (field->parent);
1912 t = mono_field_get_type_checked (field, &error);
1913 if (!mono_error_ok (&error))
1914 mono_error_raise_exception (&error);
1916 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1917 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1919 if (field->parent->image->dynamic) {
1921 g_assert_not_reached ();
1924 def_value = mono_class_get_field_default_value (field, &def_type);
1925 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1926 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1928 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1932 case MONO_TYPE_BOOLEAN:
1935 case MONO_TYPE_CHAR:
1943 case MONO_TYPE_R8: {
1946 /* boxed value type */
1947 t = g_new0 (MonoType, 1);
1949 klass = mono_class_from_mono_type (t);
1951 o = mono_object_new (domain, klass);
1952 v = ((gchar *) o) + sizeof (MonoObject);
1953 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1956 case MONO_TYPE_STRING:
1957 case MONO_TYPE_CLASS:
1958 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1961 g_assert_not_reached ();
1967 ICALL_EXPORT MonoReflectionType*
1968 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1971 MonoClassField *field = ref_field->field;
1972 MonoType *type = mono_field_get_type_checked (field, &error);
1973 if (!mono_error_ok (&error))
1974 mono_error_raise_exception (&error);
1975 return mono_type_get_object (mono_object_domain (ref_field), type);
1978 ICALL_EXPORT MonoReflectionType*
1979 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1981 MonoMethod *method = rmethod->method.method;
1983 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1986 /* From MonoProperty.cs */
1988 PInfo_Attributes = 1,
1989 PInfo_GetMethod = 1 << 1,
1990 PInfo_SetMethod = 1 << 2,
1991 PInfo_ReflectedType = 1 << 3,
1992 PInfo_DeclaringType = 1 << 4,
1997 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1999 MonoDomain *domain = mono_object_domain (property);
2001 MONO_ARCH_SAVE_REGS;
2003 if ((req_info & PInfo_ReflectedType) != 0)
2004 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2005 if ((req_info & PInfo_DeclaringType) != 0)
2006 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2008 if ((req_info & PInfo_Name) != 0)
2009 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2011 if ((req_info & PInfo_Attributes) != 0)
2012 info->attrs = property->property->attrs;
2014 if ((req_info & PInfo_GetMethod) != 0)
2015 MONO_STRUCT_SETREF (info, get, property->property->get ?
2016 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2018 if ((req_info & PInfo_SetMethod) != 0)
2019 MONO_STRUCT_SETREF (info, set, property->property->set ?
2020 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2022 * There may be other methods defined for properties, though, it seems they are not exposed
2023 * in the reflection API
2028 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2030 MonoDomain *domain = mono_object_domain (event);
2032 MONO_ARCH_SAVE_REGS;
2034 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2035 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2037 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2038 info->attrs = event->event->attrs;
2039 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2040 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2041 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2043 #ifndef MONO_SMALL_CONFIG
2044 if (event->event->other) {
2046 while (event->event->other [n])
2048 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2050 for (i = 0; i < n; i++)
2051 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2057 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2062 mono_class_setup_interfaces (klass, error);
2063 if (!mono_error_ok (error))
2066 for (i = 0; i < klass->interface_count; i++) {
2067 ic = klass->interfaces [i];
2068 g_hash_table_insert (ifaces, ic, ic);
2070 collect_interfaces (ic, ifaces, error);
2071 if (!mono_error_ok (error))
2077 MonoArray *iface_array;
2078 MonoGenericContext *context;
2082 } FillIfaceArrayData;
2085 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2087 FillIfaceArrayData *data = user_data;
2088 MonoClass *ic = key;
2089 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2091 if (!mono_error_ok (data->error))
2094 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2095 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2096 if (!mono_error_ok (data->error))
2100 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2103 mono_metadata_free_type (inflated);
2106 ICALL_EXPORT MonoArray*
2107 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2110 MonoClass *class = mono_class_from_mono_type (type->type);
2112 FillIfaceArrayData data = { 0 };
2115 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2117 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2118 data.context = mono_class_get_context (class);
2119 class = class->generic_class->container_class;
2122 for (parent = class; parent; parent = parent->parent) {
2123 mono_class_setup_interfaces (parent, &error);
2124 if (!mono_error_ok (&error))
2126 collect_interfaces (parent, iface_hash, &error);
2127 if (!mono_error_ok (&error))
2131 data.error = &error;
2132 data.domain = mono_object_domain (type);
2134 len = g_hash_table_size (iface_hash);
2136 g_hash_table_destroy (iface_hash);
2137 if (!data.domain->empty_types)
2138 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2139 return data.domain->empty_types;
2142 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2143 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2144 if (!mono_error_ok (&error))
2147 g_hash_table_destroy (iface_hash);
2148 return data.iface_array;
2151 g_hash_table_destroy (iface_hash);
2152 mono_error_raise_exception (&error);
2157 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2159 gboolean variance_used;
2160 MonoClass *class = mono_class_from_mono_type (type->type);
2161 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2162 MonoReflectionMethod *member;
2165 int i = 0, len, ioffset;
2168 MONO_ARCH_SAVE_REGS;
2169 mono_class_init_or_throw (class);
2170 mono_class_init_or_throw (iclass);
2172 mono_class_setup_vtable (class);
2174 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2178 len = mono_class_num_methods (iclass);
2179 domain = mono_object_domain (type);
2180 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2181 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2183 while ((method = mono_class_get_methods (iclass, &iter))) {
2184 member = mono_method_get_object (domain, method, iclass);
2185 mono_array_setref (*methods, i, member);
2186 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2187 mono_array_setref (*targets, i, member);
2194 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2196 MonoClass *klass = mono_class_from_mono_type (type->type);
2197 mono_class_init_or_throw (klass);
2199 if (klass->image->dynamic) {
2200 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2201 *packing = tb->packing_size;
2202 *size = tb->class_size;
2204 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2208 ICALL_EXPORT MonoReflectionType*
2209 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2213 MONO_ARCH_SAVE_REGS;
2215 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2216 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2218 class = mono_class_from_mono_type (type->type);
2219 mono_class_init_or_throw (class);
2221 // GetElementType should only return a type for:
2222 // Array Pointer PassedByRef
2223 if (type->type->byref)
2224 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2225 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2226 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2227 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2228 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2233 ICALL_EXPORT MonoReflectionType*
2234 ves_icall_get_type_parent (MonoReflectionType *type)
2236 MonoClass *class = mono_class_from_mono_type (type->type);
2237 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2240 ICALL_EXPORT MonoBoolean
2241 ves_icall_type_ispointer (MonoReflectionType *type)
2243 MONO_ARCH_SAVE_REGS;
2245 return type->type->type == MONO_TYPE_PTR;
2248 ICALL_EXPORT MonoBoolean
2249 ves_icall_type_isprimitive (MonoReflectionType *type)
2251 MONO_ARCH_SAVE_REGS;
2253 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)));
2256 ICALL_EXPORT MonoBoolean
2257 ves_icall_type_isbyref (MonoReflectionType *type)
2259 MONO_ARCH_SAVE_REGS;
2261 return type->type->byref;
2264 ICALL_EXPORT MonoBoolean
2265 ves_icall_type_iscomobject (MonoReflectionType *type)
2267 MonoClass *klass = mono_class_from_mono_type (type->type);
2268 mono_class_init_or_throw (klass);
2270 return mono_class_is_com_object (klass);
2273 ICALL_EXPORT MonoReflectionModule*
2274 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2276 MonoClass *class = mono_class_from_mono_type (type->type);
2277 return mono_module_get_object (mono_object_domain (type), class->image);
2280 ICALL_EXPORT MonoReflectionAssembly*
2281 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2283 MonoDomain *domain = mono_domain_get ();
2284 MonoClass *class = mono_class_from_mono_type (type->type);
2285 return mono_assembly_get_object (domain, class->image->assembly);
2288 ICALL_EXPORT MonoReflectionType*
2289 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2291 MonoDomain *domain = mono_domain_get ();
2294 MONO_ARCH_SAVE_REGS;
2296 if (type->type->byref)
2298 if (type->type->type == MONO_TYPE_VAR)
2299 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2300 else if (type->type->type == MONO_TYPE_MVAR)
2301 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2303 class = mono_class_from_mono_type (type->type)->nested_in;
2305 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2308 ICALL_EXPORT MonoString*
2309 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2311 MonoDomain *domain = mono_domain_get ();
2312 MonoClass *class = mono_class_from_mono_type (type->type);
2314 if (type->type->byref) {
2315 char *n = g_strdup_printf ("%s&", class->name);
2316 MonoString *res = mono_string_new (domain, n);
2322 return mono_string_new (domain, class->name);
2326 ICALL_EXPORT MonoString*
2327 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2329 MonoDomain *domain = mono_domain_get ();
2330 MonoClass *class = mono_class_from_mono_type (type->type);
2332 while (class->nested_in)
2333 class = class->nested_in;
2335 if (class->name_space [0] == '\0')
2338 return mono_string_new (domain, class->name_space);
2342 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2346 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2347 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2349 class = mono_class_from_mono_type (type->type);
2354 ICALL_EXPORT MonoArray*
2355 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2358 MonoClass *klass, *pklass;
2359 MonoDomain *domain = mono_object_domain (type);
2360 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2362 MONO_ARCH_SAVE_REGS;
2364 klass = mono_class_from_mono_type (type->type);
2366 if (klass->generic_container) {
2367 MonoGenericContainer *container = klass->generic_container;
2368 res = mono_array_new_specific (array_vtable, container->type_argc);
2369 for (i = 0; i < container->type_argc; ++i) {
2370 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2371 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2373 } else if (klass->generic_class) {
2374 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2375 res = mono_array_new_specific (array_vtable, inst->type_argc);
2376 for (i = 0; i < inst->type_argc; ++i)
2377 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2379 res = mono_array_new_specific (array_vtable, 0);
2384 ICALL_EXPORT gboolean
2385 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2388 MONO_ARCH_SAVE_REGS;
2390 if (!IS_MONOTYPE (type))
2393 if (type->type->byref)
2396 klass = mono_class_from_mono_type (type->type);
2397 return klass->generic_container != NULL;
2400 ICALL_EXPORT MonoReflectionType*
2401 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2404 MONO_ARCH_SAVE_REGS;
2406 if (type->type->byref)
2409 klass = mono_class_from_mono_type (type->type);
2411 if (klass->generic_container) {
2412 return type; /* check this one */
2414 if (klass->generic_class) {
2415 MonoClass *generic_class = klass->generic_class->container_class;
2418 tb = mono_class_get_ref_info (generic_class);
2420 if (generic_class->wastypebuilder && tb)
2423 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2428 ICALL_EXPORT MonoReflectionType*
2429 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2432 MonoType *geninst, **types;
2435 g_assert (IS_MONOTYPE (type));
2436 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2438 count = mono_array_length (type_array);
2439 types = g_new0 (MonoType *, count);
2441 for (i = 0; i < count; i++) {
2442 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2443 types [i] = t->type;
2446 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2451 class = mono_class_from_mono_type (geninst);
2453 /*we might inflate to the GTD*/
2454 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2455 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2457 return mono_type_get_object (mono_object_domain (type), geninst);
2460 ICALL_EXPORT gboolean
2461 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2464 MONO_ARCH_SAVE_REGS;
2466 if (type->type->byref)
2469 klass = mono_class_from_mono_type (type->type);
2471 return klass->generic_class != NULL;
2474 ICALL_EXPORT gboolean
2475 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2478 MONO_ARCH_SAVE_REGS;
2480 if (!IS_MONOTYPE (type))
2483 if (type->type->byref)
2486 klass = mono_class_from_mono_type (type->type);
2487 return klass->generic_class != NULL || klass->generic_container != NULL;
2491 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2493 MONO_ARCH_SAVE_REGS;
2495 if (!IS_MONOTYPE (type))
2498 if (is_generic_parameter (type->type))
2499 return mono_type_get_generic_param_num (type->type);
2503 ICALL_EXPORT GenericParameterAttributes
2504 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2506 MONO_ARCH_SAVE_REGS;
2508 g_assert (IS_MONOTYPE (type));
2509 g_assert (is_generic_parameter (type->type));
2510 return mono_generic_param_info (type->type->data.generic_param)->flags;
2513 ICALL_EXPORT MonoArray *
2514 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2516 MonoGenericParamInfo *param_info;
2522 MONO_ARCH_SAVE_REGS;
2524 g_assert (IS_MONOTYPE (type));
2526 domain = mono_object_domain (type);
2527 param_info = mono_generic_param_info (type->type->data.generic_param);
2528 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2531 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2532 for (i = 0; i < count; i++)
2533 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2539 ICALL_EXPORT MonoBoolean
2540 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2542 MONO_ARCH_SAVE_REGS;
2543 return is_generic_parameter (type->type);
2546 ICALL_EXPORT MonoBoolean
2547 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2549 MONO_ARCH_SAVE_REGS;
2550 return is_generic_parameter (tb->type.type);
2554 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2555 MonoReflectionType *t)
2557 enumtype->type = t->type;
2560 ICALL_EXPORT MonoReflectionMethod*
2561 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2562 MonoReflectionMethod* generic)
2569 MONO_ARCH_SAVE_REGS;
2571 domain = ((MonoObject *)type)->vtable->domain;
2573 klass = mono_class_from_mono_type (type->type);
2574 mono_class_init_or_throw (klass);
2577 while ((method = mono_class_get_methods (klass, &iter))) {
2578 if (method->token == generic->method->token)
2579 return mono_method_get_object (domain, method, klass);
2587 ICALL_EXPORT MonoReflectionMethod *
2588 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2591 MonoType *type = ref_type->type;
2593 MONO_ARCH_SAVE_REGS;
2595 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2596 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2597 if (type->type == MONO_TYPE_VAR)
2600 method = mono_type_get_generic_param_owner (type)->owner.method;
2602 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2605 ICALL_EXPORT MonoReflectionDllImportAttribute*
2606 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2608 static MonoClass *DllImportAttributeClass = NULL;
2609 MonoDomain *domain = mono_domain_get ();
2610 MonoReflectionDllImportAttribute *attr;
2611 MonoImage *image = method->klass->image;
2612 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2613 MonoTableInfo *tables = image->tables;
2614 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2615 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2616 guint32 im_cols [MONO_IMPLMAP_SIZE];
2617 guint32 scope_token;
2618 const char *import = NULL;
2619 const char *scope = NULL;
2622 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2625 if (!DllImportAttributeClass) {
2626 DllImportAttributeClass =
2627 mono_class_from_name (mono_defaults.corlib,
2628 "System.Runtime.InteropServices", "DllImportAttribute");
2629 g_assert (DllImportAttributeClass);
2632 if (method->klass->image->dynamic) {
2633 MonoReflectionMethodAux *method_aux =
2634 g_hash_table_lookup (
2635 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2637 import = method_aux->dllentry;
2638 scope = method_aux->dll;
2641 if (!import || !scope) {
2642 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2647 if (piinfo->implmap_idx) {
2648 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2650 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2651 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2652 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2653 scope = mono_metadata_string_heap (image, scope_token);
2656 flags = piinfo->piflags;
2658 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2660 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2661 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2662 attr->call_conv = (flags & 0x700) >> 8;
2663 attr->charset = ((flags & 0x6) >> 1) + 1;
2664 if (attr->charset == 1)
2666 attr->exact_spelling = (flags & 0x1) != 0;
2667 attr->set_last_error = (flags & 0x40) != 0;
2668 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2669 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2670 attr->preserve_sig = FALSE;
2675 ICALL_EXPORT MonoReflectionMethod *
2676 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2678 MonoMethodInflated *imethod;
2681 MONO_ARCH_SAVE_REGS;
2683 if (method->method->is_generic)
2686 if (!method->method->is_inflated)
2689 imethod = (MonoMethodInflated *) method->method;
2691 result = imethod->declaring;
2692 /* Not a generic method. */
2693 if (!result->is_generic)
2696 if (method->method->klass->image->dynamic) {
2697 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2698 MonoReflectionMethod *res;
2701 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2702 * the dynamic case as well ?
2704 mono_loader_lock ();
2705 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2706 mono_loader_unlock ();
2712 if (imethod->context.class_inst) {
2713 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2714 /*Generic methods gets the context of the GTD.*/
2715 if (mono_class_get_context (klass))
2716 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2719 return mono_method_get_object (mono_object_domain (method), result, NULL);
2722 ICALL_EXPORT gboolean
2723 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2725 MONO_ARCH_SAVE_REGS;
2727 return mono_method_signature (method->method)->generic_param_count != 0;
2730 ICALL_EXPORT gboolean
2731 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2733 MONO_ARCH_SAVE_REGS;
2735 return method->method->is_generic;
2738 ICALL_EXPORT MonoArray*
2739 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2744 MONO_ARCH_SAVE_REGS;
2746 domain = mono_object_domain (method);
2748 if (method->method->is_inflated) {
2749 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2752 count = inst->type_argc;
2753 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2755 for (i = 0; i < count; i++)
2756 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2762 count = mono_method_signature (method->method)->generic_param_count;
2763 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2765 for (i = 0; i < count; i++) {
2766 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2767 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2768 MonoClass *pklass = mono_class_from_generic_parameter (
2769 param, method->method->klass->image, TRUE);
2770 mono_array_setref (res, i,
2771 mono_type_get_object (domain, &pklass->byval_arg));
2777 ICALL_EXPORT MonoObject *
2778 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2781 * Invoke from reflection is supposed to always be a virtual call (the API
2782 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2783 * greater flexibility.
2785 MonoMethod *m = method->method;
2786 MonoMethodSignature *sig = mono_method_signature (m);
2790 MONO_ARCH_SAVE_REGS;
2794 if (mono_security_core_clr_enabled ())
2795 mono_security_core_clr_ensure_reflection_access_method (m);
2797 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2798 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2799 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2804 if (!mono_object_isinst (this, m->klass)) {
2805 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2806 char *target_name = mono_type_get_full_name (m->klass);
2807 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2808 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2810 g_free (target_name);
2814 m = mono_object_get_virtual_method (this, m);
2815 /* must pass the pointer to the value for valuetype methods */
2816 if (m->klass->valuetype)
2817 obj = mono_object_unbox (this);
2818 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2819 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2824 if (sig->ret->byref) {
2825 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"));
2829 pcount = params? mono_array_length (params): 0;
2830 if (pcount != sig->param_count) {
2831 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2835 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2836 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."));
2840 if (m->klass->image->assembly->ref_only) {
2841 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."));
2845 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2848 intptr_t *lower_bounds;
2849 pcount = mono_array_length (params);
2850 lengths = alloca (sizeof (uintptr_t) * pcount);
2851 /* Note: the synthetized array .ctors have int32 as argument type */
2852 for (i = 0; i < pcount; ++i)
2853 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2855 if (m->klass->rank == pcount) {
2856 /* Only lengths provided. */
2857 lower_bounds = NULL;
2859 g_assert (pcount == (m->klass->rank * 2));
2860 /* lower bounds are first. */
2861 lower_bounds = (intptr_t*)lengths;
2862 lengths += m->klass->rank;
2865 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2867 return mono_runtime_invoke_array (m, obj, params, NULL);
2870 #ifndef DISABLE_REMOTING
2871 ICALL_EXPORT MonoObject *
2872 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2874 MonoDomain *domain = mono_object_domain (method);
2875 MonoMethod *m = method->method;
2876 MonoMethodSignature *sig = mono_method_signature (m);
2877 MonoArray *out_args;
2879 int i, j, outarg_count = 0;
2881 MONO_ARCH_SAVE_REGS;
2883 if (m->klass == mono_defaults.object_class) {
2885 if (!strcmp (m->name, "FieldGetter")) {
2886 MonoClass *k = this->vtable->klass;
2890 /* If this is a proxy, then it must be a CBO */
2891 if (k == mono_defaults.transparent_proxy_class) {
2892 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2893 this = tp->rp->unwrapped_server;
2895 k = this->vtable->klass;
2898 name = mono_array_get (params, MonoString *, 1);
2899 str = mono_string_to_utf8 (name);
2902 MonoClassField* field = mono_class_get_field_from_name (k, str);
2904 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2905 if (field_klass->valuetype)
2906 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2908 result = *((gpointer *)((char *)this + field->offset));
2910 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2911 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2912 mono_array_setref (out_args, 0, result);
2920 g_assert_not_reached ();
2922 } else if (!strcmp (m->name, "FieldSetter")) {
2923 MonoClass *k = this->vtable->klass;
2929 /* If this is a proxy, then it must be a CBO */
2930 if (k == mono_defaults.transparent_proxy_class) {
2931 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2932 this = tp->rp->unwrapped_server;
2934 k = this->vtable->klass;
2937 name = mono_array_get (params, MonoString *, 1);
2938 str = mono_string_to_utf8 (name);
2941 MonoClassField* field = mono_class_get_field_from_name (k, str);
2943 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2944 MonoObject *val = mono_array_get (params, gpointer, 2);
2946 if (field_klass->valuetype) {
2947 size = mono_type_size (field->type, &align);
2948 g_assert (size == mono_class_value_size (field_klass, NULL));
2949 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2951 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2954 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2955 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2965 g_assert_not_reached ();
2970 for (i = 0; i < mono_array_length (params); i++) {
2971 if (sig->params [i]->byref)
2975 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2977 /* handle constructors only for objects already allocated */
2978 if (!strcmp (method->method->name, ".ctor"))
2981 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2982 g_assert (!method->method->klass->valuetype);
2983 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2985 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2986 if (sig->params [i]->byref) {
2988 arg = mono_array_get (params, gpointer, i);
2989 mono_array_setref (out_args, j, arg);
2994 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3001 read_enum_value (char *mem, int type)
3005 return *(guint8*)mem;
3007 return *(gint8*)mem;
3009 return *(guint16*)mem;
3011 return *(gint16*)mem;
3013 return *(guint32*)mem;
3015 return *(gint32*)mem;
3017 return *(guint64*)mem;
3019 return *(gint64*)mem;
3021 g_assert_not_reached ();
3027 write_enum_value (char *mem, int type, guint64 value)
3031 case MONO_TYPE_I1: {
3032 guint8 *p = (guint8*)mem;
3037 case MONO_TYPE_I2: {
3038 guint16 *p = (void*)mem;
3043 case MONO_TYPE_I4: {
3044 guint32 *p = (void*)mem;
3049 case MONO_TYPE_I8: {
3050 guint64 *p = (void*)mem;
3055 g_assert_not_reached ();
3060 ICALL_EXPORT MonoObject *
3061 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3064 MonoClass *enumc, *objc;
3069 MONO_ARCH_SAVE_REGS;
3071 MONO_CHECK_ARG_NULL (enumType);
3072 MONO_CHECK_ARG_NULL (value);
3074 domain = mono_object_domain (enumType);
3075 enumc = mono_class_from_mono_type (enumType->type);
3077 mono_class_init_or_throw (enumc);
3079 objc = value->vtable->klass;
3081 if (!enumc->enumtype)
3082 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3083 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3084 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."));
3086 etype = mono_class_enum_basetype (enumc);
3088 /* MS throws this for typebuilders */
3089 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3091 res = mono_object_new (domain, enumc);
3092 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3093 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3098 ICALL_EXPORT MonoObject *
3099 ves_icall_System_Enum_get_value (MonoObject *this)
3107 MONO_ARCH_SAVE_REGS;
3112 g_assert (this->vtable->klass->enumtype);
3114 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3115 res = mono_object_new (mono_object_domain (this), enumc);
3116 dst = (char *)res + sizeof (MonoObject);
3117 src = (char *)this + sizeof (MonoObject);
3118 size = mono_class_value_size (enumc, NULL);
3120 memcpy (dst, src, size);
3125 ICALL_EXPORT MonoReflectionType *
3126 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3131 MONO_ARCH_SAVE_REGS;
3133 klass = mono_class_from_mono_type (type->type);
3134 mono_class_init_or_throw (klass);
3136 etype = mono_class_enum_basetype (klass);
3138 /* MS throws this for typebuilders */
3139 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3141 return mono_type_get_object (mono_object_domain (type), etype);
3145 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3147 gpointer tdata = (char *)this + sizeof (MonoObject);
3148 gpointer odata = (char *)other + sizeof (MonoObject);
3149 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3150 g_assert (basetype);
3152 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3153 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3154 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3157 return me > other ? 1 : -1; \
3160 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3161 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3162 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3165 return me - other; \
3168 switch (basetype->type) {
3170 COMPARE_ENUM_VALUES (guint8);
3172 COMPARE_ENUM_VALUES (gint8);
3173 case MONO_TYPE_CHAR:
3175 COMPARE_ENUM_VALUES_RANGE (guint16);
3177 COMPARE_ENUM_VALUES (gint16);
3179 COMPARE_ENUM_VALUES (guint32);
3181 COMPARE_ENUM_VALUES (gint32);
3183 COMPARE_ENUM_VALUES (guint64);
3185 COMPARE_ENUM_VALUES (gint64);
3187 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3189 #undef COMPARE_ENUM_VALUES_RANGE
3190 #undef COMPARE_ENUM_VALUES
3195 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3197 gpointer data = (char *)this + sizeof (MonoObject);
3198 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3199 g_assert (basetype);
3201 switch (basetype->type) {
3203 return *((gint8*)data);
3205 return *((guint8*)data);
3206 case MONO_TYPE_CHAR:
3208 return *((guint16*)data);
3211 return *((gint16*)data);
3213 return *((guint32*)data);
3215 return *((gint32*)data);
3217 case MONO_TYPE_I8: {
3218 gint64 value = *((gint64*)data);
3219 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3222 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3228 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3230 MonoDomain *domain = mono_object_domain (type);
3231 MonoClass *enumc = mono_class_from_mono_type (type->type);
3232 guint j = 0, nvalues, crow;
3234 MonoClassField *field;
3236 MONO_ARCH_SAVE_REGS;
3238 mono_class_init_or_throw (enumc);
3240 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3241 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3242 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3243 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3247 while ((field = mono_class_get_fields (enumc, &iter))) {
3250 MonoTypeEnum def_type;
3252 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3254 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3256 if (mono_field_is_deleted (field))
3258 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3260 p = mono_class_get_field_default_value (field, &def_type);
3261 len = mono_metadata_decode_blob_size (p, &p);
3262 switch (mono_class_enum_basetype (enumc)->type) {
3265 mono_array_set (info->values, gchar, j, *p);
3267 case MONO_TYPE_CHAR:
3270 mono_array_set (info->values, gint16, j, read16 (p));
3274 mono_array_set (info->values, gint32, j, read32 (p));
3278 mono_array_set (info->values, gint64, j, read64 (p));
3281 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3288 BFLAGS_IgnoreCase = 1,
3289 BFLAGS_DeclaredOnly = 2,
3290 BFLAGS_Instance = 4,
3292 BFLAGS_Public = 0x10,
3293 BFLAGS_NonPublic = 0x20,
3294 BFLAGS_FlattenHierarchy = 0x40,
3295 BFLAGS_InvokeMethod = 0x100,
3296 BFLAGS_CreateInstance = 0x200,
3297 BFLAGS_GetField = 0x400,
3298 BFLAGS_SetField = 0x800,
3299 BFLAGS_GetProperty = 0x1000,
3300 BFLAGS_SetProperty = 0x2000,
3301 BFLAGS_ExactBinding = 0x10000,
3302 BFLAGS_SuppressChangeType = 0x20000,
3303 BFLAGS_OptionalParamBinding = 0x40000
3306 ICALL_EXPORT MonoReflectionField *
3307 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3310 MonoClass *startklass, *klass;
3312 MonoClassField *field;
3315 int (*compare_func) (const char *s1, const char *s2) = NULL;
3316 domain = ((MonoObject *)type)->vtable->domain;
3317 klass = startklass = mono_class_from_mono_type (type->type);
3320 mono_raise_exception (mono_get_exception_argument_null ("name"));
3321 if (type->type->byref)
3324 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3327 if (klass->exception_type != MONO_EXCEPTION_NONE)
3328 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3331 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3332 guint32 flags = mono_field_get_flags (field);
3335 if (mono_field_is_deleted_with_flags (field, flags))
3337 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3338 if (bflags & BFLAGS_Public)
3340 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3341 if (bflags & BFLAGS_NonPublic) {
3348 if (flags & FIELD_ATTRIBUTE_STATIC) {
3349 if (bflags & BFLAGS_Static)
3350 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3353 if (bflags & BFLAGS_Instance)
3360 utf8_name = mono_string_to_utf8 (name);
3362 if (compare_func (mono_field_get_name (field), utf8_name)) {
3368 return mono_field_get_object (domain, klass, field);
3370 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3376 ICALL_EXPORT MonoArray*
3377 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3380 MonoClass *startklass, *klass, *refklass;
3385 MonoClassField *field;
3386 MonoPtrArray tmp_array;
3388 MONO_ARCH_SAVE_REGS;
3390 domain = ((MonoObject *)type)->vtable->domain;
3391 if (type->type->byref)
3392 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3393 klass = startklass = mono_class_from_mono_type (type->type);
3394 refklass = mono_class_from_mono_type (reftype->type);
3396 mono_ptr_array_init (tmp_array, 2);
3399 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3400 mono_ptr_array_destroy (tmp_array);
3401 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3405 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3406 guint32 flags = mono_field_get_flags (field);
3408 if (mono_field_is_deleted_with_flags (field, flags))
3410 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3411 if (bflags & BFLAGS_Public)
3413 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3414 if (bflags & BFLAGS_NonPublic) {
3421 if (flags & FIELD_ATTRIBUTE_STATIC) {
3422 if (bflags & BFLAGS_Static)
3423 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3426 if (bflags & BFLAGS_Instance)
3432 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3433 mono_ptr_array_append (tmp_array, member);
3435 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3438 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3440 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3441 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3443 mono_ptr_array_destroy (tmp_array);
3449 method_nonpublic (MonoMethod* method, gboolean start_klass)
3451 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3452 case METHOD_ATTRIBUTE_ASSEM:
3453 return (start_klass || mono_defaults.generic_ilist_class);
3454 case METHOD_ATTRIBUTE_PRIVATE:
3456 case METHOD_ATTRIBUTE_PUBLIC:
3464 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3467 MonoClass *startklass;
3470 int len, match, nslots;
3471 /*FIXME, use MonoBitSet*/
3472 guint32 method_slots_default [8];
3473 guint32 *method_slots = NULL;
3474 int (*compare_func) (const char *s1, const char *s2) = NULL;
3476 array = g_ptr_array_new ();
3482 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3484 /* An optimization for calls made from Delegate:CreateDelegate () */
3485 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3486 method = mono_get_delegate_invoke (klass);
3487 if (mono_loader_get_last_error ())
3490 g_ptr_array_add (array, method);
3494 mono_class_setup_vtable (klass);
3495 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3498 if (is_generic_parameter (&klass->byval_arg))
3499 nslots = mono_class_get_vtable_size (klass->parent);
3501 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3502 if (nslots >= sizeof (method_slots_default) * 8) {
3503 method_slots = g_new0 (guint32, nslots / 32 + 1);
3505 method_slots = method_slots_default;
3506 memset (method_slots, 0, sizeof (method_slots_default));
3509 mono_class_setup_vtable (klass);
3510 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3514 while ((method = mono_class_get_methods (klass, &iter))) {
3516 if (method->slot != -1) {
3517 g_assert (method->slot < nslots);
3518 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3520 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3521 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3524 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3526 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3527 if (bflags & BFLAGS_Public)
3529 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3535 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3536 if (bflags & BFLAGS_Static)
3537 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3540 if (bflags & BFLAGS_Instance)
3548 if (compare_func (name, method->name))
3553 g_ptr_array_add (array, method);
3555 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3557 if (method_slots != method_slots_default)
3558 g_free (method_slots);
3563 if (method_slots != method_slots_default)
3564 g_free (method_slots);
3565 g_ptr_array_free (array, TRUE);
3567 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3568 *ex = mono_class_get_exception_for_failure (klass);
3570 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3571 mono_loader_clear_error ();
3576 ICALL_EXPORT MonoArray*
3577 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3579 static MonoClass *MethodInfo_array;
3582 MonoVTable *array_vtable;
3583 MonoException *ex = NULL;
3584 const char *mname = NULL;
3585 GPtrArray *method_array;
3586 MonoClass *klass, *refklass;
3589 if (!MethodInfo_array) {
3590 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3591 mono_memory_barrier ();
3592 MethodInfo_array = klass;
3595 klass = mono_class_from_mono_type (type->type);
3596 refklass = mono_class_from_mono_type (reftype->type);
3597 domain = ((MonoObject *)type)->vtable->domain;
3598 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3599 if (type->type->byref)
3600 return mono_array_new_specific (array_vtable, 0);
3603 mname = mono_string_to_utf8 (name);
3605 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3606 g_free ((char*)mname);
3608 mono_raise_exception (ex);
3610 res = mono_array_new_specific (array_vtable, method_array->len);
3613 for (i = 0; i < method_array->len; ++i) {
3614 MonoMethod *method = g_ptr_array_index (method_array, i);
3615 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3618 g_ptr_array_free (method_array, TRUE);
3622 ICALL_EXPORT MonoArray*
3623 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3626 static MonoClass *System_Reflection_ConstructorInfo;
3627 MonoClass *startklass, *klass, *refklass;
3632 gpointer iter = NULL;
3633 MonoPtrArray tmp_array;
3635 MONO_ARCH_SAVE_REGS;
3637 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3639 domain = ((MonoObject *)type)->vtable->domain;
3640 if (type->type->byref)
3641 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3642 klass = startklass = mono_class_from_mono_type (type->type);
3643 refklass = mono_class_from_mono_type (reftype->type);
3645 if (!System_Reflection_ConstructorInfo)
3646 System_Reflection_ConstructorInfo = mono_class_from_name (
3647 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3650 while ((method = mono_class_get_methods (klass, &iter))) {
3652 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3654 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3655 if (bflags & BFLAGS_Public)
3658 if (bflags & BFLAGS_NonPublic)
3664 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3665 if (bflags & BFLAGS_Static)
3666 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3669 if (bflags & BFLAGS_Instance)
3675 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3677 mono_ptr_array_append (tmp_array, member);
3680 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3682 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3683 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3685 mono_ptr_array_destroy (tmp_array);
3691 property_hash (gconstpointer data)
3693 MonoProperty *prop = (MonoProperty*)data;
3695 return g_str_hash (prop->name);
3699 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3701 // Properties are hide-by-name-and-signature
3702 if (!g_str_equal (prop1->name, prop2->name))
3705 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3707 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3713 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3718 return method_nonpublic (accessor, start_klass);
3721 ICALL_EXPORT MonoArray*
3722 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3726 static MonoClass *System_Reflection_PropertyInfo;
3727 MonoClass *startklass, *klass;
3733 gchar *propname = NULL;
3734 int (*compare_func) (const char *s1, const char *s2) = NULL;
3736 GHashTable *properties = NULL;
3737 MonoPtrArray tmp_array;
3739 MONO_ARCH_SAVE_REGS;
3741 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3743 if (!System_Reflection_PropertyInfo)
3744 System_Reflection_PropertyInfo = mono_class_from_name (
3745 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3747 domain = ((MonoObject *)type)->vtable->domain;
3748 if (type->type->byref)
3749 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3750 klass = startklass = mono_class_from_mono_type (type->type);
3753 propname = mono_string_to_utf8 (name);
3754 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3757 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3759 mono_class_setup_vtable (klass);
3760 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3764 while ((prop = mono_class_get_properties (klass, &iter))) {
3770 flags = method->flags;
3773 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3774 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3775 if (bflags & BFLAGS_Public)
3777 } else if (bflags & BFLAGS_NonPublic) {
3778 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3779 property_accessor_nonpublic(prop->set, startklass == klass)) {
3786 if (flags & METHOD_ATTRIBUTE_STATIC) {
3787 if (bflags & BFLAGS_Static)
3788 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3791 if (bflags & BFLAGS_Instance)
3800 if (compare_func (propname, prop->name))
3804 if (g_hash_table_lookup (properties, prop))
3807 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3809 g_hash_table_insert (properties, prop, prop);
3811 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3814 g_hash_table_destroy (properties);
3817 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3818 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3819 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3821 mono_ptr_array_destroy (tmp_array);
3827 g_hash_table_destroy (properties);
3830 mono_ptr_array_destroy (tmp_array);
3832 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3833 ex = mono_class_get_exception_for_failure (klass);
3835 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3836 mono_loader_clear_error ();
3838 mono_raise_exception (ex);
3842 ICALL_EXPORT MonoReflectionEvent *
3843 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3846 MonoClass *klass, *startklass;
3851 int (*compare_func) (const char *s1, const char *s2);
3853 MONO_ARCH_SAVE_REGS;
3855 event_name = mono_string_to_utf8 (name);
3856 if (type->type->byref)
3858 klass = startklass = mono_class_from_mono_type (type->type);
3859 domain = mono_object_domain (type);
3861 mono_class_init_or_throw (klass);
3863 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3865 if (klass->exception_type != MONO_EXCEPTION_NONE)
3866 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3869 while ((event = mono_class_get_events (klass, &iter))) {
3870 if (compare_func (event->name, event_name))
3873 method = event->add;
3875 method = event->remove;
3877 method = event->raise;
3879 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3880 if (!(bflags & BFLAGS_Public))
3883 if (!(bflags & BFLAGS_NonPublic))
3885 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3889 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3890 if (!(bflags & BFLAGS_Static))
3892 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3895 if (!(bflags & BFLAGS_Instance))
3899 if (!(bflags & BFLAGS_NonPublic))
3902 g_free (event_name);
3903 return mono_event_get_object (domain, startklass, event);
3906 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3909 g_free (event_name);
3913 ICALL_EXPORT MonoArray*
3914 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3918 static MonoClass *System_Reflection_EventInfo;
3919 MonoClass *startklass, *klass;
3926 MonoPtrArray tmp_array;
3928 MONO_ARCH_SAVE_REGS;
3930 mono_ptr_array_init (tmp_array, 4);
3932 if (!System_Reflection_EventInfo)
3933 System_Reflection_EventInfo = mono_class_from_name (
3934 mono_defaults.corlib, "System.Reflection", "EventInfo");
3936 domain = mono_object_domain (type);
3937 if (type->type->byref)
3938 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3939 klass = startklass = mono_class_from_mono_type (type->type);
3942 mono_class_setup_vtable (klass);
3943 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3947 while ((event = mono_class_get_events (klass, &iter))) {
3949 method = event->add;
3951 method = event->remove;
3953 method = event->raise;
3955 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3956 if (bflags & BFLAGS_Public)
3958 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3959 if (bflags & BFLAGS_NonPublic)
3964 if (bflags & BFLAGS_NonPublic)
3970 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3971 if (bflags & BFLAGS_Static)
3972 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3975 if (bflags & BFLAGS_Instance)
3980 if (bflags & BFLAGS_Instance)
3984 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3986 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3989 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3991 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3992 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3994 mono_ptr_array_destroy (tmp_array);
3999 mono_ptr_array_destroy (tmp_array);
4000 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4001 ex = mono_class_get_exception_for_failure (klass);
4003 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4004 mono_loader_clear_error ();
4006 mono_raise_exception (ex);
4010 ICALL_EXPORT MonoReflectionType *
4011 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4019 MONO_ARCH_SAVE_REGS;
4022 mono_raise_exception (mono_get_exception_argument_null ("name"));
4024 domain = ((MonoObject *)type)->vtable->domain;
4025 if (type->type->byref)
4027 klass = mono_class_from_mono_type (type->type);
4029 str = mono_string_to_utf8 (name);
4032 if (klass->exception_type != MONO_EXCEPTION_NONE)
4033 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4036 * If a nested type is generic, return its generic type definition.
4037 * Note that this means that the return value is essentially a
4038 * nested type of the generic type definition of @klass.
4040 * A note in MSDN claims that a generic type definition can have
4041 * nested types that aren't generic. In any case, the container of that
4042 * nested type would be the generic type definition.
4044 if (klass->generic_class)
4045 klass = klass->generic_class->container_class;
4048 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4050 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4051 if (bflags & BFLAGS_Public)
4054 if (bflags & BFLAGS_NonPublic)
4059 if (strcmp (nested->name, str) == 0){
4061 return mono_type_get_object (domain, &nested->byval_arg);
4064 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4070 ICALL_EXPORT MonoArray*
4071 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4080 MonoPtrArray tmp_array;
4082 MONO_ARCH_SAVE_REGS;
4084 domain = ((MonoObject *)type)->vtable->domain;
4085 if (type->type->byref)
4086 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4087 klass = mono_class_from_mono_type (type->type);
4090 * If a nested type is generic, return its generic type definition.
4091 * Note that this means that the return value is essentially the set
4092 * of nested types of the generic type definition of @klass.
4094 * A note in MSDN claims that a generic type definition can have
4095 * nested types that aren't generic. In any case, the container of that
4096 * nested type would be the generic type definition.
4098 if (klass->generic_class)
4099 klass = klass->generic_class->container_class;
4101 mono_ptr_array_init (tmp_array, 1);
4103 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4105 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4106 if (bflags & BFLAGS_Public)
4109 if (bflags & BFLAGS_NonPublic)
4114 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4115 mono_ptr_array_append (tmp_array, member);
4118 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4120 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4121 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4123 mono_ptr_array_destroy (tmp_array);
4128 ICALL_EXPORT MonoReflectionType*
4129 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4132 MonoType *type = NULL;
4133 MonoTypeNameParse info;
4134 gboolean type_resolve;
4136 MONO_ARCH_SAVE_REGS;
4138 /* On MS.NET, this does not fire a TypeResolve event */
4139 type_resolve = TRUE;
4140 str = mono_string_to_utf8 (name);
4141 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4142 if (!mono_reflection_parse_type (str, &info)) {
4144 mono_reflection_free_type_info (&info);
4145 if (throwOnError) /* uhm: this is a parse error, though... */
4146 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4147 /*g_print ("failed parse\n");*/
4151 if (info.assembly.name) {
4153 mono_reflection_free_type_info (&info);
4155 /* 1.0 and 2.0 throw different exceptions */
4156 if (mono_defaults.generic_ilist_class)
4157 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4159 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4164 if (module != NULL) {
4166 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4171 if (assembly->assembly->dynamic) {
4172 /* Enumerate all modules */
4173 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4177 if (abuilder->modules) {
4178 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4179 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4180 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4186 if (!type && abuilder->loaded_modules) {
4187 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4188 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4189 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4196 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4198 mono_reflection_free_type_info (&info);
4200 MonoException *e = NULL;
4203 e = mono_get_exception_type_load (name, NULL);
4205 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4206 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4208 mono_loader_clear_error ();
4211 mono_raise_exception (e);
4214 } else if (mono_loader_get_last_error ()) {
4216 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4217 mono_loader_clear_error ();
4220 if (type->type == MONO_TYPE_CLASS) {
4221 MonoClass *klass = mono_type_get_class (type);
4223 if (mono_security_enabled () && !klass->exception_type)
4224 /* Some security problems are detected during generic vtable construction */
4225 mono_class_setup_vtable (klass);
4227 /* need to report exceptions ? */
4228 if (throwOnError && klass->exception_type) {
4229 /* report SecurityException (or others) that occured when loading the assembly */
4230 MonoException *exc = mono_class_get_exception_for_failure (klass);
4231 mono_loader_clear_error ();
4232 mono_raise_exception (exc);
4233 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4238 /* g_print ("got it\n"); */
4239 return mono_type_get_object (mono_object_domain (assembly), type);
4243 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4246 gchar *shadow_ini_file;
4249 /* Check for shadow-copied assembly */
4250 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4251 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4253 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4254 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4260 g_free (shadow_ini_file);
4261 if (content != NULL) {
4264 *filename = content;
4271 ICALL_EXPORT MonoString *
4272 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4274 MonoDomain *domain = mono_object_domain (assembly);
4275 MonoAssembly *mass = assembly->assembly;
4276 MonoString *res = NULL;
4281 MONO_ARCH_SAVE_REGS;
4283 if (g_path_is_absolute (mass->image->name)) {
4284 absolute = g_strdup (mass->image->name);
4285 dirname = g_path_get_dirname (absolute);
4287 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4288 dirname = g_strdup (mass->basedir);
4291 replace_shadow_path (domain, dirname, &absolute);
4296 for (i = strlen (absolute) - 1; i >= 0; i--)
4297 if (absolute [i] == '\\')
4302 uri = g_filename_to_uri (absolute, NULL, NULL);
4304 const char *prepend = "file://";
4306 if (*absolute == '/' && *(absolute + 1) == '/') {
4309 prepend = "file:///";
4312 uri = g_strconcat (prepend, absolute, NULL);
4316 res = mono_string_new (domain, uri);
4323 ICALL_EXPORT MonoBoolean
4324 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4326 MonoAssembly *mass = assembly->assembly;
4328 MONO_ARCH_SAVE_REGS;
4330 return mass->in_gac;
4333 ICALL_EXPORT MonoReflectionAssembly*
4334 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4338 MonoImageOpenStatus status;
4340 MONO_ARCH_SAVE_REGS;
4342 name = mono_string_to_utf8 (mname);
4343 res = mono_assembly_load_with_partial_name (name, &status);
4349 return mono_assembly_get_object (mono_domain_get (), res);
4352 ICALL_EXPORT MonoString *
4353 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4355 MonoDomain *domain = mono_object_domain (assembly);
4358 MONO_ARCH_SAVE_REGS;
4360 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4365 ICALL_EXPORT MonoBoolean
4366 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4368 MONO_ARCH_SAVE_REGS;
4370 return assembly->assembly->ref_only;
4373 ICALL_EXPORT MonoString *
4374 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4376 MonoDomain *domain = mono_object_domain (assembly);
4378 MONO_ARCH_SAVE_REGS;
4380 return mono_string_new (domain, assembly->assembly->image->version);
4383 ICALL_EXPORT MonoReflectionMethod*
4384 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4386 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4388 MONO_ARCH_SAVE_REGS;
4392 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4395 ICALL_EXPORT MonoReflectionModule*
4396 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4398 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4401 ICALL_EXPORT MonoArray*
4402 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4404 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4405 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4409 MONO_ARCH_SAVE_REGS;
4411 for (i = 0; i < table->rows; ++i) {
4412 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4413 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4419 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4421 static MonoClass *System_Version = NULL;
4422 static MonoMethod *create_version = NULL;
4426 if (!System_Version) {
4427 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4428 g_assert (System_Version);
4431 if (!create_version) {
4432 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4433 create_version = mono_method_desc_search_in_class (desc, System_Version);
4434 g_assert (create_version);
4435 mono_method_desc_free (desc);
4441 args [3] = &revision;
4442 result = mono_object_new (domain, System_Version);
4443 mono_runtime_invoke (create_version, result, args, NULL);
4448 ICALL_EXPORT MonoArray*
4449 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4451 static MonoClass *System_Reflection_AssemblyName;
4453 MonoDomain *domain = mono_object_domain (assembly);
4455 static MonoMethod *create_culture = NULL;
4456 MonoImage *image = assembly->assembly->image;
4459 MONO_ARCH_SAVE_REGS;
4461 if (!System_Reflection_AssemblyName)
4462 System_Reflection_AssemblyName = mono_class_from_name (
4463 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4465 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4468 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4470 if (count > 0 && !create_culture) {
4471 MonoMethodDesc *desc = mono_method_desc_new (
4472 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4473 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4474 g_assert (create_culture);
4475 mono_method_desc_free (desc);
4478 for (i = 0; i < count; i++) {
4479 MonoReflectionAssemblyName *aname;
4480 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4482 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4484 aname = (MonoReflectionAssemblyName *) mono_object_new (
4485 domain, System_Reflection_AssemblyName);
4487 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4489 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4490 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4491 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4492 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4493 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4494 aname->versioncompat = 1; /* SameMachine (default) */
4495 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4496 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4498 if (create_culture) {
4500 MonoBoolean assembly_ref = 1;
4501 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4502 args [1] = &assembly_ref;
4503 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4506 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4507 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4508 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4510 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4511 /* public key token isn't copied - the class library will
4512 automatically generate it from the public key if required */
4513 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4514 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4516 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4517 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4520 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4523 /* note: this function doesn't return the codebase on purpose (i.e. it can
4524 be used under partial trust as path information isn't present). */
4526 mono_array_setref (result, i, aname);
4531 /* move this in some file in mono/util/ */
4533 g_concat_dir_and_file (const char *dir, const char *file)
4535 g_return_val_if_fail (dir != NULL, NULL);
4536 g_return_val_if_fail (file != NULL, NULL);
4539 * If the directory name doesn't have a / on the end, we need
4540 * to add one so we get a proper path to the file
4542 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4543 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4545 return g_strconcat (dir, file, NULL);
4549 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4551 char *n = mono_string_to_utf8 (name);
4552 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4554 guint32 cols [MONO_MANIFEST_SIZE];
4555 guint32 impl, file_idx;
4559 MONO_ARCH_SAVE_REGS;
4561 for (i = 0; i < table->rows; ++i) {
4562 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4563 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4564 if (strcmp (val, n) == 0)
4568 if (i == table->rows)
4571 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4574 * this code should only be called after obtaining the
4575 * ResourceInfo and handling the other cases.
4577 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4578 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4580 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4585 module = assembly->assembly->image;
4587 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4589 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4592 ICALL_EXPORT gboolean
4593 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4595 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4597 guint32 cols [MONO_MANIFEST_SIZE];
4598 guint32 file_cols [MONO_FILE_SIZE];
4602 MONO_ARCH_SAVE_REGS;
4604 n = mono_string_to_utf8 (name);
4605 for (i = 0; i < table->rows; ++i) {
4606 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4607 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4608 if (strcmp (val, n) == 0)
4612 if (i == table->rows)
4615 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4616 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4619 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4620 case MONO_IMPLEMENTATION_FILE:
4621 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4622 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4623 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4624 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4625 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4626 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4629 info->location = RESOURCE_LOCATION_EMBEDDED;
4632 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4633 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4634 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4635 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4636 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4637 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4639 mono_raise_exception (ex);
4641 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4643 /* Obtain info recursively */
4644 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4645 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4648 case MONO_IMPLEMENTATION_EXP_TYPE:
4649 g_assert_not_reached ();
4657 ICALL_EXPORT MonoObject*
4658 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4660 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4661 MonoArray *result = NULL;
4666 MONO_ARCH_SAVE_REGS;
4668 /* check hash if needed */
4670 n = mono_string_to_utf8 (name);
4671 for (i = 0; i < table->rows; ++i) {
4672 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4673 if (strcmp (val, n) == 0) {
4676 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4677 fn = mono_string_new (mono_object_domain (assembly), n);
4679 return (MonoObject*)fn;
4687 for (i = 0; i < table->rows; ++i) {
4688 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4692 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4695 for (i = 0; i < table->rows; ++i) {
4696 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4697 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4698 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4699 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4704 return (MonoObject*)result;
4707 ICALL_EXPORT MonoArray*
4708 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4710 MonoDomain *domain = mono_domain_get();
4713 int i, j, file_count = 0;
4714 MonoImage **modules;
4715 guint32 module_count, real_module_count;
4716 MonoTableInfo *table;
4717 guint32 cols [MONO_FILE_SIZE];
4718 MonoImage *image = assembly->assembly->image;
4720 g_assert (image != NULL);
4721 g_assert (!assembly->assembly->dynamic);
4723 table = &image->tables [MONO_TABLE_FILE];
4724 file_count = table->rows;
4726 modules = image->modules;
4727 module_count = image->module_count;
4729 real_module_count = 0;
4730 for (i = 0; i < module_count; ++i)
4732 real_module_count ++;
4734 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4735 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4737 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4739 for (i = 0; i < module_count; ++i)
4741 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4745 for (i = 0; i < file_count; ++i, ++j) {
4746 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4747 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4748 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4750 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4752 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4753 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4755 mono_array_setref (res, j, mono_module_get_object (domain, m));
4762 ICALL_EXPORT MonoReflectionMethod*
4763 ves_icall_GetCurrentMethod (void)
4765 MonoMethod *m = mono_method_get_last_managed ();
4767 while (m->is_inflated)
4768 m = ((MonoMethodInflated*)m)->declaring;
4770 return mono_method_get_object (mono_domain_get (), m, NULL);
4775 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4778 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4779 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4780 //method is inflated, we should inflate it on the other class
4781 MonoGenericContext ctx;
4782 ctx.method_inst = inflated->context.method_inst;
4783 ctx.class_inst = inflated->context.class_inst;
4784 if (klass->generic_class)
4785 ctx.class_inst = klass->generic_class->context.class_inst;
4786 else if (klass->generic_container)
4787 ctx.class_inst = klass->generic_container->context.class_inst;
4788 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4791 mono_class_setup_methods (method->klass);
4792 if (method->klass->exception_type)
4794 for (i = 0; i < method->klass->method.count; ++i) {
4795 if (method->klass->methods [i] == method) {
4800 mono_class_setup_methods (klass);
4801 if (klass->exception_type)
4803 g_assert (offset >= 0 && offset < klass->method.count);
4804 return klass->methods [offset];
4807 ICALL_EXPORT MonoReflectionMethod*
4808 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4812 klass = mono_class_from_mono_type (type);
4813 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4815 if (method->klass != klass) {
4816 method = mono_method_get_equivalent_method (method, klass);
4821 klass = method->klass;
4822 return mono_method_get_object (mono_domain_get (), method, klass);
4825 ICALL_EXPORT MonoReflectionMethod*
4826 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4828 return mono_method_get_object (mono_domain_get (), method, NULL);
4831 ICALL_EXPORT MonoReflectionMethodBody*
4832 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4834 return mono_method_body_get_object (mono_domain_get (), method);
4837 ICALL_EXPORT MonoReflectionAssembly*
4838 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4840 MonoMethod *dest = NULL;
4842 MONO_ARCH_SAVE_REGS;
4844 mono_stack_walk_no_il (get_executing, &dest);
4846 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4850 ICALL_EXPORT MonoReflectionAssembly*
4851 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4853 MonoDomain* domain = mono_domain_get ();
4855 MONO_ARCH_SAVE_REGS;
4857 if (!domain->entry_assembly)
4860 return mono_assembly_get_object (domain, domain->entry_assembly);
4863 ICALL_EXPORT MonoReflectionAssembly*
4864 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4869 MONO_ARCH_SAVE_REGS;
4872 mono_stack_walk_no_il (get_executing, &dest);
4874 mono_stack_walk_no_il (get_caller, &dest);
4877 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4880 ICALL_EXPORT MonoString *
4881 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4882 gboolean assembly_qualified)
4884 MonoDomain *domain = mono_object_domain (object);
4885 MonoTypeNameFormat format;
4890 format = assembly_qualified ?
4891 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4892 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4894 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4896 name = mono_type_get_name_full (object->type, format);
4900 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4905 res = mono_string_new (domain, name);
4912 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4914 MonoClass *klass = mono_class_from_mono_type (this->type);
4915 mono_class_init_or_throw (klass);
4916 return mono_security_core_clr_class_level (klass);
4920 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4922 static MonoMethod *create_culture = NULL;
4925 const char *pkey_ptr;
4927 MonoBoolean assembly_ref = 0;
4929 MONO_ARCH_SAVE_REGS;
4931 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4932 aname->major = name->major;
4933 aname->minor = name->minor;
4934 aname->build = name->build;
4935 aname->flags = name->flags;
4936 aname->revision = name->revision;
4937 aname->hashalg = name->hash_alg;
4938 aname->versioncompat = 1; /* SameMachine (default) */
4939 aname->processor_architecture = name->arch;
4941 if (by_default_version)
4942 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4945 if (absolute != NULL && *absolute != '\0') {
4946 const gchar *prepend = "file://";
4949 codebase = g_strdup (absolute);
4954 for (i = strlen (codebase) - 1; i >= 0; i--)
4955 if (codebase [i] == '\\')
4958 if (*codebase == '/' && *(codebase + 1) == '/') {
4961 prepend = "file:///";
4965 result = g_strconcat (prepend, codebase, NULL);
4971 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4975 if (!create_culture) {
4976 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4977 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4978 g_assert (create_culture);
4979 mono_method_desc_free (desc);
4982 if (name->culture) {
4983 args [0] = mono_string_new (domain, name->culture);
4984 args [1] = &assembly_ref;
4985 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4988 if (name->public_key) {
4989 pkey_ptr = (char*)name->public_key;
4990 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4992 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4993 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4994 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4995 } else if (default_publickey) {
4996 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4997 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5000 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5001 if (name->public_key_token [0]) {
5005 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5006 p = mono_array_addr (aname->keyToken, char, 0);
5008 for (i = 0, j = 0; i < 8; i++) {
5009 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5010 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5013 } else if (default_token) {
5014 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5018 ICALL_EXPORT MonoString *
5019 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5021 MonoDomain *domain = mono_object_domain (assembly);
5022 MonoAssembly *mass = assembly->assembly;
5026 name = mono_stringify_assembly_name (&mass->aname);
5027 res = mono_string_new (domain, name);
5034 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5037 MonoAssembly *mass = assembly->assembly;
5039 MONO_ARCH_SAVE_REGS;
5041 if (g_path_is_absolute (mass->image->name)) {
5042 fill_reflection_assembly_name (mono_object_domain (assembly),
5043 aname, &mass->aname, mass->image->name, TRUE,
5047 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5049 fill_reflection_assembly_name (mono_object_domain (assembly),
5050 aname, &mass->aname, absolute, TRUE, TRUE,
5057 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5060 MonoImageOpenStatus status = MONO_IMAGE_OK;
5063 MonoAssemblyName name;
5066 MONO_ARCH_SAVE_REGS;
5068 filename = mono_string_to_utf8 (fname);
5070 dirname = g_path_get_dirname (filename);
5071 replace_shadow_path (mono_domain_get (), dirname, &filename);
5074 image = mono_image_open (filename, &status);
5080 if (status == MONO_IMAGE_IMAGE_INVALID)
5081 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5083 exc = mono_get_exception_file_not_found2 (NULL, fname);
5084 mono_raise_exception (exc);
5087 res = mono_assembly_fill_assembly_name (image, &name);
5089 mono_image_close (image);
5091 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5094 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5098 mono_image_close (image);
5101 ICALL_EXPORT MonoBoolean
5102 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5103 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5105 MonoBoolean result = FALSE;
5106 MonoDeclSecurityEntry entry;
5108 /* SecurityAction.RequestMinimum */
5109 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5110 *minimum = entry.blob;
5111 *minLength = entry.size;
5114 /* SecurityAction.RequestOptional */
5115 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5116 *optional = entry.blob;
5117 *optLength = entry.size;
5120 /* SecurityAction.RequestRefuse */
5121 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5122 *refused = entry.blob;
5123 *refLength = entry.size;
5131 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5135 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5137 guint32 attrs, visibility;
5139 /* we start the count from 1 because we skip the special type <Module> */
5142 for (i = 1; i < tdef->rows; ++i) {
5143 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5144 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5145 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5149 count = tdef->rows - 1;
5151 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5152 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5154 for (i = 1; i < tdef->rows; ++i) {
5155 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5156 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5157 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5158 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5160 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5162 MonoLoaderError *error;
5165 error = mono_loader_get_last_error ();
5166 g_assert (error != NULL);
5168 ex = mono_loader_error_prepare_exception (error);
5169 mono_array_setref (*exceptions, count, ex);
5171 if (mono_loader_get_last_error ())
5172 mono_loader_clear_error ();
5180 ICALL_EXPORT MonoArray*
5181 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5183 MonoArray *res = NULL;
5184 MonoArray *exceptions = NULL;
5185 MonoImage *image = NULL;
5186 MonoTableInfo *table = NULL;
5189 int i, len, ex_count;
5191 MONO_ARCH_SAVE_REGS;
5193 domain = mono_object_domain (assembly);
5195 g_assert (!assembly->assembly->dynamic);
5196 image = assembly->assembly->image;
5197 table = &image->tables [MONO_TABLE_FILE];
5198 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5200 /* Append data from all modules in the assembly */
5201 for (i = 0; i < table->rows; ++i) {
5202 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5203 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5206 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5207 /* Append the new types to the end of the array */
5208 if (mono_array_length (res2) > 0) {
5210 MonoArray *res3, *ex3;
5212 len1 = mono_array_length (res);
5213 len2 = mono_array_length (res2);
5215 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5216 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5217 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5220 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5221 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5222 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5229 /* the ReflectionTypeLoadException must have all the types (Types property),
5230 * NULL replacing types which throws an exception. The LoaderException must
5231 * contain all exceptions for NULL items.
5234 len = mono_array_length (res);
5237 for (i = 0; i < len; i++) {
5238 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5242 klass = mono_type_get_class (t->type);
5243 if ((klass != NULL) && klass->exception_type) {
5244 /* keep the class in the list */
5245 list = g_list_append (list, klass);
5246 /* and replace Type with NULL */
5247 mono_array_setref (res, i, NULL);
5254 if (list || ex_count) {
5256 MonoException *exc = NULL;
5257 MonoArray *exl = NULL;
5258 int j, length = g_list_length (list) + ex_count;
5260 mono_loader_clear_error ();
5262 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5263 /* Types for which mono_class_get () succeeded */
5264 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5265 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5266 mono_array_setref (exl, i, exc);
5268 /* Types for which it don't */
5269 for (j = 0; j < mono_array_length (exceptions); ++j) {
5270 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5272 g_assert (i < length);
5273 mono_array_setref (exl, i, exc);
5280 exc = mono_get_exception_reflection_type_load (res, exl);
5281 mono_loader_clear_error ();
5282 mono_raise_exception (exc);
5288 ICALL_EXPORT gboolean
5289 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5291 MonoAssemblyName aname;
5292 MonoDomain *domain = mono_object_domain (name);
5294 gboolean is_version_defined;
5295 gboolean is_token_defined;
5297 aname.public_key = NULL;
5298 val = mono_string_to_utf8 (assname);
5299 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5300 g_free ((guint8*) aname.public_key);
5305 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5306 FALSE, is_token_defined);
5308 mono_assembly_name_free (&aname);
5309 g_free ((guint8*) aname.public_key);
5315 ICALL_EXPORT MonoReflectionType*
5316 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5318 MonoDomain *domain = mono_object_domain (module);
5321 MONO_ARCH_SAVE_REGS;
5323 g_assert (module->image);
5325 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5326 /* These images do not have a global type */
5329 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5330 return mono_type_get_object (domain, &klass->byval_arg);
5334 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5336 /*if (module->image)
5337 mono_image_close (module->image);*/
5340 ICALL_EXPORT MonoString*
5341 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5343 MonoDomain *domain = mono_object_domain (module);
5345 MONO_ARCH_SAVE_REGS;
5347 g_assert (module->image);
5348 return mono_string_new (domain, module->image->guid);
5351 ICALL_EXPORT gpointer
5352 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5355 if (module->image && module->image->is_module_handle)
5356 return module->image->raw_data;
5359 return (gpointer) (-1);
5363 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5365 if (image->dynamic) {
5366 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5367 *pe_kind = dyn->pe_kind;
5368 *machine = dyn->machine;
5371 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5372 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5377 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5379 return (image->md_version_major << 16) | (image->md_version_minor);
5382 ICALL_EXPORT MonoArray*
5383 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5385 MonoArray *exceptions;
5388 MONO_ARCH_SAVE_REGS;
5391 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5393 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5394 for (i = 0; i < mono_array_length (exceptions); ++i) {
5395 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5397 mono_raise_exception (ex);
5404 mono_memberref_is_method (MonoImage *image, guint32 token)
5406 if (!image->dynamic) {
5407 guint32 cols [MONO_MEMBERREF_SIZE];
5409 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5410 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5411 mono_metadata_decode_blob_size (sig, &sig);
5412 return (*sig != 0x6);
5414 MonoClass *handle_class;
5416 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5419 return mono_defaults.methodhandle_class == handle_class;
5424 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5427 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5428 mono_array_addr (type_args, MonoType*, 0));
5430 context->class_inst = NULL;
5432 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5433 mono_array_addr (method_args, MonoType*, 0));
5435 context->method_inst = NULL;
5438 ICALL_EXPORT MonoType*
5439 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5442 int table = mono_metadata_token_table (token);
5443 int index = mono_metadata_token_index (token);
5444 MonoGenericContext context;
5446 *error = ResolveTokenError_Other;
5448 /* Validate token */
5449 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5450 (table != MONO_TABLE_TYPESPEC)) {
5451 *error = ResolveTokenError_BadTable;
5455 if (image->dynamic) {
5456 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5457 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5458 return klass ? &klass->byval_arg : NULL;
5461 init_generic_context_from_args (&context, type_args, method_args);
5462 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5463 return klass ? &klass->byval_arg : NULL;
5466 if ((index <= 0) || (index > image->tables [table].rows)) {
5467 *error = ResolveTokenError_OutOfRange;
5471 init_generic_context_from_args (&context, type_args, method_args);
5472 klass = mono_class_get_full (image, token, &context);
5474 if (mono_loader_get_last_error ())
5475 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5478 return &klass->byval_arg;
5483 ICALL_EXPORT MonoMethod*
5484 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5486 int table = mono_metadata_token_table (token);
5487 int index = mono_metadata_token_index (token);
5488 MonoGenericContext context;
5491 *error = ResolveTokenError_Other;
5493 /* Validate token */
5494 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5495 (table != MONO_TABLE_MEMBERREF)) {
5496 *error = ResolveTokenError_BadTable;
5500 if (image->dynamic) {
5501 if (table == MONO_TABLE_METHOD)
5502 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5504 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5505 *error = ResolveTokenError_BadTable;
5509 init_generic_context_from_args (&context, type_args, method_args);
5510 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5513 if ((index <= 0) || (index > image->tables [table].rows)) {
5514 *error = ResolveTokenError_OutOfRange;
5517 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5518 *error = ResolveTokenError_BadTable;
5522 init_generic_context_from_args (&context, type_args, method_args);
5523 method = mono_get_method_full (image, token, NULL, &context);
5525 if (mono_loader_get_last_error ())
5526 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5531 ICALL_EXPORT MonoString*
5532 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5534 int index = mono_metadata_token_index (token);
5536 *error = ResolveTokenError_Other;
5538 /* Validate token */
5539 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5540 *error = ResolveTokenError_BadTable;
5545 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5547 if ((index <= 0) || (index >= image->heap_us.size)) {
5548 *error = ResolveTokenError_OutOfRange;
5552 /* FIXME: What to do if the index points into the middle of a string ? */
5554 return mono_ldstr (mono_domain_get (), image, index);
5557 ICALL_EXPORT MonoClassField*
5558 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5561 int table = mono_metadata_token_table (token);
5562 int index = mono_metadata_token_index (token);
5563 MonoGenericContext context;
5564 MonoClassField *field;
5566 *error = ResolveTokenError_Other;
5568 /* Validate token */
5569 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5570 *error = ResolveTokenError_BadTable;
5574 if (image->dynamic) {
5575 if (table == MONO_TABLE_FIELD)
5576 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5578 if (mono_memberref_is_method (image, token)) {
5579 *error = ResolveTokenError_BadTable;
5583 init_generic_context_from_args (&context, type_args, method_args);
5584 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5587 if ((index <= 0) || (index > image->tables [table].rows)) {
5588 *error = ResolveTokenError_OutOfRange;
5591 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5592 *error = ResolveTokenError_BadTable;
5596 init_generic_context_from_args (&context, type_args, method_args);
5597 field = mono_field_from_token (image, token, &klass, &context);
5599 if (mono_loader_get_last_error ())
5600 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5606 ICALL_EXPORT MonoObject*
5607 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5609 int table = mono_metadata_token_table (token);
5611 *error = ResolveTokenError_Other;
5614 case MONO_TABLE_TYPEDEF:
5615 case MONO_TABLE_TYPEREF:
5616 case MONO_TABLE_TYPESPEC: {
5617 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5619 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5623 case MONO_TABLE_METHOD:
5624 case MONO_TABLE_METHODSPEC: {
5625 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5627 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5631 case MONO_TABLE_FIELD: {
5632 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5634 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5638 case MONO_TABLE_MEMBERREF:
5639 if (mono_memberref_is_method (image, token)) {
5640 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5642 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5647 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5649 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5656 *error = ResolveTokenError_BadTable;
5662 ICALL_EXPORT MonoArray*
5663 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5665 int table = mono_metadata_token_table (token);
5666 int idx = mono_metadata_token_index (token);
5667 MonoTableInfo *tables = image->tables;
5672 *error = ResolveTokenError_OutOfRange;
5674 /* FIXME: Support other tables ? */
5675 if (table != MONO_TABLE_STANDALONESIG)
5681 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5684 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5686 ptr = mono_metadata_blob_heap (image, sig);
5687 len = mono_metadata_decode_blob_size (ptr, &ptr);
5689 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5690 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5694 ICALL_EXPORT MonoReflectionType*
5695 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5698 int isbyref = 0, rank;
5699 char *str = mono_string_to_utf8 (smodifiers);
5702 MONO_ARCH_SAVE_REGS;
5704 klass = mono_class_from_mono_type (tb->type.type);
5706 /* logic taken from mono_reflection_parse_type(): keep in sync */
5710 if (isbyref) { /* only one level allowed by the spec */
5717 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5720 klass = mono_ptr_class_get (&klass->byval_arg);
5721 mono_class_init (klass);
5732 else if (*p != '*') { /* '*' means unknown lower bound */
5743 klass = mono_array_class_get (klass, rank);
5744 mono_class_init (klass);
5751 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5754 ICALL_EXPORT MonoBoolean
5755 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5760 MONO_ARCH_SAVE_REGS;
5763 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5769 check_for_invalid_type (MonoClass *klass)
5773 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5776 name = mono_type_get_full_name (klass);
5777 str = mono_string_new (mono_domain_get (), name);
5779 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5782 ICALL_EXPORT MonoReflectionType *
5783 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5785 MonoClass *klass, *aklass;
5787 MONO_ARCH_SAVE_REGS;
5789 klass = mono_class_from_mono_type (type->type);
5790 check_for_invalid_type (klass);
5792 if (rank == 0) //single dimentional array
5793 aklass = mono_array_class_get (klass, 1);
5795 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5797 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5800 ICALL_EXPORT MonoReflectionType *
5801 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5805 MONO_ARCH_SAVE_REGS;
5807 klass = mono_class_from_mono_type (type->type);
5808 mono_class_init_or_throw (klass);
5809 check_for_invalid_type (klass);
5811 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5814 ICALL_EXPORT MonoReflectionType *
5815 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5817 MonoClass *klass, *pklass;
5819 klass = mono_class_from_mono_type (type->type);
5820 mono_class_init_or_throw (klass);
5821 check_for_invalid_type (klass);
5823 pklass = mono_ptr_class_get (type->type);
5825 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5828 ICALL_EXPORT MonoObject *
5829 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5830 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5832 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5833 MonoObject *delegate;
5835 MonoMethod *method = info->method;
5837 MONO_ARCH_SAVE_REGS;
5839 mono_class_init_or_throw (delegate_class);
5841 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5843 if (mono_security_core_clr_enabled ()) {
5844 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5848 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5850 if (method->dynamic) {
5851 /* Creating a trampoline would leak memory */
5852 func = mono_compile_method (method);
5854 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5855 method = mono_object_get_virtual_method (target, method);
5856 func = mono_create_ftnptr (mono_domain_get (),
5857 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5860 mono_delegate_ctor_with_method (delegate, target, func, method);
5866 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5868 /* Reset the invoke impl to the default one */
5869 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5873 * Magic number to convert a time which is relative to
5874 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5876 #define EPOCH_ADJUST ((guint64)62135596800LL)
5879 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5881 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5884 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5886 convert_to_absolute_date(SYSTEMTIME *date)
5888 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5889 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5890 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5891 /* from the calendar FAQ */
5892 int a = (14 - date->wMonth) / 12;
5893 int y = date->wYear - a;
5894 int m = date->wMonth + 12 * a - 2;
5895 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5897 /* d is now the day of the week for the first of the month (0 == Sunday) */
5899 int day_of_week = date->wDayOfWeek;
5901 /* set day_in_month to the first day in the month which falls on day_of_week */
5902 int day_in_month = 1 + (day_of_week - d);
5903 if (day_in_month <= 0)
5906 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5907 date->wDay = day_in_month + (date->wDay - 1) * 7;
5908 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5915 * Return's the offset from GMT of a local time.
5917 * tm is a local time
5918 * t is the same local time as seconds.
5921 gmt_offset(struct tm *tm, time_t t)
5923 #if defined (HAVE_TM_GMTOFF)
5924 return tm->tm_gmtoff;
5929 g.tm_isdst = tm->tm_isdst;
5931 return (int)difftime(t, t2);
5936 * This is heavily based on zdump.c from glibc 2.2.
5938 * * data[0]: start of daylight saving time (in DateTime ticks).
5939 * * data[1]: end of daylight saving time (in DateTime ticks).
5940 * * data[2]: utcoffset (in TimeSpan ticks).
5941 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5942 * * name[0]: name of this timezone when not daylight saving.
5943 * * name[1]: name of this timezone when daylight saving.
5945 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5946 * the class library allows years between 1 and 9999.
5948 * Returns true on success and zero on failure.
5950 ICALL_EXPORT guint32
5951 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5954 MonoDomain *domain = mono_domain_get ();
5955 struct tm start, tt;
5959 int is_daylight = 0, day;
5962 MONO_ARCH_SAVE_REGS;
5964 MONO_CHECK_ARG_NULL (data);
5965 MONO_CHECK_ARG_NULL (names);
5967 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5968 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5971 * no info is better than crashing: we'll need our own tz data
5972 * to make this work properly, anyway. The range is probably
5973 * reduced to 1970 .. 2037 because that is what mktime is
5974 * guaranteed to support (we get into an infinite loop
5978 memset (&start, 0, sizeof (start));
5981 start.tm_year = year-1900;
5983 t = mktime (&start);
5985 if ((year < 1970) || (year > 2037) || (t == -1)) {
5987 tt = *localtime (&t);
5988 strftime (tzone, sizeof (tzone), "%Z", &tt);
5989 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5990 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5994 gmtoff = gmt_offset (&start, t);
5996 /* For each day of the year, calculate the tm_gmtoff. */
5997 for (day = 0; day < 365; day++) {
6000 tt = *localtime (&t);
6002 /* Daylight saving starts or ends here. */
6003 if (gmt_offset (&tt, t) != gmtoff) {
6007 /* Try to find the exact hour when daylight saving starts/ends. */
6011 tt1 = *localtime (&t1);
6012 } while (gmt_offset (&tt1, t1) != gmtoff);
6014 /* Try to find the exact minute when daylight saving starts/ends. */
6017 tt1 = *localtime (&t1);
6018 } while (gmt_offset (&tt1, t1) == gmtoff);
6020 strftime (tzone, sizeof (tzone), "%Z", &tt);
6022 /* Write data, if we're already in daylight saving, we're done. */
6024 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6025 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6031 memset (&end, 0, sizeof (end));
6032 end.tm_year = year-1900 + 1;
6037 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6038 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6039 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6040 mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
6044 /* This is only set once when we enter daylight saving. */
6045 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6046 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6048 gmtoff = gmt_offset (&tt, t);
6053 strftime (tzone, sizeof (tzone), "%Z", &tt);
6054 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6055 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6056 mono_array_set ((*data), gint64, 0, 0);
6057 mono_array_set ((*data), gint64, 1, 0);
6058 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6059 mono_array_set ((*data), gint64, 3, 0);
6064 MonoDomain *domain = mono_domain_get ();
6065 TIME_ZONE_INFORMATION tz_info;
6070 tz_id = GetTimeZoneInformation (&tz_info);
6071 if (tz_id == TIME_ZONE_ID_INVALID)
6074 MONO_CHECK_ARG_NULL (data);
6075 MONO_CHECK_ARG_NULL (names);
6077 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6078 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6080 for (i = 0; i < 32; ++i)
6081 if (!tz_info.DaylightName [i])
6083 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6084 for (i = 0; i < 32; ++i)
6085 if (!tz_info.StandardName [i])
6087 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6089 if ((year <= 1601) || (year > 30827)) {
6091 * According to MSDN, the MS time functions can't handle dates outside
6097 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6098 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6099 tz_info.StandardDate.wYear = year;
6100 convert_to_absolute_date(&tz_info.StandardDate);
6101 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6106 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6107 tz_info.DaylightDate.wYear = year;
6108 convert_to_absolute_date(&tz_info.DaylightDate);
6109 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6114 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6116 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6117 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6123 ICALL_EXPORT gpointer
6124 ves_icall_System_Object_obj_address (MonoObject *this)
6126 MONO_ARCH_SAVE_REGS;
6133 static inline gint32
6134 mono_array_get_byte_length (MonoArray *array)
6140 klass = array->obj.vtable->klass;
6142 if (array->bounds == NULL)
6143 length = array->max_length;
6146 for (i = 0; i < klass->rank; ++ i)
6147 length *= array->bounds [i].length;
6150 switch (klass->element_class->byval_arg.type) {
6153 case MONO_TYPE_BOOLEAN:
6157 case MONO_TYPE_CHAR:
6165 return length * sizeof (gpointer);
6176 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6178 MONO_ARCH_SAVE_REGS;
6180 return mono_array_get_byte_length (array);
6184 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6186 MONO_ARCH_SAVE_REGS;
6188 return mono_array_get (array, gint8, idx);
6192 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6194 MONO_ARCH_SAVE_REGS;
6196 mono_array_set (array, gint8, idx, value);
6199 ICALL_EXPORT MonoBoolean
6200 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6202 guint8 *src_buf, *dest_buf;
6204 MONO_ARCH_SAVE_REGS;
6206 /* This is called directly from the class libraries without going through the managed wrapper */
6207 MONO_CHECK_ARG_NULL (src);
6208 MONO_CHECK_ARG_NULL (dest);
6210 /* watch out for integer overflow */
6211 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6214 src_buf = (guint8 *)src->vector + src_offset;
6215 dest_buf = (guint8 *)dest->vector + dest_offset;
6218 memcpy (dest_buf, src_buf, count);
6220 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6225 #ifndef DISABLE_REMOTING
6226 ICALL_EXPORT MonoObject *
6227 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6229 MonoDomain *domain = mono_object_domain (this);
6231 MonoRealProxy *rp = ((MonoRealProxy *)this);
6232 MonoTransparentProxy *tp;
6236 MONO_ARCH_SAVE_REGS;
6238 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6239 tp = (MonoTransparentProxy*) res;
6241 MONO_OBJECT_SETREF (tp, rp, rp);
6242 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6243 klass = mono_class_from_mono_type (type);
6245 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6246 tp->remote_class = mono_remote_class (domain, class_name, klass);
6248 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6252 ICALL_EXPORT MonoReflectionType *
6253 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6255 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6259 /* System.Environment */
6262 ves_icall_System_Environment_get_UserName (void)
6264 MONO_ARCH_SAVE_REGS;
6266 /* using glib is more portable */
6267 return mono_string_new (mono_domain_get (), g_get_user_name ());
6271 ICALL_EXPORT MonoString *
6272 ves_icall_System_Environment_get_MachineName (void)
6274 #if defined (HOST_WIN32)
6279 len = MAX_COMPUTERNAME_LENGTH + 1;
6280 buf = g_new (gunichar2, len);
6283 if (GetComputerName (buf, (PDWORD) &len))
6284 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6288 #elif !defined(DISABLE_SOCKETS)
6292 if (gethostname (buf, sizeof (buf)) == 0)
6293 result = mono_string_new (mono_domain_get (), buf);
6299 return mono_string_new (mono_domain_get (), "mono");
6304 ves_icall_System_Environment_get_Platform (void)
6306 #if defined (TARGET_WIN32)
6309 #elif defined(__MACH__)
6312 // Notice that the value is hidden from user code, and only exposed
6313 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6314 // define and making assumptions based on Unix/128/4 values before there
6315 // was a MacOS define. Lots of code would assume that not-Unix meant
6316 // Windows, but in this case, it would be OSX.
6325 ICALL_EXPORT MonoString *
6326 ves_icall_System_Environment_get_NewLine (void)
6328 MONO_ARCH_SAVE_REGS;
6330 #if defined (HOST_WIN32)
6331 return mono_string_new (mono_domain_get (), "\r\n");
6333 return mono_string_new (mono_domain_get (), "\n");
6337 ICALL_EXPORT MonoString *
6338 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6343 MONO_ARCH_SAVE_REGS;
6348 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6349 value = g_getenv (utf8_name);
6356 return mono_string_new (mono_domain_get (), value);
6360 * There is no standard way to get at environ.
6363 #ifndef __MINGW32_VERSION
6364 #if defined(__APPLE__) && !defined (__arm__)
6365 /* Apple defines this in crt_externs.h but doesn't provide that header for
6366 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6367 * in fact exist on all implementations (so far)
6369 gchar ***_NSGetEnviron(void);
6370 #define environ (*_NSGetEnviron())
6378 ICALL_EXPORT MonoArray *
6379 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6390 env_strings = GetEnvironmentStrings();
6393 env_string = env_strings;
6394 while (*env_string != '\0') {
6395 /* weird case that MS seems to skip */
6396 if (*env_string != '=')
6398 while (*env_string != '\0')
6404 domain = mono_domain_get ();
6405 names = mono_array_new (domain, mono_defaults.string_class, n);
6409 env_string = env_strings;
6410 while (*env_string != '\0') {
6411 /* weird case that MS seems to skip */
6412 if (*env_string != '=') {
6413 equal_str = wcschr(env_string, '=');
6414 g_assert(equal_str);
6415 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6416 mono_array_setref (names, n, str);
6419 while (*env_string != '\0')
6424 FreeEnvironmentStrings (env_strings);
6436 MONO_ARCH_SAVE_REGS;
6439 for (e = environ; *e != 0; ++ e)
6442 domain = mono_domain_get ();
6443 names = mono_array_new (domain, mono_defaults.string_class, n);
6446 for (e = environ; *e != 0; ++ e) {
6447 parts = g_strsplit (*e, "=", 2);
6449 str = mono_string_new (domain, *parts);
6450 mono_array_setref (names, n, str);
6463 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6465 #if !GLIB_CHECK_VERSION(2,4,0)
6466 #define g_setenv(a,b,c) setenv(a,b,c)
6467 #define g_unsetenv(a) unsetenv(a)
6471 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6476 gunichar2 *utf16_name, *utf16_value;
6478 gchar *utf8_name, *utf8_value;
6481 MONO_ARCH_SAVE_REGS;
6484 utf16_name = mono_string_to_utf16 (name);
6485 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6486 SetEnvironmentVariable (utf16_name, NULL);
6487 g_free (utf16_name);
6491 utf16_value = mono_string_to_utf16 (value);
6493 SetEnvironmentVariable (utf16_name, utf16_value);
6495 g_free (utf16_name);
6496 g_free (utf16_value);
6498 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6500 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6501 g_unsetenv (utf8_name);
6506 utf8_value = mono_string_to_utf8_checked (value, &error);
6507 if (!mono_error_ok (&error)) {
6509 mono_error_raise_exception (&error);
6511 g_setenv (utf8_name, utf8_value, TRUE);
6514 g_free (utf8_value);
6519 ves_icall_System_Environment_Exit (int result)
6521 MONO_ARCH_SAVE_REGS;
6523 /* FIXME: There are some cleanup hangs that should be worked out, but
6524 * if the program is going to exit, everything will be cleaned up when
6525 * NaCl exits anyway.
6527 #ifndef __native_client__
6528 mono_runtime_shutdown ();
6530 /* This will kill the tp threads which cannot be suspended */
6531 mono_thread_pool_cleanup ();
6533 /* Suspend all managed threads since the runtime is going away */
6534 mono_thread_suspend_all_other_threads ();
6536 mono_runtime_quit ();
6539 /* we may need to do some cleanup here... */
6543 ICALL_EXPORT MonoString*
6544 ves_icall_System_Environment_GetGacPath (void)
6546 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6549 ICALL_EXPORT MonoString*
6550 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6552 #if defined (HOST_WIN32)
6553 #ifndef CSIDL_FLAG_CREATE
6554 #define CSIDL_FLAG_CREATE 0x8000
6557 WCHAR path [MAX_PATH];
6558 /* Create directory if no existing */
6559 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6563 return mono_string_new_utf16 (mono_domain_get (), path, len);
6566 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6568 return mono_string_new (mono_domain_get (), "");
6571 ICALL_EXPORT MonoArray *
6572 ves_icall_System_Environment_GetLogicalDrives (void)
6574 gunichar2 buf [256], *ptr, *dname;
6576 guint initial_size = 127, size = 128;
6579 MonoString *drivestr;
6580 MonoDomain *domain = mono_domain_get ();
6583 MONO_ARCH_SAVE_REGS;
6588 while (size > initial_size) {
6589 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6590 if (size > initial_size) {
6593 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6594 initial_size = size;
6608 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6613 while (*u16) { u16++; len ++; }
6614 drivestr = mono_string_new_utf16 (domain, dname, len);
6615 mono_array_setref (result, ndrives++, drivestr);
6625 ICALL_EXPORT MonoString *
6626 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6628 gunichar2 volume_name [MAX_PATH + 1];
6630 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6632 return mono_string_from_utf16 (volume_name);
6635 ICALL_EXPORT MonoString *
6636 ves_icall_System_Environment_InternalGetHome (void)
6638 MONO_ARCH_SAVE_REGS;
6640 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6643 static const char *encodings [] = {
6645 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6646 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6647 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6649 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6650 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6651 "x_unicode_2_0_utf_7",
6653 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6654 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6656 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6659 "unicodefffe", "utf_16be",
6666 * Returns the internal codepage, if the value of "int_code_page" is
6667 * 1 at entry, and we can not compute a suitable code page number,
6668 * returns the code page as a string
6670 ICALL_EXPORT MonoString*
6671 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6676 char *codepage = NULL;
6678 int want_name = *int_code_page;
6681 *int_code_page = -1;
6682 MONO_ARCH_SAVE_REGS;
6684 g_get_charset (&cset);
6685 c = codepage = strdup (cset);
6686 for (c = codepage; *c; c++){
6687 if (isascii (*c) && isalpha (*c))
6692 /* g_print ("charset: %s\n", cset); */
6694 /* handle some common aliases */
6697 for (i = 0; p != 0; ){
6698 if ((gssize) p < 7){
6700 p = encodings [++i];
6703 if (strcmp (p, codepage) == 0){
6704 *int_code_page = code;
6707 p = encodings [++i];
6710 if (strstr (codepage, "utf_8") != NULL)
6711 *int_code_page |= 0x10000000;
6714 if (want_name && *int_code_page == -1)
6715 return mono_string_new (mono_domain_get (), cset);
6720 ICALL_EXPORT MonoBoolean
6721 ves_icall_System_Environment_get_HasShutdownStarted (void)
6723 if (mono_runtime_is_shutting_down ())
6726 if (mono_domain_is_unloading (mono_domain_get ()))
6733 ves_icall_System_Environment_BroadcastSettingChange (void)
6736 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6741 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6742 MonoReflectionMethod *method,
6743 MonoArray *out_args)
6745 MONO_ARCH_SAVE_REGS;
6747 mono_message_init (mono_object_domain (this), this, method, out_args);
6750 #ifndef DISABLE_REMOTING
6751 ICALL_EXPORT MonoBoolean
6752 ves_icall_IsTransparentProxy (MonoObject *proxy)
6754 MONO_ARCH_SAVE_REGS;
6759 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6765 ICALL_EXPORT MonoReflectionMethod *
6766 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6767 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6771 MonoMethod **vtable;
6772 MonoMethod *res = NULL;
6774 MONO_CHECK_ARG_NULL (rtype);
6775 MONO_CHECK_ARG_NULL (rmethod);
6777 method = rmethod->method;
6778 klass = mono_class_from_mono_type (rtype->type);
6779 mono_class_init_or_throw (klass);
6781 if (MONO_CLASS_IS_INTERFACE (klass))
6784 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6787 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6788 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6794 mono_class_setup_vtable (klass);
6795 vtable = klass->vtable;
6797 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6798 gboolean variance_used = FALSE;
6799 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6800 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6802 res = vtable [offs + method->slot];
6804 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6807 if (method->slot != -1)
6808 res = vtable [method->slot];
6814 return mono_method_get_object (mono_domain_get (), res, NULL);
6818 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6823 MONO_ARCH_SAVE_REGS;
6825 klass = mono_class_from_mono_type (type->type);
6826 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6828 mono_vtable_set_is_remote (vtable, enable);
6831 #else /* DISABLE_REMOTING */
6834 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6836 g_assert_not_reached ();
6841 ICALL_EXPORT MonoObject *
6842 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6847 MONO_ARCH_SAVE_REGS;
6849 domain = mono_object_domain (type);
6850 klass = mono_class_from_mono_type (type->type);
6851 mono_class_init_or_throw (klass);
6853 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6854 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6856 if (klass->rank >= 1) {
6857 g_assert (klass->rank == 1);
6858 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6860 /* Bypass remoting object creation check */
6861 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6865 ICALL_EXPORT MonoString *
6866 ves_icall_System_IO_get_temp_path (void)
6868 MONO_ARCH_SAVE_REGS;
6870 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6873 #ifndef PLATFORM_NO_DRIVEINFO
6874 ICALL_EXPORT MonoBoolean
6875 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6876 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6880 ULARGE_INTEGER wapi_free_bytes_avail;
6881 ULARGE_INTEGER wapi_total_number_of_bytes;
6882 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6884 MONO_ARCH_SAVE_REGS;
6886 *error = ERROR_SUCCESS;
6887 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6888 &wapi_total_number_of_free_bytes);
6891 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6892 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6893 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6895 *free_bytes_avail = 0;
6896 *total_number_of_bytes = 0;
6897 *total_number_of_free_bytes = 0;
6898 *error = GetLastError ();
6904 ICALL_EXPORT guint32
6905 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6907 MONO_ARCH_SAVE_REGS;
6909 return GetDriveType (mono_string_chars (root_path_name));
6913 ICALL_EXPORT gpointer
6914 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6916 MONO_ARCH_SAVE_REGS;
6918 return mono_compile_method (method);
6921 ICALL_EXPORT MonoString *
6922 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6927 MONO_ARCH_SAVE_REGS;
6929 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6931 #if defined (HOST_WIN32)
6932 /* Avoid mixing '/' and '\\' */
6935 for (i = strlen (path) - 1; i >= 0; i--)
6936 if (path [i] == '/')
6940 mcpath = mono_string_new (mono_domain_get (), path);
6947 get_bundled_app_config (void)
6949 const gchar *app_config;
6952 gchar *config_file_name, *config_file_path;
6956 MONO_ARCH_SAVE_REGS;
6958 domain = mono_domain_get ();
6959 file = domain->setup->configuration_file;
6963 // Retrieve config file and remove the extension
6964 config_file_name = mono_string_to_utf8 (file);
6965 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6966 if (!config_file_path)
6967 config_file_path = config_file_name;
6968 len = strlen (config_file_path) - strlen (".config");
6969 module = g_malloc0 (len + 1);
6970 memcpy (module, config_file_path, len);
6971 // Get the config file from the module name
6972 app_config = mono_config_string_for_assembly_file (module);
6975 if (config_file_name != config_file_path)
6976 g_free (config_file_name);
6977 g_free (config_file_path);
6982 return mono_string_new (mono_domain_get (), app_config);
6986 get_bundled_machine_config (void)
6988 const gchar *machine_config;
6990 MONO_ARCH_SAVE_REGS;
6992 machine_config = mono_get_machine_config ();
6994 if (!machine_config)
6997 return mono_string_new (mono_domain_get (), machine_config);
7000 ICALL_EXPORT MonoString *
7001 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7006 MONO_ARCH_SAVE_REGS;
7008 path = g_path_get_dirname (mono_get_config_dir ());
7010 #if defined (HOST_WIN32)
7011 /* Avoid mixing '/' and '\\' */
7014 for (i = strlen (path) - 1; i >= 0; i--)
7015 if (path [i] == '/')
7019 ipath = mono_string_new (mono_domain_get (), path);
7025 ICALL_EXPORT gboolean
7026 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7028 MonoPEResourceDataEntry *entry;
7031 MONO_ARCH_SAVE_REGS;
7033 if (!assembly || !result || !size)
7038 image = assembly->assembly->image;
7039 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7043 *result = mono_image_rva_map (image, entry->rde_data_offset);
7048 *size = entry->rde_size;
7053 ICALL_EXPORT MonoBoolean
7054 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7056 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7059 ICALL_EXPORT MonoBoolean
7060 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7062 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7063 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7069 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7071 if (mono_get_runtime_callbacks ()->debug_log)
7072 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7076 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7078 #if defined (HOST_WIN32)
7079 OutputDebugString (mono_string_chars (message));
7081 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7085 /* Only used for value types */
7086 ICALL_EXPORT MonoObject *
7087 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7092 MONO_ARCH_SAVE_REGS;
7094 domain = mono_object_domain (type);
7095 klass = mono_class_from_mono_type (type->type);
7096 mono_class_init_or_throw (klass);
7098 if (mono_class_is_nullable (klass))
7099 /* No arguments -> null */
7102 return mono_object_new (domain, klass);
7105 ICALL_EXPORT MonoReflectionMethod *
7106 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7108 MonoClass *klass, *parent;
7109 MonoMethod *method = m->method;
7110 MonoMethod *result = NULL;
7113 MONO_ARCH_SAVE_REGS;
7115 if (method->klass == NULL)
7118 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7119 MONO_CLASS_IS_INTERFACE (method->klass) ||
7120 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7123 slot = mono_method_get_vtable_slot (method);
7127 klass = method->klass;
7128 if (klass->generic_class)
7129 klass = klass->generic_class->container_class;
7132 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7133 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7134 mono_class_setup_vtable (parent);
7135 if (parent->vtable_size <= slot)
7140 klass = klass->parent;
7145 if (klass == method->klass)
7148 /*This is possible if definition == FALSE.
7149 * Do it here to be really sure we don't read invalid memory.
7151 if (slot >= klass->vtable_size)
7154 mono_class_setup_vtable (klass);
7156 result = klass->vtable [slot];
7157 if (result == NULL) {
7158 /* It is an abstract method */
7159 gpointer iter = NULL;
7160 while ((result = mono_class_get_methods (klass, &iter)))
7161 if (result->slot == slot)
7168 return mono_method_get_object (mono_domain_get (), result, NULL);
7171 ICALL_EXPORT MonoString*
7172 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7174 MonoMethod *method = m->method;
7176 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7181 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7183 MONO_ARCH_SAVE_REGS;
7185 iter->sig = *(MonoMethodSignature**)argsp;
7187 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7188 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7191 /* FIXME: it's not documented what start is exactly... */
7195 iter->args = argsp + sizeof (gpointer);
7197 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7199 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7202 ICALL_EXPORT MonoTypedRef
7203 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7205 guint32 i, arg_size;
7208 MONO_ARCH_SAVE_REGS;
7210 i = iter->sig->sentinelpos + iter->next_arg;
7212 g_assert (i < iter->sig->param_count);
7214 res.type = iter->sig->params [i];
7215 res.klass = mono_class_from_mono_type (res.type);
7216 arg_size = mono_type_stack_size (res.type, &align);
7217 #if defined(__arm__) || defined(__mips__)
7218 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7220 res.value = iter->args;
7221 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7222 /* Values are stored as 8 byte register sized objects, but 'value'
7223 * is dereferenced as a pointer in other routines.
7225 res.value = (char*)res.value + 4;
7227 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7228 if (arg_size <= sizeof (gpointer)) {
7230 int padding = arg_size - mono_type_size (res.type, &dummy);
7231 res.value = (guint8*)res.value + padding;
7234 iter->args = (char*)iter->args + arg_size;
7237 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7242 ICALL_EXPORT MonoTypedRef
7243 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7245 guint32 i, arg_size;
7248 MONO_ARCH_SAVE_REGS;
7250 i = iter->sig->sentinelpos + iter->next_arg;
7252 g_assert (i < iter->sig->param_count);
7254 while (i < iter->sig->param_count) {
7255 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7257 res.type = iter->sig->params [i];
7258 res.klass = mono_class_from_mono_type (res.type);
7259 /* FIXME: endianess issue... */
7260 arg_size = mono_type_stack_size (res.type, &align);
7261 #if defined(__arm__) || defined(__mips__)
7262 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7264 res.value = iter->args;
7265 iter->args = (char*)iter->args + arg_size;
7267 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7270 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7278 ICALL_EXPORT MonoType*
7279 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7282 MONO_ARCH_SAVE_REGS;
7284 i = iter->sig->sentinelpos + iter->next_arg;
7286 g_assert (i < iter->sig->param_count);
7288 return iter->sig->params [i];
7291 ICALL_EXPORT MonoObject*
7292 mono_TypedReference_ToObject (MonoTypedRef tref)
7294 MONO_ARCH_SAVE_REGS;
7296 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7297 MonoObject** objp = tref.value;
7301 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7304 ICALL_EXPORT MonoObject*
7305 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7307 MONO_ARCH_SAVE_REGS;
7309 if (MONO_TYPE_IS_REFERENCE (type)) {
7310 MonoObject** objp = value;
7314 return mono_value_box (mono_domain_get (), klass, value);
7318 prelink_method (MonoMethod *method)
7320 const char *exc_class, *exc_arg;
7321 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7323 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7325 mono_raise_exception(
7326 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7328 /* create the wrapper, too? */
7332 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7334 MONO_ARCH_SAVE_REGS;
7335 prelink_method (method->method);
7339 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7341 MonoClass *klass = mono_class_from_mono_type (type->type);
7343 gpointer iter = NULL;
7344 MONO_ARCH_SAVE_REGS;
7346 mono_class_init_or_throw (klass);
7348 while ((m = mono_class_get_methods (klass, &iter)))
7352 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7354 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7355 gint32 const **exponents,
7356 gunichar2 const **digitLowerTable,
7357 gunichar2 const **digitUpperTable,
7358 gint64 const **tenPowersList,
7359 gint32 const **decHexDigits)
7361 *mantissas = Formatter_MantissaBitsTable;
7362 *exponents = Formatter_TensExponentTable;
7363 *digitLowerTable = Formatter_DigitLowerTable;
7364 *digitUpperTable = Formatter_DigitUpperTable;
7365 *tenPowersList = Formatter_TenPowersList;
7366 *decHexDigits = Formatter_DecHexDigits;
7370 get_category_data (int version,
7371 guint8 const **category_data,
7372 guint16 const **category_astral_index)
7374 *category_astral_index = NULL;
7376 #ifndef DISABLE_NET_4_0
7378 *category_data = CategoryData_v4;
7379 #ifndef DISABLE_ASTRAL
7380 *category_astral_index = CategoryData_v4_astral_index;
7386 *category_data = CategoryData_v2;
7387 #ifndef DISABLE_ASTRAL
7388 *category_astral_index = CategoryData_v2_astral_index;
7392 /* These parameters are "readonly" in corlib/System/Char.cs */
7394 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7395 guint8 const **category_data,
7396 guint16 const **category_astral_index,
7397 guint8 const **numeric_data,
7398 gdouble const **numeric_data_values,
7399 guint16 const **to_lower_data_low,
7400 guint16 const **to_lower_data_high,
7401 guint16 const **to_upper_data_low,
7402 guint16 const **to_upper_data_high)
7404 get_category_data (category_data_version, category_data, category_astral_index);
7405 *numeric_data = NumericData;
7406 *numeric_data_values = NumericDataValues;
7407 *to_lower_data_low = ToLowerDataLow;
7408 *to_lower_data_high = ToLowerDataHigh;
7409 *to_upper_data_low = ToUpperDataLow;
7410 *to_upper_data_high = ToUpperDataHigh;
7414 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7416 return method->method->token;
7420 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7421 * and avoid useless allocations.
7424 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7428 for (i = 0; i < type->num_mods; ++i) {
7429 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7434 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7436 for (i = 0; i < type->num_mods; ++i) {
7437 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7438 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7439 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7446 ICALL_EXPORT MonoArray*
7447 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7449 MonoType *type = param->ClassImpl->type;
7450 MonoClass *member_class = mono_object_class (param->MemberImpl);
7451 MonoMethod *method = NULL;
7454 MonoMethodSignature *sig;
7456 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7457 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7458 method = rmethod->method;
7459 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7460 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7461 if (!(method = prop->property->get))
7462 method = prop->property->set;
7465 char *type_name = mono_type_get_full_name (member_class);
7466 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7467 MonoException *ex = mono_get_exception_not_supported (msg);
7470 mono_raise_exception (ex);
7473 image = method->klass->image;
7474 pos = param->PositionImpl;
7475 sig = mono_method_signature (method);
7479 type = sig->params [pos];
7481 return type_array_from_modifiers (image, type, optional);
7485 get_property_type (MonoProperty *prop)
7487 MonoMethodSignature *sig;
7489 sig = mono_method_signature (prop->get);
7491 } else if (prop->set) {
7492 sig = mono_method_signature (prop->set);
7493 return sig->params [sig->param_count - 1];
7498 ICALL_EXPORT MonoArray*
7499 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7501 MonoType *type = get_property_type (property->property);
7502 MonoImage *image = property->klass->image;
7506 return type_array_from_modifiers (image, type, optional);
7510 *Construct a MonoType suited to be used to decode a constant blob object.
7512 * @type is the target type which will be constructed
7513 * @blob_type is the blob type, for example, that comes from the constant table
7514 * @real_type is the expected constructed type.
7517 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7519 type->type = blob_type;
7520 type->data.klass = NULL;
7521 if (blob_type == MONO_TYPE_CLASS)
7522 type->data.klass = mono_defaults.object_class;
7523 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7524 /* For enums, we need to use the base type */
7525 type->type = MONO_TYPE_VALUETYPE;
7526 type->data.klass = mono_class_from_mono_type (real_type);
7528 type->data.klass = mono_class_from_mono_type (real_type);
7531 ICALL_EXPORT MonoObject*
7532 property_info_get_default_value (MonoReflectionProperty *property)
7535 MonoProperty *prop = property->property;
7536 MonoType *type = get_property_type (prop);
7537 MonoDomain *domain = mono_object_domain (property);
7538 MonoTypeEnum def_type;
7539 const char *def_value;
7542 mono_class_init (prop->parent);
7544 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7545 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7547 def_value = mono_class_get_property_default_value (prop, &def_type);
7549 mono_type_from_blob_type (&blob_type, def_type, type);
7550 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7555 ICALL_EXPORT MonoBoolean
7556 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7558 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7559 MonoCustomAttrInfo *cinfo;
7562 mono_class_init_or_throw (attr_class);
7564 cinfo = mono_reflection_get_custom_attrs_info (obj);
7567 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7569 mono_custom_attrs_free (cinfo);
7573 ICALL_EXPORT MonoArray*
7574 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7576 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7581 mono_class_init_or_throw (attr_class);
7583 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7584 if (!mono_error_ok (&error))
7585 mono_error_raise_exception (&error);
7586 if (mono_loader_get_last_error ()) {
7587 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7588 g_assert_not_reached ();
7596 ICALL_EXPORT MonoString*
7597 ves_icall_Mono_Runtime_GetDisplayName (void)
7600 MonoString *display_name;
7602 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7603 display_name = mono_string_new (mono_domain_get (), info);
7605 return display_name;
7608 ICALL_EXPORT MonoString*
7609 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7611 MonoString *message;
7615 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7616 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7619 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7621 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7629 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7630 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7631 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7632 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7633 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7634 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7635 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7636 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7640 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7645 gunichar2 last, prev_last, prev2_last;
7652 int havePadding = 0;
7654 last = prev_last = 0, prev2_last = 0;
7655 for (i = 0; i < ilength; i++) {
7657 if (c >= sizeof (dbase64)) {
7658 exc = mono_exception_from_name_msg (mono_get_corlib (),
7659 "System", "FormatException",
7660 "Invalid character found.");
7661 mono_raise_exception (exc);
7662 } else if (isspace (c)) {
7664 } else if (havePadding && c != '=') {
7665 exc = mono_exception_from_name_msg (mono_get_corlib (),
7666 "System", "FormatException",
7667 "Invalid character found.");
7668 mono_raise_exception (exc);
7670 if (c == '=') havePadding = 1;
7671 prev2_last = prev_last;
7677 olength = ilength - ignored;
7679 if (allowWhitespaceOnly && olength == 0) {
7680 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7683 if ((olength & 3) != 0 || olength <= 0) {
7684 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7685 "FormatException", "Invalid length.");
7686 mono_raise_exception (exc);
7689 if (prev2_last == '=') {
7690 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7691 mono_raise_exception (exc);
7694 olength = (olength * 3) / 4;
7698 if (prev_last == '=')
7701 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7702 res_ptr = mono_array_addr (result, guchar, 0);
7703 for (i = 0; i < ilength; ) {
7706 for (k = 0; k < 4 && i < ilength;) {
7712 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7713 exc = mono_exception_from_name_msg (mono_get_corlib (),
7714 "System", "FormatException",
7715 "Invalid character found.");
7716 mono_raise_exception (exc);
7721 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7723 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7725 *res_ptr++ = (b [2] << 6) | b [3];
7727 while (i < ilength && isspace (start [i]))
7734 ICALL_EXPORT MonoArray *
7735 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7737 MONO_ARCH_SAVE_REGS;
7739 return base64_to_byte_array (mono_string_chars (str),
7740 mono_string_length (str), allowWhitespaceOnly);
7743 ICALL_EXPORT MonoArray *
7744 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7746 MONO_ARCH_SAVE_REGS;
7748 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7752 #ifndef DISABLE_ICALL_TABLES
7754 #define ICALL_TYPE(id,name,first)
7755 #define ICALL(id,name,func) Icall_ ## id,
7758 #include "metadata/icall-def.h"
7764 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7765 #define ICALL(id,name,func)
7767 #include "metadata/icall-def.h"
7773 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7774 #define ICALL(id,name,func)
7776 guint16 first_icall;
7779 static const IcallTypeDesc
7780 icall_type_descs [] = {
7781 #include "metadata/icall-def.h"
7785 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7788 #define ICALL_TYPE(id,name,first)
7791 #ifdef HAVE_ARRAY_ELEM_INIT
7792 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7793 #define MSGSTRFIELD1(line) str##line
7795 static const struct msgstrtn_t {
7796 #define ICALL(id,name,func)
7798 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7799 #include "metadata/icall-def.h"
7801 } icall_type_names_str = {
7802 #define ICALL_TYPE(id,name,first) (name),
7803 #include "metadata/icall-def.h"
7806 static const guint16 icall_type_names_idx [] = {
7807 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7808 #include "metadata/icall-def.h"
7811 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7813 static const struct msgstr_t {
7815 #define ICALL_TYPE(id,name,first)
7816 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7817 #include "metadata/icall-def.h"
7819 } icall_names_str = {
7820 #define ICALL(id,name,func) (name),
7821 #include "metadata/icall-def.h"
7824 static const guint16 icall_names_idx [] = {
7825 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7826 #include "metadata/icall-def.h"
7829 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7835 #define ICALL_TYPE(id,name,first) name,
7836 #define ICALL(id,name,func)
7837 static const char* const
7838 icall_type_names [] = {
7839 #include "metadata/icall-def.h"
7843 #define icall_type_name_get(id) (icall_type_names [(id)])
7847 #define ICALL_TYPE(id,name,first)
7848 #define ICALL(id,name,func) name,
7849 static const char* const
7851 #include "metadata/icall-def.h"
7854 #define icall_name_get(id) icall_names [(id)]
7856 #endif /* !HAVE_ARRAY_ELEM_INIT */
7860 #define ICALL_TYPE(id,name,first)
7861 #define ICALL(id,name,func) func,
7862 static const gconstpointer
7863 icall_functions [] = {
7864 #include "metadata/icall-def.h"
7868 #ifdef ENABLE_ICALL_SYMBOL_MAP
7871 #define ICALL_TYPE(id,name,first)
7872 #define ICALL(id,name,func) #func,
7873 static const gconstpointer
7874 icall_symbols [] = {
7875 #include "metadata/icall-def.h"
7880 #endif /* DISABLE_ICALL_TABLES */
7882 static GHashTable *icall_hash = NULL;
7883 static GHashTable *jit_icall_hash_name = NULL;
7884 static GHashTable *jit_icall_hash_addr = NULL;
7887 mono_icall_init (void)
7889 #ifndef DISABLE_ICALL_TABLES
7892 /* check that tables are sorted: disable in release */
7895 const char *prev_class = NULL;
7896 const char *prev_method;
7898 for (i = 0; i < Icall_type_num; ++i) {
7899 const IcallTypeDesc *desc;
7902 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7903 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7904 prev_class = icall_type_name_get (i);
7905 desc = &icall_type_descs [i];
7906 num_icalls = icall_desc_num_icalls (desc);
7907 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7908 for (j = 0; j < num_icalls; ++j) {
7909 const char *methodn = icall_name_get (desc->first_icall + j);
7910 if (prev_method && strcmp (prev_method, methodn) >= 0)
7911 g_print ("method %s should come before method %s\n", methodn, prev_method);
7912 prev_method = methodn;
7918 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7922 mono_icall_cleanup (void)
7924 g_hash_table_destroy (icall_hash);
7925 g_hash_table_destroy (jit_icall_hash_name);
7926 g_hash_table_destroy (jit_icall_hash_addr);
7930 mono_add_internal_call (const char *name, gconstpointer method)
7932 mono_loader_lock ();
7934 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7936 mono_loader_unlock ();
7939 #ifndef DISABLE_ICALL_TABLES
7941 #ifdef HAVE_ARRAY_ELEM_INIT
7943 compare_method_imap (const void *key, const void *elem)
7945 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7946 return strcmp (key, method_name);
7950 find_method_icall (const IcallTypeDesc *imap, const char *name)
7952 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7955 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7959 compare_class_imap (const void *key, const void *elem)
7961 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7962 return strcmp (key, class_name);
7965 static const IcallTypeDesc*
7966 find_class_icalls (const char *name)
7968 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7971 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7974 #else /* HAVE_ARRAY_ELEM_INIT */
7977 compare_method_imap (const void *key, const void *elem)
7979 const char** method_name = (const char**)elem;
7980 return strcmp (key, *method_name);
7984 find_method_icall (const IcallTypeDesc *imap, const char *name)
7986 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7989 return (gpointer)icall_functions [(nameslot - icall_names)];
7993 compare_class_imap (const void *key, const void *elem)
7995 const char** class_name = (const char**)elem;
7996 return strcmp (key, *class_name);
7999 static const IcallTypeDesc*
8000 find_class_icalls (const char *name)
8002 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8005 return &icall_type_descs [nameslot - icall_type_names];
8008 #endif /* HAVE_ARRAY_ELEM_INIT */
8010 #endif /* DISABLE_ICALL_TABLES */
8013 * we should probably export this as an helper (handle nested types).
8014 * Returns the number of chars written in buf.
8017 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8019 int nspacelen, cnamelen;
8020 nspacelen = strlen (klass->name_space);
8021 cnamelen = strlen (klass->name);
8022 if (nspacelen + cnamelen + 2 > bufsize)
8025 memcpy (buf, klass->name_space, nspacelen);
8026 buf [nspacelen ++] = '.';
8028 memcpy (buf + nspacelen, klass->name, cnamelen);
8029 buf [nspacelen + cnamelen] = 0;
8030 return nspacelen + cnamelen;
8033 #ifdef DISABLE_ICALL_TABLES
8035 no_icall_table (void)
8037 g_assert_not_reached ();
8042 mono_lookup_internal_call (MonoMethod *method)
8047 int typelen = 0, mlen, siglen;
8049 #ifndef DISABLE_ICALL_TABLES
8050 const IcallTypeDesc *imap = NULL;
8053 g_assert (method != NULL);
8055 if (method->is_inflated)
8056 method = ((MonoMethodInflated *) method)->declaring;
8058 if (method->klass->nested_in) {
8059 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8063 mname [pos++] = '/';
8066 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8072 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8077 #ifndef DISABLE_ICALL_TABLES
8078 imap = find_class_icalls (mname);
8081 mname [typelen] = ':';
8082 mname [typelen + 1] = ':';
8084 mlen = strlen (method->name);
8085 memcpy (mname + typelen + 2, method->name, mlen);
8086 sigstart = mname + typelen + 2 + mlen;
8089 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8090 siglen = strlen (tmpsig);
8091 if (typelen + mlen + siglen + 6 > sizeof (mname))
8094 memcpy (sigstart + 1, tmpsig, siglen);
8095 sigstart [siglen + 1] = ')';
8096 sigstart [siglen + 2] = 0;
8099 mono_loader_lock ();
8101 res = g_hash_table_lookup (icall_hash, mname);
8103 mono_loader_unlock ();
8106 /* try without signature */
8108 res = g_hash_table_lookup (icall_hash, mname);
8110 mono_loader_unlock ();
8114 #ifdef DISABLE_ICALL_TABLES
8115 mono_loader_unlock ();
8116 /* Fail only when the result is actually used */
8117 /* mono_marshal_get_native_wrapper () depends on this */
8118 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8119 return ves_icall_System_String_ctor_RedirectToCreateString;
8121 return no_icall_table;
8123 /* it wasn't found in the static call tables */
8125 mono_loader_unlock ();
8128 res = find_method_icall (imap, sigstart - mlen);
8130 mono_loader_unlock ();
8133 /* try _with_ signature */
8135 res = find_method_icall (imap, sigstart - mlen);
8137 mono_loader_unlock ();
8141 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8142 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8143 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8144 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8145 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");
8146 g_print ("If you see other errors or faults after this message they are probably related\n");
8147 g_print ("and you need to fix your mono install first.\n");
8149 mono_loader_unlock ();
8155 #ifdef ENABLE_ICALL_SYMBOL_MAP
8157 func_cmp (gconstpointer key, gconstpointer p)
8159 return (gsize)key - (gsize)*(gsize*)p;
8164 * mono_lookup_icall_symbol:
8166 * Given the icall METHOD, returns its C symbol.
8169 mono_lookup_icall_symbol (MonoMethod *m)
8171 #ifdef DISABLE_ICALL_TABLES
8172 g_assert_not_reached ();
8175 #ifdef ENABLE_ICALL_SYMBOL_MAP
8179 static gconstpointer *functions_sorted;
8180 static const char**symbols_sorted;
8181 static gboolean inited;
8186 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8187 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8188 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8189 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8190 /* Bubble sort the two arrays */
8194 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8195 if (functions_sorted [i] > functions_sorted [i + 1]) {
8198 tmp = functions_sorted [i];
8199 functions_sorted [i] = functions_sorted [i + 1];
8200 functions_sorted [i + 1] = tmp;
8201 tmp = symbols_sorted [i];
8202 symbols_sorted [i] = symbols_sorted [i + 1];
8203 symbols_sorted [i + 1] = tmp;
8210 func = mono_lookup_internal_call (m);
8213 slot = bsearch (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8217 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8219 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8220 g_assert_not_reached ();
8227 type_from_typename (char *typename)
8229 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8231 if (!strcmp (typename, "int"))
8232 klass = mono_defaults.int_class;
8233 else if (!strcmp (typename, "ptr"))
8234 klass = mono_defaults.int_class;
8235 else if (!strcmp (typename, "void"))
8236 klass = mono_defaults.void_class;
8237 else if (!strcmp (typename, "int32"))
8238 klass = mono_defaults.int32_class;
8239 else if (!strcmp (typename, "uint32"))
8240 klass = mono_defaults.uint32_class;
8241 else if (!strcmp (typename, "int8"))
8242 klass = mono_defaults.sbyte_class;
8243 else if (!strcmp (typename, "uint8"))
8244 klass = mono_defaults.byte_class;
8245 else if (!strcmp (typename, "int16"))
8246 klass = mono_defaults.int16_class;
8247 else if (!strcmp (typename, "uint16"))
8248 klass = mono_defaults.uint16_class;
8249 else if (!strcmp (typename, "long"))
8250 klass = mono_defaults.int64_class;
8251 else if (!strcmp (typename, "ulong"))
8252 klass = mono_defaults.uint64_class;
8253 else if (!strcmp (typename, "float"))
8254 klass = mono_defaults.single_class;
8255 else if (!strcmp (typename, "double"))
8256 klass = mono_defaults.double_class;
8257 else if (!strcmp (typename, "object"))
8258 klass = mono_defaults.object_class;
8259 else if (!strcmp (typename, "obj"))
8260 klass = mono_defaults.object_class;
8261 else if (!strcmp (typename, "string"))
8262 klass = mono_defaults.string_class;
8263 else if (!strcmp (typename, "bool"))
8264 klass = mono_defaults.boolean_class;
8265 else if (!strcmp (typename, "boolean"))
8266 klass = mono_defaults.boolean_class;
8268 g_error ("%s", typename);
8269 g_assert_not_reached ();
8271 return &klass->byval_arg;
8274 MonoMethodSignature*
8275 mono_create_icall_signature (const char *sigstr)
8280 MonoMethodSignature *res;
8282 mono_loader_lock ();
8283 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8285 mono_loader_unlock ();
8289 parts = g_strsplit (sigstr, " ", 256);
8298 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8303 * Under windows, the default pinvoke calling convention is STDCALL but
8306 res->call_convention = MONO_CALL_C;
8309 res->ret = type_from_typename (parts [0]);
8310 for (i = 1; i < len; ++i) {
8311 res->params [i - 1] = type_from_typename (parts [i]);
8316 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8318 mono_loader_unlock ();
8324 mono_find_jit_icall_by_name (const char *name)
8326 MonoJitICallInfo *info;
8327 g_assert (jit_icall_hash_name);
8329 mono_loader_lock ();
8330 info = g_hash_table_lookup (jit_icall_hash_name, name);
8331 mono_loader_unlock ();
8336 mono_find_jit_icall_by_addr (gconstpointer addr)
8338 MonoJitICallInfo *info;
8339 g_assert (jit_icall_hash_addr);
8341 mono_loader_lock ();
8342 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8343 mono_loader_unlock ();
8349 * mono_get_jit_icall_info:
8351 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8352 * caller should access it while holding the loader lock.
8355 mono_get_jit_icall_info (void)
8357 return jit_icall_hash_name;
8361 * mono_lookup_jit_icall_symbol:
8363 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8366 mono_lookup_jit_icall_symbol (const char *name)
8368 MonoJitICallInfo *info;
8369 const char *res = NULL;
8371 mono_loader_lock ();
8372 info = g_hash_table_lookup (jit_icall_hash_name, name);
8374 res = info->c_symbol;
8375 mono_loader_unlock ();
8380 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8382 mono_loader_lock ();
8383 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8384 mono_loader_unlock ();
8388 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8390 MonoJitICallInfo *info;
8395 mono_loader_lock ();
8397 if (!jit_icall_hash_name) {
8398 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8399 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8402 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8403 g_warning ("jit icall already defined \"%s\"\n", name);
8404 g_assert_not_reached ();
8407 info = g_new0 (MonoJitICallInfo, 1);
8412 info->c_symbol = c_symbol;
8415 info->wrapper = func;
8417 info->wrapper = NULL;
8420 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8421 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8423 mono_loader_unlock ();
8428 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8430 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);