5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
22 #ifdef HAVE_SYS_TIME_H
28 #if defined (HOST_WIN32)
31 #if defined (HAVE_WCHAR_H)
35 #include "mono/utils/mono-membar.h"
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/threads.h>
38 #include <mono/metadata/threads-types.h>
39 #include <mono/metadata/threadpool.h>
40 #include <mono/metadata/monitor.h>
41 #include <mono/metadata/reflection.h>
42 #include <mono/metadata/assembly.h>
43 #include <mono/metadata/tabledefs.h>
44 #include <mono/metadata/exception.h>
45 #include <mono/metadata/file-io.h>
46 #include <mono/metadata/console-io.h>
47 #include <mono/metadata/socket-io.h>
48 #include <mono/metadata/mono-endian.h>
49 #include <mono/metadata/tokentype.h>
50 #include <mono/metadata/domain-internals.h>
51 #include <mono/metadata/metadata-internals.h>
52 #include <mono/metadata/class-internals.h>
53 #include <mono/metadata/marshal.h>
54 #include <mono/metadata/gc-internal.h>
55 #include <mono/metadata/mono-gc.h>
56 #include <mono/metadata/rand.h>
57 #include <mono/metadata/sysmath.h>
58 #include <mono/metadata/string-icalls.h>
59 #include <mono/metadata/debug-helpers.h>
60 #include <mono/metadata/process.h>
61 #include <mono/metadata/environment.h>
62 #include <mono/metadata/profiler-private.h>
63 #include <mono/metadata/locales.h>
64 #include <mono/metadata/filewatcher.h>
65 #include <mono/metadata/char-conversions.h>
66 #include <mono/metadata/security.h>
67 #include <mono/metadata/mono-config.h>
68 #include <mono/metadata/cil-coff.h>
69 #include <mono/metadata/number-formatter.h>
70 #include <mono/metadata/security-manager.h>
71 #include <mono/metadata/security-core-clr.h>
72 #include <mono/metadata/mono-perfcounters.h>
73 #include <mono/metadata/mono-debug.h>
74 #include <mono/metadata/mono-ptr-array.h>
75 #include <mono/metadata/verify-internals.h>
76 #include <mono/metadata/runtime.h>
77 #include <mono/io-layer/io-layer.h>
78 #include <mono/utils/strtod.h>
79 #include <mono/utils/monobitset.h>
80 #include <mono/utils/mono-time.h>
81 #include <mono/utils/mono-proclib.h>
82 #include <mono/utils/mono-string.h>
83 #include <mono/utils/mono-error-internals.h>
84 #include <mono/utils/mono-mmap.h>
85 #include <mono/utils/mono-io-portability.h>
86 #include <mono/utils/mono-digest.h>
87 #include <mono/utils/bsearch.h>
89 #if defined (HOST_WIN32)
95 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
97 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
100 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
102 static inline MonoBoolean
103 is_generic_parameter (MonoType *type)
105 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
109 mono_class_init_or_throw (MonoClass *klass)
111 if (!mono_class_init (klass))
112 mono_raise_exception (mono_class_get_exception_for_failure (klass));
116 * We expect a pointer to a char, not a string
118 ICALL_EXPORT gboolean
119 mono_double_ParseImpl (char *ptr, double *result)
121 gchar *endptr = NULL;
128 *result = strtod (ptr, &endptr);
131 /* mono_strtod () is not thread-safe */
132 EnterCriticalSection (&mono_strtod_mutex);
133 *result = mono_strtod (ptr, &endptr);
134 LeaveCriticalSection (&mono_strtod_mutex);
138 if (!*ptr || (endptr && *endptr))
144 ICALL_EXPORT MonoObject *
145 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
154 ao = (MonoArray *)this;
155 ac = (MonoClass *)ao->obj.vtable->klass;
157 esize = mono_array_element_size (ac);
158 ea = (gpointer*)((char*)ao->vector + (pos * esize));
160 if (ac->element_class->valuetype)
161 return mono_value_box (this->vtable->domain, ac->element_class, ea);
166 ICALL_EXPORT MonoObject *
167 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
175 MONO_CHECK_ARG_NULL (idxs);
177 io = (MonoArray *)idxs;
178 ic = (MonoClass *)io->obj.vtable->klass;
180 ao = (MonoArray *)this;
181 ac = (MonoClass *)ao->obj.vtable->klass;
183 g_assert (ic->rank == 1);
184 if (io->bounds != NULL || io->max_length != ac->rank)
185 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
187 ind = (gint32 *)io->vector;
189 if (ao->bounds == NULL) {
190 if (*ind < 0 || *ind >= ao->max_length)
191 mono_raise_exception (mono_get_exception_index_out_of_range ());
193 return ves_icall_System_Array_GetValueImpl (this, *ind);
196 for (i = 0; i < ac->rank; i++)
197 if ((ind [i] < ao->bounds [i].lower_bound) ||
198 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
199 mono_raise_exception (mono_get_exception_index_out_of_range ());
201 pos = ind [0] - ao->bounds [0].lower_bound;
202 for (i = 1; i < ac->rank; i++)
203 pos = pos*ao->bounds [i].length + ind [i] -
204 ao->bounds [i].lower_bound;
206 return ves_icall_System_Array_GetValueImpl (this, pos);
210 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
212 MonoClass *ac, *vc, *ec;
224 vc = value->vtable->klass;
228 ac = this->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)this->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
241 mono_gc_bzero (ea, esize);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_raise_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
250 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
251 if (esize < vsize + (extra)) \
252 mono_raise_exception (mono_get_exception_argument ( \
253 "value", "not a widening conversion")); \
256 #define INVALID_CAST G_STMT_START{ \
257 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
258 mono_raise_exception (mono_get_exception_invalid_cast ()); \
261 /* Check element (destination) type. */
262 switch (ec->byval_arg.type) {
263 case MONO_TYPE_STRING:
264 switch (vc->byval_arg.type) {
265 case MONO_TYPE_STRING:
271 case MONO_TYPE_BOOLEAN:
272 switch (vc->byval_arg.type) {
273 case MONO_TYPE_BOOLEAN:
286 NO_WIDENING_CONVERSION;
293 if (!ec->valuetype) {
294 if (!mono_object_isinst (value, ec))
296 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
300 if (mono_object_isinst (value, ec)) {
301 if (ec->has_references)
302 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
304 mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
311 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
313 et = ec->byval_arg.type;
314 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
315 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
317 vt = vc->byval_arg.type;
318 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
319 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
321 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
327 case MONO_TYPE_CHAR: \
328 CHECK_WIDENING_CONVERSION(0); \
329 *(etype *) ea = (etype) u64; \
331 /* You can't assign a signed value to an unsigned array. */ \
336 /* You can't assign a floating point number to an integer array. */ \
339 NO_WIDENING_CONVERSION; \
343 #define ASSIGN_SIGNED(etype) G_STMT_START{\
349 CHECK_WIDENING_CONVERSION(0); \
350 *(etype *) ea = (etype) i64; \
352 /* You can assign an unsigned value to a signed array if the array's */ \
353 /* element size is larger than the value size. */ \
358 case MONO_TYPE_CHAR: \
359 CHECK_WIDENING_CONVERSION(1); \
360 *(etype *) ea = (etype) u64; \
362 /* You can't assign a floating point number to an integer array. */ \
365 NO_WIDENING_CONVERSION; \
369 #define ASSIGN_REAL(etype) G_STMT_START{\
373 CHECK_WIDENING_CONVERSION(0); \
374 *(etype *) ea = (etype) r64; \
376 /* All integer values fit into a floating point array, so we don't */ \
377 /* need to CHECK_WIDENING_CONVERSION here. */ \
382 *(etype *) ea = (etype) i64; \
388 case MONO_TYPE_CHAR: \
389 *(etype *) ea = (etype) u64; \
396 u64 = *(guint8 *) va;
399 u64 = *(guint16 *) va;
402 u64 = *(guint32 *) va;
405 u64 = *(guint64 *) va;
411 i64 = *(gint16 *) va;
414 i64 = *(gint32 *) va;
417 i64 = *(gint64 *) va;
420 r64 = *(gfloat *) va;
423 r64 = *(gdouble *) va;
426 u64 = *(guint16 *) va;
428 case MONO_TYPE_BOOLEAN:
429 /* Boolean is only compatible with itself. */
442 NO_WIDENING_CONVERSION;
449 /* If we can't do a direct copy, let's try a widening conversion. */
452 ASSIGN_UNSIGNED (guint16);
454 ASSIGN_UNSIGNED (guint8);
456 ASSIGN_UNSIGNED (guint16);
458 ASSIGN_UNSIGNED (guint32);
460 ASSIGN_UNSIGNED (guint64);
462 ASSIGN_SIGNED (gint8);
464 ASSIGN_SIGNED (gint16);
466 ASSIGN_SIGNED (gint32);
468 ASSIGN_SIGNED (gint64);
470 ASSIGN_REAL (gfloat);
472 ASSIGN_REAL (gdouble);
476 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
480 #undef NO_WIDENING_CONVERSION
481 #undef CHECK_WIDENING_CONVERSION
482 #undef ASSIGN_UNSIGNED
488 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
496 MONO_CHECK_ARG_NULL (idxs);
498 ic = idxs->obj.vtable->klass;
499 ac = this->obj.vtable->klass;
501 g_assert (ic->rank == 1);
502 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
503 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
505 ind = (gint32 *)idxs->vector;
507 if (this->bounds == NULL) {
508 if (*ind < 0 || *ind >= this->max_length)
509 mono_raise_exception (mono_get_exception_index_out_of_range ());
511 ves_icall_System_Array_SetValueImpl (this, value, *ind);
515 for (i = 0; i < ac->rank; i++)
516 if ((ind [i] < this->bounds [i].lower_bound) ||
517 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
518 mono_raise_exception (mono_get_exception_index_out_of_range ());
520 pos = ind [0] - this->bounds [0].lower_bound;
521 for (i = 1; i < ac->rank; i++)
522 pos = pos * this->bounds [i].length + ind [i] -
523 this->bounds [i].lower_bound;
525 ves_icall_System_Array_SetValueImpl (this, value, pos);
528 ICALL_EXPORT MonoArray *
529 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
531 MonoClass *aklass, *klass;
534 gboolean bounded = FALSE;
538 MONO_CHECK_ARG_NULL (type);
539 MONO_CHECK_ARG_NULL (lengths);
541 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
543 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
545 for (i = 0; i < mono_array_length (lengths); i++)
546 if (mono_array_get (lengths, gint32, i) < 0)
547 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
549 klass = mono_class_from_mono_type (type->type);
550 mono_class_init_or_throw (klass);
552 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
553 /* vectors are not the same as one dimensional arrays with no-zero bounds */
558 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
560 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
561 for (i = 0; i < aklass->rank; ++i) {
562 sizes [i] = mono_array_get (lengths, guint32, i);
564 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
566 sizes [i + aklass->rank] = 0;
569 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
574 ICALL_EXPORT MonoArray *
575 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
577 MonoClass *aklass, *klass;
580 gboolean bounded = FALSE;
584 MONO_CHECK_ARG_NULL (type);
585 MONO_CHECK_ARG_NULL (lengths);
587 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
589 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
591 for (i = 0; i < mono_array_length (lengths); i++)
592 if ((mono_array_get (lengths, gint64, i) < 0) ||
593 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
594 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
596 klass = mono_class_from_mono_type (type->type);
597 mono_class_init_or_throw (klass);
599 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
600 /* vectors are not the same as one dimensional arrays with no-zero bounds */
605 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
607 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
608 for (i = 0; i < aklass->rank; ++i) {
609 sizes [i] = mono_array_get (lengths, guint64, i);
611 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
613 sizes [i + aklass->rank] = 0;
616 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
622 ves_icall_System_Array_GetRank (MonoObject *this)
626 return this->vtable->klass->rank;
630 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
632 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
637 if ((dimension < 0) || (dimension >= rank))
638 mono_raise_exception (mono_get_exception_index_out_of_range ());
640 if (this->bounds == NULL)
641 length = this->max_length;
643 length = this->bounds [dimension].length;
645 #ifdef MONO_BIG_ARRAYS
646 if (length > G_MAXINT32)
647 mono_raise_exception (mono_get_exception_overflow ());
653 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
655 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
659 if ((dimension < 0) || (dimension >= rank))
660 mono_raise_exception (mono_get_exception_index_out_of_range ());
662 if (this->bounds == NULL)
663 return this->max_length;
665 return this->bounds [dimension].length;
669 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
671 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
675 if ((dimension < 0) || (dimension >= rank))
676 mono_raise_exception (mono_get_exception_index_out_of_range ());
678 if (this->bounds == NULL)
681 return this->bounds [dimension].lower_bound;
685 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
687 int sz = mono_array_element_size (mono_object_class (arr));
688 mono_gc_bzero (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
691 ICALL_EXPORT gboolean
692 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
697 MonoVTable *src_vtable;
698 MonoVTable *dest_vtable;
699 MonoClass *src_class;
700 MonoClass *dest_class;
702 src_vtable = source->obj.vtable;
703 dest_vtable = dest->obj.vtable;
705 if (src_vtable->rank != dest_vtable->rank)
708 if (source->bounds || dest->bounds)
711 /* there's no integer overflow since mono_array_length returns an unsigned integer */
712 if ((dest_idx + length > mono_array_length_fast (dest)) ||
713 (source_idx + length > mono_array_length_fast (source)))
716 src_class = src_vtable->klass->element_class;
717 dest_class = dest_vtable->klass->element_class;
720 * Handle common cases.
723 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
724 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
726 if (src_class == mono_defaults.object_class && dest_class->valuetype)
729 /* Check if we're copying a char[] <==> (u)short[] */
730 if (src_class != dest_class) {
731 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
734 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
735 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
739 if (dest_class->valuetype) {
740 element_size = mono_array_element_size (source->obj.vtable->klass);
741 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
742 if (dest_class->has_references) {
743 mono_value_copy_array (dest, dest_idx, source_addr, length);
745 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
746 mono_gc_memmove (dest_addr, source_addr, element_size * length);
749 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
756 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
765 ao = (MonoArray *)this;
766 ac = (MonoClass *)ao->obj.vtable->klass;
768 esize = mono_array_element_size (ac);
769 ea = (gpointer*)((char*)ao->vector + (pos * esize));
771 mono_gc_memmove (value, ea, esize);
775 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
784 ao = (MonoArray *)this;
785 ac = (MonoClass *)ao->obj.vtable->klass;
786 ec = ac->element_class;
788 esize = mono_array_element_size (ac);
789 ea = (gpointer*)((char*)ao->vector + (pos * esize));
791 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
792 g_assert (esize == sizeof (gpointer));
793 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
795 g_assert (ec->inited);
796 g_assert (esize == mono_class_value_size (ec, NULL));
797 if (ec->has_references)
798 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
800 mono_gc_memmove (ea, value, esize);
805 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
807 MonoClass *klass = array->obj.vtable->klass;
808 guint32 size = mono_array_element_size (klass);
809 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
811 const char *field_data;
813 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
814 MonoException *exc = mono_get_exception_argument("array",
815 "Cannot initialize array of non-primitive type.");
816 mono_raise_exception (exc);
819 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
820 MonoException *exc = mono_get_exception_argument("field_handle",
821 "Field doesn't have an RVA");
822 mono_raise_exception (exc);
825 size *= array->max_length;
826 field_data = mono_field_get_data (field_handle);
828 if (size > mono_type_size (field_handle->type, &align)) {
829 MonoException *exc = mono_get_exception_argument("field_handle",
830 "Field not large enough to fill array");
831 mono_raise_exception (exc);
834 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
836 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
837 guint ## n *src = (guint ## n *) field_data; \
838 guint ## n *end = (guint ## n *)((char*)src + size); \
840 for (; src < end; data++, src++) { \
841 *data = read ## n (src); \
845 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
847 switch (type->type) {
864 memcpy (mono_array_addr (array, char, 0), field_data, size);
868 memcpy (mono_array_addr (array, char, 0), field_data, size);
873 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
877 return offsetof (MonoString, chars);
880 ICALL_EXPORT MonoObject *
881 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
885 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
888 return mono_object_clone (obj);
892 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
897 MONO_CHECK_ARG_NULL (handle);
899 klass = mono_class_from_mono_type (handle);
900 MONO_CHECK_ARG (handle, klass);
902 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
904 /* This will call the type constructor */
905 mono_runtime_class_init (vtable);
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
913 mono_image_check_for_module_cctor (image);
914 if (image->has_module_cctor) {
915 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
916 /*It's fine to raise the exception here*/
917 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
921 ICALL_EXPORT MonoBoolean
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
927 /* later make this configurable and per-arch */
928 int min_size = 4096 * 4 * sizeof (void*);
929 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
930 /* if we have no info we are optimistic and assume there is enough room */
933 current = (guint8 *)&stack_addr;
934 if (current > stack_addr) {
935 if ((current - stack_addr) < min_size)
938 if (current - (stack_addr - stack_size) < min_size)
944 ICALL_EXPORT MonoObject *
945 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
949 return mono_object_clone (this);
953 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
956 MonoObject **values = NULL;
960 MonoClassField* field;
965 klass = mono_object_class (this);
967 if (mono_class_num_fields (klass) == 0)
968 return mono_object_hash (this);
971 * Compute the starting value of the hashcode for fields of primitive
972 * types, and return the remaining fields in an array to the managed side.
973 * This way, we can avoid costly reflection operations in managed code.
976 while ((field = mono_class_get_fields (klass, &iter))) {
977 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
979 if (mono_field_is_deleted (field))
981 /* FIXME: Add more types */
982 switch (field->type->type) {
984 result ^= *(gint32*)((guint8*)this + field->offset);
986 case MONO_TYPE_STRING: {
988 s = *(MonoString**)((guint8*)this + field->offset);
990 result ^= mono_string_hash (s);
995 values = g_newa (MonoObject*, mono_class_num_fields (klass));
996 o = mono_field_get_value_object (mono_object_domain (this), field, this);
997 values [count++] = o;
1003 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1004 for (i = 0; i < count; ++i)
1005 mono_array_setref (*fields, i, values [i]);
1012 ICALL_EXPORT MonoBoolean
1013 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1016 MonoObject **values = NULL;
1018 MonoClassField* field;
1022 MONO_ARCH_SAVE_REGS;
1024 MONO_CHECK_ARG_NULL (that);
1026 if (this->vtable != that->vtable)
1029 klass = mono_object_class (this);
1031 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1032 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1035 * Do the comparison for fields of primitive type and return a result if
1036 * possible. Otherwise, return the remaining fields in an array to the
1037 * managed side. This way, we can avoid costly reflection operations in
1042 while ((field = mono_class_get_fields (klass, &iter))) {
1043 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1045 if (mono_field_is_deleted (field))
1047 /* FIXME: Add more types */
1048 switch (field->type->type) {
1051 case MONO_TYPE_BOOLEAN:
1052 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1057 case MONO_TYPE_CHAR:
1058 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1063 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1068 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1072 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1076 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1081 case MONO_TYPE_STRING: {
1082 MonoString *s1, *s2;
1083 guint32 s1len, s2len;
1084 s1 = *(MonoString**)((guint8*)this + field->offset);
1085 s2 = *(MonoString**)((guint8*)that + field->offset);
1088 if ((s1 == NULL) || (s2 == NULL))
1090 s1len = mono_string_length (s1);
1091 s2len = mono_string_length (s2);
1095 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1101 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1102 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1103 values [count++] = o;
1104 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1105 values [count++] = o;
1108 if (klass->enumtype)
1109 /* enums only have one non-static field */
1115 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1116 for (i = 0; i < count; ++i)
1117 mono_array_setref_fast (*fields, i, values [i]);
1124 ICALL_EXPORT MonoReflectionType *
1125 ves_icall_System_Object_GetType (MonoObject *obj)
1127 MONO_ARCH_SAVE_REGS;
1129 #ifndef DISABLE_REMOTING
1130 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1131 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1134 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1138 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1140 MONO_ARCH_SAVE_REGS;
1142 mtype->type = &obj->vtable->klass->byval_arg;
1143 g_assert (mtype->type->type);
1147 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1149 MONO_ARCH_SAVE_REGS;
1151 MONO_CHECK_ARG_NULL (obj);
1153 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1157 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1158 MonoReflectionMethod *method,
1159 MonoArray *opt_param_types)
1161 MONO_ARCH_SAVE_REGS;
1163 MONO_CHECK_ARG_NULL (method);
1165 return mono_image_create_method_token (
1166 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1170 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1172 MONO_ARCH_SAVE_REGS;
1174 mono_image_create_pefile (mb, file);
1178 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1180 MONO_ARCH_SAVE_REGS;
1182 mono_image_build_metadata (mb);
1186 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1188 MONO_ARCH_SAVE_REGS;
1190 mono_image_register_token (mb->dynamic_image, token, obj);
1194 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1196 MonoMethod **dest = data;
1198 /* skip unmanaged frames */
1214 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1216 MonoMethod **dest = data;
1218 /* skip unmanaged frames */
1223 if (!strcmp (m->klass->name_space, "System.Reflection"))
1232 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1234 MonoMethod **dest = data;
1236 /* skip unmanaged frames */
1240 if (m->wrapper_type != MONO_WRAPPER_NONE)
1243 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1257 static MonoReflectionType *
1258 type_from_name (const char *str, MonoBoolean ignoreCase)
1260 MonoType *type = NULL;
1261 MonoAssembly *assembly = NULL;
1262 MonoTypeNameParse info;
1263 char *temp_str = g_strdup (str);
1264 gboolean type_resolve = FALSE;
1266 MONO_ARCH_SAVE_REGS;
1268 /* mono_reflection_parse_type() mangles the string */
1269 if (!mono_reflection_parse_type (temp_str, &info)) {
1270 mono_reflection_free_type_info (&info);
1275 if (info.assembly.name) {
1276 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1278 MonoMethod *m = mono_method_get_last_managed ();
1279 MonoMethod *dest = m;
1281 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1286 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1287 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1288 * to crash. This only seems to happen in some strange remoting
1289 * scenarios and I was unable to figure out what's happening there.
1290 * Dec 10, 2005 - Martin.
1294 assembly = dest->klass->image->assembly;
1295 type_resolve = TRUE;
1297 g_warning (G_STRLOC);
1302 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1303 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1306 if (!info.assembly.name && !type) /* try mscorlib */
1307 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1309 if (assembly && !type && type_resolve) {
1310 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1311 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1314 mono_reflection_free_type_info (&info);
1320 return mono_type_get_object (mono_domain_get (), type);
1324 MonoReflectionType *
1325 mono_type_get (const char *str)
1327 char *copy = g_strdup (str);
1328 MonoReflectionType *type = type_from_name (copy, FALSE);
1335 ICALL_EXPORT MonoReflectionType*
1336 ves_icall_type_from_name (MonoString *name,
1337 MonoBoolean throwOnError,
1338 MonoBoolean ignoreCase)
1340 char *str = mono_string_to_utf8 (name);
1341 MonoReflectionType *type;
1343 type = type_from_name (str, ignoreCase);
1346 MonoException *e = NULL;
1349 e = mono_get_exception_type_load (name, NULL);
1351 mono_loader_clear_error ();
1353 mono_raise_exception (e);
1360 ICALL_EXPORT MonoReflectionType*
1361 ves_icall_type_from_handle (MonoType *handle)
1363 MonoDomain *domain = mono_domain_get ();
1365 MONO_ARCH_SAVE_REGS;
1367 return mono_type_get_object (domain, handle);
1370 ICALL_EXPORT MonoBoolean
1371 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1373 MONO_ARCH_SAVE_REGS;
1375 if (c && type->type && c->type)
1376 return mono_metadata_type_equal (type->type, c->type);
1378 return (type == c) ? TRUE : FALSE;
1381 /* System.TypeCode */
1400 TYPECODE_STRING = 18
1403 ICALL_EXPORT guint32
1404 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1406 int t = type->type->type;
1408 MONO_ARCH_SAVE_REGS;
1410 if (type->type->byref)
1411 return TYPECODE_OBJECT;
1415 case MONO_TYPE_VOID:
1416 return TYPECODE_OBJECT;
1417 case MONO_TYPE_BOOLEAN:
1418 return TYPECODE_BOOLEAN;
1420 return TYPECODE_BYTE;
1422 return TYPECODE_SBYTE;
1424 return TYPECODE_UINT16;
1426 return TYPECODE_INT16;
1427 case MONO_TYPE_CHAR:
1428 return TYPECODE_CHAR;
1432 return TYPECODE_OBJECT;
1434 return TYPECODE_UINT32;
1436 return TYPECODE_INT32;
1438 return TYPECODE_UINT64;
1440 return TYPECODE_INT64;
1442 return TYPECODE_SINGLE;
1444 return TYPECODE_DOUBLE;
1445 case MONO_TYPE_VALUETYPE: {
1446 MonoClass *klass = type->type->data.klass;
1448 if (klass->enumtype) {
1449 t = mono_class_enum_basetype (klass)->type;
1451 } else if (mono_is_corlib_image (klass->image)) {
1452 if (strcmp (klass->name_space, "System") == 0) {
1453 if (strcmp (klass->name, "Decimal") == 0)
1454 return TYPECODE_DECIMAL;
1455 else if (strcmp (klass->name, "DateTime") == 0)
1456 return TYPECODE_DATETIME;
1459 return TYPECODE_OBJECT;
1461 case MONO_TYPE_STRING:
1462 return TYPECODE_STRING;
1463 case MONO_TYPE_SZARRAY:
1464 case MONO_TYPE_ARRAY:
1465 case MONO_TYPE_OBJECT:
1467 case MONO_TYPE_MVAR:
1468 case MONO_TYPE_TYPEDBYREF:
1469 return TYPECODE_OBJECT;
1470 case MONO_TYPE_CLASS:
1472 MonoClass *klass = type->type->data.klass;
1473 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1474 if (strcmp (klass->name, "DBNull") == 0)
1475 return TYPECODE_DBNULL;
1478 return TYPECODE_OBJECT;
1479 case MONO_TYPE_GENERICINST:
1480 return TYPECODE_OBJECT;
1482 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1487 ICALL_EXPORT guint32
1488 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1494 MONO_ARCH_SAVE_REGS;
1496 g_assert (type != NULL);
1498 domain = ((MonoObject *)type)->vtable->domain;
1500 if (!c) /* FIXME: dont know what do do here */
1503 klass = mono_class_from_mono_type (type->type);
1504 klassc = mono_class_from_mono_type (c->type);
1506 /* Interface check requires a more complex setup so we
1507 * only do for them. Otherwise we simply avoid mono_class_init.
1509 if (check_interfaces) {
1510 mono_class_init_or_throw (klass);
1511 mono_class_init_or_throw (klassc);
1512 } else if (!klass->supertypes || !klassc->supertypes) {
1513 mono_class_setup_supertypes (klass);
1514 mono_class_setup_supertypes (klassc);
1517 if (type->type->byref)
1518 return klassc == mono_defaults.object_class;
1520 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1524 mono_type_is_primitive (MonoType *type)
1526 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1527 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1531 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1533 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1534 return mono_class_enum_basetype (type->data.klass);
1535 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1536 return mono_class_enum_basetype (type->data.generic_class->container_class);
1540 ICALL_EXPORT guint32
1541 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1547 MONO_ARCH_SAVE_REGS;
1549 g_assert (type != NULL);
1551 domain = ((MonoObject *)type)->vtable->domain;
1553 klass = mono_class_from_mono_type (type->type);
1554 klassc = mono_class_from_mono_type (c->type);
1556 mono_class_init_or_throw (klass);
1557 mono_class_init_or_throw (klassc);
1559 if (type->type->byref ^ c->type->byref)
1562 if (type->type->byref) {
1563 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1564 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1566 klass = mono_class_from_mono_type (t);
1567 klassc = mono_class_from_mono_type (ot);
1569 if (mono_type_is_primitive (t)) {
1570 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1571 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1572 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1573 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1574 return t->type == ot->type;
1576 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1579 if (klass->valuetype)
1580 return klass == klassc;
1581 return klass->valuetype == klassc->valuetype;
1584 return mono_class_is_assignable_from (klass, klassc);
1587 ICALL_EXPORT guint32
1588 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1590 MonoClass *klass = mono_class_from_mono_type (type->type);
1591 mono_class_init_or_throw (klass);
1592 return mono_object_isinst (obj, klass) != NULL;
1595 ICALL_EXPORT guint32
1596 ves_icall_get_attributes (MonoReflectionType *type)
1598 MonoClass *klass = mono_class_from_mono_type (type->type);
1599 return klass->flags;
1602 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1603 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1605 MonoClass *klass = field->field->parent;
1606 MonoMarshalType *info;
1609 if (klass->generic_container ||
1610 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1613 info = mono_marshal_load_type_info (klass);
1615 for (i = 0; i < info->num_fields; ++i) {
1616 if (info->fields [i].field == field->field) {
1617 if (!info->fields [i].mspec)
1620 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1627 ICALL_EXPORT MonoReflectionField*
1628 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1630 gboolean found = FALSE;
1637 klass = handle->parent;
1639 klass = mono_class_from_mono_type (type);
1641 /* Check that the field belongs to the class */
1642 for (k = klass; k; k = k->parent) {
1643 if (k == handle->parent) {
1650 /* The managed code will throw the exception */
1654 return mono_field_get_object (mono_domain_get (), klass, handle);
1657 ICALL_EXPORT MonoArray*
1658 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1661 MonoType *type = mono_field_get_type_checked (field->field, &error);
1662 if (!mono_error_ok (&error))
1663 mono_error_raise_exception (&error);
1665 return type_array_from_modifiers (field->field->parent->image, type, optional);
1669 vell_icall_get_method_attributes (MonoMethod *method)
1671 return method->flags;
1675 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1678 MonoDomain *domain = mono_domain_get ();
1679 MonoMethodSignature* sig;
1680 MONO_ARCH_SAVE_REGS;
1682 sig = mono_method_signature_checked (method, &error);
1683 if (!mono_error_ok (&error))
1684 mono_error_raise_exception (&error);
1687 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1688 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1689 info->attrs = method->flags;
1690 info->implattrs = method->iflags;
1691 if (sig->call_convention == MONO_CALL_DEFAULT)
1692 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1694 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1699 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1702 ICALL_EXPORT MonoArray*
1703 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1705 MonoDomain *domain = mono_domain_get ();
1707 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1710 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1711 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1713 MonoDomain *domain = mono_domain_get ();
1714 MonoReflectionMarshalAsAttribute* res = NULL;
1715 MonoMarshalSpec **mspecs;
1718 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1719 mono_method_get_marshal_info (method, mspecs);
1722 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1724 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1726 mono_metadata_free_marshal_spec (mspecs [i]);
1733 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1735 MonoClass *parent = field->field->parent;
1736 if (!parent->size_inited)
1737 mono_class_init (parent);
1739 return field->field->offset - sizeof (MonoObject);
1742 ICALL_EXPORT MonoReflectionType*
1743 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1746 MONO_ARCH_SAVE_REGS;
1748 parent = declaring? field->field->parent: field->klass;
1750 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1753 ICALL_EXPORT MonoObject *
1754 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1756 MonoClass *fklass = field->klass;
1757 MonoClassField *cf = field->field;
1758 MonoDomain *domain = mono_object_domain (field);
1760 if (fklass->image->assembly->ref_only)
1761 mono_raise_exception (mono_get_exception_invalid_operation (
1762 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1764 if (mono_security_core_clr_enabled ())
1765 mono_security_core_clr_ensure_reflection_access_field (cf);
1767 return mono_field_get_value_object (domain, cf, obj);
1771 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1774 MonoClassField *cf = field->field;
1778 MONO_ARCH_SAVE_REGS;
1780 if (field->klass->image->assembly->ref_only)
1781 mono_raise_exception (mono_get_exception_invalid_operation (
1782 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1784 if (mono_security_core_clr_enabled ())
1785 mono_security_core_clr_ensure_reflection_access_field (cf);
1787 type = mono_field_get_type_checked (cf, &error);
1788 if (!mono_error_ok (&error))
1789 mono_error_raise_exception (&error);
1791 v = (gchar *) value;
1793 switch (type->type) {
1796 case MONO_TYPE_BOOLEAN:
1799 case MONO_TYPE_CHAR:
1808 case MONO_TYPE_VALUETYPE:
1811 v += sizeof (MonoObject);
1813 case MONO_TYPE_STRING:
1814 case MONO_TYPE_OBJECT:
1815 case MONO_TYPE_CLASS:
1816 case MONO_TYPE_ARRAY:
1817 case MONO_TYPE_SZARRAY:
1820 case MONO_TYPE_GENERICINST: {
1821 MonoGenericClass *gclass = type->data.generic_class;
1822 g_assert (!gclass->context.class_inst->is_open);
1824 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1825 MonoClass *nklass = mono_class_from_mono_type (type);
1826 MonoObject *nullable;
1829 * Convert the boxed vtype into a Nullable structure.
1830 * This is complicated by the fact that Nullables have
1831 * a variable structure.
1833 nullable = mono_object_new (mono_domain_get (), nklass);
1835 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1837 v = mono_object_unbox (nullable);
1840 if (gclass->container_class->valuetype && (v != NULL))
1841 v += sizeof (MonoObject);
1845 g_error ("type 0x%x not handled in "
1846 "ves_icall_FieldInfo_SetValueInternal", type->type);
1851 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1852 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1853 if (!vtable->initialized)
1854 mono_runtime_class_init (vtable);
1855 mono_field_static_set_value (vtable, cf, v);
1857 mono_field_set_value (obj, cf, v);
1861 ICALL_EXPORT MonoObject *
1862 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1864 MonoObject *o = NULL;
1865 MonoClassField *field = this->field;
1867 MonoDomain *domain = mono_object_domain (this);
1869 MonoTypeEnum def_type;
1870 const char *def_value;
1874 MONO_ARCH_SAVE_REGS;
1876 mono_class_init (field->parent);
1878 t = mono_field_get_type_checked (field, &error);
1879 if (!mono_error_ok (&error))
1880 mono_error_raise_exception (&error);
1882 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1883 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1885 if (field->parent->image->dynamic) {
1887 g_assert_not_reached ();
1890 def_value = mono_class_get_field_default_value (field, &def_type);
1891 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1892 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1894 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1898 case MONO_TYPE_BOOLEAN:
1901 case MONO_TYPE_CHAR:
1909 case MONO_TYPE_R8: {
1912 /* boxed value type */
1913 t = g_new0 (MonoType, 1);
1915 klass = mono_class_from_mono_type (t);
1917 o = mono_object_new (domain, klass);
1918 v = ((gchar *) o) + sizeof (MonoObject);
1919 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1922 case MONO_TYPE_STRING:
1923 case MONO_TYPE_CLASS:
1924 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1927 g_assert_not_reached ();
1933 ICALL_EXPORT MonoReflectionType*
1934 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1937 MonoClassField *field = ref_field->field;
1938 MonoType *type = mono_field_get_type_checked (field, &error);
1939 if (!mono_error_ok (&error))
1940 mono_error_raise_exception (&error);
1941 return mono_type_get_object (mono_object_domain (ref_field), type);
1944 ICALL_EXPORT MonoReflectionType*
1945 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1947 MonoMethod *method = rmethod->method.method;
1949 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1952 /* From MonoProperty.cs */
1954 PInfo_Attributes = 1,
1955 PInfo_GetMethod = 1 << 1,
1956 PInfo_SetMethod = 1 << 2,
1957 PInfo_ReflectedType = 1 << 3,
1958 PInfo_DeclaringType = 1 << 4,
1963 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1965 MonoDomain *domain = mono_object_domain (property);
1967 MONO_ARCH_SAVE_REGS;
1969 if ((req_info & PInfo_ReflectedType) != 0)
1970 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1971 if ((req_info & PInfo_DeclaringType) != 0)
1972 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1974 if ((req_info & PInfo_Name) != 0)
1975 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1977 if ((req_info & PInfo_Attributes) != 0)
1978 info->attrs = property->property->attrs;
1980 if ((req_info & PInfo_GetMethod) != 0)
1981 MONO_STRUCT_SETREF (info, get, property->property->get ?
1982 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1984 if ((req_info & PInfo_SetMethod) != 0)
1985 MONO_STRUCT_SETREF (info, set, property->property->set ?
1986 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1988 * There may be other methods defined for properties, though, it seems they are not exposed
1989 * in the reflection API
1994 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1996 MonoDomain *domain = mono_object_domain (event);
1998 MONO_ARCH_SAVE_REGS;
2000 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2001 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2003 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2004 info->attrs = event->event->attrs;
2005 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2006 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2007 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2009 #ifndef MONO_SMALL_CONFIG
2010 if (event->event->other) {
2012 while (event->event->other [n])
2014 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2016 for (i = 0; i < n; i++)
2017 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2023 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2028 mono_class_setup_interfaces (klass, error);
2029 if (!mono_error_ok (error))
2032 for (i = 0; i < klass->interface_count; i++) {
2033 ic = klass->interfaces [i];
2034 g_hash_table_insert (ifaces, ic, ic);
2036 collect_interfaces (ic, ifaces, error);
2037 if (!mono_error_ok (error))
2043 MonoArray *iface_array;
2044 MonoGenericContext *context;
2048 } FillIfaceArrayData;
2051 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2053 FillIfaceArrayData *data = user_data;
2054 MonoClass *ic = key;
2055 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2057 if (!mono_error_ok (data->error))
2060 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2061 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2062 if (!mono_error_ok (data->error))
2066 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2069 mono_metadata_free_type (inflated);
2072 ICALL_EXPORT MonoArray*
2073 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2076 MonoClass *class = mono_class_from_mono_type (type->type);
2078 FillIfaceArrayData data = { 0 };
2081 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2083 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2084 data.context = mono_class_get_context (class);
2085 class = class->generic_class->container_class;
2088 for (parent = class; parent; parent = parent->parent) {
2089 mono_class_setup_interfaces (parent, &error);
2090 if (!mono_error_ok (&error))
2092 collect_interfaces (parent, iface_hash, &error);
2093 if (!mono_error_ok (&error))
2097 data.error = &error;
2098 data.domain = mono_object_domain (type);
2100 len = g_hash_table_size (iface_hash);
2102 g_hash_table_destroy (iface_hash);
2103 if (!data.domain->empty_types)
2104 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2105 return data.domain->empty_types;
2108 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2109 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2110 if (!mono_error_ok (&error))
2113 g_hash_table_destroy (iface_hash);
2114 return data.iface_array;
2117 g_hash_table_destroy (iface_hash);
2118 mono_error_raise_exception (&error);
2123 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2125 gboolean variance_used;
2126 MonoClass *class = mono_class_from_mono_type (type->type);
2127 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2128 MonoReflectionMethod *member;
2131 int i = 0, len, ioffset;
2134 MONO_ARCH_SAVE_REGS;
2135 mono_class_init_or_throw (class);
2136 mono_class_init_or_throw (iclass);
2138 mono_class_setup_vtable (class);
2140 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2144 len = mono_class_num_methods (iclass);
2145 domain = mono_object_domain (type);
2146 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2147 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2149 while ((method = mono_class_get_methods (iclass, &iter))) {
2150 member = mono_method_get_object (domain, method, iclass);
2151 mono_array_setref (*methods, i, member);
2152 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2153 mono_array_setref (*targets, i, member);
2160 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2162 MonoClass *klass = mono_class_from_mono_type (type->type);
2163 mono_class_init_or_throw (klass);
2165 if (klass->image->dynamic) {
2166 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2167 *packing = tb->packing_size;
2168 *size = tb->class_size;
2170 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2174 ICALL_EXPORT MonoReflectionType*
2175 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2179 MONO_ARCH_SAVE_REGS;
2181 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2182 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2184 class = mono_class_from_mono_type (type->type);
2185 mono_class_init_or_throw (class);
2187 // GetElementType should only return a type for:
2188 // Array Pointer PassedByRef
2189 if (type->type->byref)
2190 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2191 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2192 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2193 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2194 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2199 ICALL_EXPORT MonoReflectionType*
2200 ves_icall_get_type_parent (MonoReflectionType *type)
2202 MonoClass *class = mono_class_from_mono_type (type->type);
2203 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2206 ICALL_EXPORT MonoBoolean
2207 ves_icall_type_ispointer (MonoReflectionType *type)
2209 MONO_ARCH_SAVE_REGS;
2211 return type->type->type == MONO_TYPE_PTR;
2214 ICALL_EXPORT MonoBoolean
2215 ves_icall_type_isprimitive (MonoReflectionType *type)
2217 MONO_ARCH_SAVE_REGS;
2219 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)));
2222 ICALL_EXPORT MonoBoolean
2223 ves_icall_type_isbyref (MonoReflectionType *type)
2225 MONO_ARCH_SAVE_REGS;
2227 return type->type->byref;
2230 ICALL_EXPORT MonoBoolean
2231 ves_icall_type_iscomobject (MonoReflectionType *type)
2233 MonoClass *klass = mono_class_from_mono_type (type->type);
2234 mono_class_init_or_throw (klass);
2236 return mono_class_is_com_object (klass);
2239 ICALL_EXPORT MonoReflectionModule*
2240 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2242 MonoClass *class = mono_class_from_mono_type (type->type);
2243 return mono_module_get_object (mono_object_domain (type), class->image);
2246 ICALL_EXPORT MonoReflectionAssembly*
2247 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2249 MonoDomain *domain = mono_domain_get ();
2250 MonoClass *class = mono_class_from_mono_type (type->type);
2251 return mono_assembly_get_object (domain, class->image->assembly);
2254 ICALL_EXPORT MonoReflectionType*
2255 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2257 MonoDomain *domain = mono_domain_get ();
2260 MONO_ARCH_SAVE_REGS;
2262 if (type->type->byref)
2264 if (type->type->type == MONO_TYPE_VAR)
2265 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2266 else if (type->type->type == MONO_TYPE_MVAR)
2267 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2269 class = mono_class_from_mono_type (type->type)->nested_in;
2271 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2274 ICALL_EXPORT MonoString*
2275 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2277 MonoDomain *domain = mono_domain_get ();
2278 MonoClass *class = mono_class_from_mono_type (type->type);
2280 if (type->type->byref) {
2281 char *n = g_strdup_printf ("%s&", class->name);
2282 MonoString *res = mono_string_new (domain, n);
2288 return mono_string_new (domain, class->name);
2292 ICALL_EXPORT MonoString*
2293 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2295 MonoDomain *domain = mono_domain_get ();
2296 MonoClass *class = mono_class_from_mono_type (type->type);
2298 while (class->nested_in)
2299 class = class->nested_in;
2301 if (class->name_space [0] == '\0')
2304 return mono_string_new (domain, class->name_space);
2308 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2312 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2313 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2315 class = mono_class_from_mono_type (type->type);
2320 ICALL_EXPORT MonoArray*
2321 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2324 MonoClass *klass, *pklass;
2325 MonoDomain *domain = mono_object_domain (type);
2326 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2328 MONO_ARCH_SAVE_REGS;
2330 klass = mono_class_from_mono_type (type->type);
2332 if (klass->generic_container) {
2333 MonoGenericContainer *container = klass->generic_container;
2334 res = mono_array_new_specific (array_vtable, container->type_argc);
2335 for (i = 0; i < container->type_argc; ++i) {
2336 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2337 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2339 } else if (klass->generic_class) {
2340 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2341 res = mono_array_new_specific (array_vtable, inst->type_argc);
2342 for (i = 0; i < inst->type_argc; ++i)
2343 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2345 res = mono_array_new_specific (array_vtable, 0);
2350 ICALL_EXPORT gboolean
2351 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2354 MONO_ARCH_SAVE_REGS;
2356 if (!IS_MONOTYPE (type))
2359 if (type->type->byref)
2362 klass = mono_class_from_mono_type (type->type);
2363 return klass->generic_container != NULL;
2366 ICALL_EXPORT MonoReflectionType*
2367 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2370 MONO_ARCH_SAVE_REGS;
2372 if (type->type->byref)
2375 klass = mono_class_from_mono_type (type->type);
2377 if (klass->generic_container) {
2378 return type; /* check this one */
2380 if (klass->generic_class) {
2381 MonoClass *generic_class = klass->generic_class->container_class;
2384 tb = mono_class_get_ref_info (generic_class);
2386 if (generic_class->wastypebuilder && tb)
2389 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2394 ICALL_EXPORT MonoReflectionType*
2395 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2398 MonoType *geninst, **types;
2401 g_assert (IS_MONOTYPE (type));
2402 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2404 count = mono_array_length (type_array);
2405 types = g_new0 (MonoType *, count);
2407 for (i = 0; i < count; i++) {
2408 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2409 types [i] = t->type;
2412 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2417 class = mono_class_from_mono_type (geninst);
2419 /*we might inflate to the GTD*/
2420 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2421 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2423 return mono_type_get_object (mono_object_domain (type), geninst);
2426 ICALL_EXPORT gboolean
2427 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2430 MONO_ARCH_SAVE_REGS;
2432 if (type->type->byref)
2435 klass = mono_class_from_mono_type (type->type);
2437 return klass->generic_class != NULL;
2440 ICALL_EXPORT gboolean
2441 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2444 MONO_ARCH_SAVE_REGS;
2446 if (!IS_MONOTYPE (type))
2449 if (type->type->byref)
2452 klass = mono_class_from_mono_type (type->type);
2453 return klass->generic_class != NULL || klass->generic_container != NULL;
2457 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2459 MONO_ARCH_SAVE_REGS;
2461 if (!IS_MONOTYPE (type))
2464 if (is_generic_parameter (type->type))
2465 return mono_type_get_generic_param_num (type->type);
2469 ICALL_EXPORT GenericParameterAttributes
2470 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2472 MONO_ARCH_SAVE_REGS;
2474 g_assert (IS_MONOTYPE (type));
2475 g_assert (is_generic_parameter (type->type));
2476 return mono_generic_param_info (type->type->data.generic_param)->flags;
2479 ICALL_EXPORT MonoArray *
2480 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2482 MonoGenericParamInfo *param_info;
2488 MONO_ARCH_SAVE_REGS;
2490 g_assert (IS_MONOTYPE (type));
2492 domain = mono_object_domain (type);
2493 param_info = mono_generic_param_info (type->type->data.generic_param);
2494 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2497 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2498 for (i = 0; i < count; i++)
2499 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2505 ICALL_EXPORT MonoBoolean
2506 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2508 MONO_ARCH_SAVE_REGS;
2509 return is_generic_parameter (type->type);
2512 ICALL_EXPORT MonoBoolean
2513 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2515 MONO_ARCH_SAVE_REGS;
2516 return is_generic_parameter (tb->type.type);
2520 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2521 MonoReflectionType *t)
2523 enumtype->type = t->type;
2526 ICALL_EXPORT MonoReflectionMethod*
2527 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2528 MonoReflectionMethod* generic)
2535 MONO_ARCH_SAVE_REGS;
2537 domain = ((MonoObject *)type)->vtable->domain;
2539 klass = mono_class_from_mono_type (type->type);
2540 mono_class_init_or_throw (klass);
2543 while ((method = mono_class_get_methods (klass, &iter))) {
2544 if (method->token == generic->method->token)
2545 return mono_method_get_object (domain, method, klass);
2553 ICALL_EXPORT MonoReflectionMethod *
2554 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2557 MonoType *type = ref_type->type;
2559 MONO_ARCH_SAVE_REGS;
2561 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2562 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2563 if (type->type == MONO_TYPE_VAR)
2566 method = mono_type_get_generic_param_owner (type)->owner.method;
2568 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2571 ICALL_EXPORT MonoReflectionDllImportAttribute*
2572 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2574 static MonoClass *DllImportAttributeClass = NULL;
2575 MonoDomain *domain = mono_domain_get ();
2576 MonoReflectionDllImportAttribute *attr;
2577 MonoImage *image = method->klass->image;
2578 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2579 MonoTableInfo *tables = image->tables;
2580 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2581 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2582 guint32 im_cols [MONO_IMPLMAP_SIZE];
2583 guint32 scope_token;
2584 const char *import = NULL;
2585 const char *scope = NULL;
2588 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2591 if (!DllImportAttributeClass) {
2592 DllImportAttributeClass =
2593 mono_class_from_name (mono_defaults.corlib,
2594 "System.Runtime.InteropServices", "DllImportAttribute");
2595 g_assert (DllImportAttributeClass);
2598 if (method->klass->image->dynamic) {
2599 MonoReflectionMethodAux *method_aux =
2600 g_hash_table_lookup (
2601 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2603 import = method_aux->dllentry;
2604 scope = method_aux->dll;
2607 if (!import || !scope) {
2608 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2613 if (piinfo->implmap_idx) {
2614 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2616 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2617 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2618 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2619 scope = mono_metadata_string_heap (image, scope_token);
2622 flags = piinfo->piflags;
2624 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2626 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2627 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2628 attr->call_conv = (flags & 0x700) >> 8;
2629 attr->charset = ((flags & 0x6) >> 1) + 1;
2630 if (attr->charset == 1)
2632 attr->exact_spelling = (flags & 0x1) != 0;
2633 attr->set_last_error = (flags & 0x40) != 0;
2634 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2635 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2636 attr->preserve_sig = FALSE;
2641 ICALL_EXPORT MonoReflectionMethod *
2642 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2644 MonoMethodInflated *imethod;
2647 MONO_ARCH_SAVE_REGS;
2649 if (method->method->is_generic)
2652 if (!method->method->is_inflated)
2655 imethod = (MonoMethodInflated *) method->method;
2657 result = imethod->declaring;
2658 /* Not a generic method. */
2659 if (!result->is_generic)
2662 if (method->method->klass->image->dynamic) {
2663 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2664 MonoReflectionMethod *res;
2667 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2668 * the dynamic case as well ?
2670 mono_loader_lock ();
2671 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2672 mono_loader_unlock ();
2678 if (imethod->context.class_inst) {
2679 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2680 /*Generic methods gets the context of the GTD.*/
2681 if (mono_class_get_context (klass))
2682 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2685 return mono_method_get_object (mono_object_domain (method), result, NULL);
2688 ICALL_EXPORT gboolean
2689 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2691 MONO_ARCH_SAVE_REGS;
2693 return mono_method_signature (method->method)->generic_param_count != 0;
2696 ICALL_EXPORT gboolean
2697 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2699 MONO_ARCH_SAVE_REGS;
2701 return method->method->is_generic;
2704 ICALL_EXPORT MonoArray*
2705 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2710 MONO_ARCH_SAVE_REGS;
2712 domain = mono_object_domain (method);
2714 if (method->method->is_inflated) {
2715 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2718 count = inst->type_argc;
2719 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2721 for (i = 0; i < count; i++)
2722 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2728 count = mono_method_signature (method->method)->generic_param_count;
2729 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2731 for (i = 0; i < count; i++) {
2732 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2733 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2734 MonoClass *pklass = mono_class_from_generic_parameter (
2735 param, method->method->klass->image, TRUE);
2736 mono_array_setref (res, i,
2737 mono_type_get_object (domain, &pklass->byval_arg));
2743 ICALL_EXPORT MonoObject *
2744 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2747 * Invoke from reflection is supposed to always be a virtual call (the API
2748 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2749 * greater flexibility.
2751 MonoMethod *m = method->method;
2752 MonoMethodSignature *sig = mono_method_signature (m);
2757 MONO_ARCH_SAVE_REGS;
2761 if (mono_security_core_clr_enabled ())
2762 mono_security_core_clr_ensure_reflection_access_method (m);
2764 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2765 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2766 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2771 if (!mono_object_isinst (this, m->klass)) {
2772 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2773 char *target_name = mono_type_get_full_name (m->klass);
2774 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2775 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2777 g_free (target_name);
2781 m = mono_object_get_virtual_method (this, m);
2782 /* must pass the pointer to the value for valuetype methods */
2783 if (m->klass->valuetype)
2784 obj = mono_object_unbox (this);
2785 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2786 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2791 if (sig->ret->byref) {
2792 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"));
2796 pcount = params? mono_array_length (params): 0;
2797 if (pcount != sig->param_count) {
2798 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2802 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2803 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."));
2807 image = m->klass->image;
2808 if (image->assembly->ref_only) {
2809 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."));
2813 if (image->dynamic && !((MonoDynamicImage*)image)->run) {
2814 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2818 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2821 intptr_t *lower_bounds;
2822 pcount = mono_array_length (params);
2823 lengths = alloca (sizeof (uintptr_t) * pcount);
2824 /* Note: the synthetized array .ctors have int32 as argument type */
2825 for (i = 0; i < pcount; ++i)
2826 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2828 if (m->klass->rank == pcount) {
2829 /* Only lengths provided. */
2830 lower_bounds = NULL;
2832 g_assert (pcount == (m->klass->rank * 2));
2833 /* lower bounds are first. */
2834 lower_bounds = (intptr_t*)lengths;
2835 lengths += m->klass->rank;
2838 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2840 return mono_runtime_invoke_array (m, obj, params, NULL);
2843 #ifndef DISABLE_REMOTING
2844 ICALL_EXPORT MonoObject *
2845 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2847 MonoDomain *domain = mono_object_domain (method);
2848 MonoMethod *m = method->method;
2849 MonoMethodSignature *sig = mono_method_signature (m);
2850 MonoArray *out_args;
2852 int i, j, outarg_count = 0;
2854 MONO_ARCH_SAVE_REGS;
2856 if (m->klass == mono_defaults.object_class) {
2858 if (!strcmp (m->name, "FieldGetter")) {
2859 MonoClass *k = this->vtable->klass;
2863 /* If this is a proxy, then it must be a CBO */
2864 if (k == mono_defaults.transparent_proxy_class) {
2865 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2866 this = tp->rp->unwrapped_server;
2868 k = this->vtable->klass;
2871 name = mono_array_get (params, MonoString *, 1);
2872 str = mono_string_to_utf8 (name);
2875 MonoClassField* field = mono_class_get_field_from_name (k, str);
2877 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2878 if (field_klass->valuetype)
2879 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2881 result = *((gpointer *)((char *)this + field->offset));
2883 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2884 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2885 mono_array_setref (out_args, 0, result);
2893 g_assert_not_reached ();
2895 } else if (!strcmp (m->name, "FieldSetter")) {
2896 MonoClass *k = this->vtable->klass;
2902 /* If this is a proxy, then it must be a CBO */
2903 if (k == mono_defaults.transparent_proxy_class) {
2904 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2905 this = tp->rp->unwrapped_server;
2907 k = this->vtable->klass;
2910 name = mono_array_get (params, MonoString *, 1);
2911 str = mono_string_to_utf8 (name);
2914 MonoClassField* field = mono_class_get_field_from_name (k, str);
2916 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2917 MonoObject *val = mono_array_get (params, gpointer, 2);
2919 if (field_klass->valuetype) {
2920 size = mono_type_size (field->type, &align);
2921 g_assert (size == mono_class_value_size (field_klass, NULL));
2922 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2924 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2927 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2928 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2938 g_assert_not_reached ();
2943 for (i = 0; i < mono_array_length (params); i++) {
2944 if (sig->params [i]->byref)
2948 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2950 /* handle constructors only for objects already allocated */
2951 if (!strcmp (method->method->name, ".ctor"))
2954 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2955 g_assert (!method->method->klass->valuetype);
2956 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2958 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2959 if (sig->params [i]->byref) {
2961 arg = mono_array_get (params, gpointer, i);
2962 mono_array_setref (out_args, j, arg);
2967 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2974 read_enum_value (char *mem, int type)
2978 return *(guint8*)mem;
2980 return *(gint8*)mem;
2982 return *(guint16*)mem;
2984 return *(gint16*)mem;
2986 return *(guint32*)mem;
2988 return *(gint32*)mem;
2990 return *(guint64*)mem;
2992 return *(gint64*)mem;
2994 g_assert_not_reached ();
3000 write_enum_value (char *mem, int type, guint64 value)
3004 case MONO_TYPE_I1: {
3005 guint8 *p = (guint8*)mem;
3010 case MONO_TYPE_I2: {
3011 guint16 *p = (void*)mem;
3016 case MONO_TYPE_I4: {
3017 guint32 *p = (void*)mem;
3022 case MONO_TYPE_I8: {
3023 guint64 *p = (void*)mem;
3028 g_assert_not_reached ();
3033 ICALL_EXPORT MonoObject *
3034 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3037 MonoClass *enumc, *objc;
3042 MONO_ARCH_SAVE_REGS;
3044 MONO_CHECK_ARG_NULL (enumType);
3045 MONO_CHECK_ARG_NULL (value);
3047 domain = mono_object_domain (enumType);
3048 enumc = mono_class_from_mono_type (enumType->type);
3050 mono_class_init_or_throw (enumc);
3052 objc = value->vtable->klass;
3054 if (!enumc->enumtype)
3055 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3056 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3057 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."));
3059 etype = mono_class_enum_basetype (enumc);
3061 /* MS throws this for typebuilders */
3062 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3064 res = mono_object_new (domain, enumc);
3065 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3066 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3071 ICALL_EXPORT MonoObject *
3072 ves_icall_System_Enum_get_value (MonoObject *this)
3080 MONO_ARCH_SAVE_REGS;
3085 g_assert (this->vtable->klass->enumtype);
3087 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3088 res = mono_object_new (mono_object_domain (this), enumc);
3089 dst = (char *)res + sizeof (MonoObject);
3090 src = (char *)this + sizeof (MonoObject);
3091 size = mono_class_value_size (enumc, NULL);
3093 memcpy (dst, src, size);
3098 ICALL_EXPORT MonoReflectionType *
3099 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3104 MONO_ARCH_SAVE_REGS;
3106 klass = mono_class_from_mono_type (type->type);
3107 mono_class_init_or_throw (klass);
3109 etype = mono_class_enum_basetype (klass);
3111 /* MS throws this for typebuilders */
3112 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3114 return mono_type_get_object (mono_object_domain (type), etype);
3118 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3120 gpointer tdata = (char *)this + sizeof (MonoObject);
3121 gpointer odata = (char *)other + sizeof (MonoObject);
3122 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3123 g_assert (basetype);
3125 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3126 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3127 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3130 return me > other ? 1 : -1; \
3133 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3134 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3135 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3138 return me - other; \
3141 switch (basetype->type) {
3143 COMPARE_ENUM_VALUES (guint8);
3145 COMPARE_ENUM_VALUES (gint8);
3146 case MONO_TYPE_CHAR:
3148 COMPARE_ENUM_VALUES_RANGE (guint16);
3150 COMPARE_ENUM_VALUES (gint16);
3152 COMPARE_ENUM_VALUES (guint32);
3154 COMPARE_ENUM_VALUES (gint32);
3156 COMPARE_ENUM_VALUES (guint64);
3158 COMPARE_ENUM_VALUES (gint64);
3160 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3162 #undef COMPARE_ENUM_VALUES_RANGE
3163 #undef COMPARE_ENUM_VALUES
3168 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3170 gpointer data = (char *)this + sizeof (MonoObject);
3171 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3172 g_assert (basetype);
3174 switch (basetype->type) {
3176 return *((gint8*)data);
3178 return *((guint8*)data);
3179 case MONO_TYPE_CHAR:
3181 return *((guint16*)data);
3184 return *((gint16*)data);
3186 return *((guint32*)data);
3188 return *((gint32*)data);
3190 case MONO_TYPE_I8: {
3191 gint64 value = *((gint64*)data);
3192 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3195 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3201 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3203 MonoDomain *domain = mono_object_domain (type);
3204 MonoClass *enumc = mono_class_from_mono_type (type->type);
3205 guint j = 0, nvalues, crow;
3207 MonoClassField *field;
3209 MONO_ARCH_SAVE_REGS;
3211 mono_class_init_or_throw (enumc);
3213 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3214 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3215 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3216 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3220 while ((field = mono_class_get_fields (enumc, &iter))) {
3223 MonoTypeEnum def_type;
3225 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3227 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3229 if (mono_field_is_deleted (field))
3231 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3233 p = mono_class_get_field_default_value (field, &def_type);
3234 len = mono_metadata_decode_blob_size (p, &p);
3235 switch (mono_class_enum_basetype (enumc)->type) {
3238 mono_array_set (info->values, gchar, j, *p);
3240 case MONO_TYPE_CHAR:
3243 mono_array_set (info->values, gint16, j, read16 (p));
3247 mono_array_set (info->values, gint32, j, read32 (p));
3251 mono_array_set (info->values, gint64, j, read64 (p));
3254 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3261 BFLAGS_IgnoreCase = 1,
3262 BFLAGS_DeclaredOnly = 2,
3263 BFLAGS_Instance = 4,
3265 BFLAGS_Public = 0x10,
3266 BFLAGS_NonPublic = 0x20,
3267 BFLAGS_FlattenHierarchy = 0x40,
3268 BFLAGS_InvokeMethod = 0x100,
3269 BFLAGS_CreateInstance = 0x200,
3270 BFLAGS_GetField = 0x400,
3271 BFLAGS_SetField = 0x800,
3272 BFLAGS_GetProperty = 0x1000,
3273 BFLAGS_SetProperty = 0x2000,
3274 BFLAGS_ExactBinding = 0x10000,
3275 BFLAGS_SuppressChangeType = 0x20000,
3276 BFLAGS_OptionalParamBinding = 0x40000
3279 ICALL_EXPORT MonoReflectionField *
3280 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3283 MonoClass *startklass, *klass;
3285 MonoClassField *field;
3288 int (*compare_func) (const char *s1, const char *s2) = NULL;
3289 domain = ((MonoObject *)type)->vtable->domain;
3290 klass = startklass = mono_class_from_mono_type (type->type);
3293 mono_raise_exception (mono_get_exception_argument_null ("name"));
3294 if (type->type->byref)
3297 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3300 if (klass->exception_type != MONO_EXCEPTION_NONE)
3301 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3304 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3305 guint32 flags = mono_field_get_flags (field);
3308 if (mono_field_is_deleted_with_flags (field, flags))
3310 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3311 if (bflags & BFLAGS_Public)
3313 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3314 if (bflags & BFLAGS_NonPublic) {
3321 if (flags & FIELD_ATTRIBUTE_STATIC) {
3322 if (bflags & BFLAGS_Static)
3323 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3326 if (bflags & BFLAGS_Instance)
3333 utf8_name = mono_string_to_utf8 (name);
3335 if (compare_func (mono_field_get_name (field), utf8_name)) {
3341 return mono_field_get_object (domain, klass, field);
3343 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3349 ICALL_EXPORT MonoArray*
3350 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3353 MonoClass *startklass, *klass, *refklass;
3358 MonoClassField *field;
3359 MonoPtrArray tmp_array;
3361 MONO_ARCH_SAVE_REGS;
3363 domain = ((MonoObject *)type)->vtable->domain;
3364 if (type->type->byref)
3365 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3366 klass = startklass = mono_class_from_mono_type (type->type);
3367 refklass = mono_class_from_mono_type (reftype->type);
3369 mono_ptr_array_init (tmp_array, 2);
3372 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3373 mono_ptr_array_destroy (tmp_array);
3374 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3378 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3379 guint32 flags = mono_field_get_flags (field);
3381 if (mono_field_is_deleted_with_flags (field, flags))
3383 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3384 if (bflags & BFLAGS_Public)
3386 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3387 if (bflags & BFLAGS_NonPublic) {
3394 if (flags & FIELD_ATTRIBUTE_STATIC) {
3395 if (bflags & BFLAGS_Static)
3396 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3399 if (bflags & BFLAGS_Instance)
3405 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3406 mono_ptr_array_append (tmp_array, member);
3408 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3411 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3413 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3414 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3416 mono_ptr_array_destroy (tmp_array);
3422 method_nonpublic (MonoMethod* method, gboolean start_klass)
3424 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3425 case METHOD_ATTRIBUTE_ASSEM:
3426 return (start_klass || mono_defaults.generic_ilist_class);
3427 case METHOD_ATTRIBUTE_PRIVATE:
3429 case METHOD_ATTRIBUTE_PUBLIC:
3437 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3440 MonoClass *startklass;
3443 int len, match, nslots;
3444 /*FIXME, use MonoBitSet*/
3445 guint32 method_slots_default [8];
3446 guint32 *method_slots = NULL;
3447 int (*compare_func) (const char *s1, const char *s2) = NULL;
3449 array = g_ptr_array_new ();
3455 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3457 /* An optimization for calls made from Delegate:CreateDelegate () */
3458 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3459 method = mono_get_delegate_invoke (klass);
3460 if (mono_loader_get_last_error ())
3463 g_ptr_array_add (array, method);
3467 mono_class_setup_vtable (klass);
3468 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3471 if (is_generic_parameter (&klass->byval_arg))
3472 nslots = mono_class_get_vtable_size (klass->parent);
3474 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3475 if (nslots >= sizeof (method_slots_default) * 8) {
3476 method_slots = g_new0 (guint32, nslots / 32 + 1);
3478 method_slots = method_slots_default;
3479 memset (method_slots, 0, sizeof (method_slots_default));
3482 mono_class_setup_vtable (klass);
3483 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3487 while ((method = mono_class_get_methods (klass, &iter))) {
3489 if (method->slot != -1) {
3490 g_assert (method->slot < nslots);
3491 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3493 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3494 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3497 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3499 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3500 if (bflags & BFLAGS_Public)
3502 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3508 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3509 if (bflags & BFLAGS_Static)
3510 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3513 if (bflags & BFLAGS_Instance)
3521 if (compare_func (name, method->name))
3526 g_ptr_array_add (array, method);
3528 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3530 if (method_slots != method_slots_default)
3531 g_free (method_slots);
3536 if (method_slots != method_slots_default)
3537 g_free (method_slots);
3538 g_ptr_array_free (array, TRUE);
3540 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3541 *ex = mono_class_get_exception_for_failure (klass);
3543 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3544 mono_loader_clear_error ();
3549 ICALL_EXPORT MonoArray*
3550 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3552 static MonoClass *MethodInfo_array;
3555 MonoVTable *array_vtable;
3556 MonoException *ex = NULL;
3557 const char *mname = NULL;
3558 GPtrArray *method_array;
3559 MonoClass *klass, *refklass;
3562 if (!MethodInfo_array) {
3563 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3564 mono_memory_barrier ();
3565 MethodInfo_array = klass;
3568 klass = mono_class_from_mono_type (type->type);
3569 refklass = mono_class_from_mono_type (reftype->type);
3570 domain = ((MonoObject *)type)->vtable->domain;
3571 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3572 if (type->type->byref)
3573 return mono_array_new_specific (array_vtable, 0);
3576 mname = mono_string_to_utf8 (name);
3578 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3579 g_free ((char*)mname);
3581 mono_raise_exception (ex);
3583 res = mono_array_new_specific (array_vtable, method_array->len);
3586 for (i = 0; i < method_array->len; ++i) {
3587 MonoMethod *method = g_ptr_array_index (method_array, i);
3588 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3591 g_ptr_array_free (method_array, TRUE);
3595 ICALL_EXPORT MonoArray*
3596 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3599 static MonoClass *System_Reflection_ConstructorInfo;
3600 MonoClass *startklass, *klass, *refklass;
3605 gpointer iter = NULL;
3606 MonoPtrArray tmp_array;
3608 MONO_ARCH_SAVE_REGS;
3610 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3612 domain = ((MonoObject *)type)->vtable->domain;
3613 if (type->type->byref)
3614 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3615 klass = startklass = mono_class_from_mono_type (type->type);
3616 refklass = mono_class_from_mono_type (reftype->type);
3618 if (!System_Reflection_ConstructorInfo)
3619 System_Reflection_ConstructorInfo = mono_class_from_name (
3620 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3623 while ((method = mono_class_get_methods (klass, &iter))) {
3625 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3627 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3628 if (bflags & BFLAGS_Public)
3631 if (bflags & BFLAGS_NonPublic)
3637 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3638 if (bflags & BFLAGS_Static)
3639 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3642 if (bflags & BFLAGS_Instance)
3648 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3650 mono_ptr_array_append (tmp_array, member);
3653 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3655 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3656 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3658 mono_ptr_array_destroy (tmp_array);
3664 property_hash (gconstpointer data)
3666 MonoProperty *prop = (MonoProperty*)data;
3668 return g_str_hash (prop->name);
3672 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3674 // Properties are hide-by-name-and-signature
3675 if (!g_str_equal (prop1->name, prop2->name))
3678 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3680 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3686 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3691 return method_nonpublic (accessor, start_klass);
3694 ICALL_EXPORT MonoArray*
3695 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3699 static MonoClass *System_Reflection_PropertyInfo;
3700 MonoClass *startklass, *klass;
3706 gchar *propname = NULL;
3707 int (*compare_func) (const char *s1, const char *s2) = NULL;
3709 GHashTable *properties = NULL;
3710 MonoPtrArray tmp_array;
3712 MONO_ARCH_SAVE_REGS;
3714 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3716 if (!System_Reflection_PropertyInfo)
3717 System_Reflection_PropertyInfo = mono_class_from_name (
3718 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3720 domain = ((MonoObject *)type)->vtable->domain;
3721 if (type->type->byref)
3722 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3723 klass = startklass = mono_class_from_mono_type (type->type);
3726 propname = mono_string_to_utf8 (name);
3727 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3730 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3732 mono_class_setup_vtable (klass);
3733 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3737 while ((prop = mono_class_get_properties (klass, &iter))) {
3743 flags = method->flags;
3746 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3747 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3748 if (bflags & BFLAGS_Public)
3750 } else if (bflags & BFLAGS_NonPublic) {
3751 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3752 property_accessor_nonpublic(prop->set, startklass == klass)) {
3759 if (flags & METHOD_ATTRIBUTE_STATIC) {
3760 if (bflags & BFLAGS_Static)
3761 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3764 if (bflags & BFLAGS_Instance)
3773 if (compare_func (propname, prop->name))
3777 if (g_hash_table_lookup (properties, prop))
3780 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3782 g_hash_table_insert (properties, prop, prop);
3784 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3787 g_hash_table_destroy (properties);
3790 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3791 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3792 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3794 mono_ptr_array_destroy (tmp_array);
3800 g_hash_table_destroy (properties);
3803 mono_ptr_array_destroy (tmp_array);
3805 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3806 ex = mono_class_get_exception_for_failure (klass);
3808 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3809 mono_loader_clear_error ();
3811 mono_raise_exception (ex);
3815 ICALL_EXPORT MonoReflectionEvent *
3816 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3819 MonoClass *klass, *startklass;
3824 int (*compare_func) (const char *s1, const char *s2);
3826 MONO_ARCH_SAVE_REGS;
3828 event_name = mono_string_to_utf8 (name);
3829 if (type->type->byref)
3831 klass = startklass = mono_class_from_mono_type (type->type);
3832 domain = mono_object_domain (type);
3834 mono_class_init_or_throw (klass);
3836 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3838 if (klass->exception_type != MONO_EXCEPTION_NONE)
3839 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3842 while ((event = mono_class_get_events (klass, &iter))) {
3843 if (compare_func (event->name, event_name))
3846 method = event->add;
3848 method = event->remove;
3850 method = event->raise;
3852 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3853 if (!(bflags & BFLAGS_Public))
3856 if (!(bflags & BFLAGS_NonPublic))
3858 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3862 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3863 if (!(bflags & BFLAGS_Static))
3865 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3868 if (!(bflags & BFLAGS_Instance))
3872 if (!(bflags & BFLAGS_NonPublic))
3875 g_free (event_name);
3876 return mono_event_get_object (domain, startklass, event);
3879 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3882 g_free (event_name);
3886 ICALL_EXPORT MonoArray*
3887 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3891 static MonoClass *System_Reflection_EventInfo;
3892 MonoClass *startklass, *klass;
3899 MonoPtrArray tmp_array;
3901 MONO_ARCH_SAVE_REGS;
3903 mono_ptr_array_init (tmp_array, 4);
3905 if (!System_Reflection_EventInfo)
3906 System_Reflection_EventInfo = mono_class_from_name (
3907 mono_defaults.corlib, "System.Reflection", "EventInfo");
3909 domain = mono_object_domain (type);
3910 if (type->type->byref)
3911 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3912 klass = startklass = mono_class_from_mono_type (type->type);
3915 mono_class_setup_vtable (klass);
3916 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3920 while ((event = mono_class_get_events (klass, &iter))) {
3922 method = event->add;
3924 method = event->remove;
3926 method = event->raise;
3928 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3929 if (bflags & BFLAGS_Public)
3931 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3932 if (bflags & BFLAGS_NonPublic)
3937 if (bflags & BFLAGS_NonPublic)
3943 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3944 if (bflags & BFLAGS_Static)
3945 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3948 if (bflags & BFLAGS_Instance)
3953 if (bflags & BFLAGS_Instance)
3957 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3959 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3962 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3964 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3965 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3967 mono_ptr_array_destroy (tmp_array);
3972 mono_ptr_array_destroy (tmp_array);
3973 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3974 ex = mono_class_get_exception_for_failure (klass);
3976 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3977 mono_loader_clear_error ();
3979 mono_raise_exception (ex);
3983 ICALL_EXPORT MonoReflectionType *
3984 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3992 MONO_ARCH_SAVE_REGS;
3995 mono_raise_exception (mono_get_exception_argument_null ("name"));
3997 domain = ((MonoObject *)type)->vtable->domain;
3998 if (type->type->byref)
4000 klass = mono_class_from_mono_type (type->type);
4002 str = mono_string_to_utf8 (name);
4005 if (klass->exception_type != MONO_EXCEPTION_NONE)
4006 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4009 * If a nested type is generic, return its generic type definition.
4010 * Note that this means that the return value is essentially a
4011 * nested type of the generic type definition of @klass.
4013 * A note in MSDN claims that a generic type definition can have
4014 * nested types that aren't generic. In any case, the container of that
4015 * nested type would be the generic type definition.
4017 if (klass->generic_class)
4018 klass = klass->generic_class->container_class;
4021 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4023 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4024 if (bflags & BFLAGS_Public)
4027 if (bflags & BFLAGS_NonPublic)
4032 if (strcmp (nested->name, str) == 0){
4034 return mono_type_get_object (domain, &nested->byval_arg);
4037 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4043 ICALL_EXPORT MonoArray*
4044 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4053 MonoPtrArray tmp_array;
4055 MONO_ARCH_SAVE_REGS;
4057 domain = ((MonoObject *)type)->vtable->domain;
4058 if (type->type->byref)
4059 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4060 klass = mono_class_from_mono_type (type->type);
4063 * If a nested type is generic, return its generic type definition.
4064 * Note that this means that the return value is essentially the set
4065 * of nested types of the generic type definition of @klass.
4067 * A note in MSDN claims that a generic type definition can have
4068 * nested types that aren't generic. In any case, the container of that
4069 * nested type would be the generic type definition.
4071 if (klass->generic_class)
4072 klass = klass->generic_class->container_class;
4074 mono_ptr_array_init (tmp_array, 1);
4076 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4078 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4079 if (bflags & BFLAGS_Public)
4082 if (bflags & BFLAGS_NonPublic)
4087 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4088 mono_ptr_array_append (tmp_array, member);
4091 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4093 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4094 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4096 mono_ptr_array_destroy (tmp_array);
4101 ICALL_EXPORT MonoReflectionType*
4102 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4105 MonoType *type = NULL;
4106 MonoTypeNameParse info;
4107 gboolean type_resolve;
4109 MONO_ARCH_SAVE_REGS;
4111 /* On MS.NET, this does not fire a TypeResolve event */
4112 type_resolve = TRUE;
4113 str = mono_string_to_utf8 (name);
4114 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4115 if (!mono_reflection_parse_type (str, &info)) {
4117 mono_reflection_free_type_info (&info);
4118 if (throwOnError) /* uhm: this is a parse error, though... */
4119 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4120 /*g_print ("failed parse\n");*/
4124 if (info.assembly.name) {
4126 mono_reflection_free_type_info (&info);
4128 /* 1.0 and 2.0 throw different exceptions */
4129 if (mono_defaults.generic_ilist_class)
4130 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4132 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4137 if (module != NULL) {
4139 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4144 if (assembly->assembly->dynamic) {
4145 /* Enumerate all modules */
4146 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4150 if (abuilder->modules) {
4151 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4152 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4153 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4159 if (!type && abuilder->loaded_modules) {
4160 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4161 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4162 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4169 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4171 mono_reflection_free_type_info (&info);
4173 MonoException *e = NULL;
4176 e = mono_get_exception_type_load (name, NULL);
4178 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4179 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4181 mono_loader_clear_error ();
4184 mono_raise_exception (e);
4187 } else if (mono_loader_get_last_error ()) {
4189 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4190 mono_loader_clear_error ();
4193 if (type->type == MONO_TYPE_CLASS) {
4194 MonoClass *klass = mono_type_get_class (type);
4196 if (mono_security_enabled () && !klass->exception_type)
4197 /* Some security problems are detected during generic vtable construction */
4198 mono_class_setup_vtable (klass);
4200 /* need to report exceptions ? */
4201 if (throwOnError && klass->exception_type) {
4202 /* report SecurityException (or others) that occured when loading the assembly */
4203 MonoException *exc = mono_class_get_exception_for_failure (klass);
4204 mono_loader_clear_error ();
4205 mono_raise_exception (exc);
4206 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4211 /* g_print ("got it\n"); */
4212 return mono_type_get_object (mono_object_domain (assembly), type);
4216 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4219 gchar *shadow_ini_file;
4222 /* Check for shadow-copied assembly */
4223 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4224 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4226 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4227 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4233 g_free (shadow_ini_file);
4234 if (content != NULL) {
4237 *filename = content;
4244 ICALL_EXPORT MonoString *
4245 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4247 MonoDomain *domain = mono_object_domain (assembly);
4248 MonoAssembly *mass = assembly->assembly;
4249 MonoString *res = NULL;
4254 MONO_ARCH_SAVE_REGS;
4256 if (g_path_is_absolute (mass->image->name)) {
4257 absolute = g_strdup (mass->image->name);
4258 dirname = g_path_get_dirname (absolute);
4260 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4261 dirname = g_strdup (mass->basedir);
4264 replace_shadow_path (domain, dirname, &absolute);
4269 for (i = strlen (absolute) - 1; i >= 0; i--)
4270 if (absolute [i] == '\\')
4275 uri = g_filename_to_uri (absolute, NULL, NULL);
4277 const char *prepend = "file://";
4279 if (*absolute == '/' && *(absolute + 1) == '/') {
4282 prepend = "file:///";
4285 uri = g_strconcat (prepend, absolute, NULL);
4289 res = mono_string_new (domain, uri);
4296 ICALL_EXPORT MonoBoolean
4297 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4299 MonoAssembly *mass = assembly->assembly;
4301 MONO_ARCH_SAVE_REGS;
4303 return mass->in_gac;
4306 ICALL_EXPORT MonoReflectionAssembly*
4307 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4311 MonoImageOpenStatus status;
4313 MONO_ARCH_SAVE_REGS;
4315 name = mono_string_to_utf8 (mname);
4316 res = mono_assembly_load_with_partial_name (name, &status);
4322 return mono_assembly_get_object (mono_domain_get (), res);
4325 ICALL_EXPORT MonoString *
4326 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4328 MonoDomain *domain = mono_object_domain (assembly);
4331 MONO_ARCH_SAVE_REGS;
4333 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4338 ICALL_EXPORT MonoBoolean
4339 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4341 MONO_ARCH_SAVE_REGS;
4343 return assembly->assembly->ref_only;
4346 ICALL_EXPORT MonoString *
4347 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4349 MonoDomain *domain = mono_object_domain (assembly);
4351 MONO_ARCH_SAVE_REGS;
4353 return mono_string_new (domain, assembly->assembly->image->version);
4356 ICALL_EXPORT MonoReflectionMethod*
4357 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4359 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4361 MONO_ARCH_SAVE_REGS;
4365 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4368 ICALL_EXPORT MonoReflectionModule*
4369 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4371 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4374 ICALL_EXPORT MonoArray*
4375 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4377 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4378 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4382 MONO_ARCH_SAVE_REGS;
4384 for (i = 0; i < table->rows; ++i) {
4385 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4386 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4392 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4394 static MonoClass *System_Version = NULL;
4395 static MonoMethod *create_version = NULL;
4399 if (!System_Version) {
4400 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4401 g_assert (System_Version);
4404 if (!create_version) {
4405 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4406 create_version = mono_method_desc_search_in_class (desc, System_Version);
4407 g_assert (create_version);
4408 mono_method_desc_free (desc);
4414 args [3] = &revision;
4415 result = mono_object_new (domain, System_Version);
4416 mono_runtime_invoke (create_version, result, args, NULL);
4421 ICALL_EXPORT MonoArray*
4422 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4424 static MonoClass *System_Reflection_AssemblyName;
4426 MonoDomain *domain = mono_object_domain (assembly);
4428 static MonoMethod *create_culture = NULL;
4429 MonoImage *image = assembly->assembly->image;
4432 MONO_ARCH_SAVE_REGS;
4434 if (!System_Reflection_AssemblyName)
4435 System_Reflection_AssemblyName = mono_class_from_name (
4436 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4438 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4441 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4443 if (count > 0 && !create_culture) {
4444 MonoMethodDesc *desc = mono_method_desc_new (
4445 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4446 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4447 g_assert (create_culture);
4448 mono_method_desc_free (desc);
4451 for (i = 0; i < count; i++) {
4452 MonoReflectionAssemblyName *aname;
4453 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4455 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4457 aname = (MonoReflectionAssemblyName *) mono_object_new (
4458 domain, System_Reflection_AssemblyName);
4460 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4462 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4463 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4464 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4465 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4466 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4467 aname->versioncompat = 1; /* SameMachine (default) */
4468 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4469 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4471 if (create_culture) {
4473 MonoBoolean assembly_ref = 1;
4474 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4475 args [1] = &assembly_ref;
4476 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4479 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4480 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4481 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4483 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4484 /* public key token isn't copied - the class library will
4485 automatically generate it from the public key if required */
4486 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4487 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4489 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4490 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4493 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4496 /* note: this function doesn't return the codebase on purpose (i.e. it can
4497 be used under partial trust as path information isn't present). */
4499 mono_array_setref (result, i, aname);
4504 /* move this in some file in mono/util/ */
4506 g_concat_dir_and_file (const char *dir, const char *file)
4508 g_return_val_if_fail (dir != NULL, NULL);
4509 g_return_val_if_fail (file != NULL, NULL);
4512 * If the directory name doesn't have a / on the end, we need
4513 * to add one so we get a proper path to the file
4515 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4516 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4518 return g_strconcat (dir, file, NULL);
4522 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4524 char *n = mono_string_to_utf8 (name);
4525 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4527 guint32 cols [MONO_MANIFEST_SIZE];
4528 guint32 impl, file_idx;
4532 MONO_ARCH_SAVE_REGS;
4534 for (i = 0; i < table->rows; ++i) {
4535 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4536 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4537 if (strcmp (val, n) == 0)
4541 if (i == table->rows)
4544 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4547 * this code should only be called after obtaining the
4548 * ResourceInfo and handling the other cases.
4550 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4551 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4553 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4558 module = assembly->assembly->image;
4560 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4562 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4565 ICALL_EXPORT gboolean
4566 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4568 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4570 guint32 cols [MONO_MANIFEST_SIZE];
4571 guint32 file_cols [MONO_FILE_SIZE];
4575 MONO_ARCH_SAVE_REGS;
4577 n = mono_string_to_utf8 (name);
4578 for (i = 0; i < table->rows; ++i) {
4579 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4580 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4581 if (strcmp (val, n) == 0)
4585 if (i == table->rows)
4588 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4589 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4592 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4593 case MONO_IMPLEMENTATION_FILE:
4594 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4595 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4596 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4597 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4598 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4599 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4602 info->location = RESOURCE_LOCATION_EMBEDDED;
4605 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4606 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4607 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4608 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4609 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4610 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4612 mono_raise_exception (ex);
4614 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4616 /* Obtain info recursively */
4617 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4618 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4621 case MONO_IMPLEMENTATION_EXP_TYPE:
4622 g_assert_not_reached ();
4630 ICALL_EXPORT MonoObject*
4631 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4633 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4634 MonoArray *result = NULL;
4639 MONO_ARCH_SAVE_REGS;
4641 /* check hash if needed */
4643 n = mono_string_to_utf8 (name);
4644 for (i = 0; i < table->rows; ++i) {
4645 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4646 if (strcmp (val, n) == 0) {
4649 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4650 fn = mono_string_new (mono_object_domain (assembly), n);
4652 return (MonoObject*)fn;
4660 for (i = 0; i < table->rows; ++i) {
4661 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4665 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4668 for (i = 0; i < table->rows; ++i) {
4669 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4670 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4671 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4672 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4677 return (MonoObject*)result;
4680 ICALL_EXPORT MonoArray*
4681 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4683 MonoDomain *domain = mono_domain_get();
4686 int i, j, file_count = 0;
4687 MonoImage **modules;
4688 guint32 module_count, real_module_count;
4689 MonoTableInfo *table;
4690 guint32 cols [MONO_FILE_SIZE];
4691 MonoImage *image = assembly->assembly->image;
4693 g_assert (image != NULL);
4694 g_assert (!assembly->assembly->dynamic);
4696 table = &image->tables [MONO_TABLE_FILE];
4697 file_count = table->rows;
4699 modules = image->modules;
4700 module_count = image->module_count;
4702 real_module_count = 0;
4703 for (i = 0; i < module_count; ++i)
4705 real_module_count ++;
4707 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4708 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4710 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4712 for (i = 0; i < module_count; ++i)
4714 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4718 for (i = 0; i < file_count; ++i, ++j) {
4719 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4720 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4721 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4723 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4725 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4726 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4728 mono_array_setref (res, j, mono_module_get_object (domain, m));
4735 ICALL_EXPORT MonoReflectionMethod*
4736 ves_icall_GetCurrentMethod (void)
4738 MonoMethod *m = mono_method_get_last_managed ();
4740 while (m->is_inflated)
4741 m = ((MonoMethodInflated*)m)->declaring;
4743 return mono_method_get_object (mono_domain_get (), m, NULL);
4748 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4751 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4752 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4753 //method is inflated, we should inflate it on the other class
4754 MonoGenericContext ctx;
4755 ctx.method_inst = inflated->context.method_inst;
4756 ctx.class_inst = inflated->context.class_inst;
4757 if (klass->generic_class)
4758 ctx.class_inst = klass->generic_class->context.class_inst;
4759 else if (klass->generic_container)
4760 ctx.class_inst = klass->generic_container->context.class_inst;
4761 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4764 mono_class_setup_methods (method->klass);
4765 if (method->klass->exception_type)
4767 for (i = 0; i < method->klass->method.count; ++i) {
4768 if (method->klass->methods [i] == method) {
4773 mono_class_setup_methods (klass);
4774 if (klass->exception_type)
4776 g_assert (offset >= 0 && offset < klass->method.count);
4777 return klass->methods [offset];
4780 ICALL_EXPORT MonoReflectionMethod*
4781 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4785 klass = mono_class_from_mono_type (type);
4786 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4788 if (method->klass != klass) {
4789 method = mono_method_get_equivalent_method (method, klass);
4794 klass = method->klass;
4795 return mono_method_get_object (mono_domain_get (), method, klass);
4798 ICALL_EXPORT MonoReflectionMethod*
4799 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4801 return mono_method_get_object (mono_domain_get (), method, NULL);
4804 ICALL_EXPORT MonoReflectionMethodBody*
4805 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4807 return mono_method_body_get_object (mono_domain_get (), method);
4810 ICALL_EXPORT MonoReflectionAssembly*
4811 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4813 MonoMethod *dest = NULL;
4815 MONO_ARCH_SAVE_REGS;
4817 mono_stack_walk_no_il (get_executing, &dest);
4819 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4823 ICALL_EXPORT MonoReflectionAssembly*
4824 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4826 MonoDomain* domain = mono_domain_get ();
4828 MONO_ARCH_SAVE_REGS;
4830 if (!domain->entry_assembly)
4833 return mono_assembly_get_object (domain, domain->entry_assembly);
4836 ICALL_EXPORT MonoReflectionAssembly*
4837 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4842 MONO_ARCH_SAVE_REGS;
4845 mono_stack_walk_no_il (get_executing, &dest);
4847 mono_stack_walk_no_il (get_caller, &dest);
4850 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4853 ICALL_EXPORT MonoString *
4854 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4855 gboolean assembly_qualified)
4857 MonoDomain *domain = mono_object_domain (object);
4858 MonoTypeNameFormat format;
4863 format = assembly_qualified ?
4864 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4865 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4867 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4869 name = mono_type_get_name_full (object->type, format);
4873 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4878 res = mono_string_new (domain, name);
4885 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4887 MonoClass *klass = mono_class_from_mono_type (this->type);
4888 mono_class_init_or_throw (klass);
4889 return mono_security_core_clr_class_level (klass);
4893 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4895 static MonoMethod *create_culture = NULL;
4898 const char *pkey_ptr;
4900 MonoBoolean assembly_ref = 0;
4902 MONO_ARCH_SAVE_REGS;
4904 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4905 aname->major = name->major;
4906 aname->minor = name->minor;
4907 aname->build = name->build;
4908 aname->flags = name->flags;
4909 aname->revision = name->revision;
4910 aname->hashalg = name->hash_alg;
4911 aname->versioncompat = 1; /* SameMachine (default) */
4912 aname->processor_architecture = name->arch;
4914 if (by_default_version)
4915 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4918 if (absolute != NULL && *absolute != '\0') {
4919 const gchar *prepend = "file://";
4922 codebase = g_strdup (absolute);
4927 for (i = strlen (codebase) - 1; i >= 0; i--)
4928 if (codebase [i] == '\\')
4931 if (*codebase == '/' && *(codebase + 1) == '/') {
4934 prepend = "file:///";
4938 result = g_strconcat (prepend, codebase, NULL);
4944 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4948 if (!create_culture) {
4949 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4950 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4951 g_assert (create_culture);
4952 mono_method_desc_free (desc);
4955 if (name->culture) {
4956 args [0] = mono_string_new (domain, name->culture);
4957 args [1] = &assembly_ref;
4958 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4961 if (name->public_key) {
4962 pkey_ptr = (char*)name->public_key;
4963 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4965 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4966 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4967 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4968 } else if (default_publickey) {
4969 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4970 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4973 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4974 if (name->public_key_token [0]) {
4978 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4979 p = mono_array_addr (aname->keyToken, char, 0);
4981 for (i = 0, j = 0; i < 8; i++) {
4982 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4983 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4986 } else if (default_token) {
4987 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4991 ICALL_EXPORT MonoString *
4992 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4994 MonoDomain *domain = mono_object_domain (assembly);
4995 MonoAssembly *mass = assembly->assembly;
4999 name = mono_stringify_assembly_name (&mass->aname);
5000 res = mono_string_new (domain, name);
5007 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5010 MonoAssembly *mass = assembly->assembly;
5012 MONO_ARCH_SAVE_REGS;
5014 if (g_path_is_absolute (mass->image->name)) {
5015 fill_reflection_assembly_name (mono_object_domain (assembly),
5016 aname, &mass->aname, mass->image->name, TRUE,
5020 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5022 fill_reflection_assembly_name (mono_object_domain (assembly),
5023 aname, &mass->aname, absolute, TRUE, TRUE,
5030 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5033 MonoImageOpenStatus status = MONO_IMAGE_OK;
5036 MonoAssemblyName name;
5039 MONO_ARCH_SAVE_REGS;
5041 filename = mono_string_to_utf8 (fname);
5043 dirname = g_path_get_dirname (filename);
5044 replace_shadow_path (mono_domain_get (), dirname, &filename);
5047 image = mono_image_open (filename, &status);
5053 if (status == MONO_IMAGE_IMAGE_INVALID)
5054 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5056 exc = mono_get_exception_file_not_found2 (NULL, fname);
5057 mono_raise_exception (exc);
5060 res = mono_assembly_fill_assembly_name (image, &name);
5062 mono_image_close (image);
5064 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5067 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5071 mono_image_close (image);
5074 ICALL_EXPORT MonoBoolean
5075 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5076 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5078 MonoBoolean result = FALSE;
5079 MonoDeclSecurityEntry entry;
5081 /* SecurityAction.RequestMinimum */
5082 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5083 *minimum = entry.blob;
5084 *minLength = entry.size;
5087 /* SecurityAction.RequestOptional */
5088 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5089 *optional = entry.blob;
5090 *optLength = entry.size;
5093 /* SecurityAction.RequestRefuse */
5094 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5095 *refused = entry.blob;
5096 *refLength = entry.size;
5104 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5108 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5110 guint32 attrs, visibility;
5112 /* we start the count from 1 because we skip the special type <Module> */
5115 for (i = 1; i < tdef->rows; ++i) {
5116 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5117 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5118 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5122 count = tdef->rows - 1;
5124 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5125 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5127 for (i = 1; i < tdef->rows; ++i) {
5128 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5129 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5130 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5131 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5133 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5135 MonoLoaderError *error;
5138 error = mono_loader_get_last_error ();
5139 g_assert (error != NULL);
5141 ex = mono_loader_error_prepare_exception (error);
5142 mono_array_setref (*exceptions, count, ex);
5144 if (mono_loader_get_last_error ())
5145 mono_loader_clear_error ();
5153 ICALL_EXPORT MonoArray*
5154 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5156 MonoArray *res = NULL;
5157 MonoArray *exceptions = NULL;
5158 MonoImage *image = NULL;
5159 MonoTableInfo *table = NULL;
5162 int i, len, ex_count;
5164 MONO_ARCH_SAVE_REGS;
5166 domain = mono_object_domain (assembly);
5168 g_assert (!assembly->assembly->dynamic);
5169 image = assembly->assembly->image;
5170 table = &image->tables [MONO_TABLE_FILE];
5171 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5173 /* Append data from all modules in the assembly */
5174 for (i = 0; i < table->rows; ++i) {
5175 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5176 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5179 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5180 /* Append the new types to the end of the array */
5181 if (mono_array_length (res2) > 0) {
5183 MonoArray *res3, *ex3;
5185 len1 = mono_array_length (res);
5186 len2 = mono_array_length (res2);
5188 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5189 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5190 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5193 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5194 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5195 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5202 /* the ReflectionTypeLoadException must have all the types (Types property),
5203 * NULL replacing types which throws an exception. The LoaderException must
5204 * contain all exceptions for NULL items.
5207 len = mono_array_length (res);
5210 for (i = 0; i < len; i++) {
5211 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5215 klass = mono_type_get_class (t->type);
5216 if ((klass != NULL) && klass->exception_type) {
5217 /* keep the class in the list */
5218 list = g_list_append (list, klass);
5219 /* and replace Type with NULL */
5220 mono_array_setref (res, i, NULL);
5227 if (list || ex_count) {
5229 MonoException *exc = NULL;
5230 MonoArray *exl = NULL;
5231 int j, length = g_list_length (list) + ex_count;
5233 mono_loader_clear_error ();
5235 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5236 /* Types for which mono_class_get () succeeded */
5237 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5238 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5239 mono_array_setref (exl, i, exc);
5241 /* Types for which it don't */
5242 for (j = 0; j < mono_array_length (exceptions); ++j) {
5243 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5245 g_assert (i < length);
5246 mono_array_setref (exl, i, exc);
5253 exc = mono_get_exception_reflection_type_load (res, exl);
5254 mono_loader_clear_error ();
5255 mono_raise_exception (exc);
5261 ICALL_EXPORT gboolean
5262 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5264 MonoAssemblyName aname;
5265 MonoDomain *domain = mono_object_domain (name);
5267 gboolean is_version_defined;
5268 gboolean is_token_defined;
5270 aname.public_key = NULL;
5271 val = mono_string_to_utf8 (assname);
5272 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5273 g_free ((guint8*) aname.public_key);
5278 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5279 FALSE, is_token_defined);
5281 mono_assembly_name_free (&aname);
5282 g_free ((guint8*) aname.public_key);
5288 ICALL_EXPORT MonoReflectionType*
5289 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5291 MonoDomain *domain = mono_object_domain (module);
5294 MONO_ARCH_SAVE_REGS;
5296 g_assert (module->image);
5298 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5299 /* These images do not have a global type */
5302 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5303 return mono_type_get_object (domain, &klass->byval_arg);
5307 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5309 /*if (module->image)
5310 mono_image_close (module->image);*/
5313 ICALL_EXPORT MonoString*
5314 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5316 MonoDomain *domain = mono_object_domain (module);
5318 MONO_ARCH_SAVE_REGS;
5320 g_assert (module->image);
5321 return mono_string_new (domain, module->image->guid);
5324 ICALL_EXPORT gpointer
5325 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5328 if (module->image && module->image->is_module_handle)
5329 return module->image->raw_data;
5332 return (gpointer) (-1);
5336 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5338 if (image->dynamic) {
5339 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5340 *pe_kind = dyn->pe_kind;
5341 *machine = dyn->machine;
5344 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5345 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5350 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5352 return (image->md_version_major << 16) | (image->md_version_minor);
5355 ICALL_EXPORT MonoArray*
5356 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5358 MonoArray *exceptions;
5361 MONO_ARCH_SAVE_REGS;
5364 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5366 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5367 for (i = 0; i < mono_array_length (exceptions); ++i) {
5368 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5370 mono_raise_exception (ex);
5377 mono_memberref_is_method (MonoImage *image, guint32 token)
5379 if (!image->dynamic) {
5380 guint32 cols [MONO_MEMBERREF_SIZE];
5382 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5383 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5384 mono_metadata_decode_blob_size (sig, &sig);
5385 return (*sig != 0x6);
5387 MonoClass *handle_class;
5389 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5392 return mono_defaults.methodhandle_class == handle_class;
5397 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5400 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5401 mono_array_addr (type_args, MonoType*, 0));
5403 context->class_inst = NULL;
5405 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5406 mono_array_addr (method_args, MonoType*, 0));
5408 context->method_inst = NULL;
5411 ICALL_EXPORT MonoType*
5412 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5415 int table = mono_metadata_token_table (token);
5416 int index = mono_metadata_token_index (token);
5417 MonoGenericContext context;
5419 *error = ResolveTokenError_Other;
5421 /* Validate token */
5422 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5423 (table != MONO_TABLE_TYPESPEC)) {
5424 *error = ResolveTokenError_BadTable;
5428 if (image->dynamic) {
5429 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5430 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5431 return klass ? &klass->byval_arg : NULL;
5434 init_generic_context_from_args (&context, type_args, method_args);
5435 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5436 return klass ? &klass->byval_arg : NULL;
5439 if ((index <= 0) || (index > image->tables [table].rows)) {
5440 *error = ResolveTokenError_OutOfRange;
5444 init_generic_context_from_args (&context, type_args, method_args);
5445 klass = mono_class_get_full (image, token, &context);
5447 if (mono_loader_get_last_error ())
5448 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5451 return &klass->byval_arg;
5456 ICALL_EXPORT MonoMethod*
5457 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5459 int table = mono_metadata_token_table (token);
5460 int index = mono_metadata_token_index (token);
5461 MonoGenericContext context;
5464 *error = ResolveTokenError_Other;
5466 /* Validate token */
5467 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5468 (table != MONO_TABLE_MEMBERREF)) {
5469 *error = ResolveTokenError_BadTable;
5473 if (image->dynamic) {
5474 if (table == MONO_TABLE_METHOD)
5475 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5477 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5478 *error = ResolveTokenError_BadTable;
5482 init_generic_context_from_args (&context, type_args, method_args);
5483 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5486 if ((index <= 0) || (index > image->tables [table].rows)) {
5487 *error = ResolveTokenError_OutOfRange;
5490 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5491 *error = ResolveTokenError_BadTable;
5495 init_generic_context_from_args (&context, type_args, method_args);
5496 method = mono_get_method_full (image, token, NULL, &context);
5498 if (mono_loader_get_last_error ())
5499 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5504 ICALL_EXPORT MonoString*
5505 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5507 int index = mono_metadata_token_index (token);
5509 *error = ResolveTokenError_Other;
5511 /* Validate token */
5512 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5513 *error = ResolveTokenError_BadTable;
5518 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5520 if ((index <= 0) || (index >= image->heap_us.size)) {
5521 *error = ResolveTokenError_OutOfRange;
5525 /* FIXME: What to do if the index points into the middle of a string ? */
5527 return mono_ldstr (mono_domain_get (), image, index);
5530 ICALL_EXPORT MonoClassField*
5531 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5534 int table = mono_metadata_token_table (token);
5535 int index = mono_metadata_token_index (token);
5536 MonoGenericContext context;
5537 MonoClassField *field;
5539 *error = ResolveTokenError_Other;
5541 /* Validate token */
5542 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5543 *error = ResolveTokenError_BadTable;
5547 if (image->dynamic) {
5548 if (table == MONO_TABLE_FIELD)
5549 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5551 if (mono_memberref_is_method (image, token)) {
5552 *error = ResolveTokenError_BadTable;
5556 init_generic_context_from_args (&context, type_args, method_args);
5557 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5560 if ((index <= 0) || (index > image->tables [table].rows)) {
5561 *error = ResolveTokenError_OutOfRange;
5564 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5565 *error = ResolveTokenError_BadTable;
5569 init_generic_context_from_args (&context, type_args, method_args);
5570 field = mono_field_from_token (image, token, &klass, &context);
5572 if (mono_loader_get_last_error ())
5573 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5579 ICALL_EXPORT MonoObject*
5580 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5582 int table = mono_metadata_token_table (token);
5584 *error = ResolveTokenError_Other;
5587 case MONO_TABLE_TYPEDEF:
5588 case MONO_TABLE_TYPEREF:
5589 case MONO_TABLE_TYPESPEC: {
5590 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5592 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5596 case MONO_TABLE_METHOD:
5597 case MONO_TABLE_METHODSPEC: {
5598 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5600 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5604 case MONO_TABLE_FIELD: {
5605 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5607 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5611 case MONO_TABLE_MEMBERREF:
5612 if (mono_memberref_is_method (image, token)) {
5613 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5615 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5620 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5622 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5629 *error = ResolveTokenError_BadTable;
5635 ICALL_EXPORT MonoArray*
5636 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5638 int table = mono_metadata_token_table (token);
5639 int idx = mono_metadata_token_index (token);
5640 MonoTableInfo *tables = image->tables;
5645 *error = ResolveTokenError_OutOfRange;
5647 /* FIXME: Support other tables ? */
5648 if (table != MONO_TABLE_STANDALONESIG)
5654 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5657 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5659 ptr = mono_metadata_blob_heap (image, sig);
5660 len = mono_metadata_decode_blob_size (ptr, &ptr);
5662 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5663 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5667 ICALL_EXPORT MonoReflectionType*
5668 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5671 int isbyref = 0, rank;
5672 char *str = mono_string_to_utf8 (smodifiers);
5675 MONO_ARCH_SAVE_REGS;
5677 klass = mono_class_from_mono_type (tb->type.type);
5679 /* logic taken from mono_reflection_parse_type(): keep in sync */
5683 if (isbyref) { /* only one level allowed by the spec */
5690 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5693 klass = mono_ptr_class_get (&klass->byval_arg);
5694 mono_class_init (klass);
5705 else if (*p != '*') { /* '*' means unknown lower bound */
5716 klass = mono_array_class_get (klass, rank);
5717 mono_class_init (klass);
5724 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5727 ICALL_EXPORT MonoBoolean
5728 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5733 MONO_ARCH_SAVE_REGS;
5736 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5742 check_for_invalid_type (MonoClass *klass)
5746 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5749 name = mono_type_get_full_name (klass);
5750 str = mono_string_new (mono_domain_get (), name);
5752 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5755 ICALL_EXPORT MonoReflectionType *
5756 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5758 MonoClass *klass, *aklass;
5760 MONO_ARCH_SAVE_REGS;
5762 klass = mono_class_from_mono_type (type->type);
5763 check_for_invalid_type (klass);
5765 if (rank == 0) //single dimentional array
5766 aklass = mono_array_class_get (klass, 1);
5768 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5770 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5773 ICALL_EXPORT MonoReflectionType *
5774 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5778 MONO_ARCH_SAVE_REGS;
5780 klass = mono_class_from_mono_type (type->type);
5781 mono_class_init_or_throw (klass);
5782 check_for_invalid_type (klass);
5784 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5787 ICALL_EXPORT MonoReflectionType *
5788 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5790 MonoClass *klass, *pklass;
5792 klass = mono_class_from_mono_type (type->type);
5793 mono_class_init_or_throw (klass);
5794 check_for_invalid_type (klass);
5796 pklass = mono_ptr_class_get (type->type);
5798 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5801 ICALL_EXPORT MonoObject *
5802 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5803 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5805 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5806 MonoObject *delegate;
5808 MonoMethod *method = info->method;
5810 MONO_ARCH_SAVE_REGS;
5812 mono_class_init_or_throw (delegate_class);
5814 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5816 if (mono_security_core_clr_enabled ()) {
5817 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5821 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5823 if (method->dynamic) {
5824 /* Creating a trampoline would leak memory */
5825 func = mono_compile_method (method);
5827 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5828 method = mono_object_get_virtual_method (target, method);
5829 func = mono_create_ftnptr (mono_domain_get (),
5830 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5833 mono_delegate_ctor_with_method (delegate, target, func, method);
5839 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5841 /* Reset the invoke impl to the default one */
5842 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5846 * Magic number to convert a time which is relative to
5847 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5849 #define EPOCH_ADJUST ((guint64)62135596800LL)
5852 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5854 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5857 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5859 convert_to_absolute_date(SYSTEMTIME *date)
5861 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5862 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5863 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5864 /* from the calendar FAQ */
5865 int a = (14 - date->wMonth) / 12;
5866 int y = date->wYear - a;
5867 int m = date->wMonth + 12 * a - 2;
5868 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5870 /* d is now the day of the week for the first of the month (0 == Sunday) */
5872 int day_of_week = date->wDayOfWeek;
5874 /* set day_in_month to the first day in the month which falls on day_of_week */
5875 int day_in_month = 1 + (day_of_week - d);
5876 if (day_in_month <= 0)
5879 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5880 date->wDay = day_in_month + (date->wDay - 1) * 7;
5881 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5888 * Return's the offset from GMT of a local time.
5890 * tm is a local time
5891 * t is the same local time as seconds.
5894 gmt_offset(struct tm *tm, time_t t)
5896 #if defined (HAVE_TM_GMTOFF)
5897 return tm->tm_gmtoff;
5902 g.tm_isdst = tm->tm_isdst;
5904 return (int)difftime(t, t2);
5909 * This is heavily based on zdump.c from glibc 2.2.
5911 * * data[0]: start of daylight saving time (in DateTime ticks).
5912 * * data[1]: end of daylight saving time (in DateTime ticks).
5913 * * data[2]: utcoffset (in TimeSpan ticks).
5914 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5915 * * name[0]: name of this timezone when not daylight saving.
5916 * * name[1]: name of this timezone when daylight saving.
5918 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5919 * the class library allows years between 1 and 9999.
5921 * Returns true on success and zero on failure.
5923 ICALL_EXPORT guint32
5924 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5927 MonoDomain *domain = mono_domain_get ();
5928 struct tm start, tt;
5931 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5932 int day, transitioned;
5935 gmtoff_st = gmtoff_ds = transitioned = 0;
5937 MONO_ARCH_SAVE_REGS;
5939 MONO_CHECK_ARG_NULL (data);
5940 MONO_CHECK_ARG_NULL (names);
5942 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5943 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5946 * no info is better than crashing: we'll need our own tz data
5947 * to make this work properly, anyway. The range is probably
5948 * reduced to 1970 .. 2037 because that is what mktime is
5949 * guaranteed to support (we get into an infinite loop
5953 memset (&start, 0, sizeof (start));
5956 start.tm_year = year-1900;
5958 t = mktime (&start);
5960 if ((year < 1970) || (year > 2037) || (t == -1)) {
5962 tt = *localtime (&t);
5963 strftime (tzone, sizeof (tzone), "%Z", &tt);
5964 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5965 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5969 gmtoff = gmt_offset (&start, t);
5971 /* For each day of the year, calculate the tm_gmtoff. */
5972 for (day = 0; day < 365 && transitioned < 2; day++) {
5975 tt = *localtime (&t);
5977 gmtoff_after = gmt_offset(&tt, t);
5979 /* Daylight saving starts or ends here. */
5980 if (gmtoff_after != gmtoff) {
5984 /* Try to find the exact hour when daylight saving starts/ends. */
5988 tt1 = *localtime (&t1);
5989 } while (gmt_offset (&tt1, t1) != gmtoff);
5991 /* Try to find the exact minute when daylight saving starts/ends. */
5994 tt1 = *localtime (&t1);
5995 } while (gmt_offset (&tt1, t1) == gmtoff);
5997 strftime (tzone, sizeof (tzone), "%Z", &tt);
5999 /* Write data, if we're already in daylight saving, we're done. */
6001 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6002 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6003 if (gmtoff_ds == 0) {
6005 gmtoff_ds = gmtoff_after;
6012 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6013 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6014 if (gmtoff_ds == 0) {
6015 gmtoff_st = gmtoff_after;
6021 /* This is only set once when we enter daylight saving. */
6023 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6024 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6026 gmtoff = gmt_offset (&tt, t);
6030 if (transitioned < 2) {
6031 strftime (tzone, sizeof (tzone), "%Z", &tt);
6032 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6033 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6034 mono_array_set ((*data), gint64, 0, 0);
6035 mono_array_set ((*data), gint64, 1, 0);
6036 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6037 mono_array_set ((*data), gint64, 3, 0);
6042 MonoDomain *domain = mono_domain_get ();
6043 TIME_ZONE_INFORMATION tz_info;
6048 tz_id = GetTimeZoneInformation (&tz_info);
6049 if (tz_id == TIME_ZONE_ID_INVALID)
6052 MONO_CHECK_ARG_NULL (data);
6053 MONO_CHECK_ARG_NULL (names);
6055 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6056 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6058 for (i = 0; i < 32; ++i)
6059 if (!tz_info.DaylightName [i])
6061 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6062 for (i = 0; i < 32; ++i)
6063 if (!tz_info.StandardName [i])
6065 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6067 if ((year <= 1601) || (year > 30827)) {
6069 * According to MSDN, the MS time functions can't handle dates outside
6075 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6076 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6077 tz_info.StandardDate.wYear = year;
6078 convert_to_absolute_date(&tz_info.StandardDate);
6079 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6084 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6085 tz_info.DaylightDate.wYear = year;
6086 convert_to_absolute_date(&tz_info.DaylightDate);
6087 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6092 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6094 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6095 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6101 ICALL_EXPORT gpointer
6102 ves_icall_System_Object_obj_address (MonoObject *this)
6104 MONO_ARCH_SAVE_REGS;
6111 static inline gint32
6112 mono_array_get_byte_length (MonoArray *array)
6118 klass = array->obj.vtable->klass;
6120 if (array->bounds == NULL)
6121 length = array->max_length;
6124 for (i = 0; i < klass->rank; ++ i)
6125 length *= array->bounds [i].length;
6128 switch (klass->element_class->byval_arg.type) {
6131 case MONO_TYPE_BOOLEAN:
6135 case MONO_TYPE_CHAR:
6143 return length * sizeof (gpointer);
6154 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6156 MONO_ARCH_SAVE_REGS;
6158 return mono_array_get_byte_length (array);
6162 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6164 MONO_ARCH_SAVE_REGS;
6166 return mono_array_get (array, gint8, idx);
6170 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6172 MONO_ARCH_SAVE_REGS;
6174 mono_array_set (array, gint8, idx, value);
6177 ICALL_EXPORT MonoBoolean
6178 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6180 guint8 *src_buf, *dest_buf;
6182 MONO_ARCH_SAVE_REGS;
6184 /* This is called directly from the class libraries without going through the managed wrapper */
6185 MONO_CHECK_ARG_NULL (src);
6186 MONO_CHECK_ARG_NULL (dest);
6188 /* watch out for integer overflow */
6189 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6192 src_buf = (guint8 *)src->vector + src_offset;
6193 dest_buf = (guint8 *)dest->vector + dest_offset;
6196 memcpy (dest_buf, src_buf, count);
6198 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6203 #ifndef DISABLE_REMOTING
6204 ICALL_EXPORT MonoObject *
6205 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6207 MonoDomain *domain = mono_object_domain (this);
6209 MonoRealProxy *rp = ((MonoRealProxy *)this);
6210 MonoTransparentProxy *tp;
6214 MONO_ARCH_SAVE_REGS;
6216 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6217 tp = (MonoTransparentProxy*) res;
6219 MONO_OBJECT_SETREF (tp, rp, rp);
6220 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6221 klass = mono_class_from_mono_type (type);
6223 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6224 tp->remote_class = mono_remote_class (domain, class_name, klass);
6226 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6230 ICALL_EXPORT MonoReflectionType *
6231 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6233 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6237 /* System.Environment */
6240 ves_icall_System_Environment_get_UserName (void)
6242 MONO_ARCH_SAVE_REGS;
6244 /* using glib is more portable */
6245 return mono_string_new (mono_domain_get (), g_get_user_name ());
6249 ICALL_EXPORT MonoString *
6250 ves_icall_System_Environment_get_MachineName (void)
6252 #if defined (HOST_WIN32)
6257 len = MAX_COMPUTERNAME_LENGTH + 1;
6258 buf = g_new (gunichar2, len);
6261 if (GetComputerName (buf, (PDWORD) &len))
6262 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6266 #elif !defined(DISABLE_SOCKETS)
6270 if (gethostname (buf, sizeof (buf)) == 0)
6271 result = mono_string_new (mono_domain_get (), buf);
6277 return mono_string_new (mono_domain_get (), "mono");
6282 ves_icall_System_Environment_get_Platform (void)
6284 #if defined (TARGET_WIN32)
6287 #elif defined(__MACH__)
6290 // Notice that the value is hidden from user code, and only exposed
6291 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6292 // define and making assumptions based on Unix/128/4 values before there
6293 // was a MacOS define. Lots of code would assume that not-Unix meant
6294 // Windows, but in this case, it would be OSX.
6303 ICALL_EXPORT MonoString *
6304 ves_icall_System_Environment_get_NewLine (void)
6306 MONO_ARCH_SAVE_REGS;
6308 #if defined (HOST_WIN32)
6309 return mono_string_new (mono_domain_get (), "\r\n");
6311 return mono_string_new (mono_domain_get (), "\n");
6315 ICALL_EXPORT MonoString *
6316 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6321 MONO_ARCH_SAVE_REGS;
6326 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6327 value = g_getenv (utf8_name);
6334 return mono_string_new (mono_domain_get (), value);
6338 * There is no standard way to get at environ.
6341 #ifndef __MINGW32_VERSION
6342 #if defined(__APPLE__) && !defined (__arm__)
6343 /* Apple defines this in crt_externs.h but doesn't provide that header for
6344 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6345 * in fact exist on all implementations (so far)
6347 gchar ***_NSGetEnviron(void);
6348 #define environ (*_NSGetEnviron())
6356 ICALL_EXPORT MonoArray *
6357 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6368 env_strings = GetEnvironmentStrings();
6371 env_string = env_strings;
6372 while (*env_string != '\0') {
6373 /* weird case that MS seems to skip */
6374 if (*env_string != '=')
6376 while (*env_string != '\0')
6382 domain = mono_domain_get ();
6383 names = mono_array_new (domain, mono_defaults.string_class, n);
6387 env_string = env_strings;
6388 while (*env_string != '\0') {
6389 /* weird case that MS seems to skip */
6390 if (*env_string != '=') {
6391 equal_str = wcschr(env_string, '=');
6392 g_assert(equal_str);
6393 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6394 mono_array_setref (names, n, str);
6397 while (*env_string != '\0')
6402 FreeEnvironmentStrings (env_strings);
6414 MONO_ARCH_SAVE_REGS;
6417 for (e = environ; *e != 0; ++ e)
6420 domain = mono_domain_get ();
6421 names = mono_array_new (domain, mono_defaults.string_class, n);
6424 for (e = environ; *e != 0; ++ e) {
6425 parts = g_strsplit (*e, "=", 2);
6427 str = mono_string_new (domain, *parts);
6428 mono_array_setref (names, n, str);
6441 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6443 #if !GLIB_CHECK_VERSION(2,4,0)
6444 #define g_setenv(a,b,c) setenv(a,b,c)
6445 #define g_unsetenv(a) unsetenv(a)
6449 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6454 gunichar2 *utf16_name, *utf16_value;
6456 gchar *utf8_name, *utf8_value;
6459 MONO_ARCH_SAVE_REGS;
6462 utf16_name = mono_string_to_utf16 (name);
6463 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6464 SetEnvironmentVariable (utf16_name, NULL);
6465 g_free (utf16_name);
6469 utf16_value = mono_string_to_utf16 (value);
6471 SetEnvironmentVariable (utf16_name, utf16_value);
6473 g_free (utf16_name);
6474 g_free (utf16_value);
6476 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6478 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6479 g_unsetenv (utf8_name);
6484 utf8_value = mono_string_to_utf8_checked (value, &error);
6485 if (!mono_error_ok (&error)) {
6487 mono_error_raise_exception (&error);
6489 g_setenv (utf8_name, utf8_value, TRUE);
6492 g_free (utf8_value);
6497 ves_icall_System_Environment_Exit (int result)
6499 MONO_ARCH_SAVE_REGS;
6501 mono_environment_exitcode_set (result);
6503 /* FIXME: There are some cleanup hangs that should be worked out, but
6504 * if the program is going to exit, everything will be cleaned up when
6505 * NaCl exits anyway.
6507 #ifndef __native_client__
6508 if (!mono_runtime_try_shutdown ())
6509 mono_thread_exit ();
6511 /* Suspend all managed threads since the runtime is going away */
6512 mono_thread_suspend_all_other_threads ();
6514 mono_runtime_quit ();
6517 /* we may need to do some cleanup here... */
6521 ICALL_EXPORT MonoString*
6522 ves_icall_System_Environment_GetGacPath (void)
6524 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6527 ICALL_EXPORT MonoString*
6528 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6530 #if defined (HOST_WIN32)
6531 #ifndef CSIDL_FLAG_CREATE
6532 #define CSIDL_FLAG_CREATE 0x8000
6535 WCHAR path [MAX_PATH];
6536 /* Create directory if no existing */
6537 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6541 return mono_string_new_utf16 (mono_domain_get (), path, len);
6544 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6546 return mono_string_new (mono_domain_get (), "");
6549 ICALL_EXPORT MonoArray *
6550 ves_icall_System_Environment_GetLogicalDrives (void)
6552 gunichar2 buf [256], *ptr, *dname;
6554 guint initial_size = 127, size = 128;
6557 MonoString *drivestr;
6558 MonoDomain *domain = mono_domain_get ();
6561 MONO_ARCH_SAVE_REGS;
6566 while (size > initial_size) {
6567 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6568 if (size > initial_size) {
6571 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6572 initial_size = size;
6586 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6591 while (*u16) { u16++; len ++; }
6592 drivestr = mono_string_new_utf16 (domain, dname, len);
6593 mono_array_setref (result, ndrives++, drivestr);
6603 ICALL_EXPORT MonoString *
6604 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6606 gunichar2 volume_name [MAX_PATH + 1];
6608 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6610 return mono_string_from_utf16 (volume_name);
6613 ICALL_EXPORT MonoString *
6614 ves_icall_System_Environment_InternalGetHome (void)
6616 MONO_ARCH_SAVE_REGS;
6618 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6621 static const char *encodings [] = {
6623 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6624 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6625 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6627 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6628 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6629 "x_unicode_2_0_utf_7",
6631 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6632 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6634 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6637 "unicodefffe", "utf_16be",
6644 * Returns the internal codepage, if the value of "int_code_page" is
6645 * 1 at entry, and we can not compute a suitable code page number,
6646 * returns the code page as a string
6648 ICALL_EXPORT MonoString*
6649 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6654 char *codepage = NULL;
6656 int want_name = *int_code_page;
6659 *int_code_page = -1;
6660 MONO_ARCH_SAVE_REGS;
6662 g_get_charset (&cset);
6663 c = codepage = strdup (cset);
6664 for (c = codepage; *c; c++){
6665 if (isascii (*c) && isalpha (*c))
6670 /* g_print ("charset: %s\n", cset); */
6672 /* handle some common aliases */
6675 for (i = 0; p != 0; ){
6676 if ((gssize) p < 7){
6678 p = encodings [++i];
6681 if (strcmp (p, codepage) == 0){
6682 *int_code_page = code;
6685 p = encodings [++i];
6688 if (strstr (codepage, "utf_8") != NULL)
6689 *int_code_page |= 0x10000000;
6692 if (want_name && *int_code_page == -1)
6693 return mono_string_new (mono_domain_get (), cset);
6698 ICALL_EXPORT MonoBoolean
6699 ves_icall_System_Environment_get_HasShutdownStarted (void)
6701 if (mono_runtime_is_shutting_down ())
6704 if (mono_domain_is_unloading (mono_domain_get ()))
6711 ves_icall_System_Environment_BroadcastSettingChange (void)
6714 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6719 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6720 MonoReflectionMethod *method,
6721 MonoArray *out_args)
6723 MONO_ARCH_SAVE_REGS;
6725 mono_message_init (mono_object_domain (this), this, method, out_args);
6728 #ifndef DISABLE_REMOTING
6729 ICALL_EXPORT MonoBoolean
6730 ves_icall_IsTransparentProxy (MonoObject *proxy)
6732 MONO_ARCH_SAVE_REGS;
6737 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6743 ICALL_EXPORT MonoReflectionMethod *
6744 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6745 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6749 MonoMethod **vtable;
6750 MonoMethod *res = NULL;
6752 MONO_CHECK_ARG_NULL (rtype);
6753 MONO_CHECK_ARG_NULL (rmethod);
6755 method = rmethod->method;
6756 klass = mono_class_from_mono_type (rtype->type);
6757 mono_class_init_or_throw (klass);
6759 if (MONO_CLASS_IS_INTERFACE (klass))
6762 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6765 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6766 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6772 mono_class_setup_vtable (klass);
6773 vtable = klass->vtable;
6775 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6776 gboolean variance_used = FALSE;
6777 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6778 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6780 res = vtable [offs + method->slot];
6782 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6785 if (method->slot != -1)
6786 res = vtable [method->slot];
6792 return mono_method_get_object (mono_domain_get (), res, NULL);
6796 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6801 MONO_ARCH_SAVE_REGS;
6803 klass = mono_class_from_mono_type (type->type);
6804 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6806 mono_vtable_set_is_remote (vtable, enable);
6809 #else /* DISABLE_REMOTING */
6812 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6814 g_assert_not_reached ();
6819 ICALL_EXPORT MonoObject *
6820 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6825 MONO_ARCH_SAVE_REGS;
6827 domain = mono_object_domain (type);
6828 klass = mono_class_from_mono_type (type->type);
6829 mono_class_init_or_throw (klass);
6831 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6832 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6834 if (klass->rank >= 1) {
6835 g_assert (klass->rank == 1);
6836 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6838 /* Bypass remoting object creation check */
6839 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6843 ICALL_EXPORT MonoString *
6844 ves_icall_System_IO_get_temp_path (void)
6846 MONO_ARCH_SAVE_REGS;
6848 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6851 #ifndef PLATFORM_NO_DRIVEINFO
6852 ICALL_EXPORT MonoBoolean
6853 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6854 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6858 ULARGE_INTEGER wapi_free_bytes_avail;
6859 ULARGE_INTEGER wapi_total_number_of_bytes;
6860 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6862 MONO_ARCH_SAVE_REGS;
6864 *error = ERROR_SUCCESS;
6865 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6866 &wapi_total_number_of_free_bytes);
6869 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6870 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6871 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6873 *free_bytes_avail = 0;
6874 *total_number_of_bytes = 0;
6875 *total_number_of_free_bytes = 0;
6876 *error = GetLastError ();
6882 ICALL_EXPORT guint32
6883 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6885 MONO_ARCH_SAVE_REGS;
6887 return GetDriveType (mono_string_chars (root_path_name));
6891 ICALL_EXPORT gpointer
6892 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6894 MONO_ARCH_SAVE_REGS;
6896 return mono_compile_method (method);
6899 ICALL_EXPORT MonoString *
6900 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6905 MONO_ARCH_SAVE_REGS;
6907 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6909 #if defined (HOST_WIN32)
6910 /* Avoid mixing '/' and '\\' */
6913 for (i = strlen (path) - 1; i >= 0; i--)
6914 if (path [i] == '/')
6918 mcpath = mono_string_new (mono_domain_get (), path);
6925 get_bundled_app_config (void)
6927 const gchar *app_config;
6930 gchar *config_file_name, *config_file_path;
6934 MONO_ARCH_SAVE_REGS;
6936 domain = mono_domain_get ();
6937 file = domain->setup->configuration_file;
6941 // Retrieve config file and remove the extension
6942 config_file_name = mono_string_to_utf8 (file);
6943 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6944 if (!config_file_path)
6945 config_file_path = config_file_name;
6946 len = strlen (config_file_path) - strlen (".config");
6947 module = g_malloc0 (len + 1);
6948 memcpy (module, config_file_path, len);
6949 // Get the config file from the module name
6950 app_config = mono_config_string_for_assembly_file (module);
6953 if (config_file_name != config_file_path)
6954 g_free (config_file_name);
6955 g_free (config_file_path);
6960 return mono_string_new (mono_domain_get (), app_config);
6964 get_bundled_machine_config (void)
6966 const gchar *machine_config;
6968 MONO_ARCH_SAVE_REGS;
6970 machine_config = mono_get_machine_config ();
6972 if (!machine_config)
6975 return mono_string_new (mono_domain_get (), machine_config);
6978 ICALL_EXPORT MonoString *
6979 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6984 MONO_ARCH_SAVE_REGS;
6986 path = g_path_get_dirname (mono_get_config_dir ());
6988 #if defined (HOST_WIN32)
6989 /* Avoid mixing '/' and '\\' */
6992 for (i = strlen (path) - 1; i >= 0; i--)
6993 if (path [i] == '/')
6997 ipath = mono_string_new (mono_domain_get (), path);
7003 ICALL_EXPORT gboolean
7004 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7006 MonoPEResourceDataEntry *entry;
7009 MONO_ARCH_SAVE_REGS;
7011 if (!assembly || !result || !size)
7016 image = assembly->assembly->image;
7017 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7021 *result = mono_image_rva_map (image, entry->rde_data_offset);
7026 *size = entry->rde_size;
7031 ICALL_EXPORT MonoBoolean
7032 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7034 return mono_is_debugger_attached ();
7037 ICALL_EXPORT MonoBoolean
7038 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7040 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7041 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7047 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7049 if (mono_get_runtime_callbacks ()->debug_log)
7050 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7054 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7056 #if defined (HOST_WIN32)
7057 OutputDebugString (mono_string_chars (message));
7059 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7063 /* Only used for value types */
7064 ICALL_EXPORT MonoObject *
7065 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7070 MONO_ARCH_SAVE_REGS;
7072 domain = mono_object_domain (type);
7073 klass = mono_class_from_mono_type (type->type);
7074 mono_class_init_or_throw (klass);
7076 if (mono_class_is_nullable (klass))
7077 /* No arguments -> null */
7080 return mono_object_new (domain, klass);
7083 ICALL_EXPORT MonoReflectionMethod *
7084 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7086 MonoClass *klass, *parent;
7087 MonoMethod *method = m->method;
7088 MonoMethod *result = NULL;
7091 MONO_ARCH_SAVE_REGS;
7093 if (method->klass == NULL)
7096 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7097 MONO_CLASS_IS_INTERFACE (method->klass) ||
7098 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7101 slot = mono_method_get_vtable_slot (method);
7105 klass = method->klass;
7106 if (klass->generic_class)
7107 klass = klass->generic_class->container_class;
7110 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7111 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7112 mono_class_setup_vtable (parent);
7113 if (parent->vtable_size <= slot)
7118 klass = klass->parent;
7123 if (klass == method->klass)
7126 /*This is possible if definition == FALSE.
7127 * Do it here to be really sure we don't read invalid memory.
7129 if (slot >= klass->vtable_size)
7132 mono_class_setup_vtable (klass);
7134 result = klass->vtable [slot];
7135 if (result == NULL) {
7136 /* It is an abstract method */
7137 gpointer iter = NULL;
7138 while ((result = mono_class_get_methods (klass, &iter)))
7139 if (result->slot == slot)
7146 return mono_method_get_object (mono_domain_get (), result, NULL);
7149 ICALL_EXPORT MonoString*
7150 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7152 MonoMethod *method = m->method;
7154 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7159 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7161 MONO_ARCH_SAVE_REGS;
7163 iter->sig = *(MonoMethodSignature**)argsp;
7165 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7166 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7169 /* FIXME: it's not documented what start is exactly... */
7173 iter->args = argsp + sizeof (gpointer);
7175 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7177 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7180 ICALL_EXPORT MonoTypedRef
7181 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7183 guint32 i, arg_size;
7186 MONO_ARCH_SAVE_REGS;
7188 i = iter->sig->sentinelpos + iter->next_arg;
7190 g_assert (i < iter->sig->param_count);
7192 res.type = iter->sig->params [i];
7193 res.klass = mono_class_from_mono_type (res.type);
7194 arg_size = mono_type_stack_size (res.type, &align);
7195 #if defined(__arm__) || defined(__mips__)
7196 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7198 res.value = iter->args;
7199 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7200 /* Values are stored as 8 byte register sized objects, but 'value'
7201 * is dereferenced as a pointer in other routines.
7203 res.value = (char*)res.value + 4;
7205 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7206 if (arg_size <= sizeof (gpointer)) {
7208 int padding = arg_size - mono_type_size (res.type, &dummy);
7209 res.value = (guint8*)res.value + padding;
7212 iter->args = (char*)iter->args + arg_size;
7215 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7220 ICALL_EXPORT MonoTypedRef
7221 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7223 guint32 i, arg_size;
7226 MONO_ARCH_SAVE_REGS;
7228 i = iter->sig->sentinelpos + iter->next_arg;
7230 g_assert (i < iter->sig->param_count);
7232 while (i < iter->sig->param_count) {
7233 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7235 res.type = iter->sig->params [i];
7236 res.klass = mono_class_from_mono_type (res.type);
7237 /* FIXME: endianess issue... */
7238 arg_size = mono_type_stack_size (res.type, &align);
7239 #if defined(__arm__) || defined(__mips__)
7240 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7242 res.value = iter->args;
7243 iter->args = (char*)iter->args + arg_size;
7245 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7248 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7256 ICALL_EXPORT MonoType*
7257 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7260 MONO_ARCH_SAVE_REGS;
7262 i = iter->sig->sentinelpos + iter->next_arg;
7264 g_assert (i < iter->sig->param_count);
7266 return iter->sig->params [i];
7269 ICALL_EXPORT MonoObject*
7270 mono_TypedReference_ToObject (MonoTypedRef tref)
7272 MONO_ARCH_SAVE_REGS;
7274 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7275 MonoObject** objp = tref.value;
7279 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7282 ICALL_EXPORT MonoObject*
7283 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7285 MONO_ARCH_SAVE_REGS;
7287 if (MONO_TYPE_IS_REFERENCE (type)) {
7288 MonoObject** objp = value;
7292 return mono_value_box (mono_domain_get (), klass, value);
7296 prelink_method (MonoMethod *method)
7298 const char *exc_class, *exc_arg;
7299 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7301 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7303 mono_raise_exception(
7304 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7306 /* create the wrapper, too? */
7310 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7312 MONO_ARCH_SAVE_REGS;
7313 prelink_method (method->method);
7317 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7319 MonoClass *klass = mono_class_from_mono_type (type->type);
7321 gpointer iter = NULL;
7322 MONO_ARCH_SAVE_REGS;
7324 mono_class_init_or_throw (klass);
7326 while ((m = mono_class_get_methods (klass, &iter)))
7330 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7332 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7333 gint32 const **exponents,
7334 gunichar2 const **digitLowerTable,
7335 gunichar2 const **digitUpperTable,
7336 gint64 const **tenPowersList,
7337 gint32 const **decHexDigits)
7339 *mantissas = Formatter_MantissaBitsTable;
7340 *exponents = Formatter_TensExponentTable;
7341 *digitLowerTable = Formatter_DigitLowerTable;
7342 *digitUpperTable = Formatter_DigitUpperTable;
7343 *tenPowersList = Formatter_TenPowersList;
7344 *decHexDigits = Formatter_DecHexDigits;
7348 get_category_data (int version,
7349 guint8 const **category_data,
7350 guint16 const **category_astral_index)
7352 *category_astral_index = NULL;
7354 #ifndef DISABLE_NET_4_0
7356 *category_data = CategoryData_v4;
7357 #ifndef DISABLE_ASTRAL
7358 *category_astral_index = CategoryData_v4_astral_index;
7364 *category_data = CategoryData_v2;
7365 #ifndef DISABLE_ASTRAL
7366 *category_astral_index = CategoryData_v2_astral_index;
7370 /* These parameters are "readonly" in corlib/System/Char.cs */
7372 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7373 guint8 const **category_data,
7374 guint16 const **category_astral_index,
7375 guint8 const **numeric_data,
7376 gdouble const **numeric_data_values,
7377 guint16 const **to_lower_data_low,
7378 guint16 const **to_lower_data_high,
7379 guint16 const **to_upper_data_low,
7380 guint16 const **to_upper_data_high)
7382 get_category_data (category_data_version, category_data, category_astral_index);
7383 *numeric_data = NumericData;
7384 *numeric_data_values = NumericDataValues;
7385 *to_lower_data_low = ToLowerDataLow;
7386 *to_lower_data_high = ToLowerDataHigh;
7387 *to_upper_data_low = ToUpperDataLow;
7388 *to_upper_data_high = ToUpperDataHigh;
7392 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7394 return method->method->token;
7398 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7399 * and avoid useless allocations.
7402 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7406 for (i = 0; i < type->num_mods; ++i) {
7407 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7412 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7414 for (i = 0; i < type->num_mods; ++i) {
7415 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7416 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7417 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7424 ICALL_EXPORT MonoArray*
7425 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7427 MonoType *type = param->ClassImpl->type;
7428 MonoClass *member_class = mono_object_class (param->MemberImpl);
7429 MonoMethod *method = NULL;
7432 MonoMethodSignature *sig;
7434 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7435 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7436 method = rmethod->method;
7437 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7438 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7439 if (!(method = prop->property->get))
7440 method = prop->property->set;
7443 char *type_name = mono_type_get_full_name (member_class);
7444 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7445 MonoException *ex = mono_get_exception_not_supported (msg);
7448 mono_raise_exception (ex);
7451 image = method->klass->image;
7452 pos = param->PositionImpl;
7453 sig = mono_method_signature (method);
7457 type = sig->params [pos];
7459 return type_array_from_modifiers (image, type, optional);
7463 get_property_type (MonoProperty *prop)
7465 MonoMethodSignature *sig;
7467 sig = mono_method_signature (prop->get);
7469 } else if (prop->set) {
7470 sig = mono_method_signature (prop->set);
7471 return sig->params [sig->param_count - 1];
7476 ICALL_EXPORT MonoArray*
7477 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7479 MonoType *type = get_property_type (property->property);
7480 MonoImage *image = property->klass->image;
7484 return type_array_from_modifiers (image, type, optional);
7488 *Construct a MonoType suited to be used to decode a constant blob object.
7490 * @type is the target type which will be constructed
7491 * @blob_type is the blob type, for example, that comes from the constant table
7492 * @real_type is the expected constructed type.
7495 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7497 type->type = blob_type;
7498 type->data.klass = NULL;
7499 if (blob_type == MONO_TYPE_CLASS)
7500 type->data.klass = mono_defaults.object_class;
7501 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7502 /* For enums, we need to use the base type */
7503 type->type = MONO_TYPE_VALUETYPE;
7504 type->data.klass = mono_class_from_mono_type (real_type);
7506 type->data.klass = mono_class_from_mono_type (real_type);
7509 ICALL_EXPORT MonoObject*
7510 property_info_get_default_value (MonoReflectionProperty *property)
7513 MonoProperty *prop = property->property;
7514 MonoType *type = get_property_type (prop);
7515 MonoDomain *domain = mono_object_domain (property);
7516 MonoTypeEnum def_type;
7517 const char *def_value;
7520 mono_class_init (prop->parent);
7522 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7523 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7525 def_value = mono_class_get_property_default_value (prop, &def_type);
7527 mono_type_from_blob_type (&blob_type, def_type, type);
7528 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7533 ICALL_EXPORT MonoBoolean
7534 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7536 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7537 MonoCustomAttrInfo *cinfo;
7540 mono_class_init_or_throw (attr_class);
7542 cinfo = mono_reflection_get_custom_attrs_info (obj);
7545 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7547 mono_custom_attrs_free (cinfo);
7551 ICALL_EXPORT MonoArray*
7552 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7554 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7559 mono_class_init_or_throw (attr_class);
7561 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7562 if (!mono_error_ok (&error))
7563 mono_error_raise_exception (&error);
7564 if (mono_loader_get_last_error ()) {
7565 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7566 g_assert_not_reached ();
7574 ICALL_EXPORT MonoString*
7575 ves_icall_Mono_Runtime_GetDisplayName (void)
7578 MonoString *display_name;
7580 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7581 display_name = mono_string_new (mono_domain_get (), info);
7583 return display_name;
7586 ICALL_EXPORT MonoString*
7587 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7589 MonoString *message;
7593 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7594 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7597 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7599 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7607 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7608 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7609 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7610 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7611 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7612 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7613 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7614 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7618 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7623 gunichar2 last, prev_last, prev2_last;
7630 int havePadding = 0;
7632 last = prev_last = 0, prev2_last = 0;
7633 for (i = 0; i < ilength; i++) {
7635 if (c >= sizeof (dbase64)) {
7636 exc = mono_exception_from_name_msg (mono_get_corlib (),
7637 "System", "FormatException",
7638 "Invalid character found.");
7639 mono_raise_exception (exc);
7640 } else if (isspace (c)) {
7642 } else if (havePadding && c != '=') {
7643 exc = mono_exception_from_name_msg (mono_get_corlib (),
7644 "System", "FormatException",
7645 "Invalid character found.");
7646 mono_raise_exception (exc);
7648 if (c == '=') havePadding = 1;
7649 prev2_last = prev_last;
7655 olength = ilength - ignored;
7657 if (allowWhitespaceOnly && olength == 0) {
7658 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7661 if ((olength & 3) != 0 || olength <= 0) {
7662 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7663 "FormatException", "Invalid length.");
7664 mono_raise_exception (exc);
7667 if (prev2_last == '=') {
7668 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7669 mono_raise_exception (exc);
7672 olength = (olength * 3) / 4;
7676 if (prev_last == '=')
7679 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7680 res_ptr = mono_array_addr (result, guchar, 0);
7681 for (i = 0; i < ilength; ) {
7684 for (k = 0; k < 4 && i < ilength;) {
7690 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7691 exc = mono_exception_from_name_msg (mono_get_corlib (),
7692 "System", "FormatException",
7693 "Invalid character found.");
7694 mono_raise_exception (exc);
7699 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7701 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7703 *res_ptr++ = (b [2] << 6) | b [3];
7705 while (i < ilength && isspace (start [i]))
7712 ICALL_EXPORT MonoArray *
7713 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7715 MONO_ARCH_SAVE_REGS;
7717 return base64_to_byte_array (mono_string_chars (str),
7718 mono_string_length (str), allowWhitespaceOnly);
7721 ICALL_EXPORT MonoArray *
7722 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7724 MONO_ARCH_SAVE_REGS;
7726 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7730 #ifndef DISABLE_ICALL_TABLES
7732 #define ICALL_TYPE(id,name,first)
7733 #define ICALL(id,name,func) Icall_ ## id,
7736 #include "metadata/icall-def.h"
7742 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7743 #define ICALL(id,name,func)
7745 #include "metadata/icall-def.h"
7751 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7752 #define ICALL(id,name,func)
7754 guint16 first_icall;
7757 static const IcallTypeDesc
7758 icall_type_descs [] = {
7759 #include "metadata/icall-def.h"
7763 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7766 #define ICALL_TYPE(id,name,first)
7769 #ifdef HAVE_ARRAY_ELEM_INIT
7770 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7771 #define MSGSTRFIELD1(line) str##line
7773 static const struct msgstrtn_t {
7774 #define ICALL(id,name,func)
7776 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7777 #include "metadata/icall-def.h"
7779 } icall_type_names_str = {
7780 #define ICALL_TYPE(id,name,first) (name),
7781 #include "metadata/icall-def.h"
7784 static const guint16 icall_type_names_idx [] = {
7785 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7786 #include "metadata/icall-def.h"
7789 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7791 static const struct msgstr_t {
7793 #define ICALL_TYPE(id,name,first)
7794 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7795 #include "metadata/icall-def.h"
7797 } icall_names_str = {
7798 #define ICALL(id,name,func) (name),
7799 #include "metadata/icall-def.h"
7802 static const guint16 icall_names_idx [] = {
7803 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7804 #include "metadata/icall-def.h"
7807 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7813 #define ICALL_TYPE(id,name,first) name,
7814 #define ICALL(id,name,func)
7815 static const char* const
7816 icall_type_names [] = {
7817 #include "metadata/icall-def.h"
7821 #define icall_type_name_get(id) (icall_type_names [(id)])
7825 #define ICALL_TYPE(id,name,first)
7826 #define ICALL(id,name,func) name,
7827 static const char* const
7829 #include "metadata/icall-def.h"
7832 #define icall_name_get(id) icall_names [(id)]
7834 #endif /* !HAVE_ARRAY_ELEM_INIT */
7838 #define ICALL_TYPE(id,name,first)
7839 #define ICALL(id,name,func) func,
7840 static const gconstpointer
7841 icall_functions [] = {
7842 #include "metadata/icall-def.h"
7846 #ifdef ENABLE_ICALL_SYMBOL_MAP
7849 #define ICALL_TYPE(id,name,first)
7850 #define ICALL(id,name,func) #func,
7851 static const gconstpointer
7852 icall_symbols [] = {
7853 #include "metadata/icall-def.h"
7858 #endif /* DISABLE_ICALL_TABLES */
7860 static GHashTable *icall_hash = NULL;
7861 static GHashTable *jit_icall_hash_name = NULL;
7862 static GHashTable *jit_icall_hash_addr = NULL;
7865 mono_icall_init (void)
7867 #ifndef DISABLE_ICALL_TABLES
7870 /* check that tables are sorted: disable in release */
7873 const char *prev_class = NULL;
7874 const char *prev_method;
7876 for (i = 0; i < Icall_type_num; ++i) {
7877 const IcallTypeDesc *desc;
7880 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7881 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7882 prev_class = icall_type_name_get (i);
7883 desc = &icall_type_descs [i];
7884 num_icalls = icall_desc_num_icalls (desc);
7885 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7886 for (j = 0; j < num_icalls; ++j) {
7887 const char *methodn = icall_name_get (desc->first_icall + j);
7888 if (prev_method && strcmp (prev_method, methodn) >= 0)
7889 g_print ("method %s should come before method %s\n", methodn, prev_method);
7890 prev_method = methodn;
7896 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7900 mono_icall_cleanup (void)
7902 g_hash_table_destroy (icall_hash);
7903 g_hash_table_destroy (jit_icall_hash_name);
7904 g_hash_table_destroy (jit_icall_hash_addr);
7908 mono_add_internal_call (const char *name, gconstpointer method)
7910 mono_loader_lock ();
7912 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7914 mono_loader_unlock ();
7917 #ifndef DISABLE_ICALL_TABLES
7919 #ifdef HAVE_ARRAY_ELEM_INIT
7921 compare_method_imap (const void *key, const void *elem)
7923 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7924 return strcmp (key, method_name);
7928 find_method_icall (const IcallTypeDesc *imap, const char *name)
7930 const guint16 *nameslot = mono_binary_search (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7933 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7937 compare_class_imap (const void *key, const void *elem)
7939 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7940 return strcmp (key, class_name);
7943 static const IcallTypeDesc*
7944 find_class_icalls (const char *name)
7946 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7949 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7952 #else /* HAVE_ARRAY_ELEM_INIT */
7955 compare_method_imap (const void *key, const void *elem)
7957 const char** method_name = (const char**)elem;
7958 return strcmp (key, *method_name);
7962 find_method_icall (const IcallTypeDesc *imap, const char *name)
7964 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7967 return (gpointer)icall_functions [(nameslot - icall_names)];
7971 compare_class_imap (const void *key, const void *elem)
7973 const char** class_name = (const char**)elem;
7974 return strcmp (key, *class_name);
7977 static const IcallTypeDesc*
7978 find_class_icalls (const char *name)
7980 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7983 return &icall_type_descs [nameslot - icall_type_names];
7986 #endif /* HAVE_ARRAY_ELEM_INIT */
7988 #endif /* DISABLE_ICALL_TABLES */
7991 * we should probably export this as an helper (handle nested types).
7992 * Returns the number of chars written in buf.
7995 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7997 int nspacelen, cnamelen;
7998 nspacelen = strlen (klass->name_space);
7999 cnamelen = strlen (klass->name);
8000 if (nspacelen + cnamelen + 2 > bufsize)
8003 memcpy (buf, klass->name_space, nspacelen);
8004 buf [nspacelen ++] = '.';
8006 memcpy (buf + nspacelen, klass->name, cnamelen);
8007 buf [nspacelen + cnamelen] = 0;
8008 return nspacelen + cnamelen;
8011 #ifdef DISABLE_ICALL_TABLES
8013 no_icall_table (void)
8015 g_assert_not_reached ();
8020 mono_lookup_internal_call (MonoMethod *method)
8025 int typelen = 0, mlen, siglen;
8027 #ifndef DISABLE_ICALL_TABLES
8028 const IcallTypeDesc *imap = NULL;
8031 g_assert (method != NULL);
8033 if (method->is_inflated)
8034 method = ((MonoMethodInflated *) method)->declaring;
8036 if (method->klass->nested_in) {
8037 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8041 mname [pos++] = '/';
8044 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8050 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8055 #ifndef DISABLE_ICALL_TABLES
8056 imap = find_class_icalls (mname);
8059 mname [typelen] = ':';
8060 mname [typelen + 1] = ':';
8062 mlen = strlen (method->name);
8063 memcpy (mname + typelen + 2, method->name, mlen);
8064 sigstart = mname + typelen + 2 + mlen;
8067 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8068 siglen = strlen (tmpsig);
8069 if (typelen + mlen + siglen + 6 > sizeof (mname))
8072 memcpy (sigstart + 1, tmpsig, siglen);
8073 sigstart [siglen + 1] = ')';
8074 sigstart [siglen + 2] = 0;
8077 mono_loader_lock ();
8079 res = g_hash_table_lookup (icall_hash, mname);
8081 mono_loader_unlock ();
8084 /* try without signature */
8086 res = g_hash_table_lookup (icall_hash, mname);
8088 mono_loader_unlock ();
8092 #ifdef DISABLE_ICALL_TABLES
8093 mono_loader_unlock ();
8094 /* Fail only when the result is actually used */
8095 /* mono_marshal_get_native_wrapper () depends on this */
8096 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8097 return ves_icall_System_String_ctor_RedirectToCreateString;
8099 return no_icall_table;
8101 /* it wasn't found in the static call tables */
8103 mono_loader_unlock ();
8106 res = find_method_icall (imap, sigstart - mlen);
8108 mono_loader_unlock ();
8111 /* try _with_ signature */
8113 res = find_method_icall (imap, sigstart - mlen);
8115 mono_loader_unlock ();
8119 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8120 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8121 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8122 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8123 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");
8124 g_print ("If you see other errors or faults after this message they are probably related\n");
8125 g_print ("and you need to fix your mono install first.\n");
8127 mono_loader_unlock ();
8133 #ifdef ENABLE_ICALL_SYMBOL_MAP
8135 func_cmp (gconstpointer key, gconstpointer p)
8137 return (gsize)key - (gsize)*(gsize*)p;
8142 * mono_lookup_icall_symbol:
8144 * Given the icall METHOD, returns its C symbol.
8147 mono_lookup_icall_symbol (MonoMethod *m)
8149 #ifdef DISABLE_ICALL_TABLES
8150 g_assert_not_reached ();
8153 #ifdef ENABLE_ICALL_SYMBOL_MAP
8157 static gconstpointer *functions_sorted;
8158 static const char**symbols_sorted;
8159 static gboolean inited;
8164 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8165 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8166 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8167 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8168 /* Bubble sort the two arrays */
8172 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8173 if (functions_sorted [i] > functions_sorted [i + 1]) {
8176 tmp = functions_sorted [i];
8177 functions_sorted [i] = functions_sorted [i + 1];
8178 functions_sorted [i + 1] = tmp;
8179 tmp = symbols_sorted [i];
8180 symbols_sorted [i] = symbols_sorted [i + 1];
8181 symbols_sorted [i + 1] = tmp;
8188 func = mono_lookup_internal_call (m);
8191 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8195 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8197 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8198 g_assert_not_reached ();
8205 type_from_typename (char *typename)
8207 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8209 if (!strcmp (typename, "int"))
8210 klass = mono_defaults.int_class;
8211 else if (!strcmp (typename, "ptr"))
8212 klass = mono_defaults.int_class;
8213 else if (!strcmp (typename, "void"))
8214 klass = mono_defaults.void_class;
8215 else if (!strcmp (typename, "int32"))
8216 klass = mono_defaults.int32_class;
8217 else if (!strcmp (typename, "uint32"))
8218 klass = mono_defaults.uint32_class;
8219 else if (!strcmp (typename, "int8"))
8220 klass = mono_defaults.sbyte_class;
8221 else if (!strcmp (typename, "uint8"))
8222 klass = mono_defaults.byte_class;
8223 else if (!strcmp (typename, "int16"))
8224 klass = mono_defaults.int16_class;
8225 else if (!strcmp (typename, "uint16"))
8226 klass = mono_defaults.uint16_class;
8227 else if (!strcmp (typename, "long"))
8228 klass = mono_defaults.int64_class;
8229 else if (!strcmp (typename, "ulong"))
8230 klass = mono_defaults.uint64_class;
8231 else if (!strcmp (typename, "float"))
8232 klass = mono_defaults.single_class;
8233 else if (!strcmp (typename, "double"))
8234 klass = mono_defaults.double_class;
8235 else if (!strcmp (typename, "object"))
8236 klass = mono_defaults.object_class;
8237 else if (!strcmp (typename, "obj"))
8238 klass = mono_defaults.object_class;
8239 else if (!strcmp (typename, "string"))
8240 klass = mono_defaults.string_class;
8241 else if (!strcmp (typename, "bool"))
8242 klass = mono_defaults.boolean_class;
8243 else if (!strcmp (typename, "boolean"))
8244 klass = mono_defaults.boolean_class;
8246 g_error ("%s", typename);
8247 g_assert_not_reached ();
8249 return &klass->byval_arg;
8252 MonoMethodSignature*
8253 mono_create_icall_signature (const char *sigstr)
8258 MonoMethodSignature *res;
8260 mono_loader_lock ();
8261 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8263 mono_loader_unlock ();
8267 parts = g_strsplit (sigstr, " ", 256);
8276 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8281 * Under windows, the default pinvoke calling convention is STDCALL but
8284 res->call_convention = MONO_CALL_C;
8287 res->ret = type_from_typename (parts [0]);
8288 for (i = 1; i < len; ++i) {
8289 res->params [i - 1] = type_from_typename (parts [i]);
8294 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8296 mono_loader_unlock ();
8302 mono_find_jit_icall_by_name (const char *name)
8304 MonoJitICallInfo *info;
8305 g_assert (jit_icall_hash_name);
8307 mono_loader_lock ();
8308 info = g_hash_table_lookup (jit_icall_hash_name, name);
8309 mono_loader_unlock ();
8314 mono_find_jit_icall_by_addr (gconstpointer addr)
8316 MonoJitICallInfo *info;
8317 g_assert (jit_icall_hash_addr);
8319 mono_loader_lock ();
8320 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8321 mono_loader_unlock ();
8327 * mono_get_jit_icall_info:
8329 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8330 * caller should access it while holding the loader lock.
8333 mono_get_jit_icall_info (void)
8335 return jit_icall_hash_name;
8339 * mono_lookup_jit_icall_symbol:
8341 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8344 mono_lookup_jit_icall_symbol (const char *name)
8346 MonoJitICallInfo *info;
8347 const char *res = NULL;
8349 mono_loader_lock ();
8350 info = g_hash_table_lookup (jit_icall_hash_name, name);
8352 res = info->c_symbol;
8353 mono_loader_unlock ();
8358 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8360 mono_loader_lock ();
8361 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8362 mono_loader_unlock ();
8366 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8368 MonoJitICallInfo *info;
8373 mono_loader_lock ();
8375 if (!jit_icall_hash_name) {
8376 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8377 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8380 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8381 g_warning ("jit icall already defined \"%s\"\n", name);
8382 g_assert_not_reached ();
8385 info = g_new0 (MonoJitICallInfo, 1);
8390 info->c_symbol = c_symbol;
8393 info->wrapper = func;
8395 info->wrapper = NULL;
8398 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8399 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8401 mono_loader_unlock ();
8406 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8408 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);