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_loader_lock ();
1514 mono_class_setup_supertypes (klass);
1515 mono_class_setup_supertypes (klassc);
1516 mono_loader_unlock ();
1519 if (type->type->byref)
1520 return klassc == mono_defaults.object_class;
1522 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1526 mono_type_is_primitive (MonoType *type)
1528 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1529 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1533 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1535 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1536 return mono_class_enum_basetype (type->data.klass);
1537 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1538 return mono_class_enum_basetype (type->data.generic_class->container_class);
1542 ICALL_EXPORT guint32
1543 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1549 MONO_ARCH_SAVE_REGS;
1551 g_assert (type != NULL);
1553 domain = ((MonoObject *)type)->vtable->domain;
1555 klass = mono_class_from_mono_type (type->type);
1556 klassc = mono_class_from_mono_type (c->type);
1558 mono_class_init_or_throw (klass);
1559 mono_class_init_or_throw (klassc);
1561 if (type->type->byref ^ c->type->byref)
1564 if (type->type->byref) {
1565 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1566 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1568 klass = mono_class_from_mono_type (t);
1569 klassc = mono_class_from_mono_type (ot);
1571 if (mono_type_is_primitive (t)) {
1572 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1573 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1574 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1575 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1576 return t->type == ot->type;
1578 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1581 if (klass->valuetype)
1582 return klass == klassc;
1583 return klass->valuetype == klassc->valuetype;
1586 return mono_class_is_assignable_from (klass, klassc);
1589 ICALL_EXPORT guint32
1590 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1592 MonoClass *klass = mono_class_from_mono_type (type->type);
1593 mono_class_init_or_throw (klass);
1594 return mono_object_isinst (obj, klass) != NULL;
1597 ICALL_EXPORT guint32
1598 ves_icall_get_attributes (MonoReflectionType *type)
1600 MonoClass *klass = mono_class_from_mono_type (type->type);
1601 return klass->flags;
1604 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1605 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1607 MonoClass *klass = field->field->parent;
1608 MonoMarshalType *info;
1611 if (klass->generic_container ||
1612 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1615 info = mono_marshal_load_type_info (klass);
1617 for (i = 0; i < info->num_fields; ++i) {
1618 if (info->fields [i].field == field->field) {
1619 if (!info->fields [i].mspec)
1622 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1629 ICALL_EXPORT MonoReflectionField*
1630 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1632 gboolean found = FALSE;
1639 klass = handle->parent;
1641 klass = mono_class_from_mono_type (type);
1643 /* Check that the field belongs to the class */
1644 for (k = klass; k; k = k->parent) {
1645 if (k == handle->parent) {
1652 /* The managed code will throw the exception */
1656 return mono_field_get_object (mono_domain_get (), klass, handle);
1659 ICALL_EXPORT MonoArray*
1660 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1663 MonoType *type = mono_field_get_type_checked (field->field, &error);
1664 if (!mono_error_ok (&error))
1665 mono_error_raise_exception (&error);
1667 return type_array_from_modifiers (field->field->parent->image, type, optional);
1671 vell_icall_get_method_attributes (MonoMethod *method)
1673 return method->flags;
1677 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1680 MonoDomain *domain = mono_domain_get ();
1681 MonoMethodSignature* sig;
1682 MONO_ARCH_SAVE_REGS;
1684 sig = mono_method_signature_checked (method, &error);
1685 if (!mono_error_ok (&error))
1686 mono_error_raise_exception (&error);
1689 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1690 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1691 info->attrs = method->flags;
1692 info->implattrs = method->iflags;
1693 if (sig->call_convention == MONO_CALL_DEFAULT)
1694 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1696 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1701 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1704 ICALL_EXPORT MonoArray*
1705 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1707 MonoDomain *domain = mono_domain_get ();
1709 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1712 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1713 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1715 MonoDomain *domain = mono_domain_get ();
1716 MonoReflectionMarshalAsAttribute* res = NULL;
1717 MonoMarshalSpec **mspecs;
1720 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1721 mono_method_get_marshal_info (method, mspecs);
1724 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1726 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1728 mono_metadata_free_marshal_spec (mspecs [i]);
1735 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1737 MonoClass *parent = field->field->parent;
1738 if (!parent->size_inited)
1739 mono_class_init (parent);
1741 return field->field->offset - sizeof (MonoObject);
1744 ICALL_EXPORT MonoReflectionType*
1745 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1748 MONO_ARCH_SAVE_REGS;
1750 parent = declaring? field->field->parent: field->klass;
1752 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1755 ICALL_EXPORT MonoObject *
1756 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1758 MonoClass *fklass = field->klass;
1759 MonoClassField *cf = field->field;
1760 MonoDomain *domain = mono_object_domain (field);
1762 if (fklass->image->assembly->ref_only)
1763 mono_raise_exception (mono_get_exception_invalid_operation (
1764 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1766 if (mono_security_core_clr_enabled ())
1767 mono_security_core_clr_ensure_reflection_access_field (cf);
1769 return mono_field_get_value_object (domain, cf, obj);
1773 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1776 MonoClassField *cf = field->field;
1780 MONO_ARCH_SAVE_REGS;
1782 if (field->klass->image->assembly->ref_only)
1783 mono_raise_exception (mono_get_exception_invalid_operation (
1784 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1786 if (mono_security_core_clr_enabled ())
1787 mono_security_core_clr_ensure_reflection_access_field (cf);
1789 type = mono_field_get_type_checked (cf, &error);
1790 if (!mono_error_ok (&error))
1791 mono_error_raise_exception (&error);
1793 v = (gchar *) value;
1795 switch (type->type) {
1798 case MONO_TYPE_BOOLEAN:
1801 case MONO_TYPE_CHAR:
1810 case MONO_TYPE_VALUETYPE:
1813 v += sizeof (MonoObject);
1815 case MONO_TYPE_STRING:
1816 case MONO_TYPE_OBJECT:
1817 case MONO_TYPE_CLASS:
1818 case MONO_TYPE_ARRAY:
1819 case MONO_TYPE_SZARRAY:
1822 case MONO_TYPE_GENERICINST: {
1823 MonoGenericClass *gclass = type->data.generic_class;
1824 g_assert (!gclass->context.class_inst->is_open);
1826 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1827 MonoClass *nklass = mono_class_from_mono_type (type);
1828 MonoObject *nullable;
1831 * Convert the boxed vtype into a Nullable structure.
1832 * This is complicated by the fact that Nullables have
1833 * a variable structure.
1835 nullable = mono_object_new (mono_domain_get (), nklass);
1837 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1839 v = mono_object_unbox (nullable);
1842 if (gclass->container_class->valuetype && (v != NULL))
1843 v += sizeof (MonoObject);
1847 g_error ("type 0x%x not handled in "
1848 "ves_icall_FieldInfo_SetValueInternal", type->type);
1853 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1854 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1855 if (!vtable->initialized)
1856 mono_runtime_class_init (vtable);
1857 mono_field_static_set_value (vtable, cf, v);
1859 mono_field_set_value (obj, cf, v);
1863 ICALL_EXPORT MonoObject *
1864 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1866 MonoObject *o = NULL;
1867 MonoClassField *field = this->field;
1869 MonoDomain *domain = mono_object_domain (this);
1871 MonoTypeEnum def_type;
1872 const char *def_value;
1876 MONO_ARCH_SAVE_REGS;
1878 mono_class_init (field->parent);
1880 t = mono_field_get_type_checked (field, &error);
1881 if (!mono_error_ok (&error))
1882 mono_error_raise_exception (&error);
1884 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1885 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1887 if (field->parent->image->dynamic) {
1889 g_assert_not_reached ();
1892 def_value = mono_class_get_field_default_value (field, &def_type);
1893 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1894 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1896 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1900 case MONO_TYPE_BOOLEAN:
1903 case MONO_TYPE_CHAR:
1911 case MONO_TYPE_R8: {
1914 /* boxed value type */
1915 t = g_new0 (MonoType, 1);
1917 klass = mono_class_from_mono_type (t);
1919 o = mono_object_new (domain, klass);
1920 v = ((gchar *) o) + sizeof (MonoObject);
1921 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1924 case MONO_TYPE_STRING:
1925 case MONO_TYPE_CLASS:
1926 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1929 g_assert_not_reached ();
1935 ICALL_EXPORT MonoReflectionType*
1936 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1939 MonoClassField *field = ref_field->field;
1940 MonoType *type = mono_field_get_type_checked (field, &error);
1941 if (!mono_error_ok (&error))
1942 mono_error_raise_exception (&error);
1943 return mono_type_get_object (mono_object_domain (ref_field), type);
1946 ICALL_EXPORT MonoReflectionType*
1947 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1949 MonoMethod *method = rmethod->method.method;
1951 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1954 /* From MonoProperty.cs */
1956 PInfo_Attributes = 1,
1957 PInfo_GetMethod = 1 << 1,
1958 PInfo_SetMethod = 1 << 2,
1959 PInfo_ReflectedType = 1 << 3,
1960 PInfo_DeclaringType = 1 << 4,
1965 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1967 MonoDomain *domain = mono_object_domain (property);
1969 MONO_ARCH_SAVE_REGS;
1971 if ((req_info & PInfo_ReflectedType) != 0)
1972 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1973 if ((req_info & PInfo_DeclaringType) != 0)
1974 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1976 if ((req_info & PInfo_Name) != 0)
1977 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1979 if ((req_info & PInfo_Attributes) != 0)
1980 info->attrs = property->property->attrs;
1982 if ((req_info & PInfo_GetMethod) != 0)
1983 MONO_STRUCT_SETREF (info, get, property->property->get ?
1984 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1986 if ((req_info & PInfo_SetMethod) != 0)
1987 MONO_STRUCT_SETREF (info, set, property->property->set ?
1988 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1990 * There may be other methods defined for properties, though, it seems they are not exposed
1991 * in the reflection API
1996 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1998 MonoDomain *domain = mono_object_domain (event);
2000 MONO_ARCH_SAVE_REGS;
2002 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2003 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2005 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2006 info->attrs = event->event->attrs;
2007 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2008 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2009 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2011 #ifndef MONO_SMALL_CONFIG
2012 if (event->event->other) {
2014 while (event->event->other [n])
2016 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2018 for (i = 0; i < n; i++)
2019 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2025 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2030 mono_class_setup_interfaces (klass, error);
2031 if (!mono_error_ok (error))
2034 for (i = 0; i < klass->interface_count; i++) {
2035 ic = klass->interfaces [i];
2036 g_hash_table_insert (ifaces, ic, ic);
2038 collect_interfaces (ic, ifaces, error);
2039 if (!mono_error_ok (error))
2045 MonoArray *iface_array;
2046 MonoGenericContext *context;
2050 } FillIfaceArrayData;
2053 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2055 FillIfaceArrayData *data = user_data;
2056 MonoClass *ic = key;
2057 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2059 if (!mono_error_ok (data->error))
2062 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2063 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2064 if (!mono_error_ok (data->error))
2068 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2071 mono_metadata_free_type (inflated);
2074 ICALL_EXPORT MonoArray*
2075 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2078 MonoClass *class = mono_class_from_mono_type (type->type);
2080 FillIfaceArrayData data = { 0 };
2083 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2085 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2086 data.context = mono_class_get_context (class);
2087 class = class->generic_class->container_class;
2090 for (parent = class; parent; parent = parent->parent) {
2091 mono_class_setup_interfaces (parent, &error);
2092 if (!mono_error_ok (&error))
2094 collect_interfaces (parent, iface_hash, &error);
2095 if (!mono_error_ok (&error))
2099 data.error = &error;
2100 data.domain = mono_object_domain (type);
2102 len = g_hash_table_size (iface_hash);
2104 g_hash_table_destroy (iface_hash);
2105 if (!data.domain->empty_types)
2106 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2107 return data.domain->empty_types;
2110 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2111 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2112 if (!mono_error_ok (&error))
2115 g_hash_table_destroy (iface_hash);
2116 return data.iface_array;
2119 g_hash_table_destroy (iface_hash);
2120 mono_error_raise_exception (&error);
2125 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2127 gboolean variance_used;
2128 MonoClass *class = mono_class_from_mono_type (type->type);
2129 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2130 MonoReflectionMethod *member;
2133 int i = 0, len, ioffset;
2136 MONO_ARCH_SAVE_REGS;
2137 mono_class_init_or_throw (class);
2138 mono_class_init_or_throw (iclass);
2140 mono_class_setup_vtable (class);
2142 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2146 len = mono_class_num_methods (iclass);
2147 domain = mono_object_domain (type);
2148 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2149 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2151 while ((method = mono_class_get_methods (iclass, &iter))) {
2152 member = mono_method_get_object (domain, method, iclass);
2153 mono_array_setref (*methods, i, member);
2154 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2155 mono_array_setref (*targets, i, member);
2162 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2164 MonoClass *klass = mono_class_from_mono_type (type->type);
2165 mono_class_init_or_throw (klass);
2167 if (klass->image->dynamic) {
2168 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2169 *packing = tb->packing_size;
2170 *size = tb->class_size;
2172 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2176 ICALL_EXPORT MonoReflectionType*
2177 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2181 MONO_ARCH_SAVE_REGS;
2183 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2184 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2186 class = mono_class_from_mono_type (type->type);
2187 mono_class_init_or_throw (class);
2189 // GetElementType should only return a type for:
2190 // Array Pointer PassedByRef
2191 if (type->type->byref)
2192 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2193 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2194 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2195 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2196 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2201 ICALL_EXPORT MonoReflectionType*
2202 ves_icall_get_type_parent (MonoReflectionType *type)
2204 MonoClass *class = mono_class_from_mono_type (type->type);
2205 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2208 ICALL_EXPORT MonoBoolean
2209 ves_icall_type_ispointer (MonoReflectionType *type)
2211 MONO_ARCH_SAVE_REGS;
2213 return type->type->type == MONO_TYPE_PTR;
2216 ICALL_EXPORT MonoBoolean
2217 ves_icall_type_isprimitive (MonoReflectionType *type)
2219 MONO_ARCH_SAVE_REGS;
2221 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)));
2224 ICALL_EXPORT MonoBoolean
2225 ves_icall_type_isbyref (MonoReflectionType *type)
2227 MONO_ARCH_SAVE_REGS;
2229 return type->type->byref;
2232 ICALL_EXPORT MonoBoolean
2233 ves_icall_type_iscomobject (MonoReflectionType *type)
2235 MonoClass *klass = mono_class_from_mono_type (type->type);
2236 mono_class_init_or_throw (klass);
2238 return mono_class_is_com_object (klass);
2241 ICALL_EXPORT MonoReflectionModule*
2242 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2244 MonoClass *class = mono_class_from_mono_type (type->type);
2245 return mono_module_get_object (mono_object_domain (type), class->image);
2248 ICALL_EXPORT MonoReflectionAssembly*
2249 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2251 MonoDomain *domain = mono_domain_get ();
2252 MonoClass *class = mono_class_from_mono_type (type->type);
2253 return mono_assembly_get_object (domain, class->image->assembly);
2256 ICALL_EXPORT MonoReflectionType*
2257 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2259 MonoDomain *domain = mono_domain_get ();
2262 MONO_ARCH_SAVE_REGS;
2264 if (type->type->byref)
2266 if (type->type->type == MONO_TYPE_VAR)
2267 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2268 else if (type->type->type == MONO_TYPE_MVAR)
2269 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2271 class = mono_class_from_mono_type (type->type)->nested_in;
2273 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2276 ICALL_EXPORT MonoString*
2277 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2279 MonoDomain *domain = mono_domain_get ();
2280 MonoClass *class = mono_class_from_mono_type (type->type);
2282 if (type->type->byref) {
2283 char *n = g_strdup_printf ("%s&", class->name);
2284 MonoString *res = mono_string_new (domain, n);
2290 return mono_string_new (domain, class->name);
2294 ICALL_EXPORT MonoString*
2295 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2297 MonoDomain *domain = mono_domain_get ();
2298 MonoClass *class = mono_class_from_mono_type (type->type);
2300 while (class->nested_in)
2301 class = class->nested_in;
2303 if (class->name_space [0] == '\0')
2306 return mono_string_new (domain, class->name_space);
2310 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2314 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2315 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2317 class = mono_class_from_mono_type (type->type);
2322 ICALL_EXPORT MonoArray*
2323 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2326 MonoClass *klass, *pklass;
2327 MonoDomain *domain = mono_object_domain (type);
2328 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2330 MONO_ARCH_SAVE_REGS;
2332 klass = mono_class_from_mono_type (type->type);
2334 if (klass->generic_container) {
2335 MonoGenericContainer *container = klass->generic_container;
2336 res = mono_array_new_specific (array_vtable, container->type_argc);
2337 for (i = 0; i < container->type_argc; ++i) {
2338 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2339 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2341 } else if (klass->generic_class) {
2342 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2343 res = mono_array_new_specific (array_vtable, inst->type_argc);
2344 for (i = 0; i < inst->type_argc; ++i)
2345 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2347 res = mono_array_new_specific (array_vtable, 0);
2352 ICALL_EXPORT gboolean
2353 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2356 MONO_ARCH_SAVE_REGS;
2358 if (!IS_MONOTYPE (type))
2361 if (type->type->byref)
2364 klass = mono_class_from_mono_type (type->type);
2365 return klass->generic_container != NULL;
2368 ICALL_EXPORT MonoReflectionType*
2369 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2372 MONO_ARCH_SAVE_REGS;
2374 if (type->type->byref)
2377 klass = mono_class_from_mono_type (type->type);
2379 if (klass->generic_container) {
2380 return type; /* check this one */
2382 if (klass->generic_class) {
2383 MonoClass *generic_class = klass->generic_class->container_class;
2386 tb = mono_class_get_ref_info (generic_class);
2388 if (generic_class->wastypebuilder && tb)
2391 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2396 ICALL_EXPORT MonoReflectionType*
2397 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2400 MonoType *geninst, **types;
2403 g_assert (IS_MONOTYPE (type));
2404 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2406 count = mono_array_length (type_array);
2407 types = g_new0 (MonoType *, count);
2409 for (i = 0; i < count; i++) {
2410 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2411 types [i] = t->type;
2414 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2419 class = mono_class_from_mono_type (geninst);
2421 /*we might inflate to the GTD*/
2422 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2423 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2425 return mono_type_get_object (mono_object_domain (type), geninst);
2428 ICALL_EXPORT gboolean
2429 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2432 MONO_ARCH_SAVE_REGS;
2434 if (type->type->byref)
2437 klass = mono_class_from_mono_type (type->type);
2439 return klass->generic_class != NULL;
2442 ICALL_EXPORT gboolean
2443 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2446 MONO_ARCH_SAVE_REGS;
2448 if (!IS_MONOTYPE (type))
2451 if (type->type->byref)
2454 klass = mono_class_from_mono_type (type->type);
2455 return klass->generic_class != NULL || klass->generic_container != NULL;
2459 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2461 MONO_ARCH_SAVE_REGS;
2463 if (!IS_MONOTYPE (type))
2466 if (is_generic_parameter (type->type))
2467 return mono_type_get_generic_param_num (type->type);
2471 ICALL_EXPORT GenericParameterAttributes
2472 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2474 MONO_ARCH_SAVE_REGS;
2476 g_assert (IS_MONOTYPE (type));
2477 g_assert (is_generic_parameter (type->type));
2478 return mono_generic_param_info (type->type->data.generic_param)->flags;
2481 ICALL_EXPORT MonoArray *
2482 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2484 MonoGenericParamInfo *param_info;
2490 MONO_ARCH_SAVE_REGS;
2492 g_assert (IS_MONOTYPE (type));
2494 domain = mono_object_domain (type);
2495 param_info = mono_generic_param_info (type->type->data.generic_param);
2496 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2499 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2500 for (i = 0; i < count; i++)
2501 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2507 ICALL_EXPORT MonoBoolean
2508 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2510 MONO_ARCH_SAVE_REGS;
2511 return is_generic_parameter (type->type);
2514 ICALL_EXPORT MonoBoolean
2515 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2517 MONO_ARCH_SAVE_REGS;
2518 return is_generic_parameter (tb->type.type);
2522 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2523 MonoReflectionType *t)
2525 enumtype->type = t->type;
2528 ICALL_EXPORT MonoReflectionMethod*
2529 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2530 MonoReflectionMethod* generic)
2537 MONO_ARCH_SAVE_REGS;
2539 domain = ((MonoObject *)type)->vtable->domain;
2541 klass = mono_class_from_mono_type (type->type);
2542 mono_class_init_or_throw (klass);
2545 while ((method = mono_class_get_methods (klass, &iter))) {
2546 if (method->token == generic->method->token)
2547 return mono_method_get_object (domain, method, klass);
2555 ICALL_EXPORT MonoReflectionMethod *
2556 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2559 MonoType *type = ref_type->type;
2561 MONO_ARCH_SAVE_REGS;
2563 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2564 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2565 if (type->type == MONO_TYPE_VAR)
2568 method = mono_type_get_generic_param_owner (type)->owner.method;
2570 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2573 ICALL_EXPORT MonoReflectionDllImportAttribute*
2574 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2576 static MonoClass *DllImportAttributeClass = NULL;
2577 MonoDomain *domain = mono_domain_get ();
2578 MonoReflectionDllImportAttribute *attr;
2579 MonoImage *image = method->klass->image;
2580 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2581 MonoTableInfo *tables = image->tables;
2582 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2583 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2584 guint32 im_cols [MONO_IMPLMAP_SIZE];
2585 guint32 scope_token;
2586 const char *import = NULL;
2587 const char *scope = NULL;
2590 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2593 if (!DllImportAttributeClass) {
2594 DllImportAttributeClass =
2595 mono_class_from_name (mono_defaults.corlib,
2596 "System.Runtime.InteropServices", "DllImportAttribute");
2597 g_assert (DllImportAttributeClass);
2600 if (method->klass->image->dynamic) {
2601 MonoReflectionMethodAux *method_aux =
2602 g_hash_table_lookup (
2603 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2605 import = method_aux->dllentry;
2606 scope = method_aux->dll;
2609 if (!import || !scope) {
2610 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2615 if (piinfo->implmap_idx) {
2616 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2618 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2619 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2620 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2621 scope = mono_metadata_string_heap (image, scope_token);
2624 flags = piinfo->piflags;
2626 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2628 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2629 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2630 attr->call_conv = (flags & 0x700) >> 8;
2631 attr->charset = ((flags & 0x6) >> 1) + 1;
2632 if (attr->charset == 1)
2634 attr->exact_spelling = (flags & 0x1) != 0;
2635 attr->set_last_error = (flags & 0x40) != 0;
2636 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2637 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2638 attr->preserve_sig = FALSE;
2643 ICALL_EXPORT MonoReflectionMethod *
2644 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2646 MonoMethodInflated *imethod;
2649 MONO_ARCH_SAVE_REGS;
2651 if (method->method->is_generic)
2654 if (!method->method->is_inflated)
2657 imethod = (MonoMethodInflated *) method->method;
2659 result = imethod->declaring;
2660 /* Not a generic method. */
2661 if (!result->is_generic)
2664 if (method->method->klass->image->dynamic) {
2665 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2666 MonoReflectionMethod *res;
2669 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2670 * the dynamic case as well ?
2672 mono_loader_lock ();
2673 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2674 mono_loader_unlock ();
2680 if (imethod->context.class_inst) {
2681 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2682 /*Generic methods gets the context of the GTD.*/
2683 if (mono_class_get_context (klass))
2684 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2687 return mono_method_get_object (mono_object_domain (method), result, NULL);
2690 ICALL_EXPORT gboolean
2691 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2693 MONO_ARCH_SAVE_REGS;
2695 return mono_method_signature (method->method)->generic_param_count != 0;
2698 ICALL_EXPORT gboolean
2699 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2701 MONO_ARCH_SAVE_REGS;
2703 return method->method->is_generic;
2706 ICALL_EXPORT MonoArray*
2707 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2712 MONO_ARCH_SAVE_REGS;
2714 domain = mono_object_domain (method);
2716 if (method->method->is_inflated) {
2717 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2720 count = inst->type_argc;
2721 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2723 for (i = 0; i < count; i++)
2724 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2730 count = mono_method_signature (method->method)->generic_param_count;
2731 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2733 for (i = 0; i < count; i++) {
2734 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2735 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2736 MonoClass *pklass = mono_class_from_generic_parameter (
2737 param, method->method->klass->image, TRUE);
2738 mono_array_setref (res, i,
2739 mono_type_get_object (domain, &pklass->byval_arg));
2745 ICALL_EXPORT MonoObject *
2746 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2749 * Invoke from reflection is supposed to always be a virtual call (the API
2750 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2751 * greater flexibility.
2753 MonoMethod *m = method->method;
2754 MonoMethodSignature *sig = mono_method_signature (m);
2759 MONO_ARCH_SAVE_REGS;
2763 if (mono_security_core_clr_enabled ())
2764 mono_security_core_clr_ensure_reflection_access_method (m);
2766 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2767 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2768 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2773 if (!mono_object_isinst (this, m->klass)) {
2774 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2775 char *target_name = mono_type_get_full_name (m->klass);
2776 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2777 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2779 g_free (target_name);
2783 m = mono_object_get_virtual_method (this, m);
2784 /* must pass the pointer to the value for valuetype methods */
2785 if (m->klass->valuetype)
2786 obj = mono_object_unbox (this);
2787 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2788 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2793 if (sig->ret->byref) {
2794 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"));
2798 pcount = params? mono_array_length (params): 0;
2799 if (pcount != sig->param_count) {
2800 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2804 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2805 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."));
2809 image = m->klass->image;
2810 if (image->assembly->ref_only) {
2811 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."));
2815 if (image->dynamic && !((MonoDynamicImage*)image)->run) {
2816 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2820 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2823 intptr_t *lower_bounds;
2824 pcount = mono_array_length (params);
2825 lengths = alloca (sizeof (uintptr_t) * pcount);
2826 /* Note: the synthetized array .ctors have int32 as argument type */
2827 for (i = 0; i < pcount; ++i)
2828 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2830 if (m->klass->rank == pcount) {
2831 /* Only lengths provided. */
2832 lower_bounds = NULL;
2834 g_assert (pcount == (m->klass->rank * 2));
2835 /* lower bounds are first. */
2836 lower_bounds = (intptr_t*)lengths;
2837 lengths += m->klass->rank;
2840 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2842 return mono_runtime_invoke_array (m, obj, params, NULL);
2845 #ifndef DISABLE_REMOTING
2846 ICALL_EXPORT MonoObject *
2847 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2849 MonoDomain *domain = mono_object_domain (method);
2850 MonoMethod *m = method->method;
2851 MonoMethodSignature *sig = mono_method_signature (m);
2852 MonoArray *out_args;
2854 int i, j, outarg_count = 0;
2856 MONO_ARCH_SAVE_REGS;
2858 if (m->klass == mono_defaults.object_class) {
2860 if (!strcmp (m->name, "FieldGetter")) {
2861 MonoClass *k = this->vtable->klass;
2865 /* If this is a proxy, then it must be a CBO */
2866 if (k == mono_defaults.transparent_proxy_class) {
2867 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2868 this = tp->rp->unwrapped_server;
2870 k = this->vtable->klass;
2873 name = mono_array_get (params, MonoString *, 1);
2874 str = mono_string_to_utf8 (name);
2877 MonoClassField* field = mono_class_get_field_from_name (k, str);
2879 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2880 if (field_klass->valuetype)
2881 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2883 result = *((gpointer *)((char *)this + field->offset));
2885 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2886 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2887 mono_array_setref (out_args, 0, result);
2895 g_assert_not_reached ();
2897 } else if (!strcmp (m->name, "FieldSetter")) {
2898 MonoClass *k = this->vtable->klass;
2904 /* If this is a proxy, then it must be a CBO */
2905 if (k == mono_defaults.transparent_proxy_class) {
2906 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2907 this = tp->rp->unwrapped_server;
2909 k = this->vtable->klass;
2912 name = mono_array_get (params, MonoString *, 1);
2913 str = mono_string_to_utf8 (name);
2916 MonoClassField* field = mono_class_get_field_from_name (k, str);
2918 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2919 MonoObject *val = mono_array_get (params, gpointer, 2);
2921 if (field_klass->valuetype) {
2922 size = mono_type_size (field->type, &align);
2923 g_assert (size == mono_class_value_size (field_klass, NULL));
2924 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2926 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2929 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2930 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2940 g_assert_not_reached ();
2945 for (i = 0; i < mono_array_length (params); i++) {
2946 if (sig->params [i]->byref)
2950 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2952 /* handle constructors only for objects already allocated */
2953 if (!strcmp (method->method->name, ".ctor"))
2956 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2957 g_assert (!method->method->klass->valuetype);
2958 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2960 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2961 if (sig->params [i]->byref) {
2963 arg = mono_array_get (params, gpointer, i);
2964 mono_array_setref (out_args, j, arg);
2969 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2976 read_enum_value (char *mem, int type)
2980 return *(guint8*)mem;
2982 return *(gint8*)mem;
2984 return *(guint16*)mem;
2986 return *(gint16*)mem;
2988 return *(guint32*)mem;
2990 return *(gint32*)mem;
2992 return *(guint64*)mem;
2994 return *(gint64*)mem;
2996 g_assert_not_reached ();
3002 write_enum_value (char *mem, int type, guint64 value)
3006 case MONO_TYPE_I1: {
3007 guint8 *p = (guint8*)mem;
3012 case MONO_TYPE_I2: {
3013 guint16 *p = (void*)mem;
3018 case MONO_TYPE_I4: {
3019 guint32 *p = (void*)mem;
3024 case MONO_TYPE_I8: {
3025 guint64 *p = (void*)mem;
3030 g_assert_not_reached ();
3035 ICALL_EXPORT MonoObject *
3036 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3039 MonoClass *enumc, *objc;
3044 MONO_ARCH_SAVE_REGS;
3046 MONO_CHECK_ARG_NULL (enumType);
3047 MONO_CHECK_ARG_NULL (value);
3049 domain = mono_object_domain (enumType);
3050 enumc = mono_class_from_mono_type (enumType->type);
3052 mono_class_init_or_throw (enumc);
3054 objc = value->vtable->klass;
3056 if (!enumc->enumtype)
3057 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3058 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3059 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."));
3061 etype = mono_class_enum_basetype (enumc);
3063 /* MS throws this for typebuilders */
3064 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3066 res = mono_object_new (domain, enumc);
3067 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3068 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3073 ICALL_EXPORT MonoObject *
3074 ves_icall_System_Enum_get_value (MonoObject *this)
3082 MONO_ARCH_SAVE_REGS;
3087 g_assert (this->vtable->klass->enumtype);
3089 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3090 res = mono_object_new (mono_object_domain (this), enumc);
3091 dst = (char *)res + sizeof (MonoObject);
3092 src = (char *)this + sizeof (MonoObject);
3093 size = mono_class_value_size (enumc, NULL);
3095 memcpy (dst, src, size);
3100 ICALL_EXPORT MonoReflectionType *
3101 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3106 MONO_ARCH_SAVE_REGS;
3108 klass = mono_class_from_mono_type (type->type);
3109 mono_class_init_or_throw (klass);
3111 etype = mono_class_enum_basetype (klass);
3113 /* MS throws this for typebuilders */
3114 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3116 return mono_type_get_object (mono_object_domain (type), etype);
3120 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3122 gpointer tdata = (char *)this + sizeof (MonoObject);
3123 gpointer odata = (char *)other + sizeof (MonoObject);
3124 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3125 g_assert (basetype);
3127 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3128 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3129 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3132 return me > other ? 1 : -1; \
3135 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3136 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3137 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3140 return me - other; \
3143 switch (basetype->type) {
3145 COMPARE_ENUM_VALUES (guint8);
3147 COMPARE_ENUM_VALUES (gint8);
3148 case MONO_TYPE_CHAR:
3150 COMPARE_ENUM_VALUES_RANGE (guint16);
3152 COMPARE_ENUM_VALUES (gint16);
3154 COMPARE_ENUM_VALUES (guint32);
3156 COMPARE_ENUM_VALUES (gint32);
3158 COMPARE_ENUM_VALUES (guint64);
3160 COMPARE_ENUM_VALUES (gint64);
3162 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3164 #undef COMPARE_ENUM_VALUES_RANGE
3165 #undef COMPARE_ENUM_VALUES
3170 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3172 gpointer data = (char *)this + sizeof (MonoObject);
3173 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3174 g_assert (basetype);
3176 switch (basetype->type) {
3178 return *((gint8*)data);
3180 return *((guint8*)data);
3181 case MONO_TYPE_CHAR:
3183 return *((guint16*)data);
3186 return *((gint16*)data);
3188 return *((guint32*)data);
3190 return *((gint32*)data);
3192 case MONO_TYPE_I8: {
3193 gint64 value = *((gint64*)data);
3194 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3197 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3203 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3205 MonoDomain *domain = mono_object_domain (type);
3206 MonoClass *enumc = mono_class_from_mono_type (type->type);
3207 guint j = 0, nvalues, crow;
3209 MonoClassField *field;
3211 MONO_ARCH_SAVE_REGS;
3213 mono_class_init_or_throw (enumc);
3215 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3216 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3217 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3218 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3222 while ((field = mono_class_get_fields (enumc, &iter))) {
3225 MonoTypeEnum def_type;
3227 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3229 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3231 if (mono_field_is_deleted (field))
3233 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3235 p = mono_class_get_field_default_value (field, &def_type);
3236 len = mono_metadata_decode_blob_size (p, &p);
3237 switch (mono_class_enum_basetype (enumc)->type) {
3240 mono_array_set (info->values, gchar, j, *p);
3242 case MONO_TYPE_CHAR:
3245 mono_array_set (info->values, gint16, j, read16 (p));
3249 mono_array_set (info->values, gint32, j, read32 (p));
3253 mono_array_set (info->values, gint64, j, read64 (p));
3256 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3263 BFLAGS_IgnoreCase = 1,
3264 BFLAGS_DeclaredOnly = 2,
3265 BFLAGS_Instance = 4,
3267 BFLAGS_Public = 0x10,
3268 BFLAGS_NonPublic = 0x20,
3269 BFLAGS_FlattenHierarchy = 0x40,
3270 BFLAGS_InvokeMethod = 0x100,
3271 BFLAGS_CreateInstance = 0x200,
3272 BFLAGS_GetField = 0x400,
3273 BFLAGS_SetField = 0x800,
3274 BFLAGS_GetProperty = 0x1000,
3275 BFLAGS_SetProperty = 0x2000,
3276 BFLAGS_ExactBinding = 0x10000,
3277 BFLAGS_SuppressChangeType = 0x20000,
3278 BFLAGS_OptionalParamBinding = 0x40000
3281 ICALL_EXPORT MonoReflectionField *
3282 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3285 MonoClass *startklass, *klass;
3287 MonoClassField *field;
3290 int (*compare_func) (const char *s1, const char *s2) = NULL;
3291 domain = ((MonoObject *)type)->vtable->domain;
3292 klass = startklass = mono_class_from_mono_type (type->type);
3295 mono_raise_exception (mono_get_exception_argument_null ("name"));
3296 if (type->type->byref)
3299 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3302 if (klass->exception_type != MONO_EXCEPTION_NONE)
3303 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3306 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3307 guint32 flags = mono_field_get_flags (field);
3310 if (mono_field_is_deleted_with_flags (field, flags))
3312 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3313 if (bflags & BFLAGS_Public)
3315 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3316 if (bflags & BFLAGS_NonPublic) {
3323 if (flags & FIELD_ATTRIBUTE_STATIC) {
3324 if (bflags & BFLAGS_Static)
3325 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3328 if (bflags & BFLAGS_Instance)
3335 utf8_name = mono_string_to_utf8 (name);
3337 if (compare_func (mono_field_get_name (field), utf8_name)) {
3343 return mono_field_get_object (domain, klass, field);
3345 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3351 ICALL_EXPORT MonoArray*
3352 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3355 MonoClass *startklass, *klass, *refklass;
3360 MonoClassField *field;
3361 MonoPtrArray tmp_array;
3363 MONO_ARCH_SAVE_REGS;
3365 domain = ((MonoObject *)type)->vtable->domain;
3366 if (type->type->byref)
3367 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3368 klass = startklass = mono_class_from_mono_type (type->type);
3369 refklass = mono_class_from_mono_type (reftype->type);
3371 mono_ptr_array_init (tmp_array, 2);
3374 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3375 mono_ptr_array_destroy (tmp_array);
3376 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3380 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3381 guint32 flags = mono_field_get_flags (field);
3383 if (mono_field_is_deleted_with_flags (field, flags))
3385 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3386 if (bflags & BFLAGS_Public)
3388 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3389 if (bflags & BFLAGS_NonPublic) {
3396 if (flags & FIELD_ATTRIBUTE_STATIC) {
3397 if (bflags & BFLAGS_Static)
3398 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3401 if (bflags & BFLAGS_Instance)
3407 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3408 mono_ptr_array_append (tmp_array, member);
3410 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3413 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3415 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3416 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3418 mono_ptr_array_destroy (tmp_array);
3424 method_nonpublic (MonoMethod* method, gboolean start_klass)
3426 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3427 case METHOD_ATTRIBUTE_ASSEM:
3428 return (start_klass || mono_defaults.generic_ilist_class);
3429 case METHOD_ATTRIBUTE_PRIVATE:
3431 case METHOD_ATTRIBUTE_PUBLIC:
3439 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3442 MonoClass *startklass;
3445 int len, match, nslots;
3446 /*FIXME, use MonoBitSet*/
3447 guint32 method_slots_default [8];
3448 guint32 *method_slots = NULL;
3449 int (*compare_func) (const char *s1, const char *s2) = NULL;
3451 array = g_ptr_array_new ();
3457 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3459 /* An optimization for calls made from Delegate:CreateDelegate () */
3460 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3461 method = mono_get_delegate_invoke (klass);
3462 if (mono_loader_get_last_error ())
3465 g_ptr_array_add (array, method);
3469 mono_class_setup_vtable (klass);
3470 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3473 if (is_generic_parameter (&klass->byval_arg))
3474 nslots = mono_class_get_vtable_size (klass->parent);
3476 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3477 if (nslots >= sizeof (method_slots_default) * 8) {
3478 method_slots = g_new0 (guint32, nslots / 32 + 1);
3480 method_slots = method_slots_default;
3481 memset (method_slots, 0, sizeof (method_slots_default));
3484 mono_class_setup_vtable (klass);
3485 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3489 while ((method = mono_class_get_methods (klass, &iter))) {
3491 if (method->slot != -1) {
3492 g_assert (method->slot < nslots);
3493 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3495 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3496 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3499 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3501 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3502 if (bflags & BFLAGS_Public)
3504 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3510 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3511 if (bflags & BFLAGS_Static)
3512 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3515 if (bflags & BFLAGS_Instance)
3523 if (compare_func (name, method->name))
3528 g_ptr_array_add (array, method);
3530 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3532 if (method_slots != method_slots_default)
3533 g_free (method_slots);
3538 if (method_slots != method_slots_default)
3539 g_free (method_slots);
3540 g_ptr_array_free (array, TRUE);
3542 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3543 *ex = mono_class_get_exception_for_failure (klass);
3545 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3546 mono_loader_clear_error ();
3551 ICALL_EXPORT MonoArray*
3552 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3554 static MonoClass *MethodInfo_array;
3557 MonoVTable *array_vtable;
3558 MonoException *ex = NULL;
3559 const char *mname = NULL;
3560 GPtrArray *method_array;
3561 MonoClass *klass, *refklass;
3564 if (!MethodInfo_array) {
3565 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3566 mono_memory_barrier ();
3567 MethodInfo_array = klass;
3570 klass = mono_class_from_mono_type (type->type);
3571 refklass = mono_class_from_mono_type (reftype->type);
3572 domain = ((MonoObject *)type)->vtable->domain;
3573 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3574 if (type->type->byref)
3575 return mono_array_new_specific (array_vtable, 0);
3578 mname = mono_string_to_utf8 (name);
3580 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3581 g_free ((char*)mname);
3583 mono_raise_exception (ex);
3585 res = mono_array_new_specific (array_vtable, method_array->len);
3588 for (i = 0; i < method_array->len; ++i) {
3589 MonoMethod *method = g_ptr_array_index (method_array, i);
3590 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3593 g_ptr_array_free (method_array, TRUE);
3597 ICALL_EXPORT MonoArray*
3598 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3601 static MonoClass *System_Reflection_ConstructorInfo;
3602 MonoClass *startklass, *klass, *refklass;
3607 gpointer iter = NULL;
3608 MonoPtrArray tmp_array;
3610 MONO_ARCH_SAVE_REGS;
3612 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3614 domain = ((MonoObject *)type)->vtable->domain;
3615 if (type->type->byref)
3616 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3617 klass = startklass = mono_class_from_mono_type (type->type);
3618 refklass = mono_class_from_mono_type (reftype->type);
3620 if (!System_Reflection_ConstructorInfo)
3621 System_Reflection_ConstructorInfo = mono_class_from_name (
3622 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3625 while ((method = mono_class_get_methods (klass, &iter))) {
3627 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3629 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3630 if (bflags & BFLAGS_Public)
3633 if (bflags & BFLAGS_NonPublic)
3639 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3640 if (bflags & BFLAGS_Static)
3641 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3644 if (bflags & BFLAGS_Instance)
3650 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3652 mono_ptr_array_append (tmp_array, member);
3655 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3657 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3658 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3660 mono_ptr_array_destroy (tmp_array);
3666 property_hash (gconstpointer data)
3668 MonoProperty *prop = (MonoProperty*)data;
3670 return g_str_hash (prop->name);
3674 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3676 // Properties are hide-by-name-and-signature
3677 if (!g_str_equal (prop1->name, prop2->name))
3680 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3682 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3688 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3693 return method_nonpublic (accessor, start_klass);
3696 ICALL_EXPORT MonoArray*
3697 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3701 static MonoClass *System_Reflection_PropertyInfo;
3702 MonoClass *startklass, *klass;
3708 gchar *propname = NULL;
3709 int (*compare_func) (const char *s1, const char *s2) = NULL;
3711 GHashTable *properties = NULL;
3712 MonoPtrArray tmp_array;
3714 MONO_ARCH_SAVE_REGS;
3716 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3718 if (!System_Reflection_PropertyInfo)
3719 System_Reflection_PropertyInfo = mono_class_from_name (
3720 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3722 domain = ((MonoObject *)type)->vtable->domain;
3723 if (type->type->byref)
3724 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3725 klass = startklass = mono_class_from_mono_type (type->type);
3728 propname = mono_string_to_utf8 (name);
3729 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3732 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3734 mono_class_setup_vtable (klass);
3735 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3739 while ((prop = mono_class_get_properties (klass, &iter))) {
3745 flags = method->flags;
3748 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3749 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3750 if (bflags & BFLAGS_Public)
3752 } else if (bflags & BFLAGS_NonPublic) {
3753 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3754 property_accessor_nonpublic(prop->set, startklass == klass)) {
3761 if (flags & METHOD_ATTRIBUTE_STATIC) {
3762 if (bflags & BFLAGS_Static)
3763 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3766 if (bflags & BFLAGS_Instance)
3775 if (compare_func (propname, prop->name))
3779 if (g_hash_table_lookup (properties, prop))
3782 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3784 g_hash_table_insert (properties, prop, prop);
3786 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3789 g_hash_table_destroy (properties);
3792 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3793 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3794 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3796 mono_ptr_array_destroy (tmp_array);
3802 g_hash_table_destroy (properties);
3805 mono_ptr_array_destroy (tmp_array);
3807 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3808 ex = mono_class_get_exception_for_failure (klass);
3810 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3811 mono_loader_clear_error ();
3813 mono_raise_exception (ex);
3817 ICALL_EXPORT MonoReflectionEvent *
3818 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3821 MonoClass *klass, *startklass;
3826 int (*compare_func) (const char *s1, const char *s2);
3828 MONO_ARCH_SAVE_REGS;
3830 event_name = mono_string_to_utf8 (name);
3831 if (type->type->byref)
3833 klass = startklass = mono_class_from_mono_type (type->type);
3834 domain = mono_object_domain (type);
3836 mono_class_init_or_throw (klass);
3838 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3840 if (klass->exception_type != MONO_EXCEPTION_NONE)
3841 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3844 while ((event = mono_class_get_events (klass, &iter))) {
3845 if (compare_func (event->name, event_name))
3848 method = event->add;
3850 method = event->remove;
3852 method = event->raise;
3854 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3855 if (!(bflags & BFLAGS_Public))
3858 if (!(bflags & BFLAGS_NonPublic))
3860 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3864 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3865 if (!(bflags & BFLAGS_Static))
3867 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3870 if (!(bflags & BFLAGS_Instance))
3874 if (!(bflags & BFLAGS_NonPublic))
3877 g_free (event_name);
3878 return mono_event_get_object (domain, startklass, event);
3881 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3884 g_free (event_name);
3888 ICALL_EXPORT MonoArray*
3889 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3893 static MonoClass *System_Reflection_EventInfo;
3894 MonoClass *startklass, *klass;
3901 MonoPtrArray tmp_array;
3903 MONO_ARCH_SAVE_REGS;
3905 mono_ptr_array_init (tmp_array, 4);
3907 if (!System_Reflection_EventInfo)
3908 System_Reflection_EventInfo = mono_class_from_name (
3909 mono_defaults.corlib, "System.Reflection", "EventInfo");
3911 domain = mono_object_domain (type);
3912 if (type->type->byref)
3913 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3914 klass = startklass = mono_class_from_mono_type (type->type);
3917 mono_class_setup_vtable (klass);
3918 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3922 while ((event = mono_class_get_events (klass, &iter))) {
3924 method = event->add;
3926 method = event->remove;
3928 method = event->raise;
3930 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3931 if (bflags & BFLAGS_Public)
3933 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3934 if (bflags & BFLAGS_NonPublic)
3939 if (bflags & BFLAGS_NonPublic)
3945 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3946 if (bflags & BFLAGS_Static)
3947 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3950 if (bflags & BFLAGS_Instance)
3955 if (bflags & BFLAGS_Instance)
3959 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3961 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3964 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3966 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3967 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3969 mono_ptr_array_destroy (tmp_array);
3974 mono_ptr_array_destroy (tmp_array);
3975 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3976 ex = mono_class_get_exception_for_failure (klass);
3978 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3979 mono_loader_clear_error ();
3981 mono_raise_exception (ex);
3985 ICALL_EXPORT MonoReflectionType *
3986 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3994 MONO_ARCH_SAVE_REGS;
3997 mono_raise_exception (mono_get_exception_argument_null ("name"));
3999 domain = ((MonoObject *)type)->vtable->domain;
4000 if (type->type->byref)
4002 klass = mono_class_from_mono_type (type->type);
4004 str = mono_string_to_utf8 (name);
4007 if (klass->exception_type != MONO_EXCEPTION_NONE)
4008 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4011 * If a nested type is generic, return its generic type definition.
4012 * Note that this means that the return value is essentially a
4013 * nested type of the generic type definition of @klass.
4015 * A note in MSDN claims that a generic type definition can have
4016 * nested types that aren't generic. In any case, the container of that
4017 * nested type would be the generic type definition.
4019 if (klass->generic_class)
4020 klass = klass->generic_class->container_class;
4023 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4025 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4026 if (bflags & BFLAGS_Public)
4029 if (bflags & BFLAGS_NonPublic)
4034 if (strcmp (nested->name, str) == 0){
4036 return mono_type_get_object (domain, &nested->byval_arg);
4039 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4045 ICALL_EXPORT MonoArray*
4046 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4055 MonoPtrArray tmp_array;
4057 MONO_ARCH_SAVE_REGS;
4059 domain = ((MonoObject *)type)->vtable->domain;
4060 if (type->type->byref)
4061 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4062 klass = mono_class_from_mono_type (type->type);
4065 * If a nested type is generic, return its generic type definition.
4066 * Note that this means that the return value is essentially the set
4067 * of nested types of the generic type definition of @klass.
4069 * A note in MSDN claims that a generic type definition can have
4070 * nested types that aren't generic. In any case, the container of that
4071 * nested type would be the generic type definition.
4073 if (klass->generic_class)
4074 klass = klass->generic_class->container_class;
4076 mono_ptr_array_init (tmp_array, 1);
4078 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4080 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4081 if (bflags & BFLAGS_Public)
4084 if (bflags & BFLAGS_NonPublic)
4089 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4090 mono_ptr_array_append (tmp_array, member);
4093 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4095 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4096 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4098 mono_ptr_array_destroy (tmp_array);
4103 ICALL_EXPORT MonoReflectionType*
4104 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4107 MonoType *type = NULL;
4108 MonoTypeNameParse info;
4109 gboolean type_resolve;
4111 MONO_ARCH_SAVE_REGS;
4113 /* On MS.NET, this does not fire a TypeResolve event */
4114 type_resolve = TRUE;
4115 str = mono_string_to_utf8 (name);
4116 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4117 if (!mono_reflection_parse_type (str, &info)) {
4119 mono_reflection_free_type_info (&info);
4120 if (throwOnError) /* uhm: this is a parse error, though... */
4121 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4122 /*g_print ("failed parse\n");*/
4126 if (info.assembly.name) {
4128 mono_reflection_free_type_info (&info);
4130 /* 1.0 and 2.0 throw different exceptions */
4131 if (mono_defaults.generic_ilist_class)
4132 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4134 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4139 if (module != NULL) {
4141 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4146 if (assembly->assembly->dynamic) {
4147 /* Enumerate all modules */
4148 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4152 if (abuilder->modules) {
4153 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4154 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4155 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4161 if (!type && abuilder->loaded_modules) {
4162 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4163 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4164 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4171 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4173 mono_reflection_free_type_info (&info);
4175 MonoException *e = NULL;
4178 e = mono_get_exception_type_load (name, NULL);
4180 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4181 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4183 mono_loader_clear_error ();
4186 mono_raise_exception (e);
4189 } else if (mono_loader_get_last_error ()) {
4191 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4192 mono_loader_clear_error ();
4195 if (type->type == MONO_TYPE_CLASS) {
4196 MonoClass *klass = mono_type_get_class (type);
4198 if (mono_security_enabled () && !klass->exception_type)
4199 /* Some security problems are detected during generic vtable construction */
4200 mono_class_setup_vtable (klass);
4202 /* need to report exceptions ? */
4203 if (throwOnError && klass->exception_type) {
4204 /* report SecurityException (or others) that occured when loading the assembly */
4205 MonoException *exc = mono_class_get_exception_for_failure (klass);
4206 mono_loader_clear_error ();
4207 mono_raise_exception (exc);
4208 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4213 /* g_print ("got it\n"); */
4214 return mono_type_get_object (mono_object_domain (assembly), type);
4218 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4221 gchar *shadow_ini_file;
4224 /* Check for shadow-copied assembly */
4225 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4226 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4228 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4229 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4235 g_free (shadow_ini_file);
4236 if (content != NULL) {
4239 *filename = content;
4246 ICALL_EXPORT MonoString *
4247 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4249 MonoDomain *domain = mono_object_domain (assembly);
4250 MonoAssembly *mass = assembly->assembly;
4251 MonoString *res = NULL;
4256 MONO_ARCH_SAVE_REGS;
4258 if (g_path_is_absolute (mass->image->name)) {
4259 absolute = g_strdup (mass->image->name);
4260 dirname = g_path_get_dirname (absolute);
4262 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4263 dirname = g_strdup (mass->basedir);
4266 replace_shadow_path (domain, dirname, &absolute);
4271 for (i = strlen (absolute) - 1; i >= 0; i--)
4272 if (absolute [i] == '\\')
4277 uri = g_filename_to_uri (absolute, NULL, NULL);
4279 const char *prepend = "file://";
4281 if (*absolute == '/' && *(absolute + 1) == '/') {
4284 prepend = "file:///";
4287 uri = g_strconcat (prepend, absolute, NULL);
4291 res = mono_string_new (domain, uri);
4298 ICALL_EXPORT MonoBoolean
4299 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4301 MonoAssembly *mass = assembly->assembly;
4303 MONO_ARCH_SAVE_REGS;
4305 return mass->in_gac;
4308 ICALL_EXPORT MonoReflectionAssembly*
4309 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4313 MonoImageOpenStatus status;
4315 MONO_ARCH_SAVE_REGS;
4317 name = mono_string_to_utf8 (mname);
4318 res = mono_assembly_load_with_partial_name (name, &status);
4324 return mono_assembly_get_object (mono_domain_get (), res);
4327 ICALL_EXPORT MonoString *
4328 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4330 MonoDomain *domain = mono_object_domain (assembly);
4333 MONO_ARCH_SAVE_REGS;
4335 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4340 ICALL_EXPORT MonoBoolean
4341 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4343 MONO_ARCH_SAVE_REGS;
4345 return assembly->assembly->ref_only;
4348 ICALL_EXPORT MonoString *
4349 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4351 MonoDomain *domain = mono_object_domain (assembly);
4353 MONO_ARCH_SAVE_REGS;
4355 return mono_string_new (domain, assembly->assembly->image->version);
4358 ICALL_EXPORT MonoReflectionMethod*
4359 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4361 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4363 MONO_ARCH_SAVE_REGS;
4367 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4370 ICALL_EXPORT MonoReflectionModule*
4371 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4373 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4376 ICALL_EXPORT MonoArray*
4377 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4379 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4380 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4384 MONO_ARCH_SAVE_REGS;
4386 for (i = 0; i < table->rows; ++i) {
4387 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4388 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4394 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4396 static MonoClass *System_Version = NULL;
4397 static MonoMethod *create_version = NULL;
4401 if (!System_Version) {
4402 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4403 g_assert (System_Version);
4406 if (!create_version) {
4407 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4408 create_version = mono_method_desc_search_in_class (desc, System_Version);
4409 g_assert (create_version);
4410 mono_method_desc_free (desc);
4416 args [3] = &revision;
4417 result = mono_object_new (domain, System_Version);
4418 mono_runtime_invoke (create_version, result, args, NULL);
4423 ICALL_EXPORT MonoArray*
4424 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4426 static MonoClass *System_Reflection_AssemblyName;
4428 MonoDomain *domain = mono_object_domain (assembly);
4430 static MonoMethod *create_culture = NULL;
4431 MonoImage *image = assembly->assembly->image;
4434 MONO_ARCH_SAVE_REGS;
4436 if (!System_Reflection_AssemblyName)
4437 System_Reflection_AssemblyName = mono_class_from_name (
4438 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4440 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4443 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4445 if (count > 0 && !create_culture) {
4446 MonoMethodDesc *desc = mono_method_desc_new (
4447 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4448 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4449 g_assert (create_culture);
4450 mono_method_desc_free (desc);
4453 for (i = 0; i < count; i++) {
4454 MonoReflectionAssemblyName *aname;
4455 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4457 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4459 aname = (MonoReflectionAssemblyName *) mono_object_new (
4460 domain, System_Reflection_AssemblyName);
4462 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4464 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4465 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4466 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4467 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4468 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4469 aname->versioncompat = 1; /* SameMachine (default) */
4470 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4471 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4473 if (create_culture) {
4475 MonoBoolean assembly_ref = 1;
4476 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4477 args [1] = &assembly_ref;
4478 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4481 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4482 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4483 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4485 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4486 /* public key token isn't copied - the class library will
4487 automatically generate it from the public key if required */
4488 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4489 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4491 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4492 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4495 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4498 /* note: this function doesn't return the codebase on purpose (i.e. it can
4499 be used under partial trust as path information isn't present). */
4501 mono_array_setref (result, i, aname);
4506 /* move this in some file in mono/util/ */
4508 g_concat_dir_and_file (const char *dir, const char *file)
4510 g_return_val_if_fail (dir != NULL, NULL);
4511 g_return_val_if_fail (file != NULL, NULL);
4514 * If the directory name doesn't have a / on the end, we need
4515 * to add one so we get a proper path to the file
4517 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4518 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4520 return g_strconcat (dir, file, NULL);
4524 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4526 char *n = mono_string_to_utf8 (name);
4527 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4529 guint32 cols [MONO_MANIFEST_SIZE];
4530 guint32 impl, file_idx;
4534 MONO_ARCH_SAVE_REGS;
4536 for (i = 0; i < table->rows; ++i) {
4537 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4538 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4539 if (strcmp (val, n) == 0)
4543 if (i == table->rows)
4546 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4549 * this code should only be called after obtaining the
4550 * ResourceInfo and handling the other cases.
4552 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4553 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4555 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4560 module = assembly->assembly->image;
4562 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4564 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4567 ICALL_EXPORT gboolean
4568 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4570 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4572 guint32 cols [MONO_MANIFEST_SIZE];
4573 guint32 file_cols [MONO_FILE_SIZE];
4577 MONO_ARCH_SAVE_REGS;
4579 n = mono_string_to_utf8 (name);
4580 for (i = 0; i < table->rows; ++i) {
4581 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4582 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4583 if (strcmp (val, n) == 0)
4587 if (i == table->rows)
4590 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4591 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4594 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4595 case MONO_IMPLEMENTATION_FILE:
4596 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4597 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4598 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4599 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4600 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4601 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4604 info->location = RESOURCE_LOCATION_EMBEDDED;
4607 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4608 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4609 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4610 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4611 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4612 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4614 mono_raise_exception (ex);
4616 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4618 /* Obtain info recursively */
4619 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4620 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4623 case MONO_IMPLEMENTATION_EXP_TYPE:
4624 g_assert_not_reached ();
4632 ICALL_EXPORT MonoObject*
4633 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4635 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4636 MonoArray *result = NULL;
4641 MONO_ARCH_SAVE_REGS;
4643 /* check hash if needed */
4645 n = mono_string_to_utf8 (name);
4646 for (i = 0; i < table->rows; ++i) {
4647 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4648 if (strcmp (val, n) == 0) {
4651 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4652 fn = mono_string_new (mono_object_domain (assembly), n);
4654 return (MonoObject*)fn;
4662 for (i = 0; i < table->rows; ++i) {
4663 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4667 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4670 for (i = 0; i < table->rows; ++i) {
4671 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4672 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4673 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4674 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4679 return (MonoObject*)result;
4682 ICALL_EXPORT MonoArray*
4683 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4685 MonoDomain *domain = mono_domain_get();
4688 int i, j, file_count = 0;
4689 MonoImage **modules;
4690 guint32 module_count, real_module_count;
4691 MonoTableInfo *table;
4692 guint32 cols [MONO_FILE_SIZE];
4693 MonoImage *image = assembly->assembly->image;
4695 g_assert (image != NULL);
4696 g_assert (!assembly->assembly->dynamic);
4698 table = &image->tables [MONO_TABLE_FILE];
4699 file_count = table->rows;
4701 modules = image->modules;
4702 module_count = image->module_count;
4704 real_module_count = 0;
4705 for (i = 0; i < module_count; ++i)
4707 real_module_count ++;
4709 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4710 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4712 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4714 for (i = 0; i < module_count; ++i)
4716 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4720 for (i = 0; i < file_count; ++i, ++j) {
4721 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4722 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4723 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4725 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4727 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4728 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4730 mono_array_setref (res, j, mono_module_get_object (domain, m));
4737 ICALL_EXPORT MonoReflectionMethod*
4738 ves_icall_GetCurrentMethod (void)
4740 MonoMethod *m = mono_method_get_last_managed ();
4742 while (m->is_inflated)
4743 m = ((MonoMethodInflated*)m)->declaring;
4745 return mono_method_get_object (mono_domain_get (), m, NULL);
4750 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4753 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4754 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4755 //method is inflated, we should inflate it on the other class
4756 MonoGenericContext ctx;
4757 ctx.method_inst = inflated->context.method_inst;
4758 ctx.class_inst = inflated->context.class_inst;
4759 if (klass->generic_class)
4760 ctx.class_inst = klass->generic_class->context.class_inst;
4761 else if (klass->generic_container)
4762 ctx.class_inst = klass->generic_container->context.class_inst;
4763 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4766 mono_class_setup_methods (method->klass);
4767 if (method->klass->exception_type)
4769 for (i = 0; i < method->klass->method.count; ++i) {
4770 if (method->klass->methods [i] == method) {
4775 mono_class_setup_methods (klass);
4776 if (klass->exception_type)
4778 g_assert (offset >= 0 && offset < klass->method.count);
4779 return klass->methods [offset];
4782 ICALL_EXPORT MonoReflectionMethod*
4783 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4787 klass = mono_class_from_mono_type (type);
4788 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4790 if (method->klass != klass) {
4791 method = mono_method_get_equivalent_method (method, klass);
4796 klass = method->klass;
4797 return mono_method_get_object (mono_domain_get (), method, klass);
4800 ICALL_EXPORT MonoReflectionMethod*
4801 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4803 return mono_method_get_object (mono_domain_get (), method, NULL);
4806 ICALL_EXPORT MonoReflectionMethodBody*
4807 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4809 return mono_method_body_get_object (mono_domain_get (), method);
4812 ICALL_EXPORT MonoReflectionAssembly*
4813 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4815 MonoMethod *dest = NULL;
4817 MONO_ARCH_SAVE_REGS;
4819 mono_stack_walk_no_il (get_executing, &dest);
4821 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4825 ICALL_EXPORT MonoReflectionAssembly*
4826 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4828 MonoDomain* domain = mono_domain_get ();
4830 MONO_ARCH_SAVE_REGS;
4832 if (!domain->entry_assembly)
4835 return mono_assembly_get_object (domain, domain->entry_assembly);
4838 ICALL_EXPORT MonoReflectionAssembly*
4839 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4844 MONO_ARCH_SAVE_REGS;
4847 mono_stack_walk_no_il (get_executing, &dest);
4849 mono_stack_walk_no_il (get_caller, &dest);
4852 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4855 ICALL_EXPORT MonoString *
4856 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4857 gboolean assembly_qualified)
4859 MonoDomain *domain = mono_object_domain (object);
4860 MonoTypeNameFormat format;
4865 format = assembly_qualified ?
4866 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4867 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4869 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4871 name = mono_type_get_name_full (object->type, format);
4875 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4880 res = mono_string_new (domain, name);
4887 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4889 MonoClass *klass = mono_class_from_mono_type (this->type);
4890 mono_class_init_or_throw (klass);
4891 return mono_security_core_clr_class_level (klass);
4895 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4897 static MonoMethod *create_culture = NULL;
4900 const char *pkey_ptr;
4902 MonoBoolean assembly_ref = 0;
4904 MONO_ARCH_SAVE_REGS;
4906 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4907 aname->major = name->major;
4908 aname->minor = name->minor;
4909 aname->build = name->build;
4910 aname->flags = name->flags;
4911 aname->revision = name->revision;
4912 aname->hashalg = name->hash_alg;
4913 aname->versioncompat = 1; /* SameMachine (default) */
4914 aname->processor_architecture = name->arch;
4916 if (by_default_version)
4917 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4920 if (absolute != NULL && *absolute != '\0') {
4921 const gchar *prepend = "file://";
4924 codebase = g_strdup (absolute);
4929 for (i = strlen (codebase) - 1; i >= 0; i--)
4930 if (codebase [i] == '\\')
4933 if (*codebase == '/' && *(codebase + 1) == '/') {
4936 prepend = "file:///";
4940 result = g_strconcat (prepend, codebase, NULL);
4946 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4950 if (!create_culture) {
4951 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4952 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4953 g_assert (create_culture);
4954 mono_method_desc_free (desc);
4957 if (name->culture) {
4958 args [0] = mono_string_new (domain, name->culture);
4959 args [1] = &assembly_ref;
4960 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4963 if (name->public_key) {
4964 pkey_ptr = (char*)name->public_key;
4965 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4967 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4968 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4969 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4970 } else if (default_publickey) {
4971 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4972 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4975 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4976 if (name->public_key_token [0]) {
4980 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4981 p = mono_array_addr (aname->keyToken, char, 0);
4983 for (i = 0, j = 0; i < 8; i++) {
4984 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4985 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4988 } else if (default_token) {
4989 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4993 ICALL_EXPORT MonoString *
4994 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4996 MonoDomain *domain = mono_object_domain (assembly);
4997 MonoAssembly *mass = assembly->assembly;
5001 name = mono_stringify_assembly_name (&mass->aname);
5002 res = mono_string_new (domain, name);
5009 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5012 MonoAssembly *mass = assembly->assembly;
5014 MONO_ARCH_SAVE_REGS;
5016 if (g_path_is_absolute (mass->image->name)) {
5017 fill_reflection_assembly_name (mono_object_domain (assembly),
5018 aname, &mass->aname, mass->image->name, TRUE,
5022 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5024 fill_reflection_assembly_name (mono_object_domain (assembly),
5025 aname, &mass->aname, absolute, TRUE, TRUE,
5032 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5035 MonoImageOpenStatus status = MONO_IMAGE_OK;
5038 MonoAssemblyName name;
5041 MONO_ARCH_SAVE_REGS;
5043 filename = mono_string_to_utf8 (fname);
5045 dirname = g_path_get_dirname (filename);
5046 replace_shadow_path (mono_domain_get (), dirname, &filename);
5049 image = mono_image_open (filename, &status);
5055 if (status == MONO_IMAGE_IMAGE_INVALID)
5056 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5058 exc = mono_get_exception_file_not_found2 (NULL, fname);
5059 mono_raise_exception (exc);
5062 res = mono_assembly_fill_assembly_name (image, &name);
5064 mono_image_close (image);
5066 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5069 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5073 mono_image_close (image);
5076 ICALL_EXPORT MonoBoolean
5077 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5078 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5080 MonoBoolean result = FALSE;
5081 MonoDeclSecurityEntry entry;
5083 /* SecurityAction.RequestMinimum */
5084 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5085 *minimum = entry.blob;
5086 *minLength = entry.size;
5089 /* SecurityAction.RequestOptional */
5090 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5091 *optional = entry.blob;
5092 *optLength = entry.size;
5095 /* SecurityAction.RequestRefuse */
5096 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5097 *refused = entry.blob;
5098 *refLength = entry.size;
5106 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5110 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5112 guint32 attrs, visibility;
5114 /* we start the count from 1 because we skip the special type <Module> */
5117 for (i = 1; i < tdef->rows; ++i) {
5118 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5119 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5120 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5124 count = tdef->rows - 1;
5126 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5127 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5129 for (i = 1; i < tdef->rows; ++i) {
5130 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5131 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5132 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5133 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5135 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5137 MonoLoaderError *error;
5140 error = mono_loader_get_last_error ();
5141 g_assert (error != NULL);
5143 ex = mono_loader_error_prepare_exception (error);
5144 mono_array_setref (*exceptions, count, ex);
5146 if (mono_loader_get_last_error ())
5147 mono_loader_clear_error ();
5155 ICALL_EXPORT MonoArray*
5156 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5158 MonoArray *res = NULL;
5159 MonoArray *exceptions = NULL;
5160 MonoImage *image = NULL;
5161 MonoTableInfo *table = NULL;
5164 int i, len, ex_count;
5166 MONO_ARCH_SAVE_REGS;
5168 domain = mono_object_domain (assembly);
5170 g_assert (!assembly->assembly->dynamic);
5171 image = assembly->assembly->image;
5172 table = &image->tables [MONO_TABLE_FILE];
5173 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5175 /* Append data from all modules in the assembly */
5176 for (i = 0; i < table->rows; ++i) {
5177 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5178 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5181 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5182 /* Append the new types to the end of the array */
5183 if (mono_array_length (res2) > 0) {
5185 MonoArray *res3, *ex3;
5187 len1 = mono_array_length (res);
5188 len2 = mono_array_length (res2);
5190 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5191 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5192 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5195 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5196 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5197 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5204 /* the ReflectionTypeLoadException must have all the types (Types property),
5205 * NULL replacing types which throws an exception. The LoaderException must
5206 * contain all exceptions for NULL items.
5209 len = mono_array_length (res);
5212 for (i = 0; i < len; i++) {
5213 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5217 klass = mono_type_get_class (t->type);
5218 if ((klass != NULL) && klass->exception_type) {
5219 /* keep the class in the list */
5220 list = g_list_append (list, klass);
5221 /* and replace Type with NULL */
5222 mono_array_setref (res, i, NULL);
5229 if (list || ex_count) {
5231 MonoException *exc = NULL;
5232 MonoArray *exl = NULL;
5233 int j, length = g_list_length (list) + ex_count;
5235 mono_loader_clear_error ();
5237 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5238 /* Types for which mono_class_get () succeeded */
5239 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5240 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5241 mono_array_setref (exl, i, exc);
5243 /* Types for which it don't */
5244 for (j = 0; j < mono_array_length (exceptions); ++j) {
5245 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5247 g_assert (i < length);
5248 mono_array_setref (exl, i, exc);
5255 exc = mono_get_exception_reflection_type_load (res, exl);
5256 mono_loader_clear_error ();
5257 mono_raise_exception (exc);
5263 ICALL_EXPORT gboolean
5264 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5266 MonoAssemblyName aname;
5267 MonoDomain *domain = mono_object_domain (name);
5269 gboolean is_version_defined;
5270 gboolean is_token_defined;
5272 aname.public_key = NULL;
5273 val = mono_string_to_utf8 (assname);
5274 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5275 g_free ((guint8*) aname.public_key);
5280 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5281 FALSE, is_token_defined);
5283 mono_assembly_name_free (&aname);
5284 g_free ((guint8*) aname.public_key);
5290 ICALL_EXPORT MonoReflectionType*
5291 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5293 MonoDomain *domain = mono_object_domain (module);
5296 MONO_ARCH_SAVE_REGS;
5298 g_assert (module->image);
5300 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5301 /* These images do not have a global type */
5304 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5305 return mono_type_get_object (domain, &klass->byval_arg);
5309 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5311 /*if (module->image)
5312 mono_image_close (module->image);*/
5315 ICALL_EXPORT MonoString*
5316 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5318 MonoDomain *domain = mono_object_domain (module);
5320 MONO_ARCH_SAVE_REGS;
5322 g_assert (module->image);
5323 return mono_string_new (domain, module->image->guid);
5326 ICALL_EXPORT gpointer
5327 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5330 if (module->image && module->image->is_module_handle)
5331 return module->image->raw_data;
5334 return (gpointer) (-1);
5338 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5340 if (image->dynamic) {
5341 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5342 *pe_kind = dyn->pe_kind;
5343 *machine = dyn->machine;
5346 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5347 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5352 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5354 return (image->md_version_major << 16) | (image->md_version_minor);
5357 ICALL_EXPORT MonoArray*
5358 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5360 MonoArray *exceptions;
5363 MONO_ARCH_SAVE_REGS;
5366 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5368 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5369 for (i = 0; i < mono_array_length (exceptions); ++i) {
5370 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5372 mono_raise_exception (ex);
5379 mono_memberref_is_method (MonoImage *image, guint32 token)
5381 if (!image->dynamic) {
5382 guint32 cols [MONO_MEMBERREF_SIZE];
5384 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5385 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5386 mono_metadata_decode_blob_size (sig, &sig);
5387 return (*sig != 0x6);
5389 MonoClass *handle_class;
5391 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5394 return mono_defaults.methodhandle_class == handle_class;
5399 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5402 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5403 mono_array_addr (type_args, MonoType*, 0));
5405 context->class_inst = NULL;
5407 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5408 mono_array_addr (method_args, MonoType*, 0));
5410 context->method_inst = NULL;
5413 ICALL_EXPORT MonoType*
5414 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5417 int table = mono_metadata_token_table (token);
5418 int index = mono_metadata_token_index (token);
5419 MonoGenericContext context;
5421 *error = ResolveTokenError_Other;
5423 /* Validate token */
5424 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5425 (table != MONO_TABLE_TYPESPEC)) {
5426 *error = ResolveTokenError_BadTable;
5430 if (image->dynamic) {
5431 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5432 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5433 return klass ? &klass->byval_arg : NULL;
5436 init_generic_context_from_args (&context, type_args, method_args);
5437 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5438 return klass ? &klass->byval_arg : NULL;
5441 if ((index <= 0) || (index > image->tables [table].rows)) {
5442 *error = ResolveTokenError_OutOfRange;
5446 init_generic_context_from_args (&context, type_args, method_args);
5447 klass = mono_class_get_full (image, token, &context);
5449 if (mono_loader_get_last_error ())
5450 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5453 return &klass->byval_arg;
5458 ICALL_EXPORT MonoMethod*
5459 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5461 int table = mono_metadata_token_table (token);
5462 int index = mono_metadata_token_index (token);
5463 MonoGenericContext context;
5466 *error = ResolveTokenError_Other;
5468 /* Validate token */
5469 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5470 (table != MONO_TABLE_MEMBERREF)) {
5471 *error = ResolveTokenError_BadTable;
5475 if (image->dynamic) {
5476 if (table == MONO_TABLE_METHOD)
5477 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5479 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5480 *error = ResolveTokenError_BadTable;
5484 init_generic_context_from_args (&context, type_args, method_args);
5485 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5488 if ((index <= 0) || (index > image->tables [table].rows)) {
5489 *error = ResolveTokenError_OutOfRange;
5492 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5493 *error = ResolveTokenError_BadTable;
5497 init_generic_context_from_args (&context, type_args, method_args);
5498 method = mono_get_method_full (image, token, NULL, &context);
5500 if (mono_loader_get_last_error ())
5501 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5506 ICALL_EXPORT MonoString*
5507 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5509 int index = mono_metadata_token_index (token);
5511 *error = ResolveTokenError_Other;
5513 /* Validate token */
5514 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5515 *error = ResolveTokenError_BadTable;
5520 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5522 if ((index <= 0) || (index >= image->heap_us.size)) {
5523 *error = ResolveTokenError_OutOfRange;
5527 /* FIXME: What to do if the index points into the middle of a string ? */
5529 return mono_ldstr (mono_domain_get (), image, index);
5532 ICALL_EXPORT MonoClassField*
5533 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5536 int table = mono_metadata_token_table (token);
5537 int index = mono_metadata_token_index (token);
5538 MonoGenericContext context;
5539 MonoClassField *field;
5541 *error = ResolveTokenError_Other;
5543 /* Validate token */
5544 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5545 *error = ResolveTokenError_BadTable;
5549 if (image->dynamic) {
5550 if (table == MONO_TABLE_FIELD)
5551 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5553 if (mono_memberref_is_method (image, token)) {
5554 *error = ResolveTokenError_BadTable;
5558 init_generic_context_from_args (&context, type_args, method_args);
5559 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5562 if ((index <= 0) || (index > image->tables [table].rows)) {
5563 *error = ResolveTokenError_OutOfRange;
5566 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5567 *error = ResolveTokenError_BadTable;
5571 init_generic_context_from_args (&context, type_args, method_args);
5572 field = mono_field_from_token (image, token, &klass, &context);
5574 if (mono_loader_get_last_error ())
5575 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5581 ICALL_EXPORT MonoObject*
5582 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5584 int table = mono_metadata_token_table (token);
5586 *error = ResolveTokenError_Other;
5589 case MONO_TABLE_TYPEDEF:
5590 case MONO_TABLE_TYPEREF:
5591 case MONO_TABLE_TYPESPEC: {
5592 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5594 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5598 case MONO_TABLE_METHOD:
5599 case MONO_TABLE_METHODSPEC: {
5600 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5602 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5606 case MONO_TABLE_FIELD: {
5607 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5609 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5613 case MONO_TABLE_MEMBERREF:
5614 if (mono_memberref_is_method (image, token)) {
5615 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5617 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5622 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5624 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5631 *error = ResolveTokenError_BadTable;
5637 ICALL_EXPORT MonoArray*
5638 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5640 int table = mono_metadata_token_table (token);
5641 int idx = mono_metadata_token_index (token);
5642 MonoTableInfo *tables = image->tables;
5647 *error = ResolveTokenError_OutOfRange;
5649 /* FIXME: Support other tables ? */
5650 if (table != MONO_TABLE_STANDALONESIG)
5656 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5659 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5661 ptr = mono_metadata_blob_heap (image, sig);
5662 len = mono_metadata_decode_blob_size (ptr, &ptr);
5664 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5665 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5669 ICALL_EXPORT MonoReflectionType*
5670 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5673 int isbyref = 0, rank;
5674 char *str = mono_string_to_utf8 (smodifiers);
5677 MONO_ARCH_SAVE_REGS;
5679 klass = mono_class_from_mono_type (tb->type.type);
5681 /* logic taken from mono_reflection_parse_type(): keep in sync */
5685 if (isbyref) { /* only one level allowed by the spec */
5692 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5695 klass = mono_ptr_class_get (&klass->byval_arg);
5696 mono_class_init (klass);
5707 else if (*p != '*') { /* '*' means unknown lower bound */
5718 klass = mono_array_class_get (klass, rank);
5719 mono_class_init (klass);
5726 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5729 ICALL_EXPORT MonoBoolean
5730 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5735 MONO_ARCH_SAVE_REGS;
5738 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5744 check_for_invalid_type (MonoClass *klass)
5748 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5751 name = mono_type_get_full_name (klass);
5752 str = mono_string_new (mono_domain_get (), name);
5754 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5757 ICALL_EXPORT MonoReflectionType *
5758 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5760 MonoClass *klass, *aklass;
5762 MONO_ARCH_SAVE_REGS;
5764 klass = mono_class_from_mono_type (type->type);
5765 check_for_invalid_type (klass);
5767 if (rank == 0) //single dimentional array
5768 aklass = mono_array_class_get (klass, 1);
5770 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5772 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5775 ICALL_EXPORT MonoReflectionType *
5776 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5780 MONO_ARCH_SAVE_REGS;
5782 klass = mono_class_from_mono_type (type->type);
5783 mono_class_init_or_throw (klass);
5784 check_for_invalid_type (klass);
5786 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5789 ICALL_EXPORT MonoReflectionType *
5790 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5792 MonoClass *klass, *pklass;
5794 klass = mono_class_from_mono_type (type->type);
5795 mono_class_init_or_throw (klass);
5796 check_for_invalid_type (klass);
5798 pklass = mono_ptr_class_get (type->type);
5800 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5803 ICALL_EXPORT MonoObject *
5804 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5805 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5807 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5808 MonoObject *delegate;
5810 MonoMethod *method = info->method;
5812 MONO_ARCH_SAVE_REGS;
5814 mono_class_init_or_throw (delegate_class);
5816 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5818 if (mono_security_core_clr_enabled ()) {
5819 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5823 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5825 if (method->dynamic) {
5826 /* Creating a trampoline would leak memory */
5827 func = mono_compile_method (method);
5829 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5830 method = mono_object_get_virtual_method (target, method);
5831 func = mono_create_ftnptr (mono_domain_get (),
5832 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5835 mono_delegate_ctor_with_method (delegate, target, func, method);
5841 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5843 /* Reset the invoke impl to the default one */
5844 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5848 * Magic number to convert a time which is relative to
5849 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5851 #define EPOCH_ADJUST ((guint64)62135596800LL)
5854 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5856 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5859 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5861 convert_to_absolute_date(SYSTEMTIME *date)
5863 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5864 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5865 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5866 /* from the calendar FAQ */
5867 int a = (14 - date->wMonth) / 12;
5868 int y = date->wYear - a;
5869 int m = date->wMonth + 12 * a - 2;
5870 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5872 /* d is now the day of the week for the first of the month (0 == Sunday) */
5874 int day_of_week = date->wDayOfWeek;
5876 /* set day_in_month to the first day in the month which falls on day_of_week */
5877 int day_in_month = 1 + (day_of_week - d);
5878 if (day_in_month <= 0)
5881 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5882 date->wDay = day_in_month + (date->wDay - 1) * 7;
5883 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5890 * Return's the offset from GMT of a local time.
5892 * tm is a local time
5893 * t is the same local time as seconds.
5896 gmt_offset(struct tm *tm, time_t t)
5898 #if defined (HAVE_TM_GMTOFF)
5899 return tm->tm_gmtoff;
5904 g.tm_isdst = tm->tm_isdst;
5906 return (int)difftime(t, t2);
5911 * This is heavily based on zdump.c from glibc 2.2.
5913 * * data[0]: start of daylight saving time (in DateTime ticks).
5914 * * data[1]: end of daylight saving time (in DateTime ticks).
5915 * * data[2]: utcoffset (in TimeSpan ticks).
5916 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5917 * * name[0]: name of this timezone when not daylight saving.
5918 * * name[1]: name of this timezone when daylight saving.
5920 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5921 * the class library allows years between 1 and 9999.
5923 * Returns true on success and zero on failure.
5925 ICALL_EXPORT guint32
5926 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5929 MonoDomain *domain = mono_domain_get ();
5930 struct tm start, tt;
5933 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5934 int day, transitioned;
5937 gmtoff_st = gmtoff_ds = transitioned = 0;
5939 MONO_ARCH_SAVE_REGS;
5941 MONO_CHECK_ARG_NULL (data);
5942 MONO_CHECK_ARG_NULL (names);
5944 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5945 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5948 * no info is better than crashing: we'll need our own tz data
5949 * to make this work properly, anyway. The range is probably
5950 * reduced to 1970 .. 2037 because that is what mktime is
5951 * guaranteed to support (we get into an infinite loop
5955 memset (&start, 0, sizeof (start));
5958 start.tm_year = year-1900;
5960 t = mktime (&start);
5962 if ((year < 1970) || (year > 2037) || (t == -1)) {
5964 tt = *localtime (&t);
5965 strftime (tzone, sizeof (tzone), "%Z", &tt);
5966 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5967 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5971 gmtoff = gmt_offset (&start, t);
5973 /* For each day of the year, calculate the tm_gmtoff. */
5974 for (day = 0; day < 365 && transitioned < 2; day++) {
5977 tt = *localtime (&t);
5979 gmtoff_after = gmt_offset(&tt, t);
5981 /* Daylight saving starts or ends here. */
5982 if (gmtoff_after != gmtoff) {
5986 /* Try to find the exact hour when daylight saving starts/ends. */
5990 tt1 = *localtime (&t1);
5991 } while (gmt_offset (&tt1, t1) != gmtoff);
5993 /* Try to find the exact minute when daylight saving starts/ends. */
5996 tt1 = *localtime (&t1);
5997 } while (gmt_offset (&tt1, t1) == gmtoff);
5999 strftime (tzone, sizeof (tzone), "%Z", &tt);
6001 /* Write data, if we're already in daylight saving, we're done. */
6003 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6004 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6005 if (gmtoff_ds == 0) {
6007 gmtoff_ds = gmtoff_after;
6014 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6015 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6016 if (gmtoff_ds == 0) {
6017 gmtoff_st = gmtoff_after;
6023 /* This is only set once when we enter daylight saving. */
6025 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6026 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6028 gmtoff = gmt_offset (&tt, t);
6032 if (transitioned < 2) {
6033 strftime (tzone, sizeof (tzone), "%Z", &tt);
6034 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6035 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6036 mono_array_set ((*data), gint64, 0, 0);
6037 mono_array_set ((*data), gint64, 1, 0);
6038 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6039 mono_array_set ((*data), gint64, 3, 0);
6044 MonoDomain *domain = mono_domain_get ();
6045 TIME_ZONE_INFORMATION tz_info;
6050 tz_id = GetTimeZoneInformation (&tz_info);
6051 if (tz_id == TIME_ZONE_ID_INVALID)
6054 MONO_CHECK_ARG_NULL (data);
6055 MONO_CHECK_ARG_NULL (names);
6057 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6058 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6060 for (i = 0; i < 32; ++i)
6061 if (!tz_info.DaylightName [i])
6063 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6064 for (i = 0; i < 32; ++i)
6065 if (!tz_info.StandardName [i])
6067 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6069 if ((year <= 1601) || (year > 30827)) {
6071 * According to MSDN, the MS time functions can't handle dates outside
6077 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6078 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6079 tz_info.StandardDate.wYear = year;
6080 convert_to_absolute_date(&tz_info.StandardDate);
6081 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6086 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6087 tz_info.DaylightDate.wYear = year;
6088 convert_to_absolute_date(&tz_info.DaylightDate);
6089 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6094 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6096 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6097 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6103 ICALL_EXPORT gpointer
6104 ves_icall_System_Object_obj_address (MonoObject *this)
6106 MONO_ARCH_SAVE_REGS;
6113 static inline gint32
6114 mono_array_get_byte_length (MonoArray *array)
6120 klass = array->obj.vtable->klass;
6122 if (array->bounds == NULL)
6123 length = array->max_length;
6126 for (i = 0; i < klass->rank; ++ i)
6127 length *= array->bounds [i].length;
6130 switch (klass->element_class->byval_arg.type) {
6133 case MONO_TYPE_BOOLEAN:
6137 case MONO_TYPE_CHAR:
6145 return length * sizeof (gpointer);
6156 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6158 MONO_ARCH_SAVE_REGS;
6160 return mono_array_get_byte_length (array);
6164 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6166 MONO_ARCH_SAVE_REGS;
6168 return mono_array_get (array, gint8, idx);
6172 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6174 MONO_ARCH_SAVE_REGS;
6176 mono_array_set (array, gint8, idx, value);
6179 ICALL_EXPORT MonoBoolean
6180 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6182 guint8 *src_buf, *dest_buf;
6184 MONO_ARCH_SAVE_REGS;
6186 /* This is called directly from the class libraries without going through the managed wrapper */
6187 MONO_CHECK_ARG_NULL (src);
6188 MONO_CHECK_ARG_NULL (dest);
6190 /* watch out for integer overflow */
6191 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6194 src_buf = (guint8 *)src->vector + src_offset;
6195 dest_buf = (guint8 *)dest->vector + dest_offset;
6198 memcpy (dest_buf, src_buf, count);
6200 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6205 #ifndef DISABLE_REMOTING
6206 ICALL_EXPORT MonoObject *
6207 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6209 MonoDomain *domain = mono_object_domain (this);
6211 MonoRealProxy *rp = ((MonoRealProxy *)this);
6212 MonoTransparentProxy *tp;
6216 MONO_ARCH_SAVE_REGS;
6218 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6219 tp = (MonoTransparentProxy*) res;
6221 MONO_OBJECT_SETREF (tp, rp, rp);
6222 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6223 klass = mono_class_from_mono_type (type);
6225 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6226 tp->remote_class = mono_remote_class (domain, class_name, klass);
6228 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6232 ICALL_EXPORT MonoReflectionType *
6233 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6235 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6239 /* System.Environment */
6242 ves_icall_System_Environment_get_UserName (void)
6244 MONO_ARCH_SAVE_REGS;
6246 /* using glib is more portable */
6247 return mono_string_new (mono_domain_get (), g_get_user_name ());
6251 ICALL_EXPORT MonoString *
6252 ves_icall_System_Environment_get_MachineName (void)
6254 #if defined (HOST_WIN32)
6259 len = MAX_COMPUTERNAME_LENGTH + 1;
6260 buf = g_new (gunichar2, len);
6263 if (GetComputerName (buf, (PDWORD) &len))
6264 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6268 #elif !defined(DISABLE_SOCKETS)
6272 if (gethostname (buf, sizeof (buf)) == 0)
6273 result = mono_string_new (mono_domain_get (), buf);
6279 return mono_string_new (mono_domain_get (), "mono");
6284 ves_icall_System_Environment_get_Platform (void)
6286 #if defined (TARGET_WIN32)
6289 #elif defined(__MACH__)
6292 // Notice that the value is hidden from user code, and only exposed
6293 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6294 // define and making assumptions based on Unix/128/4 values before there
6295 // was a MacOS define. Lots of code would assume that not-Unix meant
6296 // Windows, but in this case, it would be OSX.
6305 ICALL_EXPORT MonoString *
6306 ves_icall_System_Environment_get_NewLine (void)
6308 MONO_ARCH_SAVE_REGS;
6310 #if defined (HOST_WIN32)
6311 return mono_string_new (mono_domain_get (), "\r\n");
6313 return mono_string_new (mono_domain_get (), "\n");
6317 ICALL_EXPORT MonoString *
6318 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6323 MONO_ARCH_SAVE_REGS;
6328 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6329 value = g_getenv (utf8_name);
6336 return mono_string_new (mono_domain_get (), value);
6340 * There is no standard way to get at environ.
6343 #ifndef __MINGW32_VERSION
6344 #if defined(__APPLE__) && !defined (__arm__)
6345 /* Apple defines this in crt_externs.h but doesn't provide that header for
6346 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6347 * in fact exist on all implementations (so far)
6349 gchar ***_NSGetEnviron(void);
6350 #define environ (*_NSGetEnviron())
6358 ICALL_EXPORT MonoArray *
6359 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6370 env_strings = GetEnvironmentStrings();
6373 env_string = env_strings;
6374 while (*env_string != '\0') {
6375 /* weird case that MS seems to skip */
6376 if (*env_string != '=')
6378 while (*env_string != '\0')
6384 domain = mono_domain_get ();
6385 names = mono_array_new (domain, mono_defaults.string_class, n);
6389 env_string = env_strings;
6390 while (*env_string != '\0') {
6391 /* weird case that MS seems to skip */
6392 if (*env_string != '=') {
6393 equal_str = wcschr(env_string, '=');
6394 g_assert(equal_str);
6395 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6396 mono_array_setref (names, n, str);
6399 while (*env_string != '\0')
6404 FreeEnvironmentStrings (env_strings);
6416 MONO_ARCH_SAVE_REGS;
6419 for (e = environ; *e != 0; ++ e)
6422 domain = mono_domain_get ();
6423 names = mono_array_new (domain, mono_defaults.string_class, n);
6426 for (e = environ; *e != 0; ++ e) {
6427 parts = g_strsplit (*e, "=", 2);
6429 str = mono_string_new (domain, *parts);
6430 mono_array_setref (names, n, str);
6443 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6445 #if !GLIB_CHECK_VERSION(2,4,0)
6446 #define g_setenv(a,b,c) setenv(a,b,c)
6447 #define g_unsetenv(a) unsetenv(a)
6451 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6456 gunichar2 *utf16_name, *utf16_value;
6458 gchar *utf8_name, *utf8_value;
6461 MONO_ARCH_SAVE_REGS;
6464 utf16_name = mono_string_to_utf16 (name);
6465 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6466 SetEnvironmentVariable (utf16_name, NULL);
6467 g_free (utf16_name);
6471 utf16_value = mono_string_to_utf16 (value);
6473 SetEnvironmentVariable (utf16_name, utf16_value);
6475 g_free (utf16_name);
6476 g_free (utf16_value);
6478 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6480 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6481 g_unsetenv (utf8_name);
6486 utf8_value = mono_string_to_utf8_checked (value, &error);
6487 if (!mono_error_ok (&error)) {
6489 mono_error_raise_exception (&error);
6491 g_setenv (utf8_name, utf8_value, TRUE);
6494 g_free (utf8_value);
6499 ves_icall_System_Environment_Exit (int result)
6501 MONO_ARCH_SAVE_REGS;
6503 mono_environment_exitcode_set (result);
6505 /* FIXME: There are some cleanup hangs that should be worked out, but
6506 * if the program is going to exit, everything will be cleaned up when
6507 * NaCl exits anyway.
6509 #ifndef __native_client__
6510 if (!mono_runtime_try_shutdown ())
6511 mono_thread_exit ();
6513 /* Suspend all managed threads since the runtime is going away */
6514 mono_thread_suspend_all_other_threads ();
6516 mono_runtime_quit ();
6519 /* we may need to do some cleanup here... */
6523 ICALL_EXPORT MonoString*
6524 ves_icall_System_Environment_GetGacPath (void)
6526 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6529 ICALL_EXPORT MonoString*
6530 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6532 #if defined (HOST_WIN32)
6533 #ifndef CSIDL_FLAG_CREATE
6534 #define CSIDL_FLAG_CREATE 0x8000
6537 WCHAR path [MAX_PATH];
6538 /* Create directory if no existing */
6539 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6543 return mono_string_new_utf16 (mono_domain_get (), path, len);
6546 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6548 return mono_string_new (mono_domain_get (), "");
6551 ICALL_EXPORT MonoArray *
6552 ves_icall_System_Environment_GetLogicalDrives (void)
6554 gunichar2 buf [256], *ptr, *dname;
6556 guint initial_size = 127, size = 128;
6559 MonoString *drivestr;
6560 MonoDomain *domain = mono_domain_get ();
6563 MONO_ARCH_SAVE_REGS;
6568 while (size > initial_size) {
6569 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6570 if (size > initial_size) {
6573 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6574 initial_size = size;
6588 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6593 while (*u16) { u16++; len ++; }
6594 drivestr = mono_string_new_utf16 (domain, dname, len);
6595 mono_array_setref (result, ndrives++, drivestr);
6605 ICALL_EXPORT MonoString *
6606 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6608 gunichar2 volume_name [MAX_PATH + 1];
6610 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6612 return mono_string_from_utf16 (volume_name);
6615 ICALL_EXPORT MonoString *
6616 ves_icall_System_Environment_InternalGetHome (void)
6618 MONO_ARCH_SAVE_REGS;
6620 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6623 static const char *encodings [] = {
6625 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6626 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6627 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6629 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6630 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6631 "x_unicode_2_0_utf_7",
6633 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6634 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6636 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6639 "unicodefffe", "utf_16be",
6646 * Returns the internal codepage, if the value of "int_code_page" is
6647 * 1 at entry, and we can not compute a suitable code page number,
6648 * returns the code page as a string
6650 ICALL_EXPORT MonoString*
6651 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6656 char *codepage = NULL;
6658 int want_name = *int_code_page;
6661 *int_code_page = -1;
6662 MONO_ARCH_SAVE_REGS;
6664 g_get_charset (&cset);
6665 c = codepage = strdup (cset);
6666 for (c = codepage; *c; c++){
6667 if (isascii (*c) && isalpha (*c))
6672 /* g_print ("charset: %s\n", cset); */
6674 /* handle some common aliases */
6677 for (i = 0; p != 0; ){
6678 if ((gssize) p < 7){
6680 p = encodings [++i];
6683 if (strcmp (p, codepage) == 0){
6684 *int_code_page = code;
6687 p = encodings [++i];
6690 if (strstr (codepage, "utf_8") != NULL)
6691 *int_code_page |= 0x10000000;
6694 if (want_name && *int_code_page == -1)
6695 return mono_string_new (mono_domain_get (), cset);
6700 ICALL_EXPORT MonoBoolean
6701 ves_icall_System_Environment_get_HasShutdownStarted (void)
6703 if (mono_runtime_is_shutting_down ())
6706 if (mono_domain_is_unloading (mono_domain_get ()))
6713 ves_icall_System_Environment_BroadcastSettingChange (void)
6716 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6721 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6722 MonoReflectionMethod *method,
6723 MonoArray *out_args)
6725 MONO_ARCH_SAVE_REGS;
6727 mono_message_init (mono_object_domain (this), this, method, out_args);
6730 #ifndef DISABLE_REMOTING
6731 ICALL_EXPORT MonoBoolean
6732 ves_icall_IsTransparentProxy (MonoObject *proxy)
6734 MONO_ARCH_SAVE_REGS;
6739 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6745 ICALL_EXPORT MonoReflectionMethod *
6746 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6747 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6751 MonoMethod **vtable;
6752 MonoMethod *res = NULL;
6754 MONO_CHECK_ARG_NULL (rtype);
6755 MONO_CHECK_ARG_NULL (rmethod);
6757 method = rmethod->method;
6758 klass = mono_class_from_mono_type (rtype->type);
6759 mono_class_init_or_throw (klass);
6761 if (MONO_CLASS_IS_INTERFACE (klass))
6764 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6767 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6768 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6774 mono_class_setup_vtable (klass);
6775 vtable = klass->vtable;
6777 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6778 gboolean variance_used = FALSE;
6779 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6780 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6782 res = vtable [offs + method->slot];
6784 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6787 if (method->slot != -1)
6788 res = vtable [method->slot];
6794 return mono_method_get_object (mono_domain_get (), res, NULL);
6798 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6803 MONO_ARCH_SAVE_REGS;
6805 klass = mono_class_from_mono_type (type->type);
6806 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6808 mono_vtable_set_is_remote (vtable, enable);
6811 #else /* DISABLE_REMOTING */
6814 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6816 g_assert_not_reached ();
6821 ICALL_EXPORT MonoObject *
6822 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6827 MONO_ARCH_SAVE_REGS;
6829 domain = mono_object_domain (type);
6830 klass = mono_class_from_mono_type (type->type);
6831 mono_class_init_or_throw (klass);
6833 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6834 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6836 if (klass->rank >= 1) {
6837 g_assert (klass->rank == 1);
6838 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6840 /* Bypass remoting object creation check */
6841 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6845 ICALL_EXPORT MonoString *
6846 ves_icall_System_IO_get_temp_path (void)
6848 MONO_ARCH_SAVE_REGS;
6850 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6853 #ifndef PLATFORM_NO_DRIVEINFO
6854 ICALL_EXPORT MonoBoolean
6855 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6856 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6860 ULARGE_INTEGER wapi_free_bytes_avail;
6861 ULARGE_INTEGER wapi_total_number_of_bytes;
6862 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6864 MONO_ARCH_SAVE_REGS;
6866 *error = ERROR_SUCCESS;
6867 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6868 &wapi_total_number_of_free_bytes);
6871 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6872 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6873 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6875 *free_bytes_avail = 0;
6876 *total_number_of_bytes = 0;
6877 *total_number_of_free_bytes = 0;
6878 *error = GetLastError ();
6884 ICALL_EXPORT guint32
6885 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6887 MONO_ARCH_SAVE_REGS;
6889 return GetDriveType (mono_string_chars (root_path_name));
6893 ICALL_EXPORT gpointer
6894 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6896 MONO_ARCH_SAVE_REGS;
6898 return mono_compile_method (method);
6901 ICALL_EXPORT MonoString *
6902 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6907 MONO_ARCH_SAVE_REGS;
6909 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6911 #if defined (HOST_WIN32)
6912 /* Avoid mixing '/' and '\\' */
6915 for (i = strlen (path) - 1; i >= 0; i--)
6916 if (path [i] == '/')
6920 mcpath = mono_string_new (mono_domain_get (), path);
6927 get_bundled_app_config (void)
6929 const gchar *app_config;
6932 gchar *config_file_name, *config_file_path;
6936 MONO_ARCH_SAVE_REGS;
6938 domain = mono_domain_get ();
6939 file = domain->setup->configuration_file;
6943 // Retrieve config file and remove the extension
6944 config_file_name = mono_string_to_utf8 (file);
6945 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6946 if (!config_file_path)
6947 config_file_path = config_file_name;
6948 len = strlen (config_file_path) - strlen (".config");
6949 module = g_malloc0 (len + 1);
6950 memcpy (module, config_file_path, len);
6951 // Get the config file from the module name
6952 app_config = mono_config_string_for_assembly_file (module);
6955 if (config_file_name != config_file_path)
6956 g_free (config_file_name);
6957 g_free (config_file_path);
6962 return mono_string_new (mono_domain_get (), app_config);
6966 get_bundled_machine_config (void)
6968 const gchar *machine_config;
6970 MONO_ARCH_SAVE_REGS;
6972 machine_config = mono_get_machine_config ();
6974 if (!machine_config)
6977 return mono_string_new (mono_domain_get (), machine_config);
6980 ICALL_EXPORT MonoString *
6981 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6986 MONO_ARCH_SAVE_REGS;
6988 path = g_path_get_dirname (mono_get_config_dir ());
6990 #if defined (HOST_WIN32)
6991 /* Avoid mixing '/' and '\\' */
6994 for (i = strlen (path) - 1; i >= 0; i--)
6995 if (path [i] == '/')
6999 ipath = mono_string_new (mono_domain_get (), path);
7005 ICALL_EXPORT gboolean
7006 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7008 MonoPEResourceDataEntry *entry;
7011 MONO_ARCH_SAVE_REGS;
7013 if (!assembly || !result || !size)
7018 image = assembly->assembly->image;
7019 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7023 *result = mono_image_rva_map (image, entry->rde_data_offset);
7028 *size = entry->rde_size;
7033 ICALL_EXPORT MonoBoolean
7034 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7036 return mono_is_debugger_attached ();
7039 ICALL_EXPORT MonoBoolean
7040 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7042 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7043 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7049 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7051 if (mono_get_runtime_callbacks ()->debug_log)
7052 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7056 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7058 #if defined (HOST_WIN32)
7059 OutputDebugString (mono_string_chars (message));
7061 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7065 /* Only used for value types */
7066 ICALL_EXPORT MonoObject *
7067 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7072 MONO_ARCH_SAVE_REGS;
7074 domain = mono_object_domain (type);
7075 klass = mono_class_from_mono_type (type->type);
7076 mono_class_init_or_throw (klass);
7078 if (mono_class_is_nullable (klass))
7079 /* No arguments -> null */
7082 return mono_object_new (domain, klass);
7085 ICALL_EXPORT MonoReflectionMethod *
7086 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7088 MonoClass *klass, *parent;
7089 MonoMethod *method = m->method;
7090 MonoMethod *result = NULL;
7093 MONO_ARCH_SAVE_REGS;
7095 if (method->klass == NULL)
7098 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7099 MONO_CLASS_IS_INTERFACE (method->klass) ||
7100 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7103 slot = mono_method_get_vtable_slot (method);
7107 klass = method->klass;
7108 if (klass->generic_class)
7109 klass = klass->generic_class->container_class;
7112 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7113 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7114 mono_class_setup_vtable (parent);
7115 if (parent->vtable_size <= slot)
7120 klass = klass->parent;
7125 if (klass == method->klass)
7128 /*This is possible if definition == FALSE.
7129 * Do it here to be really sure we don't read invalid memory.
7131 if (slot >= klass->vtable_size)
7134 mono_class_setup_vtable (klass);
7136 result = klass->vtable [slot];
7137 if (result == NULL) {
7138 /* It is an abstract method */
7139 gpointer iter = NULL;
7140 while ((result = mono_class_get_methods (klass, &iter)))
7141 if (result->slot == slot)
7148 return mono_method_get_object (mono_domain_get (), result, NULL);
7151 ICALL_EXPORT MonoString*
7152 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7154 MonoMethod *method = m->method;
7156 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7161 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7163 MONO_ARCH_SAVE_REGS;
7165 iter->sig = *(MonoMethodSignature**)argsp;
7167 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7168 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7171 /* FIXME: it's not documented what start is exactly... */
7175 iter->args = argsp + sizeof (gpointer);
7177 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7179 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7182 ICALL_EXPORT MonoTypedRef
7183 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7185 guint32 i, arg_size;
7188 MONO_ARCH_SAVE_REGS;
7190 i = iter->sig->sentinelpos + iter->next_arg;
7192 g_assert (i < iter->sig->param_count);
7194 res.type = iter->sig->params [i];
7195 res.klass = mono_class_from_mono_type (res.type);
7196 arg_size = mono_type_stack_size (res.type, &align);
7197 #if defined(__arm__) || defined(__mips__)
7198 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7200 res.value = iter->args;
7201 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7202 /* Values are stored as 8 byte register sized objects, but 'value'
7203 * is dereferenced as a pointer in other routines.
7205 res.value = (char*)res.value + 4;
7207 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7208 if (arg_size <= sizeof (gpointer)) {
7210 int padding = arg_size - mono_type_size (res.type, &dummy);
7211 res.value = (guint8*)res.value + padding;
7214 iter->args = (char*)iter->args + arg_size;
7217 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7222 ICALL_EXPORT MonoTypedRef
7223 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7225 guint32 i, arg_size;
7228 MONO_ARCH_SAVE_REGS;
7230 i = iter->sig->sentinelpos + iter->next_arg;
7232 g_assert (i < iter->sig->param_count);
7234 while (i < iter->sig->param_count) {
7235 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7237 res.type = iter->sig->params [i];
7238 res.klass = mono_class_from_mono_type (res.type);
7239 /* FIXME: endianess issue... */
7240 arg_size = mono_type_stack_size (res.type, &align);
7241 #if defined(__arm__) || defined(__mips__)
7242 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7244 res.value = iter->args;
7245 iter->args = (char*)iter->args + arg_size;
7247 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7250 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7258 ICALL_EXPORT MonoType*
7259 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7262 MONO_ARCH_SAVE_REGS;
7264 i = iter->sig->sentinelpos + iter->next_arg;
7266 g_assert (i < iter->sig->param_count);
7268 return iter->sig->params [i];
7271 ICALL_EXPORT MonoObject*
7272 mono_TypedReference_ToObject (MonoTypedRef tref)
7274 MONO_ARCH_SAVE_REGS;
7276 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7277 MonoObject** objp = tref.value;
7281 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7284 ICALL_EXPORT MonoObject*
7285 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7287 MONO_ARCH_SAVE_REGS;
7289 if (MONO_TYPE_IS_REFERENCE (type)) {
7290 MonoObject** objp = value;
7294 return mono_value_box (mono_domain_get (), klass, value);
7298 prelink_method (MonoMethod *method)
7300 const char *exc_class, *exc_arg;
7301 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7303 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7305 mono_raise_exception(
7306 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7308 /* create the wrapper, too? */
7312 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7314 MONO_ARCH_SAVE_REGS;
7315 prelink_method (method->method);
7319 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7321 MonoClass *klass = mono_class_from_mono_type (type->type);
7323 gpointer iter = NULL;
7324 MONO_ARCH_SAVE_REGS;
7326 mono_class_init_or_throw (klass);
7328 while ((m = mono_class_get_methods (klass, &iter)))
7332 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7334 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7335 gint32 const **exponents,
7336 gunichar2 const **digitLowerTable,
7337 gunichar2 const **digitUpperTable,
7338 gint64 const **tenPowersList,
7339 gint32 const **decHexDigits)
7341 *mantissas = Formatter_MantissaBitsTable;
7342 *exponents = Formatter_TensExponentTable;
7343 *digitLowerTable = Formatter_DigitLowerTable;
7344 *digitUpperTable = Formatter_DigitUpperTable;
7345 *tenPowersList = Formatter_TenPowersList;
7346 *decHexDigits = Formatter_DecHexDigits;
7350 get_category_data (int version,
7351 guint8 const **category_data,
7352 guint16 const **category_astral_index)
7354 *category_astral_index = NULL;
7356 #ifndef DISABLE_NET_4_0
7358 *category_data = CategoryData_v4;
7359 #ifndef DISABLE_ASTRAL
7360 *category_astral_index = CategoryData_v4_astral_index;
7366 *category_data = CategoryData_v2;
7367 #ifndef DISABLE_ASTRAL
7368 *category_astral_index = CategoryData_v2_astral_index;
7372 /* These parameters are "readonly" in corlib/System/Char.cs */
7374 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7375 guint8 const **category_data,
7376 guint16 const **category_astral_index,
7377 guint8 const **numeric_data,
7378 gdouble const **numeric_data_values,
7379 guint16 const **to_lower_data_low,
7380 guint16 const **to_lower_data_high,
7381 guint16 const **to_upper_data_low,
7382 guint16 const **to_upper_data_high)
7384 get_category_data (category_data_version, category_data, category_astral_index);
7385 *numeric_data = NumericData;
7386 *numeric_data_values = NumericDataValues;
7387 *to_lower_data_low = ToLowerDataLow;
7388 *to_lower_data_high = ToLowerDataHigh;
7389 *to_upper_data_low = ToUpperDataLow;
7390 *to_upper_data_high = ToUpperDataHigh;
7394 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7396 return method->method->token;
7400 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7401 * and avoid useless allocations.
7404 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7408 for (i = 0; i < type->num_mods; ++i) {
7409 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7414 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7416 for (i = 0; i < type->num_mods; ++i) {
7417 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7418 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7419 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7426 ICALL_EXPORT MonoArray*
7427 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7429 MonoType *type = param->ClassImpl->type;
7430 MonoClass *member_class = mono_object_class (param->MemberImpl);
7431 MonoMethod *method = NULL;
7434 MonoMethodSignature *sig;
7436 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7437 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7438 method = rmethod->method;
7439 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7440 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7441 if (!(method = prop->property->get))
7442 method = prop->property->set;
7445 char *type_name = mono_type_get_full_name (member_class);
7446 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7447 MonoException *ex = mono_get_exception_not_supported (msg);
7450 mono_raise_exception (ex);
7453 image = method->klass->image;
7454 pos = param->PositionImpl;
7455 sig = mono_method_signature (method);
7459 type = sig->params [pos];
7461 return type_array_from_modifiers (image, type, optional);
7465 get_property_type (MonoProperty *prop)
7467 MonoMethodSignature *sig;
7469 sig = mono_method_signature (prop->get);
7471 } else if (prop->set) {
7472 sig = mono_method_signature (prop->set);
7473 return sig->params [sig->param_count - 1];
7478 ICALL_EXPORT MonoArray*
7479 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7481 MonoType *type = get_property_type (property->property);
7482 MonoImage *image = property->klass->image;
7486 return type_array_from_modifiers (image, type, optional);
7490 *Construct a MonoType suited to be used to decode a constant blob object.
7492 * @type is the target type which will be constructed
7493 * @blob_type is the blob type, for example, that comes from the constant table
7494 * @real_type is the expected constructed type.
7497 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7499 type->type = blob_type;
7500 type->data.klass = NULL;
7501 if (blob_type == MONO_TYPE_CLASS)
7502 type->data.klass = mono_defaults.object_class;
7503 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7504 /* For enums, we need to use the base type */
7505 type->type = MONO_TYPE_VALUETYPE;
7506 type->data.klass = mono_class_from_mono_type (real_type);
7508 type->data.klass = mono_class_from_mono_type (real_type);
7511 ICALL_EXPORT MonoObject*
7512 property_info_get_default_value (MonoReflectionProperty *property)
7515 MonoProperty *prop = property->property;
7516 MonoType *type = get_property_type (prop);
7517 MonoDomain *domain = mono_object_domain (property);
7518 MonoTypeEnum def_type;
7519 const char *def_value;
7522 mono_class_init (prop->parent);
7524 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7525 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7527 def_value = mono_class_get_property_default_value (prop, &def_type);
7529 mono_type_from_blob_type (&blob_type, def_type, type);
7530 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7535 ICALL_EXPORT MonoBoolean
7536 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7538 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7539 MonoCustomAttrInfo *cinfo;
7542 mono_class_init_or_throw (attr_class);
7544 cinfo = mono_reflection_get_custom_attrs_info (obj);
7547 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7549 mono_custom_attrs_free (cinfo);
7553 ICALL_EXPORT MonoArray*
7554 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7556 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7561 mono_class_init_or_throw (attr_class);
7563 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7564 if (!mono_error_ok (&error))
7565 mono_error_raise_exception (&error);
7566 if (mono_loader_get_last_error ()) {
7567 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7568 g_assert_not_reached ();
7576 ICALL_EXPORT MonoString*
7577 ves_icall_Mono_Runtime_GetDisplayName (void)
7580 MonoString *display_name;
7582 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7583 display_name = mono_string_new (mono_domain_get (), info);
7585 return display_name;
7588 ICALL_EXPORT MonoString*
7589 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7591 MonoString *message;
7595 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7596 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7599 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7601 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7609 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7610 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7611 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7612 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7613 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7614 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7615 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7616 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7620 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7625 gunichar2 last, prev_last, prev2_last;
7632 int havePadding = 0;
7634 last = prev_last = 0, prev2_last = 0;
7635 for (i = 0; i < ilength; i++) {
7637 if (c >= sizeof (dbase64)) {
7638 exc = mono_exception_from_name_msg (mono_get_corlib (),
7639 "System", "FormatException",
7640 "Invalid character found.");
7641 mono_raise_exception (exc);
7642 } else if (isspace (c)) {
7644 } else if (havePadding && c != '=') {
7645 exc = mono_exception_from_name_msg (mono_get_corlib (),
7646 "System", "FormatException",
7647 "Invalid character found.");
7648 mono_raise_exception (exc);
7650 if (c == '=') havePadding = 1;
7651 prev2_last = prev_last;
7657 olength = ilength - ignored;
7659 if (allowWhitespaceOnly && olength == 0) {
7660 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7663 if ((olength & 3) != 0 || olength <= 0) {
7664 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7665 "FormatException", "Invalid length.");
7666 mono_raise_exception (exc);
7669 if (prev2_last == '=') {
7670 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7671 mono_raise_exception (exc);
7674 olength = (olength * 3) / 4;
7678 if (prev_last == '=')
7681 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7682 res_ptr = mono_array_addr (result, guchar, 0);
7683 for (i = 0; i < ilength; ) {
7686 for (k = 0; k < 4 && i < ilength;) {
7692 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7693 exc = mono_exception_from_name_msg (mono_get_corlib (),
7694 "System", "FormatException",
7695 "Invalid character found.");
7696 mono_raise_exception (exc);
7701 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7703 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7705 *res_ptr++ = (b [2] << 6) | b [3];
7707 while (i < ilength && isspace (start [i]))
7714 ICALL_EXPORT MonoArray *
7715 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7717 MONO_ARCH_SAVE_REGS;
7719 return base64_to_byte_array (mono_string_chars (str),
7720 mono_string_length (str), allowWhitespaceOnly);
7723 ICALL_EXPORT MonoArray *
7724 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7726 MONO_ARCH_SAVE_REGS;
7728 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7732 #ifndef DISABLE_ICALL_TABLES
7734 #define ICALL_TYPE(id,name,first)
7735 #define ICALL(id,name,func) Icall_ ## id,
7738 #include "metadata/icall-def.h"
7744 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7745 #define ICALL(id,name,func)
7747 #include "metadata/icall-def.h"
7753 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7754 #define ICALL(id,name,func)
7756 guint16 first_icall;
7759 static const IcallTypeDesc
7760 icall_type_descs [] = {
7761 #include "metadata/icall-def.h"
7765 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7768 #define ICALL_TYPE(id,name,first)
7771 #ifdef HAVE_ARRAY_ELEM_INIT
7772 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7773 #define MSGSTRFIELD1(line) str##line
7775 static const struct msgstrtn_t {
7776 #define ICALL(id,name,func)
7778 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7779 #include "metadata/icall-def.h"
7781 } icall_type_names_str = {
7782 #define ICALL_TYPE(id,name,first) (name),
7783 #include "metadata/icall-def.h"
7786 static const guint16 icall_type_names_idx [] = {
7787 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7788 #include "metadata/icall-def.h"
7791 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7793 static const struct msgstr_t {
7795 #define ICALL_TYPE(id,name,first)
7796 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7797 #include "metadata/icall-def.h"
7799 } icall_names_str = {
7800 #define ICALL(id,name,func) (name),
7801 #include "metadata/icall-def.h"
7804 static const guint16 icall_names_idx [] = {
7805 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7806 #include "metadata/icall-def.h"
7809 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7815 #define ICALL_TYPE(id,name,first) name,
7816 #define ICALL(id,name,func)
7817 static const char* const
7818 icall_type_names [] = {
7819 #include "metadata/icall-def.h"
7823 #define icall_type_name_get(id) (icall_type_names [(id)])
7827 #define ICALL_TYPE(id,name,first)
7828 #define ICALL(id,name,func) name,
7829 static const char* const
7831 #include "metadata/icall-def.h"
7834 #define icall_name_get(id) icall_names [(id)]
7836 #endif /* !HAVE_ARRAY_ELEM_INIT */
7840 #define ICALL_TYPE(id,name,first)
7841 #define ICALL(id,name,func) func,
7842 static const gconstpointer
7843 icall_functions [] = {
7844 #include "metadata/icall-def.h"
7848 #ifdef ENABLE_ICALL_SYMBOL_MAP
7851 #define ICALL_TYPE(id,name,first)
7852 #define ICALL(id,name,func) #func,
7853 static const gconstpointer
7854 icall_symbols [] = {
7855 #include "metadata/icall-def.h"
7860 #endif /* DISABLE_ICALL_TABLES */
7862 static GHashTable *icall_hash = NULL;
7863 static GHashTable *jit_icall_hash_name = NULL;
7864 static GHashTable *jit_icall_hash_addr = NULL;
7867 mono_icall_init (void)
7869 #ifndef DISABLE_ICALL_TABLES
7872 /* check that tables are sorted: disable in release */
7875 const char *prev_class = NULL;
7876 const char *prev_method;
7878 for (i = 0; i < Icall_type_num; ++i) {
7879 const IcallTypeDesc *desc;
7882 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7883 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7884 prev_class = icall_type_name_get (i);
7885 desc = &icall_type_descs [i];
7886 num_icalls = icall_desc_num_icalls (desc);
7887 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7888 for (j = 0; j < num_icalls; ++j) {
7889 const char *methodn = icall_name_get (desc->first_icall + j);
7890 if (prev_method && strcmp (prev_method, methodn) >= 0)
7891 g_print ("method %s should come before method %s\n", methodn, prev_method);
7892 prev_method = methodn;
7898 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7902 mono_icall_cleanup (void)
7904 g_hash_table_destroy (icall_hash);
7905 g_hash_table_destroy (jit_icall_hash_name);
7906 g_hash_table_destroy (jit_icall_hash_addr);
7910 mono_add_internal_call (const char *name, gconstpointer method)
7912 mono_loader_lock ();
7914 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7916 mono_loader_unlock ();
7919 #ifndef DISABLE_ICALL_TABLES
7921 #ifdef HAVE_ARRAY_ELEM_INIT
7923 compare_method_imap (const void *key, const void *elem)
7925 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7926 return strcmp (key, method_name);
7930 find_method_icall (const IcallTypeDesc *imap, const char *name)
7932 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);
7935 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7939 compare_class_imap (const void *key, const void *elem)
7941 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7942 return strcmp (key, class_name);
7945 static const IcallTypeDesc*
7946 find_class_icalls (const char *name)
7948 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7951 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7954 #else /* HAVE_ARRAY_ELEM_INIT */
7957 compare_method_imap (const void *key, const void *elem)
7959 const char** method_name = (const char**)elem;
7960 return strcmp (key, *method_name);
7964 find_method_icall (const IcallTypeDesc *imap, const char *name)
7966 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7969 return (gpointer)icall_functions [(nameslot - icall_names)];
7973 compare_class_imap (const void *key, const void *elem)
7975 const char** class_name = (const char**)elem;
7976 return strcmp (key, *class_name);
7979 static const IcallTypeDesc*
7980 find_class_icalls (const char *name)
7982 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7985 return &icall_type_descs [nameslot - icall_type_names];
7988 #endif /* HAVE_ARRAY_ELEM_INIT */
7990 #endif /* DISABLE_ICALL_TABLES */
7993 * we should probably export this as an helper (handle nested types).
7994 * Returns the number of chars written in buf.
7997 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7999 int nspacelen, cnamelen;
8000 nspacelen = strlen (klass->name_space);
8001 cnamelen = strlen (klass->name);
8002 if (nspacelen + cnamelen + 2 > bufsize)
8005 memcpy (buf, klass->name_space, nspacelen);
8006 buf [nspacelen ++] = '.';
8008 memcpy (buf + nspacelen, klass->name, cnamelen);
8009 buf [nspacelen + cnamelen] = 0;
8010 return nspacelen + cnamelen;
8013 #ifdef DISABLE_ICALL_TABLES
8015 no_icall_table (void)
8017 g_assert_not_reached ();
8022 mono_lookup_internal_call (MonoMethod *method)
8027 int typelen = 0, mlen, siglen;
8029 #ifndef DISABLE_ICALL_TABLES
8030 const IcallTypeDesc *imap = NULL;
8033 g_assert (method != NULL);
8035 if (method->is_inflated)
8036 method = ((MonoMethodInflated *) method)->declaring;
8038 if (method->klass->nested_in) {
8039 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8043 mname [pos++] = '/';
8046 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8052 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8057 #ifndef DISABLE_ICALL_TABLES
8058 imap = find_class_icalls (mname);
8061 mname [typelen] = ':';
8062 mname [typelen + 1] = ':';
8064 mlen = strlen (method->name);
8065 memcpy (mname + typelen + 2, method->name, mlen);
8066 sigstart = mname + typelen + 2 + mlen;
8069 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8070 siglen = strlen (tmpsig);
8071 if (typelen + mlen + siglen + 6 > sizeof (mname))
8074 memcpy (sigstart + 1, tmpsig, siglen);
8075 sigstart [siglen + 1] = ')';
8076 sigstart [siglen + 2] = 0;
8079 mono_loader_lock ();
8081 res = g_hash_table_lookup (icall_hash, mname);
8083 mono_loader_unlock ();
8086 /* try without signature */
8088 res = g_hash_table_lookup (icall_hash, mname);
8090 mono_loader_unlock ();
8094 #ifdef DISABLE_ICALL_TABLES
8095 mono_loader_unlock ();
8096 /* Fail only when the result is actually used */
8097 /* mono_marshal_get_native_wrapper () depends on this */
8098 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8099 return ves_icall_System_String_ctor_RedirectToCreateString;
8101 return no_icall_table;
8103 /* it wasn't found in the static call tables */
8105 mono_loader_unlock ();
8108 res = find_method_icall (imap, sigstart - mlen);
8110 mono_loader_unlock ();
8113 /* try _with_ signature */
8115 res = find_method_icall (imap, sigstart - mlen);
8117 mono_loader_unlock ();
8121 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8122 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8123 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8124 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8125 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");
8126 g_print ("If you see other errors or faults after this message they are probably related\n");
8127 g_print ("and you need to fix your mono install first.\n");
8129 mono_loader_unlock ();
8135 #ifdef ENABLE_ICALL_SYMBOL_MAP
8137 func_cmp (gconstpointer key, gconstpointer p)
8139 return (gsize)key - (gsize)*(gsize*)p;
8144 * mono_lookup_icall_symbol:
8146 * Given the icall METHOD, returns its C symbol.
8149 mono_lookup_icall_symbol (MonoMethod *m)
8151 #ifdef DISABLE_ICALL_TABLES
8152 g_assert_not_reached ();
8155 #ifdef ENABLE_ICALL_SYMBOL_MAP
8159 static gconstpointer *functions_sorted;
8160 static const char**symbols_sorted;
8161 static gboolean inited;
8166 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8167 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8168 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8169 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8170 /* Bubble sort the two arrays */
8174 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8175 if (functions_sorted [i] > functions_sorted [i + 1]) {
8178 tmp = functions_sorted [i];
8179 functions_sorted [i] = functions_sorted [i + 1];
8180 functions_sorted [i + 1] = tmp;
8181 tmp = symbols_sorted [i];
8182 symbols_sorted [i] = symbols_sorted [i + 1];
8183 symbols_sorted [i + 1] = tmp;
8190 func = mono_lookup_internal_call (m);
8193 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8197 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8199 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8200 g_assert_not_reached ();
8207 type_from_typename (char *typename)
8209 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8211 if (!strcmp (typename, "int"))
8212 klass = mono_defaults.int_class;
8213 else if (!strcmp (typename, "ptr"))
8214 klass = mono_defaults.int_class;
8215 else if (!strcmp (typename, "void"))
8216 klass = mono_defaults.void_class;
8217 else if (!strcmp (typename, "int32"))
8218 klass = mono_defaults.int32_class;
8219 else if (!strcmp (typename, "uint32"))
8220 klass = mono_defaults.uint32_class;
8221 else if (!strcmp (typename, "int8"))
8222 klass = mono_defaults.sbyte_class;
8223 else if (!strcmp (typename, "uint8"))
8224 klass = mono_defaults.byte_class;
8225 else if (!strcmp (typename, "int16"))
8226 klass = mono_defaults.int16_class;
8227 else if (!strcmp (typename, "uint16"))
8228 klass = mono_defaults.uint16_class;
8229 else if (!strcmp (typename, "long"))
8230 klass = mono_defaults.int64_class;
8231 else if (!strcmp (typename, "ulong"))
8232 klass = mono_defaults.uint64_class;
8233 else if (!strcmp (typename, "float"))
8234 klass = mono_defaults.single_class;
8235 else if (!strcmp (typename, "double"))
8236 klass = mono_defaults.double_class;
8237 else if (!strcmp (typename, "object"))
8238 klass = mono_defaults.object_class;
8239 else if (!strcmp (typename, "obj"))
8240 klass = mono_defaults.object_class;
8241 else if (!strcmp (typename, "string"))
8242 klass = mono_defaults.string_class;
8243 else if (!strcmp (typename, "bool"))
8244 klass = mono_defaults.boolean_class;
8245 else if (!strcmp (typename, "boolean"))
8246 klass = mono_defaults.boolean_class;
8248 g_error ("%s", typename);
8249 g_assert_not_reached ();
8251 return &klass->byval_arg;
8254 MonoMethodSignature*
8255 mono_create_icall_signature (const char *sigstr)
8260 MonoMethodSignature *res;
8262 mono_loader_lock ();
8263 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8265 mono_loader_unlock ();
8269 parts = g_strsplit (sigstr, " ", 256);
8278 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8283 * Under windows, the default pinvoke calling convention is STDCALL but
8286 res->call_convention = MONO_CALL_C;
8289 res->ret = type_from_typename (parts [0]);
8290 for (i = 1; i < len; ++i) {
8291 res->params [i - 1] = type_from_typename (parts [i]);
8296 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8298 mono_loader_unlock ();
8304 mono_find_jit_icall_by_name (const char *name)
8306 MonoJitICallInfo *info;
8307 g_assert (jit_icall_hash_name);
8309 mono_loader_lock ();
8310 info = g_hash_table_lookup (jit_icall_hash_name, name);
8311 mono_loader_unlock ();
8316 mono_find_jit_icall_by_addr (gconstpointer addr)
8318 MonoJitICallInfo *info;
8319 g_assert (jit_icall_hash_addr);
8321 mono_loader_lock ();
8322 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8323 mono_loader_unlock ();
8329 * mono_get_jit_icall_info:
8331 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8332 * caller should access it while holding the loader lock.
8335 mono_get_jit_icall_info (void)
8337 return jit_icall_hash_name;
8341 * mono_lookup_jit_icall_symbol:
8343 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8346 mono_lookup_jit_icall_symbol (const char *name)
8348 MonoJitICallInfo *info;
8349 const char *res = NULL;
8351 mono_loader_lock ();
8352 info = g_hash_table_lookup (jit_icall_hash_name, name);
8354 res = info->c_symbol;
8355 mono_loader_unlock ();
8360 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8362 mono_loader_lock ();
8363 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8364 mono_loader_unlock ();
8368 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8370 MonoJitICallInfo *info;
8375 mono_loader_lock ();
8377 if (!jit_icall_hash_name) {
8378 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8379 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8382 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8383 g_warning ("jit icall already defined \"%s\"\n", name);
8384 g_assert_not_reached ();
8387 info = g_new0 (MonoJitICallInfo, 1);
8392 info->c_symbol = c_symbol;
8395 info->wrapper = func;
8397 info->wrapper = NULL;
8400 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8401 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8403 mono_loader_unlock ();
8408 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8410 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);