Merge pull request #3734 from kumpera/monoclass_reorg
[mono-project.git] / mono / metadata / icall.c
blob0f54ea16dc0211be3e891e3d9e1a30d0e57cd9c1
1 /*
2 * icall.c:
4 * Authors:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
17 #include <config.h>
18 #include <glib.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <ctype.h>
22 #ifdef HAVE_ALLOCA_H
23 #include <alloca.h>
24 #endif
25 #ifdef HAVE_SYS_TIME_H
26 #include <sys/time.h>
27 #endif
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #if defined (HAVE_WCHAR_H)
32 #include <wchar.h>
33 #endif
34 #include "mono/metadata/icall-internals.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-ms.h>
40 #include <mono/metadata/threadpool-ms-io.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/image-internals.h>
44 #include <mono/metadata/assembly.h>
45 #include <mono/metadata/assembly-internals.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/exception-internals.h>
49 #include <mono/metadata/file-io.h>
50 #include <mono/metadata/console-io.h>
51 #include <mono/metadata/mono-route.h>
52 #include <mono/metadata/socket-io.h>
53 #include <mono/metadata/mono-endian.h>
54 #include <mono/metadata/tokentype.h>
55 #include <mono/metadata/domain-internals.h>
56 #include <mono/metadata/metadata-internals.h>
57 #include <mono/metadata/class-internals.h>
58 #include <mono/metadata/reflection-internals.h>
59 #include <mono/metadata/marshal.h>
60 #include <mono/metadata/gc-internals.h>
61 #include <mono/metadata/mono-gc.h>
62 #include <mono/metadata/rand.h>
63 #include <mono/metadata/sysmath.h>
64 #include <mono/metadata/string-icalls.h>
65 #include <mono/metadata/debug-helpers.h>
66 #include <mono/metadata/w32process.h>
67 #include <mono/metadata/environment.h>
68 #include <mono/metadata/profiler-private.h>
69 #include <mono/metadata/locales.h>
70 #include <mono/metadata/filewatcher.h>
71 #include <mono/metadata/security.h>
72 #include <mono/metadata/mono-config.h>
73 #include <mono/metadata/cil-coff.h>
74 #include <mono/metadata/number-formatter.h>
75 #include <mono/metadata/security-manager.h>
76 #include <mono/metadata/security-core-clr.h>
77 #include <mono/metadata/mono-perfcounters.h>
78 #include <mono/metadata/mono-debug.h>
79 #include <mono/metadata/mono-ptr-array.h>
80 #include <mono/metadata/verify-internals.h>
81 #include <mono/metadata/runtime.h>
82 #include <mono/metadata/file-mmap.h>
83 #include <mono/metadata/seq-points-data.h>
84 #include <mono/metadata/handle.h>
85 #include <mono/metadata/w32mutex.h>
86 #include <mono/metadata/w32semaphore.h>
87 #include <mono/metadata/w32event.h>
88 #include <mono/io-layer/io-layer.h>
89 #include <mono/utils/monobitset.h>
90 #include <mono/utils/mono-time.h>
91 #include <mono/utils/mono-proclib.h>
92 #include <mono/utils/mono-string.h>
93 #include <mono/utils/mono-error-internals.h>
94 #include <mono/utils/mono-mmap.h>
95 #include <mono/utils/mono-io-portability.h>
96 #include <mono/utils/mono-digest.h>
97 #include <mono/utils/bsearch.h>
98 #include <mono/utils/mono-os-mutex.h>
99 #include <mono/utils/mono-threads.h>
101 #include "decimal-ms.h"
102 #include "number-ms.h"
104 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
105 #include <sys/utsname.h>
106 #endif
108 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
110 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 /* Lazy class loading functions */
113 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
114 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
115 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
120 static MonoArray*
121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
123 static inline MonoBoolean
124 is_generic_parameter (MonoType *type)
126 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
129 static void
130 mono_class_init_checked (MonoClass *klass, MonoError *error)
132 mono_error_init (error);
134 if (!mono_class_init (klass))
135 mono_error_set_for_class_failure (error, klass);
138 #ifndef HOST_WIN32
139 static inline void
140 mono_icall_make_platform_path (gchar *path)
142 return;
145 static inline const gchar *
146 mono_icall_get_file_path_prefix (const gchar *path)
148 return "file://";
150 #endif /* HOST_WIN32 */
152 ICALL_EXPORT MonoObject *
153 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
155 MonoError error;
156 MonoClass *ac;
157 gint32 esize;
158 gpointer *ea;
159 MonoObject *result = NULL;
161 ac = (MonoClass *)arr->obj.vtable->klass;
163 esize = mono_array_element_size (ac);
164 ea = (gpointer*)((char*)arr->vector + (pos * esize));
166 if (ac->element_class->valuetype) {
167 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
168 mono_error_set_pending_exception (&error);
169 } else
170 result = (MonoObject *)*ea;
171 return result;
174 ICALL_EXPORT MonoObject *
175 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
177 MonoClass *ac, *ic;
178 MonoArray *io;
179 gint32 i, pos, *ind;
181 MONO_CHECK_ARG_NULL (idxs, NULL);
183 io = idxs;
184 ic = (MonoClass *)io->obj.vtable->klass;
186 ac = (MonoClass *)arr->obj.vtable->klass;
188 g_assert (ic->rank == 1);
189 if (io->bounds != NULL || io->max_length != ac->rank) {
190 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
191 return NULL;
194 ind = (gint32 *)io->vector;
196 if (arr->bounds == NULL) {
197 if (*ind < 0 || *ind >= arr->max_length) {
198 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
199 return NULL;
202 return ves_icall_System_Array_GetValueImpl (arr, *ind);
205 for (i = 0; i < ac->rank; i++) {
206 if ((ind [i] < arr->bounds [i].lower_bound) ||
207 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
208 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
209 return NULL;
213 pos = ind [0] - arr->bounds [0].lower_bound;
214 for (i = 1; i < ac->rank; i++)
215 pos = pos * arr->bounds [i].length + ind [i] -
216 arr->bounds [i].lower_bound;
218 return ves_icall_System_Array_GetValueImpl (arr, pos);
221 ICALL_EXPORT void
222 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
224 MonoError error;
225 MonoClass *ac, *vc, *ec;
226 gint32 esize, vsize;
227 gpointer *ea, *va;
228 int et, vt;
230 guint64 u64 = 0;
231 gint64 i64 = 0;
232 gdouble r64 = 0;
234 mono_error_init (&error);
236 if (value)
237 vc = value->vtable->klass;
238 else
239 vc = NULL;
241 ac = arr->obj.vtable->klass;
242 ec = ac->element_class;
244 esize = mono_array_element_size (ac);
245 ea = (gpointer*)((char*)arr->vector + (pos * esize));
246 va = (gpointer*)((char*)value + sizeof (MonoObject));
248 if (mono_class_is_nullable (ec)) {
249 mono_nullable_init ((guint8*)ea, value, ec);
250 return;
253 if (!value) {
254 mono_gc_bzero_atomic (ea, esize);
255 return;
258 #define NO_WIDENING_CONVERSION G_STMT_START{\
259 mono_set_pending_exception (mono_get_exception_argument ( \
260 "value", "not a widening conversion")); \
261 return; \
262 }G_STMT_END
264 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
265 if (esize < vsize + (extra)) { \
266 mono_set_pending_exception (mono_get_exception_argument ( \
267 "value", "not a widening conversion")); \
268 return; \
270 }G_STMT_END
272 #define INVALID_CAST G_STMT_START{ \
273 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
274 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
275 return; \
276 }G_STMT_END
278 /* Check element (destination) type. */
279 switch (ec->byval_arg.type) {
280 case MONO_TYPE_STRING:
281 switch (vc->byval_arg.type) {
282 case MONO_TYPE_STRING:
283 break;
284 default:
285 INVALID_CAST;
287 break;
288 case MONO_TYPE_BOOLEAN:
289 switch (vc->byval_arg.type) {
290 case MONO_TYPE_BOOLEAN:
291 break;
292 case MONO_TYPE_CHAR:
293 case MONO_TYPE_U1:
294 case MONO_TYPE_U2:
295 case MONO_TYPE_U4:
296 case MONO_TYPE_U8:
297 case MONO_TYPE_I1:
298 case MONO_TYPE_I2:
299 case MONO_TYPE_I4:
300 case MONO_TYPE_I8:
301 case MONO_TYPE_R4:
302 case MONO_TYPE_R8:
303 NO_WIDENING_CONVERSION;
304 default:
305 INVALID_CAST;
307 break;
308 default:
309 break;
312 if (!ec->valuetype) {
313 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
314 if (mono_error_set_pending_exception (&error))
315 return;
316 if (!castOk)
317 INVALID_CAST;
318 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
319 return;
322 if (mono_object_isinst_checked (value, ec, &error)) {
323 if (ec->has_references)
324 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
325 else
326 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
327 return;
329 if (mono_error_set_pending_exception (&error))
330 return;
332 if (!vc->valuetype)
333 INVALID_CAST;
335 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
337 et = ec->byval_arg.type;
338 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
339 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
341 vt = vc->byval_arg.type;
342 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
343 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
345 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
346 switch (vt) { \
347 case MONO_TYPE_U1: \
348 case MONO_TYPE_U2: \
349 case MONO_TYPE_U4: \
350 case MONO_TYPE_U8: \
351 case MONO_TYPE_CHAR: \
352 CHECK_WIDENING_CONVERSION(0); \
353 *(etype *) ea = (etype) u64; \
354 return; \
355 /* You can't assign a signed value to an unsigned array. */ \
356 case MONO_TYPE_I1: \
357 case MONO_TYPE_I2: \
358 case MONO_TYPE_I4: \
359 case MONO_TYPE_I8: \
360 /* You can't assign a floating point number to an integer array. */ \
361 case MONO_TYPE_R4: \
362 case MONO_TYPE_R8: \
363 NO_WIDENING_CONVERSION; \
365 }G_STMT_END
367 #define ASSIGN_SIGNED(etype) G_STMT_START{\
368 switch (vt) { \
369 case MONO_TYPE_I1: \
370 case MONO_TYPE_I2: \
371 case MONO_TYPE_I4: \
372 case MONO_TYPE_I8: \
373 CHECK_WIDENING_CONVERSION(0); \
374 *(etype *) ea = (etype) i64; \
375 return; \
376 /* You can assign an unsigned value to a signed array if the array's */ \
377 /* element size is larger than the value size. */ \
378 case MONO_TYPE_U1: \
379 case MONO_TYPE_U2: \
380 case MONO_TYPE_U4: \
381 case MONO_TYPE_U8: \
382 case MONO_TYPE_CHAR: \
383 CHECK_WIDENING_CONVERSION(1); \
384 *(etype *) ea = (etype) u64; \
385 return; \
386 /* You can't assign a floating point number to an integer array. */ \
387 case MONO_TYPE_R4: \
388 case MONO_TYPE_R8: \
389 NO_WIDENING_CONVERSION; \
391 }G_STMT_END
393 #define ASSIGN_REAL(etype) G_STMT_START{\
394 switch (vt) { \
395 case MONO_TYPE_R4: \
396 case MONO_TYPE_R8: \
397 CHECK_WIDENING_CONVERSION(0); \
398 *(etype *) ea = (etype) r64; \
399 return; \
400 /* All integer values fit into a floating point array, so we don't */ \
401 /* need to CHECK_WIDENING_CONVERSION here. */ \
402 case MONO_TYPE_I1: \
403 case MONO_TYPE_I2: \
404 case MONO_TYPE_I4: \
405 case MONO_TYPE_I8: \
406 *(etype *) ea = (etype) i64; \
407 return; \
408 case MONO_TYPE_U1: \
409 case MONO_TYPE_U2: \
410 case MONO_TYPE_U4: \
411 case MONO_TYPE_U8: \
412 case MONO_TYPE_CHAR: \
413 *(etype *) ea = (etype) u64; \
414 return; \
416 }G_STMT_END
418 switch (vt) {
419 case MONO_TYPE_U1:
420 u64 = *(guint8 *) va;
421 break;
422 case MONO_TYPE_U2:
423 u64 = *(guint16 *) va;
424 break;
425 case MONO_TYPE_U4:
426 u64 = *(guint32 *) va;
427 break;
428 case MONO_TYPE_U8:
429 u64 = *(guint64 *) va;
430 break;
431 case MONO_TYPE_I1:
432 i64 = *(gint8 *) va;
433 break;
434 case MONO_TYPE_I2:
435 i64 = *(gint16 *) va;
436 break;
437 case MONO_TYPE_I4:
438 i64 = *(gint32 *) va;
439 break;
440 case MONO_TYPE_I8:
441 i64 = *(gint64 *) va;
442 break;
443 case MONO_TYPE_R4:
444 r64 = *(gfloat *) va;
445 break;
446 case MONO_TYPE_R8:
447 r64 = *(gdouble *) va;
448 break;
449 case MONO_TYPE_CHAR:
450 u64 = *(guint16 *) va;
451 break;
452 case MONO_TYPE_BOOLEAN:
453 /* Boolean is only compatible with itself. */
454 switch (et) {
455 case MONO_TYPE_CHAR:
456 case MONO_TYPE_U1:
457 case MONO_TYPE_U2:
458 case MONO_TYPE_U4:
459 case MONO_TYPE_U8:
460 case MONO_TYPE_I1:
461 case MONO_TYPE_I2:
462 case MONO_TYPE_I4:
463 case MONO_TYPE_I8:
464 case MONO_TYPE_R4:
465 case MONO_TYPE_R8:
466 NO_WIDENING_CONVERSION;
467 default:
468 INVALID_CAST;
470 break;
473 /* If we can't do a direct copy, let's try a widening conversion. */
474 switch (et) {
475 case MONO_TYPE_CHAR:
476 ASSIGN_UNSIGNED (guint16);
477 case MONO_TYPE_U1:
478 ASSIGN_UNSIGNED (guint8);
479 case MONO_TYPE_U2:
480 ASSIGN_UNSIGNED (guint16);
481 case MONO_TYPE_U4:
482 ASSIGN_UNSIGNED (guint32);
483 case MONO_TYPE_U8:
484 ASSIGN_UNSIGNED (guint64);
485 case MONO_TYPE_I1:
486 ASSIGN_SIGNED (gint8);
487 case MONO_TYPE_I2:
488 ASSIGN_SIGNED (gint16);
489 case MONO_TYPE_I4:
490 ASSIGN_SIGNED (gint32);
491 case MONO_TYPE_I8:
492 ASSIGN_SIGNED (gint64);
493 case MONO_TYPE_R4:
494 ASSIGN_REAL (gfloat);
495 case MONO_TYPE_R8:
496 ASSIGN_REAL (gdouble);
499 INVALID_CAST;
500 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
501 return;
503 #undef INVALID_CAST
504 #undef NO_WIDENING_CONVERSION
505 #undef CHECK_WIDENING_CONVERSION
506 #undef ASSIGN_UNSIGNED
507 #undef ASSIGN_SIGNED
508 #undef ASSIGN_REAL
511 ICALL_EXPORT void
512 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
513 MonoArray *idxs)
515 MonoClass *ac, *ic;
516 gint32 i, pos, *ind;
518 MONO_CHECK_ARG_NULL (idxs,);
520 ic = idxs->obj.vtable->klass;
521 ac = arr->obj.vtable->klass;
523 g_assert (ic->rank == 1);
524 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
525 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
526 return;
529 ind = (gint32 *)idxs->vector;
531 if (arr->bounds == NULL) {
532 if (*ind < 0 || *ind >= arr->max_length) {
533 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
534 return;
537 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
538 return;
541 for (i = 0; i < ac->rank; i++)
542 if ((ind [i] < arr->bounds [i].lower_bound) ||
543 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
544 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
545 return;
548 pos = ind [0] - arr->bounds [0].lower_bound;
549 for (i = 1; i < ac->rank; i++)
550 pos = pos * arr->bounds [i].length + ind [i] -
551 arr->bounds [i].lower_bound;
553 ves_icall_System_Array_SetValueImpl (arr, value, pos);
556 ICALL_EXPORT MonoArray *
557 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
559 MonoError error;
560 MonoClass *aklass, *klass;
561 MonoArray *array;
562 uintptr_t *sizes, i;
563 gboolean bounded = FALSE;
565 MONO_CHECK_ARG_NULL (type, NULL);
566 MONO_CHECK_ARG_NULL (lengths, NULL);
568 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
569 if (bounds)
570 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
572 for (i = 0; i < mono_array_length (lengths); i++) {
573 if (mono_array_get (lengths, gint32, i) < 0) {
574 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
575 return NULL;
579 klass = mono_class_from_mono_type (type->type);
580 mono_class_init_checked (klass, &error);
581 if (mono_error_set_pending_exception (&error))
582 return NULL;
584 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
585 /* vectors are not the same as one dimensional arrays with no-zero bounds */
586 bounded = TRUE;
587 else
588 bounded = FALSE;
590 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
592 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
593 for (i = 0; i < aklass->rank; ++i) {
594 sizes [i] = mono_array_get (lengths, guint32, i);
595 if (bounds)
596 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
597 else
598 sizes [i + aklass->rank] = 0;
601 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
602 mono_error_set_pending_exception (&error);
604 return array;
607 ICALL_EXPORT MonoArray *
608 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
610 MonoError error;
611 MonoClass *aklass, *klass;
612 MonoArray *array;
613 uintptr_t *sizes, i;
614 gboolean bounded = FALSE;
616 MONO_CHECK_ARG_NULL (type, NULL);
617 MONO_CHECK_ARG_NULL (lengths, NULL);
619 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
620 if (bounds)
621 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
623 for (i = 0; i < mono_array_length (lengths); i++) {
624 if ((mono_array_get (lengths, gint64, i) < 0) ||
625 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
626 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
627 return NULL;
631 klass = mono_class_from_mono_type (type->type);
632 mono_class_init_checked (klass, &error);
633 if (mono_error_set_pending_exception (&error))
634 return NULL;
636 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
637 /* vectors are not the same as one dimensional arrays with no-zero bounds */
638 bounded = TRUE;
639 else
640 bounded = FALSE;
642 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
644 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
645 for (i = 0; i < aklass->rank; ++i) {
646 sizes [i] = mono_array_get (lengths, guint64, i);
647 if (bounds)
648 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
649 else
650 sizes [i + aklass->rank] = 0;
653 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
654 mono_error_set_pending_exception (&error);
656 return array;
659 ICALL_EXPORT gint32
660 ves_icall_System_Array_GetRank (MonoObject *arr)
662 return arr->vtable->klass->rank;
665 ICALL_EXPORT gint32
666 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
668 gint32 rank = arr->obj.vtable->klass->rank;
669 uintptr_t length;
671 if ((dimension < 0) || (dimension >= rank)) {
672 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
673 return 0;
676 if (arr->bounds == NULL)
677 length = arr->max_length;
678 else
679 length = arr->bounds [dimension].length;
681 #ifdef MONO_BIG_ARRAYS
682 if (length > G_MAXINT32) {
683 mono_set_pending_exception (mono_get_exception_overflow ());
684 return 0;
686 #endif
687 return length;
690 ICALL_EXPORT gint64
691 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
693 gint32 rank = arr->obj.vtable->klass->rank;
695 if ((dimension < 0) || (dimension >= rank)) {
696 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
697 return 0;
700 if (arr->bounds == NULL)
701 return arr->max_length;
703 return arr->bounds [dimension].length;
706 ICALL_EXPORT gint32
707 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
709 gint32 rank = arr->obj.vtable->klass->rank;
711 if ((dimension < 0) || (dimension >= rank)) {
712 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
713 return 0;
716 if (arr->bounds == NULL)
717 return 0;
719 return arr->bounds [dimension].lower_bound;
722 ICALL_EXPORT void
723 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
725 int sz = mono_array_element_size (mono_object_class (arr));
726 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
729 ICALL_EXPORT MonoArray*
730 ves_icall_System_Array_Clone (MonoArray *arr)
732 MonoError error;
733 MonoArray *result = mono_array_clone_checked (arr, &error);
734 mono_error_set_pending_exception (&error);
735 return result;
738 ICALL_EXPORT gboolean
739 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
741 int element_size;
742 void * dest_addr;
743 void * source_addr;
744 MonoVTable *src_vtable;
745 MonoVTable *dest_vtable;
746 MonoClass *src_class;
747 MonoClass *dest_class;
749 src_vtable = source->obj.vtable;
750 dest_vtable = dest->obj.vtable;
752 if (src_vtable->rank != dest_vtable->rank)
753 return FALSE;
755 if (source->bounds || dest->bounds)
756 return FALSE;
758 /* there's no integer overflow since mono_array_length returns an unsigned integer */
759 if ((dest_idx + length > mono_array_length_fast (dest)) ||
760 (source_idx + length > mono_array_length_fast (source)))
761 return FALSE;
763 src_class = src_vtable->klass->element_class;
764 dest_class = dest_vtable->klass->element_class;
767 * Handle common cases.
770 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
771 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
773 if (src_class == mono_defaults.object_class && dest_class->valuetype)
774 return FALSE;
776 /* Check if we're copying a char[] <==> (u)short[] */
777 if (src_class != dest_class) {
778 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
779 return FALSE;
781 /* 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. */
782 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
783 return FALSE;
786 if (dest_class->valuetype) {
787 element_size = mono_array_element_size (source->obj.vtable->klass);
788 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
789 if (dest_class->has_references) {
790 mono_value_copy_array (dest, dest_idx, source_addr, length);
791 } else {
792 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
793 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
795 } else {
796 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
799 return TRUE;
802 ICALL_EXPORT void
803 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
805 MonoClass *ac;
806 gint32 esize;
807 gpointer *ea;
809 ac = (MonoClass *)arr->obj.vtable->klass;
811 esize = mono_array_element_size (ac);
812 ea = (gpointer*)((char*)arr->vector + (pos * esize));
814 mono_gc_memmove_atomic (value, ea, esize);
817 ICALL_EXPORT void
818 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
820 MonoClass *ac, *ec;
821 gint32 esize;
822 gpointer *ea;
824 ac = (MonoClass *)arr->obj.vtable->klass;
825 ec = ac->element_class;
827 esize = mono_array_element_size (ac);
828 ea = (gpointer*)((char*)arr->vector + (pos * esize));
830 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
831 g_assert (esize == sizeof (gpointer));
832 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
833 } else {
834 g_assert (ec->inited);
835 g_assert (esize == mono_class_value_size (ec, NULL));
836 if (ec->has_references)
837 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
838 else
839 mono_gc_memmove_atomic (ea, value, esize);
843 ICALL_EXPORT void
844 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
846 MonoClass *klass = array->obj.vtable->klass;
847 guint32 size = mono_array_element_size (klass);
848 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
849 int align;
850 const char *field_data;
852 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
853 MonoException *exc = mono_get_exception_argument("array",
854 "Cannot initialize array of non-primitive type.");
855 mono_set_pending_exception (exc);
856 return;
859 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
860 MonoException *exc = mono_get_exception_argument("field_handle",
861 "Field doesn't have an RVA");
862 mono_set_pending_exception (exc);
863 return;
866 size *= array->max_length;
867 field_data = mono_field_get_data (field_handle);
869 if (size > mono_type_size (field_handle->type, &align)) {
870 MonoException *exc = mono_get_exception_argument("field_handle",
871 "Field not large enough to fill array");
872 mono_set_pending_exception (exc);
873 return;
876 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
877 #define SWAP(n) { \
878 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
879 guint ## n *src = (guint ## n *) field_data; \
880 int i, \
881 nEnt = (size / sizeof(guint ## n)); \
883 for (i = 0; i < nEnt; i++) { \
884 data[i] = read ## n (&src[i]); \
888 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
890 switch (type->type) {
891 case MONO_TYPE_CHAR:
892 case MONO_TYPE_I2:
893 case MONO_TYPE_U2:
894 SWAP (16);
895 break;
896 case MONO_TYPE_I4:
897 case MONO_TYPE_U4:
898 case MONO_TYPE_R4:
899 SWAP (32);
900 break;
901 case MONO_TYPE_I8:
902 case MONO_TYPE_U8:
903 case MONO_TYPE_R8:
904 SWAP (64);
905 break;
906 default:
907 memcpy (mono_array_addr (array, char, 0), field_data, size);
908 break;
910 #else
911 memcpy (mono_array_addr (array, char, 0), field_data, size);
912 #endif
915 ICALL_EXPORT gint
916 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
918 return offsetof (MonoString, chars);
921 ICALL_EXPORT MonoObject *
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
924 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
925 return obj;
926 else {
927 MonoError error;
928 MonoObject *ret = mono_object_clone_checked (obj, &error);
929 mono_error_set_pending_exception (&error);
931 return ret;
935 ICALL_EXPORT void
936 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
938 MonoError error;
939 MonoClass *klass;
940 MonoVTable *vtable;
942 MONO_CHECK_ARG_NULL (handle,);
944 klass = mono_class_from_mono_type (handle);
945 MONO_CHECK_ARG (handle, klass,);
947 if (mono_class_is_gtd (klass))
948 return;
950 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
951 if (!is_ok (&error)) {
952 mono_error_set_pending_exception (&error);
953 return;
956 /* This will call the type constructor */
957 if (!mono_runtime_class_init_full (vtable, &error))
958 mono_error_set_pending_exception (&error);
961 ICALL_EXPORT void
962 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
964 MonoError error;
966 mono_image_check_for_module_cctor (image);
967 if (image->has_module_cctor) {
968 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
969 if (!mono_error_ok (&error)) {
970 mono_error_set_pending_exception (&error);
971 return;
973 /*It's fine to raise the exception here*/
974 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
975 if (!is_ok (&error)) {
976 mono_error_set_pending_exception (&error);
977 return;
979 if (!mono_runtime_class_init_full (vtable, &error))
980 mono_error_set_pending_exception (&error);
984 ICALL_EXPORT MonoBoolean
985 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
987 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
988 // It does not work on win32
989 #else
990 guint8 *stack_addr;
991 guint8 *current;
992 size_t stack_size;
993 int min_size;
994 MonoInternalThread *thread;
996 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
997 /* if we have no info we are optimistic and assume there is enough room */
998 if (!stack_addr)
999 return TRUE;
1001 thread = mono_thread_internal_current ();
1002 // .net seems to check that at least 50% of stack is available
1003 min_size = thread->stack_size / 2;
1005 current = (guint8 *)&stack_addr;
1006 if (current > stack_addr) {
1007 if ((current - stack_addr) < min_size)
1008 return FALSE;
1009 } else {
1010 if (current - (stack_addr - stack_size) < min_size)
1011 return FALSE;
1013 #endif
1014 return TRUE;
1017 ICALL_EXPORT MonoObject *
1018 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1020 MonoError error;
1021 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1022 mono_error_set_pending_exception (&error);
1024 return ret;
1027 ICALL_EXPORT gint32
1028 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1030 MonoError error;
1031 MonoClass *klass;
1032 MonoObject **values = NULL;
1033 MonoObject *o;
1034 int count = 0;
1035 gint32 result = (int)(gsize)mono_defaults.int32_class;
1036 MonoClassField* field;
1037 gpointer iter;
1039 klass = mono_object_class (this_obj);
1041 if (mono_class_num_fields (klass) == 0)
1042 return result;
1045 * Compute the starting value of the hashcode for fields of primitive
1046 * types, and return the remaining fields in an array to the managed side.
1047 * This way, we can avoid costly reflection operations in managed code.
1049 iter = NULL;
1050 while ((field = mono_class_get_fields (klass, &iter))) {
1051 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1052 continue;
1053 if (mono_field_is_deleted (field))
1054 continue;
1055 /* FIXME: Add more types */
1056 switch (field->type->type) {
1057 case MONO_TYPE_I4:
1058 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1059 break;
1060 case MONO_TYPE_STRING: {
1061 MonoString *s;
1062 s = *(MonoString**)((guint8*)this_obj + field->offset);
1063 if (s != NULL)
1064 result ^= mono_string_hash (s);
1065 break;
1067 default:
1068 if (!values)
1069 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1070 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1071 if (!is_ok (&error)) {
1072 mono_error_set_pending_exception (&error);
1073 return 0;
1075 values [count++] = o;
1079 if (values) {
1080 int i;
1081 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1082 if (mono_error_set_pending_exception (&error))
1083 return 0;
1084 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1085 for (i = 0; i < count; ++i)
1086 mono_array_setref (*fields, i, values [i]);
1087 } else {
1088 *fields = NULL;
1090 return result;
1093 ICALL_EXPORT MonoBoolean
1094 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1096 MonoError error;
1097 MonoClass *klass;
1098 MonoObject **values = NULL;
1099 MonoObject *o;
1100 MonoClassField* field;
1101 gpointer iter;
1102 int count = 0;
1104 MONO_CHECK_ARG_NULL (that, FALSE);
1106 if (this_obj->vtable != that->vtable)
1107 return FALSE;
1109 klass = mono_object_class (this_obj);
1111 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1112 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1115 * Do the comparison for fields of primitive type and return a result if
1116 * possible. Otherwise, return the remaining fields in an array to the
1117 * managed side. This way, we can avoid costly reflection operations in
1118 * managed code.
1120 *fields = NULL;
1121 iter = NULL;
1122 while ((field = mono_class_get_fields (klass, &iter))) {
1123 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1124 continue;
1125 if (mono_field_is_deleted (field))
1126 continue;
1127 /* FIXME: Add more types */
1128 switch (field->type->type) {
1129 case MONO_TYPE_U1:
1130 case MONO_TYPE_I1:
1131 case MONO_TYPE_BOOLEAN:
1132 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1133 return FALSE;
1134 break;
1135 case MONO_TYPE_U2:
1136 case MONO_TYPE_I2:
1137 case MONO_TYPE_CHAR:
1138 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1139 return FALSE;
1140 break;
1141 case MONO_TYPE_U4:
1142 case MONO_TYPE_I4:
1143 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1144 return FALSE;
1145 break;
1146 case MONO_TYPE_U8:
1147 case MONO_TYPE_I8:
1148 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1149 return FALSE;
1150 break;
1151 case MONO_TYPE_R4:
1152 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1153 return FALSE;
1154 break;
1155 case MONO_TYPE_R8:
1156 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1157 return FALSE;
1158 break;
1161 case MONO_TYPE_STRING: {
1162 MonoString *s1, *s2;
1163 guint32 s1len, s2len;
1164 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1165 s2 = *(MonoString**)((guint8*)that + field->offset);
1166 if (s1 == s2)
1167 break;
1168 if ((s1 == NULL) || (s2 == NULL))
1169 return FALSE;
1170 s1len = mono_string_length (s1);
1171 s2len = mono_string_length (s2);
1172 if (s1len != s2len)
1173 return FALSE;
1175 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1176 return FALSE;
1177 break;
1179 default:
1180 if (!values)
1181 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1182 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1183 if (!is_ok (&error)) {
1184 mono_error_set_pending_exception (&error);
1185 return FALSE;
1187 values [count++] = o;
1188 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1189 if (!is_ok (&error)) {
1190 mono_error_set_pending_exception (&error);
1191 return FALSE;
1193 values [count++] = o;
1196 if (klass->enumtype)
1197 /* enums only have one non-static field */
1198 break;
1201 if (values) {
1202 int i;
1203 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1204 if (mono_error_set_pending_exception (&error))
1205 return FALSE;
1206 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1207 for (i = 0; i < count; ++i)
1208 mono_array_setref_fast (*fields, i, values [i]);
1209 return FALSE;
1210 } else {
1211 return TRUE;
1215 ICALL_EXPORT MonoReflectionType *
1216 ves_icall_System_Object_GetType (MonoObject *obj)
1218 MonoError error;
1219 MonoReflectionType *ret;
1220 #ifndef DISABLE_REMOTING
1221 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1222 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1223 else
1224 #endif
1225 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1227 mono_error_set_pending_exception (&error);
1228 return ret;
1231 static gboolean
1232 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1234 MonoMethod **dest = (MonoMethod **)data;
1236 /* skip unmanaged frames */
1237 if (!managed)
1238 return FALSE;
1240 if (!(*dest)) {
1241 if (!strcmp (m->klass->name_space, "System.Reflection"))
1242 return FALSE;
1243 *dest = m;
1244 return TRUE;
1246 return FALSE;
1249 static gboolean
1250 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1252 MonoMethod **dest = (MonoMethod **)data;
1254 /* skip unmanaged frames */
1255 if (!managed)
1256 return FALSE;
1258 if (m->wrapper_type != MONO_WRAPPER_NONE)
1259 return FALSE;
1261 if (m == *dest) {
1262 *dest = NULL;
1263 return FALSE;
1266 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1267 return FALSE;
1269 if (!(*dest)) {
1270 *dest = m;
1271 return TRUE;
1273 return FALSE;
1276 static gboolean
1277 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1279 MonoMethod **dest = (MonoMethod **)data;
1281 /* skip unmanaged frames */
1282 if (!managed)
1283 return FALSE;
1285 if (m->wrapper_type != MONO_WRAPPER_NONE)
1286 return FALSE;
1288 if (m == *dest) {
1289 *dest = NULL;
1290 return FALSE;
1293 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1294 || (!strcmp (m->klass->name_space, "System"))))
1295 return FALSE;
1297 if (!(*dest)) {
1298 *dest = m;
1299 return TRUE;
1301 return FALSE;
1304 static MonoReflectionType *
1305 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoAssembly **caller_assembly, MonoError *error)
1307 MonoMethod *m, *dest;
1309 MonoType *type = NULL;
1310 MonoAssembly *assembly = NULL;
1311 gboolean type_resolve = FALSE;
1312 MonoImage *rootimage = NULL;
1314 mono_error_init (error);
1317 * We must compute the calling assembly as type loading must happen under a metadata context.
1318 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1319 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1321 m = mono_method_get_last_managed ();
1322 dest = m;
1323 if (m && m->klass->image != mono_defaults.corlib) {
1324 /* Happens with inlining */
1325 } else {
1326 /* Ugly hack: type_from_parsed_name is called from
1327 * System.Type.internal_from_name, which is called most
1328 * directly from System.Type.GetType(string,bool,bool) but
1329 * also indirectly from places such as
1330 * System.Type.GetType(string,func,func) (via
1331 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1332 * so we need to skip over all of those to find the true caller.
1334 * It would be nice if we had stack marks.
1336 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1337 if (!dest)
1338 dest = m;
1342 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1343 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1344 * to crash. This only seems to happen in some strange remoting
1345 * scenarios and I was unable to figure out what's happening there.
1346 * Dec 10, 2005 - Martin.
1349 if (dest) {
1350 assembly = dest->klass->image->assembly;
1351 type_resolve = TRUE;
1352 rootimage = assembly->image;
1353 } else {
1354 g_warning (G_STRLOC);
1356 *caller_assembly = assembly;
1358 if (info->assembly.name)
1359 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1361 if (assembly) {
1362 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1363 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1364 return_val_if_nok (error, NULL);
1367 // XXXX - aleksey -
1368 // Say we're looking for System.Generic.Dict<int, Local>
1369 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1370 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1371 // is messed up when we go to construct the Local as the type arg...
1373 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1374 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1375 if (!info->assembly.name && !type) {
1376 /* try mscorlib */
1377 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1378 return_val_if_nok (error, NULL);
1380 if (assembly && !type && type_resolve) {
1381 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1382 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1383 return_val_if_nok (error, NULL);
1386 if (!type)
1387 return NULL;
1389 return mono_type_get_object_checked (mono_domain_get (), type, error);
1392 ICALL_EXPORT MonoReflectionType*
1393 ves_icall_System_Type_internal_from_name (MonoString *name,
1394 MonoBoolean throwOnError,
1395 MonoBoolean ignoreCase)
1397 MonoError error;
1398 MonoTypeNameParse info;
1399 MonoReflectionType *type = NULL;
1400 gboolean parsedOk;
1401 MonoAssembly *caller_assembly;
1403 char *str = mono_string_to_utf8_checked (name, &error);
1404 if (!is_ok (&error))
1405 goto leave;
1407 parsedOk = mono_reflection_parse_type (str, &info);
1409 /* mono_reflection_parse_type() mangles the string */
1410 if (!parsedOk) {
1411 mono_reflection_free_type_info (&info);
1412 if (throwOnError)
1413 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1414 goto leave;
1417 type = type_from_parsed_name (&info, ignoreCase, &caller_assembly, &error);
1419 if (!is_ok (&error)) {
1420 mono_reflection_free_type_info (&info);
1421 goto leave;
1424 if (type == NULL) {
1425 if (throwOnError) {
1426 char *tname = info.name_space ? g_strdup_printf ("%s.%s", info.name_space, info.name) : g_strdup (info.name);
1427 char *aname;
1428 if (info.assembly.name)
1429 aname = mono_stringify_assembly_name (&info.assembly);
1430 else if (caller_assembly)
1431 aname = mono_stringify_assembly_name (mono_assembly_get_name (caller_assembly));
1432 else
1433 aname = g_strdup ("");
1434 mono_error_set_type_load_name (&error, tname, aname, "");
1436 mono_reflection_free_type_info (&info);
1437 goto leave;
1440 leave:
1441 g_free (str);
1442 if (!is_ok (&error)) {
1443 if (throwOnError)
1444 mono_error_set_pending_exception (&error);
1445 else
1446 mono_error_cleanup (&error);
1447 return NULL;
1450 return type;
1454 ICALL_EXPORT MonoReflectionType*
1455 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1457 MonoError error;
1458 MonoReflectionType *ret;
1459 MonoDomain *domain = mono_domain_get ();
1461 ret = mono_type_get_object_checked (domain, handle, &error);
1462 mono_error_set_pending_exception (&error);
1464 return ret;
1467 ICALL_EXPORT MonoType*
1468 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1470 return mono_class_get_type (klass);
1473 ICALL_EXPORT void
1474 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1476 g_ptr_array_free (ptr_array, TRUE);
1479 ICALL_EXPORT void
1480 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1482 g_free (c_str);
1485 ICALL_EXPORT char*
1486 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1488 MonoError error;
1489 char *res = mono_string_to_utf8_checked (s, &error);
1490 mono_error_set_pending_exception (&error);
1491 return res;
1494 /* System.TypeCode */
1495 typedef enum {
1496 TYPECODE_EMPTY,
1497 TYPECODE_OBJECT,
1498 TYPECODE_DBNULL,
1499 TYPECODE_BOOLEAN,
1500 TYPECODE_CHAR,
1501 TYPECODE_SBYTE,
1502 TYPECODE_BYTE,
1503 TYPECODE_INT16,
1504 TYPECODE_UINT16,
1505 TYPECODE_INT32,
1506 TYPECODE_UINT32,
1507 TYPECODE_INT64,
1508 TYPECODE_UINT64,
1509 TYPECODE_SINGLE,
1510 TYPECODE_DOUBLE,
1511 TYPECODE_DECIMAL,
1512 TYPECODE_DATETIME,
1513 TYPECODE_STRING = 18
1514 } TypeCode;
1516 ICALL_EXPORT guint32
1517 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1519 int t = type->type->type;
1521 if (type->type->byref)
1522 return TYPECODE_OBJECT;
1524 handle_enum:
1525 switch (t) {
1526 case MONO_TYPE_VOID:
1527 return TYPECODE_OBJECT;
1528 case MONO_TYPE_BOOLEAN:
1529 return TYPECODE_BOOLEAN;
1530 case MONO_TYPE_U1:
1531 return TYPECODE_BYTE;
1532 case MONO_TYPE_I1:
1533 return TYPECODE_SBYTE;
1534 case MONO_TYPE_U2:
1535 return TYPECODE_UINT16;
1536 case MONO_TYPE_I2:
1537 return TYPECODE_INT16;
1538 case MONO_TYPE_CHAR:
1539 return TYPECODE_CHAR;
1540 case MONO_TYPE_PTR:
1541 case MONO_TYPE_U:
1542 case MONO_TYPE_I:
1543 return TYPECODE_OBJECT;
1544 case MONO_TYPE_U4:
1545 return TYPECODE_UINT32;
1546 case MONO_TYPE_I4:
1547 return TYPECODE_INT32;
1548 case MONO_TYPE_U8:
1549 return TYPECODE_UINT64;
1550 case MONO_TYPE_I8:
1551 return TYPECODE_INT64;
1552 case MONO_TYPE_R4:
1553 return TYPECODE_SINGLE;
1554 case MONO_TYPE_R8:
1555 return TYPECODE_DOUBLE;
1556 case MONO_TYPE_VALUETYPE: {
1557 MonoClass *klass = type->type->data.klass;
1559 if (klass->enumtype) {
1560 t = mono_class_enum_basetype (klass)->type;
1561 goto handle_enum;
1562 } else if (mono_is_corlib_image (klass->image)) {
1563 if (strcmp (klass->name_space, "System") == 0) {
1564 if (strcmp (klass->name, "Decimal") == 0)
1565 return TYPECODE_DECIMAL;
1566 else if (strcmp (klass->name, "DateTime") == 0)
1567 return TYPECODE_DATETIME;
1570 return TYPECODE_OBJECT;
1572 case MONO_TYPE_STRING:
1573 return TYPECODE_STRING;
1574 case MONO_TYPE_SZARRAY:
1575 case MONO_TYPE_ARRAY:
1576 case MONO_TYPE_OBJECT:
1577 case MONO_TYPE_VAR:
1578 case MONO_TYPE_MVAR:
1579 case MONO_TYPE_TYPEDBYREF:
1580 return TYPECODE_OBJECT;
1581 case MONO_TYPE_CLASS:
1583 MonoClass *klass = type->type->data.klass;
1584 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1585 if (strcmp (klass->name, "DBNull") == 0)
1586 return TYPECODE_DBNULL;
1589 return TYPECODE_OBJECT;
1590 case MONO_TYPE_GENERICINST:
1591 return TYPECODE_OBJECT;
1592 default:
1593 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1595 return 0;
1598 static gboolean
1599 mono_type_is_primitive (MonoType *type)
1601 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1602 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1605 static MonoType*
1606 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1608 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1609 return mono_class_enum_basetype (type->data.klass);
1610 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1611 return mono_class_enum_basetype (type->data.generic_class->container_class);
1612 return type;
1615 ICALL_EXPORT guint32
1616 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1618 MonoClass *klass;
1619 MonoClass *klassc;
1621 g_assert (type != NULL);
1623 klass = mono_class_from_mono_type (type->type);
1624 klassc = mono_class_from_mono_type (c->type);
1626 if (type->type->byref ^ c->type->byref)
1627 return FALSE;
1629 if (type->type->byref) {
1630 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1631 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1633 klass = mono_class_from_mono_type (t);
1634 klassc = mono_class_from_mono_type (ot);
1636 if (mono_type_is_primitive (t)) {
1637 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1638 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1639 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1640 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1641 return t->type == ot->type;
1642 } else {
1643 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1644 return FALSE;
1646 if (klass->valuetype)
1647 return klass == klassc;
1648 return klass->valuetype == klassc->valuetype;
1651 return mono_class_is_assignable_from (klass, klassc);
1654 ICALL_EXPORT guint32
1655 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1657 MonoError error;
1658 MonoClass *klass = mono_class_from_mono_type (type->type);
1659 mono_class_init_checked (klass, &error);
1660 if (!is_ok (&error)) {
1661 mono_error_set_pending_exception (&error);
1662 return FALSE;
1664 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1665 mono_error_set_pending_exception (&error);
1666 return result;
1669 ICALL_EXPORT guint32
1670 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1672 MonoClass *klass = mono_class_from_mono_type (type->type);
1673 return mono_class_get_flags (klass);
1676 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1677 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1679 MonoError error;
1680 MonoClass *klass = field->field->parent;
1681 MonoMarshalType *info;
1682 MonoType *ftype;
1683 int i;
1685 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1686 if (mono_class_is_gtd (klass) ||
1687 (gklass && gklass->context.class_inst->is_open))
1688 return NULL;
1690 ftype = mono_field_get_type (field->field);
1691 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1692 return NULL;
1694 info = mono_marshal_load_type_info (klass);
1696 for (i = 0; i < info->num_fields; ++i) {
1697 if (info->fields [i].field == field->field) {
1698 if (!info->fields [i].mspec)
1699 return NULL;
1700 else {
1701 MonoReflectionMarshalAsAttribute* obj;
1702 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1703 if (!mono_error_ok (&error))
1704 mono_error_set_pending_exception (&error);
1705 return obj;
1710 return NULL;
1713 ICALL_EXPORT MonoReflectionField*
1714 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1716 MonoError error;
1717 gboolean found = FALSE;
1718 MonoClass *klass;
1720 g_assert (handle);
1722 if (!type) {
1723 klass = handle->parent;
1724 } else {
1725 klass = mono_class_from_mono_type (type);
1727 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1729 if (!found)
1730 /* The managed code will throw the exception */
1731 return NULL;
1734 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1735 mono_error_set_pending_exception (&error);
1736 return result;
1739 ICALL_EXPORT MonoReflectionEvent*
1740 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1742 MonoError error;
1743 MonoClass *klass;
1745 g_assert (handle);
1747 if (!type) {
1748 klass = handle->parent;
1749 } else {
1750 klass = mono_class_from_mono_type (type);
1752 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1753 if (!found)
1754 /* Managed code will throw an exception */
1755 return NULL;
1758 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1759 mono_error_set_pending_exception (&error);
1760 return result;
1764 ICALL_EXPORT MonoReflectionProperty*
1765 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1767 MonoError error;
1768 MonoClass *klass;
1770 g_assert (handle);
1772 if (!type) {
1773 klass = handle->parent;
1774 } else {
1775 klass = mono_class_from_mono_type (type);
1777 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1778 if (!found)
1779 /* Managed code will throw an exception */
1780 return NULL;
1783 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1784 mono_error_set_pending_exception (&error);
1785 return result;
1788 ICALL_EXPORT MonoArray*
1789 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1791 MonoError error;
1792 MonoType *type = mono_field_get_type_checked (field->field, &error);
1793 MonoArray *res;
1795 if (!mono_error_ok (&error)) {
1796 mono_error_set_pending_exception (&error);
1797 return NULL;
1800 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1801 mono_error_set_pending_exception (&error);
1802 return res;
1805 ICALL_EXPORT int
1806 vell_icall_get_method_attributes (MonoMethod *method)
1808 return method->flags;
1811 ICALL_EXPORT void
1812 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1814 MonoError error;
1815 MonoReflectionType *rt;
1816 MonoDomain *domain = mono_domain_get ();
1817 MonoMethodSignature* sig;
1819 sig = mono_method_signature_checked (method, &error);
1820 if (!mono_error_ok (&error)) {
1821 mono_error_set_pending_exception (&error);
1822 return;
1825 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1826 if (!mono_error_ok (&error)) {
1827 mono_error_set_pending_exception (&error);
1828 return;
1831 MONO_STRUCT_SETREF (info, parent, rt);
1833 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1834 if (!mono_error_ok (&error)) {
1835 mono_error_set_pending_exception (&error);
1836 return;
1839 MONO_STRUCT_SETREF (info, ret, rt);
1841 info->attrs = method->flags;
1842 info->implattrs = method->iflags;
1843 if (sig->call_convention == MONO_CALL_DEFAULT)
1844 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1845 else {
1846 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1847 info->callconv = 2;
1848 else
1849 info->callconv = 1;
1851 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1854 ICALL_EXPORT MonoArray*
1855 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1857 MonoError error;
1858 MonoDomain *domain = mono_domain_get ();
1860 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1861 mono_error_set_pending_exception (&error);
1862 return result;
1865 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1866 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1868 MonoError error;
1869 MonoDomain *domain = mono_domain_get ();
1870 MonoReflectionMarshalAsAttribute* res = NULL;
1871 MonoMarshalSpec **mspecs;
1872 int i;
1874 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1875 mono_method_get_marshal_info (method, mspecs);
1877 if (mspecs [0]) {
1878 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1879 if (!mono_error_ok (&error)) {
1880 mono_error_set_pending_exception (&error);
1881 return NULL;
1885 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1886 if (mspecs [i])
1887 mono_metadata_free_marshal_spec (mspecs [i]);
1888 g_free (mspecs);
1890 return res;
1893 ICALL_EXPORT gint32
1894 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1896 MonoClass *parent = field->field->parent;
1897 mono_class_setup_fields (parent);
1899 return field->field->offset - sizeof (MonoObject);
1902 ICALL_EXPORT MonoReflectionType*
1903 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1905 MonoError error;
1906 MonoReflectionType *ret;
1907 MonoClass *parent;
1909 parent = declaring? field->field->parent: field->klass;
1911 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1912 mono_error_set_pending_exception (&error);
1914 return ret;
1918 ICALL_EXPORT MonoObject *
1919 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1921 MonoError error;
1922 MonoClass *fklass = field->klass;
1923 MonoClassField *cf = field->field;
1924 MonoDomain *domain = mono_object_domain (field);
1926 if (fklass->image->assembly->ref_only) {
1927 mono_set_pending_exception (mono_get_exception_invalid_operation (
1928 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1929 return NULL;
1932 if (mono_security_core_clr_enabled () &&
1933 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1934 mono_error_set_pending_exception (&error);
1935 return NULL;
1938 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1939 mono_error_set_pending_exception (&error);
1940 return result;
1943 ICALL_EXPORT void
1944 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1946 MonoError error;
1947 MonoClassField *cf = field->field;
1948 MonoType *type;
1949 gchar *v;
1951 if (field->klass->image->assembly->ref_only) {
1952 mono_set_pending_exception (mono_get_exception_invalid_operation (
1953 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1954 return;
1957 if (mono_security_core_clr_enabled () &&
1958 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1959 mono_error_set_pending_exception (&error);
1960 return;
1963 type = mono_field_get_type_checked (cf, &error);
1964 if (!mono_error_ok (&error)) {
1965 mono_error_set_pending_exception (&error);
1966 return;
1969 v = (gchar *) value;
1970 if (!type->byref) {
1971 switch (type->type) {
1972 case MONO_TYPE_U1:
1973 case MONO_TYPE_I1:
1974 case MONO_TYPE_BOOLEAN:
1975 case MONO_TYPE_U2:
1976 case MONO_TYPE_I2:
1977 case MONO_TYPE_CHAR:
1978 case MONO_TYPE_U:
1979 case MONO_TYPE_I:
1980 case MONO_TYPE_U4:
1981 case MONO_TYPE_I4:
1982 case MONO_TYPE_R4:
1983 case MONO_TYPE_U8:
1984 case MONO_TYPE_I8:
1985 case MONO_TYPE_R8:
1986 case MONO_TYPE_VALUETYPE:
1987 case MONO_TYPE_PTR:
1988 if (v != NULL)
1989 v += sizeof (MonoObject);
1990 break;
1991 case MONO_TYPE_STRING:
1992 case MONO_TYPE_OBJECT:
1993 case MONO_TYPE_CLASS:
1994 case MONO_TYPE_ARRAY:
1995 case MONO_TYPE_SZARRAY:
1996 /* Do nothing */
1997 break;
1998 case MONO_TYPE_GENERICINST: {
1999 MonoGenericClass *gclass = type->data.generic_class;
2000 g_assert (!gclass->context.class_inst->is_open);
2002 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2003 MonoClass *nklass = mono_class_from_mono_type (type);
2004 MonoObject *nullable;
2007 * Convert the boxed vtype into a Nullable structure.
2008 * This is complicated by the fact that Nullables have
2009 * a variable structure.
2011 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2012 if (!mono_error_ok (&error)) {
2013 mono_error_set_pending_exception (&error);
2014 return;
2017 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2019 v = (gchar *)mono_object_unbox (nullable);
2021 else
2022 if (gclass->container_class->valuetype && (v != NULL))
2023 v += sizeof (MonoObject);
2024 break;
2026 default:
2027 g_error ("type 0x%x not handled in "
2028 "ves_icall_FieldInfo_SetValueInternal", type->type);
2029 return;
2033 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2034 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2035 if (!is_ok (&error)) {
2036 mono_error_set_pending_exception (&error);
2037 return;
2039 if (!vtable->initialized) {
2040 if (!mono_runtime_class_init_full (vtable, &error)) {
2041 mono_error_set_pending_exception (&error);
2042 return;
2045 mono_field_static_set_value (vtable, cf, v);
2046 } else {
2047 mono_field_set_value (obj, cf, v);
2051 ICALL_EXPORT void
2052 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2054 MonoClassField *f;
2056 g_assert (field);
2057 g_assert (obj);
2058 g_assert (value);
2060 f = field->field;
2061 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2062 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2063 return;
2066 if (MONO_TYPE_IS_REFERENCE (f->type))
2067 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2068 else
2069 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2072 ICALL_EXPORT MonoObject *
2073 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2075 MonoObject *o = NULL;
2076 MonoClassField *field = rfield->field;
2077 MonoClass *klass;
2078 MonoDomain *domain = mono_object_domain (rfield);
2079 gchar *v;
2080 MonoTypeEnum def_type;
2081 const char *def_value;
2082 MonoType *t;
2083 MonoError error;
2085 mono_class_init (field->parent);
2087 t = mono_field_get_type_checked (field, &error);
2088 if (!mono_error_ok (&error)) {
2089 mono_error_set_pending_exception (&error);
2090 return NULL;
2093 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2094 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2095 return NULL;
2098 if (image_is_dynamic (field->parent->image)) {
2099 MonoClass *klass = field->parent;
2100 int fidx = field - klass->fields;
2102 g_assert (fidx >= 0 && fidx < klass->field.count);
2103 g_assert (klass->ext);
2104 g_assert (klass->ext->field_def_values);
2105 def_type = klass->ext->field_def_values [fidx].def_type;
2106 def_value = klass->ext->field_def_values [fidx].data;
2107 if (def_type == MONO_TYPE_END) {
2108 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2109 return NULL;
2111 } else {
2112 def_value = mono_class_get_field_default_value (field, &def_type);
2113 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2114 if (!def_value) {
2115 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2116 return NULL;
2120 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2121 switch (def_type) {
2122 case MONO_TYPE_U1:
2123 case MONO_TYPE_I1:
2124 case MONO_TYPE_BOOLEAN:
2125 case MONO_TYPE_U2:
2126 case MONO_TYPE_I2:
2127 case MONO_TYPE_CHAR:
2128 case MONO_TYPE_U:
2129 case MONO_TYPE_I:
2130 case MONO_TYPE_U4:
2131 case MONO_TYPE_I4:
2132 case MONO_TYPE_R4:
2133 case MONO_TYPE_U8:
2134 case MONO_TYPE_I8:
2135 case MONO_TYPE_R8: {
2136 MonoType *t;
2138 /* boxed value type */
2139 t = g_new0 (MonoType, 1);
2140 t->type = def_type;
2141 klass = mono_class_from_mono_type (t);
2142 g_free (t);
2143 o = mono_object_new_checked (domain, klass, &error);
2144 if (!mono_error_ok (&error)) {
2145 mono_error_set_pending_exception (&error);
2146 return NULL;
2148 v = ((gchar *) o) + sizeof (MonoObject);
2149 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2150 if (mono_error_set_pending_exception (&error))
2151 return NULL;
2152 break;
2154 case MONO_TYPE_STRING:
2155 case MONO_TYPE_CLASS:
2156 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2157 if (mono_error_set_pending_exception (&error))
2158 return NULL;
2159 break;
2160 default:
2161 g_assert_not_reached ();
2164 return o;
2167 ICALL_EXPORT MonoReflectionType*
2168 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2170 MonoError error;
2171 MonoReflectionType *ret;
2172 MonoType *type;
2174 type = mono_field_get_type_checked (ref_field->field, &error);
2175 if (!mono_error_ok (&error)) {
2176 mono_error_set_pending_exception (&error);
2177 return NULL;
2180 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2181 if (!mono_error_ok (&error)) {
2182 mono_error_set_pending_exception (&error);
2183 return NULL;
2186 return ret;
2189 /* From MonoProperty.cs */
2190 typedef enum {
2191 PInfo_Attributes = 1,
2192 PInfo_GetMethod = 1 << 1,
2193 PInfo_SetMethod = 1 << 2,
2194 PInfo_ReflectedType = 1 << 3,
2195 PInfo_DeclaringType = 1 << 4,
2196 PInfo_Name = 1 << 5
2197 } PInfo;
2199 ICALL_EXPORT void
2200 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2202 MonoError error;
2203 MonoReflectionType *rt;
2204 MonoReflectionMethod *rm;
2205 MonoDomain *domain = mono_object_domain (property);
2206 const MonoProperty *pproperty = property->property;
2208 if ((req_info & PInfo_ReflectedType) != 0) {
2209 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2210 if (mono_error_set_pending_exception (&error))
2211 return;
2213 MONO_STRUCT_SETREF (info, parent, rt);
2215 if ((req_info & PInfo_DeclaringType) != 0) {
2216 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2217 if (mono_error_set_pending_exception (&error))
2218 return;
2220 MONO_STRUCT_SETREF (info, declaring_type, rt);
2223 if ((req_info & PInfo_Name) != 0)
2224 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2226 if ((req_info & PInfo_Attributes) != 0)
2227 info->attrs = pproperty->attrs;
2229 if ((req_info & PInfo_GetMethod) != 0) {
2230 if (pproperty->get &&
2231 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2232 pproperty->get->klass == property->klass)) {
2233 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2234 if (mono_error_set_pending_exception (&error))
2235 return;
2236 } else {
2237 rm = NULL;
2240 MONO_STRUCT_SETREF (info, get, rm);
2242 if ((req_info & PInfo_SetMethod) != 0) {
2243 if (pproperty->set &&
2244 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2245 pproperty->set->klass == property->klass)) {
2246 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2247 if (mono_error_set_pending_exception (&error))
2248 return;
2249 } else {
2250 rm = NULL;
2253 MONO_STRUCT_SETREF (info, set, rm);
2256 * There may be other methods defined for properties, though, it seems they are not exposed
2257 * in the reflection API
2261 ICALL_EXPORT void
2262 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2264 MonoError error;
2265 MonoReflectionType *rt;
2266 MonoReflectionMethod *rm;
2267 MonoDomain *domain = mono_object_domain (event);
2269 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2270 if (mono_error_set_pending_exception (&error))
2271 return;
2273 MONO_STRUCT_SETREF (info, reflected_type, rt);
2275 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2276 if (mono_error_set_pending_exception (&error))
2277 return;
2279 MONO_STRUCT_SETREF (info, declaring_type, rt);
2281 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2282 info->attrs = event->event->attrs;
2284 if (event->event->add) {
2285 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2286 if (mono_error_set_pending_exception (&error))
2287 return;
2288 } else {
2289 rm = NULL;
2292 MONO_STRUCT_SETREF (info, add_method, rm);
2294 if (event->event->remove) {
2295 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2296 if (mono_error_set_pending_exception (&error))
2297 return;
2298 } else {
2299 rm = NULL;
2302 MONO_STRUCT_SETREF (info, remove_method, rm);
2304 if (event->event->raise) {
2305 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2306 if (mono_error_set_pending_exception (&error))
2307 return;
2308 } else {
2309 rm = NULL;
2312 MONO_STRUCT_SETREF (info, raise_method, rm);
2314 #ifndef MONO_SMALL_CONFIG
2315 if (event->event->other) {
2316 int i, n = 0;
2317 while (event->event->other [n])
2318 n++;
2319 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2320 if (mono_error_set_pending_exception (&error))
2321 return;
2322 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2324 for (i = 0; i < n; i++) {
2325 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2326 if (mono_error_set_pending_exception (&error))
2327 return;
2328 mono_array_setref (info->other_methods, i, rm);
2331 #endif
2334 static void
2335 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2337 int i;
2338 MonoClass *ic;
2340 mono_class_setup_interfaces (klass, error);
2341 if (!mono_error_ok (error))
2342 return;
2344 for (i = 0; i < klass->interface_count; i++) {
2345 ic = klass->interfaces [i];
2346 g_hash_table_insert (ifaces, ic, ic);
2348 collect_interfaces (ic, ifaces, error);
2349 if (!mono_error_ok (error))
2350 return;
2354 typedef struct {
2355 MonoArray *iface_array;
2356 MonoGenericContext *context;
2357 MonoError *error;
2358 MonoDomain *domain;
2359 int next_idx;
2360 } FillIfaceArrayData;
2362 static void
2363 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2365 MonoReflectionType *rt;
2366 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2367 MonoClass *ic = (MonoClass *)key;
2368 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2370 if (!mono_error_ok (data->error))
2371 return;
2373 if (data->context && mono_class_is_ginst (ic) && mono_class_get_generic_class (ic)->context.class_inst->is_open) {
2374 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2375 if (!mono_error_ok (data->error))
2376 return;
2379 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2380 if (!mono_error_ok (data->error))
2381 return;
2383 mono_array_setref (data->iface_array, data->next_idx++, rt);
2385 if (inflated)
2386 mono_metadata_free_type (inflated);
2389 static guint
2390 get_interfaces_hash (gconstpointer v1)
2392 MonoClass *k = (MonoClass*)v1;
2394 return k->type_token;
2397 ICALL_EXPORT MonoArray*
2398 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2400 MonoError error;
2401 MonoClass *klass = mono_class_from_mono_type (type->type);
2402 MonoClass *parent;
2403 FillIfaceArrayData data = { 0 };
2404 int len;
2406 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2408 if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open) {
2409 data.context = mono_class_get_context (klass);
2410 klass = mono_class_get_generic_class (klass)->container_class;
2413 for (parent = klass; parent; parent = parent->parent) {
2414 mono_class_setup_interfaces (parent, &error);
2415 if (!mono_error_ok (&error))
2416 goto fail;
2417 collect_interfaces (parent, iface_hash, &error);
2418 if (!mono_error_ok (&error))
2419 goto fail;
2422 data.error = &error;
2423 data.domain = mono_object_domain (type);
2425 len = g_hash_table_size (iface_hash);
2426 if (len == 0) {
2427 g_hash_table_destroy (iface_hash);
2428 if (!data.domain->empty_types) {
2429 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2430 if (!is_ok (&error))
2431 goto fail;
2433 return data.domain->empty_types;
2436 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2437 if (!is_ok (&error))
2438 goto fail;
2439 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2440 if (!mono_error_ok (&error))
2441 goto fail;
2443 g_hash_table_destroy (iface_hash);
2444 return data.iface_array;
2446 fail:
2447 g_hash_table_destroy (iface_hash);
2448 mono_error_set_pending_exception (&error);
2449 return NULL;
2452 ICALL_EXPORT void
2453 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2455 gboolean variance_used;
2456 MonoClass *klass = mono_class_from_mono_type (type->type);
2457 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2458 MonoReflectionMethod *member;
2459 MonoMethod* method;
2460 gpointer iter;
2461 int i = 0, len, ioffset;
2462 MonoDomain *domain;
2463 MonoError error;
2465 mono_class_init_checked (klass, &error);
2466 if (mono_error_set_pending_exception (&error))
2467 return;
2468 mono_class_init_checked (iclass, &error);
2469 if (mono_error_set_pending_exception (&error))
2470 return;
2472 mono_class_setup_vtable (klass);
2474 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2475 if (ioffset == -1)
2476 return;
2478 len = mono_class_num_methods (iclass);
2479 domain = mono_object_domain (type);
2480 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2481 if (mono_error_set_pending_exception (&error))
2482 return;
2483 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2484 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2485 if (mono_error_set_pending_exception (&error))
2486 return;
2487 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2488 iter = NULL;
2489 while ((method = mono_class_get_methods (iclass, &iter))) {
2490 member = mono_method_get_object_checked (domain, method, iclass, &error);
2491 if (mono_error_set_pending_exception (&error))
2492 return;
2493 mono_array_setref (*methods, i, member);
2494 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2495 if (mono_error_set_pending_exception (&error))
2496 return;
2497 mono_array_setref (*targets, i, member);
2499 i ++;
2503 ICALL_EXPORT void
2504 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2506 MonoError error;
2507 MonoClass *klass = mono_class_from_mono_type (type->type);
2509 mono_class_init_checked (klass, &error);
2510 if (mono_error_set_pending_exception (&error))
2511 return;
2513 if (image_is_dynamic (klass->image)) {
2514 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2515 *packing = tb->packing_size;
2516 *size = tb->class_size;
2517 } else {
2518 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2522 ICALL_EXPORT MonoReflectionType*
2523 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2525 MonoError error;
2526 MonoReflectionType *ret;
2527 MonoClass *klass;
2529 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2530 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2531 mono_error_set_pending_exception (&error);
2532 return ret;
2535 klass = mono_class_from_mono_type (type->type);
2536 mono_class_init_checked (klass, &error);
2537 if (mono_error_set_pending_exception (&error))
2538 return NULL;
2541 // GetElementType should only return a type for:
2542 // Array Pointer PassedByRef
2543 if (type->type->byref)
2544 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2545 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2546 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2547 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2548 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2549 else
2550 return NULL;
2552 mono_error_set_pending_exception (&error);
2554 return ret;
2557 ICALL_EXPORT MonoReflectionType*
2558 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2560 MonoError error;
2561 MonoReflectionType *ret;
2563 if (type->type->byref)
2564 return NULL;
2566 MonoClass *klass = mono_class_from_mono_type (type->type);
2567 if (!klass->parent)
2568 return NULL;
2570 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2571 mono_error_set_pending_exception (&error);
2573 return ret;
2576 ICALL_EXPORT MonoBoolean
2577 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2579 return type->type->type == MONO_TYPE_PTR;
2582 ICALL_EXPORT MonoBoolean
2583 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2585 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)));
2588 ICALL_EXPORT MonoBoolean
2589 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2591 return type->type->byref;
2594 ICALL_EXPORT MonoBoolean
2595 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2597 MonoError error;
2598 MonoClass *klass = mono_class_from_mono_type (type->type);
2599 mono_class_init_checked (klass, &error);
2600 if (mono_error_set_pending_exception (&error))
2601 return FALSE;
2603 return mono_class_is_com_object (klass);
2606 ICALL_EXPORT guint32
2607 ves_icall_reflection_get_token (MonoObject* obj)
2609 MonoError error;
2610 guint32 result = mono_reflection_get_token_checked (obj, &error);
2611 mono_error_set_pending_exception (&error);
2612 return result;
2615 ICALL_EXPORT MonoReflectionModule*
2616 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2618 MonoError error;
2619 MonoReflectionModule *result = NULL;
2620 MonoClass *klass = mono_class_from_mono_type (type->type);
2621 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2622 mono_error_set_pending_exception (&error);
2623 return result;
2626 ICALL_EXPORT MonoReflectionAssembly*
2627 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2629 MonoError error;
2630 MonoDomain *domain = mono_domain_get ();
2631 MonoClass *klass = mono_class_from_mono_type (type->type);
2632 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2633 mono_error_set_pending_exception (&error);
2634 return result;
2637 ICALL_EXPORT MonoReflectionType*
2638 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2640 MonoError error;
2641 MonoReflectionType *ret;
2642 MonoDomain *domain = mono_domain_get ();
2643 MonoClass *klass;
2645 if (type->type->byref)
2646 return NULL;
2647 if (type->type->type == MONO_TYPE_VAR) {
2648 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2649 klass = param ? param->owner.klass : NULL;
2650 } else if (type->type->type == MONO_TYPE_MVAR) {
2651 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2652 klass = param ? param->owner.method->klass : NULL;
2653 } else {
2654 klass = mono_class_from_mono_type (type->type)->nested_in;
2657 if (!klass)
2658 return NULL;
2660 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2661 mono_error_set_pending_exception (&error);
2663 return ret;
2666 ICALL_EXPORT MonoStringHandle
2667 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2669 MonoDomain *domain = mono_domain_get ();
2670 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2671 MonoClass *klass = mono_class_from_mono_type (type);
2673 if (type->byref) {
2674 char *n = g_strdup_printf ("%s&", klass->name);
2675 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2677 g_free (n);
2679 return res;
2680 } else {
2681 return mono_string_new_handle (domain, klass->name, error);
2685 ICALL_EXPORT MonoStringHandle
2686 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2688 MonoDomain *domain = mono_domain_get ();
2689 MonoClass *klass = mono_class_from_mono_type_handle (type);
2691 while (klass->nested_in)
2692 klass = klass->nested_in;
2694 if (klass->name_space [0] == '\0')
2695 return NULL_HANDLE_STRING;
2696 else
2697 return mono_string_new_handle (domain, klass->name_space, error);
2700 ICALL_EXPORT gint32
2701 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2703 MonoClass *klass;
2705 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2706 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2707 return 0;
2710 klass = mono_class_from_mono_type (type->type);
2712 return klass->rank;
2715 static MonoArray*
2716 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2718 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2721 ICALL_EXPORT MonoArray*
2722 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2724 MonoError error;
2725 MonoReflectionType *rt;
2726 MonoArray *res;
2727 MonoClass *klass, *pklass;
2728 MonoDomain *domain = mono_object_domain (type);
2729 int i;
2731 klass = mono_class_from_mono_type (type->type);
2733 if (mono_class_is_gtd (klass)) {
2734 MonoGenericContainer *container = mono_class_get_generic_container (klass);
2735 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2736 if (mono_error_set_pending_exception (&error))
2737 return NULL;
2738 for (i = 0; i < container->type_argc; ++i) {
2739 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2741 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2742 if (mono_error_set_pending_exception (&error))
2743 return NULL;
2745 mono_array_setref (res, i, rt);
2747 } else if (mono_class_is_ginst (klass)) {
2748 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
2749 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2750 if (mono_error_set_pending_exception (&error))
2751 return NULL;
2752 for (i = 0; i < inst->type_argc; ++i) {
2753 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2754 if (mono_error_set_pending_exception (&error))
2755 return NULL;
2757 mono_array_setref (res, i, rt);
2759 } else {
2760 res = NULL;
2762 return res;
2765 ICALL_EXPORT gboolean
2766 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2768 MonoClass *klass;
2770 if (!IS_MONOTYPE (type))
2771 return FALSE;
2773 if (type->type->byref)
2774 return FALSE;
2776 klass = mono_class_from_mono_type (type->type);
2777 return mono_class_is_gtd (klass);
2780 ICALL_EXPORT MonoReflectionType*
2781 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2783 MonoError error;
2784 MonoReflectionType *ret;
2785 MonoClass *klass;
2787 if (type->type->byref)
2788 return NULL;
2790 klass = mono_class_from_mono_type (type->type);
2792 if (mono_class_is_gtd (klass)) {
2793 return type; /* check this one */
2795 if (mono_class_is_ginst (klass)) {
2796 MonoClass *generic_class = mono_class_get_generic_class (klass)->container_class;
2797 gpointer tb;
2799 tb = mono_class_get_ref_info (generic_class);
2801 if (generic_class->wastypebuilder && tb)
2802 return (MonoReflectionType *)tb;
2803 else {
2804 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2805 mono_error_set_pending_exception (&error);
2807 return ret;
2810 return NULL;
2813 ICALL_EXPORT MonoReflectionType*
2814 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2816 MonoError error;
2817 MonoReflectionType *ret;
2818 MonoClass *klass;
2819 MonoType *geninst, **types;
2820 int i, count;
2822 g_assert (IS_MONOTYPE (type));
2823 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2824 if (mono_error_set_pending_exception (&error))
2825 return NULL;
2827 count = mono_array_length (type_array);
2828 types = g_new0 (MonoType *, count);
2830 for (i = 0; i < count; i++) {
2831 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2832 types [i] = t->type;
2835 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2836 g_free (types);
2837 if (!geninst) {
2838 mono_error_set_pending_exception (&error);
2839 return NULL;
2842 klass = mono_class_from_mono_type (geninst);
2844 /*we might inflate to the GTD*/
2845 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2846 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2847 return NULL;
2850 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2851 mono_error_set_pending_exception (&error);
2853 return ret;
2856 ICALL_EXPORT gboolean
2857 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2859 MonoClass *klass;
2861 if (!IS_MONOTYPE (type))
2862 return FALSE;
2864 if (type->type->byref)
2865 return FALSE;
2867 klass = mono_class_from_mono_type (type->type);
2868 return mono_class_is_ginst (klass) || mono_class_is_gtd (klass);
2871 ICALL_EXPORT gint32
2872 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2874 if (!IS_MONOTYPE (type))
2875 return -1;
2877 if (is_generic_parameter (type->type))
2878 return mono_type_get_generic_param_num (type->type);
2879 return -1;
2882 ICALL_EXPORT MonoGenericParamInfo *
2883 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2885 return mono_generic_param_info (type->type->data.generic_param);
2888 ICALL_EXPORT MonoBoolean
2889 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2891 return is_generic_parameter (type->type);
2894 ICALL_EXPORT MonoReflectionMethod*
2895 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2896 MonoReflectionMethod* generic)
2898 MonoDomain *domain;
2899 MonoClass *klass;
2900 MonoMethod *method;
2901 gpointer iter;
2902 MonoError error;
2903 MonoReflectionMethod *ret = NULL;
2905 domain = ((MonoObject *)type)->vtable->domain;
2907 klass = mono_class_from_mono_type (type->type);
2908 mono_class_init_checked (klass, &error);
2909 if (mono_error_set_pending_exception (&error))
2910 return NULL;
2912 iter = NULL;
2913 while ((method = mono_class_get_methods (klass, &iter))) {
2914 if (method->token == generic->method->token) {
2915 ret = mono_method_get_object_checked (domain, method, klass, &error);
2916 if (mono_error_set_pending_exception (&error))
2917 return NULL;
2921 return ret;
2924 ICALL_EXPORT MonoReflectionMethod *
2925 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2927 MonoMethod *method;
2928 MonoType *type = ref_type->type;
2929 MonoError error;
2930 MonoReflectionMethod *ret = NULL;
2932 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2933 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2934 return NULL;
2936 if (type->type == MONO_TYPE_VAR)
2937 return NULL;
2939 method = mono_type_get_generic_param_owner (type)->owner.method;
2940 g_assert (method);
2942 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2943 if (!mono_error_ok (&error))
2944 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2945 return ret;
2948 ICALL_EXPORT MonoBoolean
2949 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2951 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2952 return FALSE;
2955 ICALL_EXPORT MonoBoolean
2956 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2958 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2959 return FALSE;
2962 ICALL_EXPORT void
2963 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2965 MonoDomain *domain = mono_domain_get ();
2966 MonoImage *image = method->method->klass->image;
2967 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2968 MonoTableInfo *tables = image->tables;
2969 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2970 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2971 guint32 im_cols [MONO_IMPLMAP_SIZE];
2972 guint32 scope_token;
2973 const char *import = NULL;
2974 const char *scope = NULL;
2976 if (image_is_dynamic (image)) {
2977 MonoReflectionMethodAux *method_aux =
2978 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2979 if (method_aux) {
2980 import = method_aux->dllentry;
2981 scope = method_aux->dll;
2984 if (!import || !scope) {
2985 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2986 return;
2989 else {
2990 if (piinfo->implmap_idx) {
2991 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2993 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2994 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2995 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2996 scope = mono_metadata_string_heap (image, scope_token);
3000 *flags = piinfo->piflags;
3001 *entry_point = mono_string_new (domain, import);
3002 *dll_name = mono_string_new (domain, scope);
3005 ICALL_EXPORT MonoReflectionMethod *
3006 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3008 MonoMethodInflated *imethod;
3009 MonoMethod *result;
3010 MonoReflectionMethod *ret = NULL;
3011 MonoError error;
3013 if (method->method->is_generic)
3014 return method;
3016 if (!method->method->is_inflated)
3017 return NULL;
3019 imethod = (MonoMethodInflated *) method->method;
3021 result = imethod->declaring;
3022 /* Not a generic method. */
3023 if (!result->is_generic)
3024 return NULL;
3026 if (image_is_dynamic (method->method->klass->image)) {
3027 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3028 MonoReflectionMethod *res;
3031 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3032 * the dynamic case as well ?
3034 mono_image_lock ((MonoImage*)image);
3035 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3036 mono_image_unlock ((MonoImage*)image);
3038 if (res)
3039 return res;
3042 if (imethod->context.class_inst) {
3043 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3044 /*Generic methods gets the context of the GTD.*/
3045 if (mono_class_get_context (klass)) {
3046 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3047 if (!mono_error_ok (&error))
3048 goto leave;
3052 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3053 leave:
3054 if (!mono_error_ok (&error))
3055 mono_error_set_pending_exception (&error);
3056 return ret;
3059 ICALL_EXPORT gboolean
3060 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3062 return mono_method_signature (method->method)->generic_param_count != 0;
3065 ICALL_EXPORT gboolean
3066 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3068 return method->method->is_generic;
3071 ICALL_EXPORT MonoArray*
3072 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3074 MonoError error;
3075 MonoReflectionType *rt;
3076 MonoArray *res;
3077 MonoDomain *domain;
3078 int count, i;
3080 domain = mono_object_domain (method);
3082 if (method->method->is_inflated) {
3083 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3085 if (inst) {
3086 count = inst->type_argc;
3087 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3088 if (mono_error_set_pending_exception (&error))
3089 return NULL;
3091 for (i = 0; i < count; i++) {
3092 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3093 if (mono_error_set_pending_exception (&error))
3094 return NULL;
3096 mono_array_setref (res, i, rt);
3099 return res;
3103 count = mono_method_signature (method->method)->generic_param_count;
3104 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3105 if (mono_error_set_pending_exception (&error))
3106 return NULL;
3108 for (i = 0; i < count; i++) {
3109 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3110 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3111 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3113 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3114 if (mono_error_set_pending_exception (&error))
3115 return NULL;
3117 mono_array_setref (res, i, rt);
3120 return res;
3123 ICALL_EXPORT MonoObject *
3124 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3126 MonoError error;
3128 * Invoke from reflection is supposed to always be a virtual call (the API
3129 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3130 * greater flexibility.
3132 MonoMethod *m = method->method;
3133 MonoMethodSignature *sig = mono_method_signature (m);
3134 MonoImage *image;
3135 int pcount;
3136 void *obj = this_arg;
3138 *exc = NULL;
3140 if (mono_security_core_clr_enabled () &&
3141 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3142 mono_error_set_pending_exception (&error);
3143 return NULL;
3146 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3147 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3148 mono_error_cleanup (&error); /* FIXME does this make sense? */
3149 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3150 return NULL;
3153 if (this_arg) {
3154 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3155 if (!is_ok (&error)) {
3156 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3157 return NULL;
3159 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3160 char *target_name = mono_type_get_full_name (m->klass);
3161 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3162 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3163 g_free (msg);
3164 g_free (target_name);
3165 g_free (this_name);
3166 return NULL;
3168 m = mono_object_get_virtual_method (this_arg, m);
3169 /* must pass the pointer to the value for valuetype methods */
3170 if (m->klass->valuetype)
3171 obj = mono_object_unbox (this_arg);
3172 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3173 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3174 return NULL;
3178 if (sig->ret->byref) {
3179 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"));
3180 return NULL;
3183 pcount = params? mono_array_length (params): 0;
3184 if (pcount != sig->param_count) {
3185 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3186 return NULL;
3189 if (mono_class_is_abstract (m->klass) && !strcmp (m->name, ".ctor") && !this_arg) {
3190 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."));
3191 return NULL;
3194 image = m->klass->image;
3195 if (image->assembly->ref_only) {
3196 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."));
3197 return NULL;
3200 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3201 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3202 return NULL;
3205 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3206 MonoArray *arr;
3207 int i;
3208 uintptr_t *lengths;
3209 intptr_t *lower_bounds;
3210 pcount = mono_array_length (params);
3211 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3212 /* Note: the synthetized array .ctors have int32 as argument type */
3213 for (i = 0; i < pcount; ++i)
3214 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3216 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3217 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3218 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3219 if (!mono_error_ok (&error)) {
3220 mono_error_set_pending_exception (&error);
3221 return NULL;
3224 for (i = 0; i < mono_array_length (arr); ++i) {
3225 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3226 if (!mono_error_ok (&error)) {
3227 mono_error_set_pending_exception (&error);
3228 return NULL;
3230 mono_array_setref_fast (arr, i, subarray);
3232 return (MonoObject*)arr;
3235 if (m->klass->rank == pcount) {
3236 /* Only lengths provided. */
3237 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3238 if (!mono_error_ok (&error)) {
3239 mono_error_set_pending_exception (&error);
3240 return NULL;
3243 return (MonoObject*)arr;
3244 } else {
3245 g_assert (pcount == (m->klass->rank * 2));
3246 /* The arguments are lower-bound-length pairs */
3247 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3249 for (i = 0; i < pcount / 2; ++i) {
3250 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3251 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3254 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3255 if (!mono_error_ok (&error)) {
3256 mono_error_set_pending_exception (&error);
3257 return NULL;
3260 return (MonoObject*)arr;
3263 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3264 mono_error_set_pending_exception (&error);
3265 return result;
3268 #ifndef DISABLE_REMOTING
3269 ICALL_EXPORT MonoObject *
3270 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3272 MonoError error;
3273 MonoDomain *domain = mono_object_domain (method);
3274 MonoMethod *m = method->method;
3275 MonoMethodSignature *sig = mono_method_signature (m);
3276 MonoArray *out_args;
3277 MonoObject *result;
3278 int i, j, outarg_count = 0;
3280 if (m->klass == mono_defaults.object_class) {
3281 if (!strcmp (m->name, "FieldGetter")) {
3282 MonoClass *k = this_arg->vtable->klass;
3283 MonoString *name;
3284 char *str;
3286 /* If this is a proxy, then it must be a CBO */
3287 if (k == mono_defaults.transparent_proxy_class) {
3288 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3289 this_arg = tp->rp->unwrapped_server;
3290 g_assert (this_arg);
3291 k = this_arg->vtable->klass;
3294 name = mono_array_get (params, MonoString *, 1);
3295 str = mono_string_to_utf8_checked (name, &error);
3296 if (mono_error_set_pending_exception (&error))
3297 return NULL;
3299 do {
3300 MonoClassField* field = mono_class_get_field_from_name (k, str);
3301 if (field) {
3302 g_free (str);
3303 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3304 if (field_klass->valuetype) {
3305 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3306 if (mono_error_set_pending_exception (&error))
3307 return NULL;
3308 } else
3309 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3311 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3312 if (mono_error_set_pending_exception (&error))
3313 return NULL;
3314 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3315 mono_array_setref (out_args, 0, result);
3316 return NULL;
3318 k = k->parent;
3319 } while (k);
3321 g_free (str);
3322 g_assert_not_reached ();
3324 } else if (!strcmp (m->name, "FieldSetter")) {
3325 MonoClass *k = this_arg->vtable->klass;
3326 MonoString *name;
3327 guint32 size;
3328 gint32 align;
3329 char *str;
3331 /* If this is a proxy, then it must be a CBO */
3332 if (k == mono_defaults.transparent_proxy_class) {
3333 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3334 this_arg = tp->rp->unwrapped_server;
3335 g_assert (this_arg);
3336 k = this_arg->vtable->klass;
3339 name = mono_array_get (params, MonoString *, 1);
3340 str = mono_string_to_utf8_checked (name, &error);
3341 if (mono_error_set_pending_exception (&error))
3342 return NULL;
3344 do {
3345 MonoClassField* field = mono_class_get_field_from_name (k, str);
3346 if (field) {
3347 g_free (str);
3348 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3349 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3351 if (field_klass->valuetype) {
3352 size = mono_type_size (field->type, &align);
3353 g_assert (size == mono_class_value_size (field_klass, NULL));
3354 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3355 } else {
3356 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3359 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3360 if (mono_error_set_pending_exception (&error))
3361 return NULL;
3362 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3364 return NULL;
3367 k = k->parent;
3368 } while (k);
3370 g_free (str);
3371 g_assert_not_reached ();
3376 for (i = 0; i < mono_array_length (params); i++) {
3377 if (sig->params [i]->byref)
3378 outarg_count++;
3381 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3382 if (mono_error_set_pending_exception (&error))
3383 return NULL;
3385 /* handle constructors only for objects already allocated */
3386 if (!strcmp (method->method->name, ".ctor"))
3387 g_assert (this_arg);
3389 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3390 g_assert (!method->method->klass->valuetype);
3391 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3392 if (mono_error_set_pending_exception (&error))
3393 return NULL;
3395 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3396 if (sig->params [i]->byref) {
3397 gpointer arg;
3398 arg = mono_array_get (params, gpointer, i);
3399 mono_array_setref (out_args, j, arg);
3400 j++;
3404 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3406 return result;
3408 #endif
3410 static guint64
3411 read_enum_value (const char *mem, int type)
3413 switch (type) {
3414 case MONO_TYPE_BOOLEAN:
3415 case MONO_TYPE_U1:
3416 return *(guint8*)mem;
3417 case MONO_TYPE_I1:
3418 return *(gint8*)mem;
3419 case MONO_TYPE_CHAR:
3420 case MONO_TYPE_U2:
3421 return read16 (mem);
3422 case MONO_TYPE_I2:
3423 return (gint16) read16 (mem);
3424 case MONO_TYPE_U4:
3425 return read32 (mem);
3426 case MONO_TYPE_I4:
3427 return (gint32) read32 (mem);
3428 case MONO_TYPE_U8:
3429 case MONO_TYPE_I8:
3430 return read64 (mem);
3431 default:
3432 g_assert_not_reached ();
3434 return 0;
3437 static void
3438 write_enum_value (char *mem, int type, guint64 value)
3440 switch (type) {
3441 case MONO_TYPE_U1:
3442 case MONO_TYPE_I1: {
3443 guint8 *p = (guint8*)mem;
3444 *p = value;
3445 break;
3447 case MONO_TYPE_U2:
3448 case MONO_TYPE_I2:
3449 case MONO_TYPE_CHAR: {
3450 guint16 *p = (guint16 *)mem;
3451 *p = value;
3452 break;
3454 case MONO_TYPE_U4:
3455 case MONO_TYPE_I4: {
3456 guint32 *p = (guint32 *)mem;
3457 *p = value;
3458 break;
3460 case MONO_TYPE_U8:
3461 case MONO_TYPE_I8: {
3462 guint64 *p = (guint64 *)mem;
3463 *p = value;
3464 break;
3466 default:
3467 g_assert_not_reached ();
3469 return;
3472 ICALL_EXPORT MonoObject *
3473 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3475 MonoError error;
3476 MonoDomain *domain;
3477 MonoClass *enumc;
3478 MonoObject *res;
3479 MonoType *etype;
3481 domain = mono_object_domain (enumType);
3482 enumc = mono_class_from_mono_type (enumType->type);
3484 mono_class_init_checked (enumc, &error);
3485 if (mono_error_set_pending_exception (&error))
3486 return NULL;
3488 etype = mono_class_enum_basetype (enumc);
3490 res = mono_object_new_checked (domain, enumc, &error);
3491 if (mono_error_set_pending_exception (&error))
3492 return NULL;
3493 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3495 return res;
3498 ICALL_EXPORT MonoBoolean
3499 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3501 int size = mono_class_value_size (a->vtable->klass, NULL);
3502 guint64 a_val = 0, b_val = 0;
3504 memcpy (&a_val, mono_object_unbox (a), size);
3505 memcpy (&b_val, mono_object_unbox (b), size);
3507 return (a_val & b_val) == b_val;
3510 ICALL_EXPORT MonoObject *
3511 ves_icall_System_Enum_get_value (MonoObject *eobj)
3513 MonoError error;
3514 MonoObject *res;
3515 MonoClass *enumc;
3516 gpointer dst;
3517 gpointer src;
3518 int size;
3520 if (!eobj)
3521 return NULL;
3523 g_assert (eobj->vtable->klass->enumtype);
3525 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3526 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3527 if (mono_error_set_pending_exception (&error))
3528 return NULL;
3529 dst = (char *)res + sizeof (MonoObject);
3530 src = (char *)eobj + sizeof (MonoObject);
3531 size = mono_class_value_size (enumc, NULL);
3533 memcpy (dst, src, size);
3535 return res;
3538 ICALL_EXPORT MonoReflectionType *
3539 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3541 MonoError error;
3542 MonoReflectionType *ret;
3543 MonoType *etype;
3544 MonoClass *klass;
3546 klass = mono_class_from_mono_type (type->type);
3547 mono_class_init_checked (klass, &error);
3548 if (mono_error_set_pending_exception (&error))
3549 return NULL;
3551 etype = mono_class_enum_basetype (klass);
3552 if (!etype) {
3553 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3554 return NULL;
3557 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3558 mono_error_set_pending_exception (&error);
3560 return ret;
3563 ICALL_EXPORT int
3564 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3566 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3567 gpointer odata = (char *)other + sizeof (MonoObject);
3568 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3569 g_assert (basetype);
3571 if (other == NULL)
3572 return 1;
3574 if (eobj->vtable->klass != other->vtable->klass)
3575 return 2;
3577 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3578 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3579 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3580 if (me == other) \
3581 return 0; \
3582 return me > other ? 1 : -1; \
3583 } while (0)
3585 switch (basetype->type) {
3586 case MONO_TYPE_U1:
3587 COMPARE_ENUM_VALUES (guint8);
3588 case MONO_TYPE_I1:
3589 COMPARE_ENUM_VALUES (gint8);
3590 case MONO_TYPE_CHAR:
3591 case MONO_TYPE_U2:
3592 COMPARE_ENUM_VALUES (guint16);
3593 case MONO_TYPE_I2:
3594 COMPARE_ENUM_VALUES (gint16);
3595 case MONO_TYPE_U4:
3596 COMPARE_ENUM_VALUES (guint32);
3597 case MONO_TYPE_I4:
3598 COMPARE_ENUM_VALUES (gint32);
3599 case MONO_TYPE_U8:
3600 COMPARE_ENUM_VALUES (guint64);
3601 case MONO_TYPE_I8:
3602 COMPARE_ENUM_VALUES (gint64);
3603 default:
3604 break;
3606 #undef COMPARE_ENUM_VALUES
3607 /* indicates that the enum was of an unsupported unerlying type */
3608 return 3;
3611 ICALL_EXPORT int
3612 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3614 gpointer data = (char *)eobj + sizeof (MonoObject);
3615 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3616 g_assert (basetype);
3618 switch (basetype->type) {
3619 case MONO_TYPE_I1: {
3620 gint8 value = *((gint8*)data);
3621 return ((int)value ^ (int)value << 8);
3623 case MONO_TYPE_U1:
3624 return *((guint8*)data);
3625 case MONO_TYPE_CHAR:
3626 case MONO_TYPE_U2:
3627 return *((guint16*)data);
3629 case MONO_TYPE_I2: {
3630 gint16 value = *((gint16*)data);
3631 return ((int)(guint16)value | (((int)value) << 16));
3633 case MONO_TYPE_U4:
3634 return *((guint32*)data);
3635 case MONO_TYPE_I4:
3636 return *((gint32*)data);
3637 case MONO_TYPE_U8:
3638 case MONO_TYPE_I8: {
3639 gint64 value = *((gint64*)data);
3640 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3642 default:
3643 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3645 return 0;
3648 ICALL_EXPORT MonoBoolean
3649 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3651 MonoError error;
3652 MonoDomain *domain = mono_object_domain (type);
3653 MonoClass *enumc = mono_class_from_mono_type (type->type);
3654 guint j = 0, nvalues;
3655 gpointer iter;
3656 MonoClassField *field;
3657 int base_type;
3658 guint64 field_value, previous_value = 0;
3659 gboolean sorted = TRUE;
3661 mono_class_init_checked (enumc, &error);
3662 if (mono_error_set_pending_exception (&error))
3663 return FALSE;
3666 if (!enumc->enumtype) {
3667 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3668 return TRUE;
3671 base_type = mono_class_enum_basetype (enumc)->type;
3673 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3674 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3675 if (mono_error_set_pending_exception (&error))
3676 return FALSE;
3677 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3678 if (mono_error_set_pending_exception (&error))
3679 return FALSE;
3681 iter = NULL;
3682 while ((field = mono_class_get_fields (enumc, &iter))) {
3683 const char *p;
3684 MonoTypeEnum def_type;
3686 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3687 continue;
3688 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3689 continue;
3690 if (mono_field_is_deleted (field))
3691 continue;
3692 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3694 p = mono_class_get_field_default_value (field, &def_type);
3695 /* len = */ mono_metadata_decode_blob_size (p, &p);
3697 field_value = read_enum_value (p, base_type);
3698 mono_array_set (*values, guint64, j, field_value);
3700 if (previous_value > field_value)
3701 sorted = FALSE;
3703 previous_value = field_value;
3704 ++j;
3707 return sorted;
3710 enum {
3711 BFLAGS_IgnoreCase = 1,
3712 BFLAGS_DeclaredOnly = 2,
3713 BFLAGS_Instance = 4,
3714 BFLAGS_Static = 8,
3715 BFLAGS_Public = 0x10,
3716 BFLAGS_NonPublic = 0x20,
3717 BFLAGS_FlattenHierarchy = 0x40,
3718 BFLAGS_InvokeMethod = 0x100,
3719 BFLAGS_CreateInstance = 0x200,
3720 BFLAGS_GetField = 0x400,
3721 BFLAGS_SetField = 0x800,
3722 BFLAGS_GetProperty = 0x1000,
3723 BFLAGS_SetProperty = 0x2000,
3724 BFLAGS_ExactBinding = 0x10000,
3725 BFLAGS_SuppressChangeType = 0x20000,
3726 BFLAGS_OptionalParamBinding = 0x40000
3729 ICALL_EXPORT GPtrArray*
3730 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3732 MonoError error;
3733 MonoClass *startklass, *klass;
3734 int match;
3735 gpointer iter;
3736 int (*compare_func) (const char *s1, const char *s2) = NULL;
3737 MonoClassField *field;
3739 if (type->type->byref) {
3740 return g_ptr_array_new ();
3743 mono_error_init (&error);
3745 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3747 klass = startklass = mono_class_from_mono_type (type->type);
3749 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3751 handle_parent:
3752 if (mono_class_has_failure (klass)) {
3753 mono_error_set_for_class_failure (&error, klass);
3754 goto fail;
3757 iter = NULL;
3758 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3759 guint32 flags = mono_field_get_flags (field);
3760 match = 0;
3761 if (mono_field_is_deleted_with_flags (field, flags))
3762 continue;
3763 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3764 if (bflags & BFLAGS_Public)
3765 match++;
3766 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3767 if (bflags & BFLAGS_NonPublic) {
3768 match++;
3771 if (!match)
3772 continue;
3773 match = 0;
3774 if (flags & FIELD_ATTRIBUTE_STATIC) {
3775 if (bflags & BFLAGS_Static)
3776 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3777 match++;
3778 } else {
3779 if (bflags & BFLAGS_Instance)
3780 match++;
3783 if (!match)
3784 continue;
3786 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3787 continue;
3789 g_ptr_array_add (ptr_array, field);
3791 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3792 goto handle_parent;
3794 return ptr_array;
3796 fail:
3797 g_ptr_array_free (ptr_array, TRUE);
3798 mono_error_set_pending_exception (&error);
3799 return NULL;
3802 static gboolean
3803 method_nonpublic (MonoMethod* method, gboolean start_klass)
3805 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3806 case METHOD_ATTRIBUTE_ASSEM:
3807 return (start_klass || mono_defaults.generic_ilist_class);
3808 case METHOD_ATTRIBUTE_PRIVATE:
3809 return start_klass;
3810 case METHOD_ATTRIBUTE_PUBLIC:
3811 return FALSE;
3812 default:
3813 return TRUE;
3817 GPtrArray*
3818 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3820 GPtrArray *array;
3821 MonoClass *startklass;
3822 MonoMethod *method;
3823 gpointer iter;
3824 int match, nslots;
3825 /*FIXME, use MonoBitSet*/
3826 guint32 method_slots_default [8];
3827 guint32 *method_slots = NULL;
3828 int (*compare_func) (const char *s1, const char *s2) = NULL;
3830 array = g_ptr_array_new ();
3831 startklass = klass;
3832 mono_error_init (error);
3834 if (name != NULL)
3835 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3837 /* An optimization for calls made from Delegate:CreateDelegate () */
3838 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3839 method = mono_get_delegate_invoke (klass);
3840 g_assert (method);
3842 g_ptr_array_add (array, method);
3843 return array;
3846 mono_class_setup_methods (klass);
3847 mono_class_setup_vtable (klass);
3848 if (mono_class_has_failure (klass))
3849 goto loader_error;
3851 if (is_generic_parameter (&klass->byval_arg))
3852 nslots = mono_class_get_vtable_size (klass->parent);
3853 else
3854 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3855 if (nslots >= sizeof (method_slots_default) * 8) {
3856 method_slots = g_new0 (guint32, nslots / 32 + 1);
3857 } else {
3858 method_slots = method_slots_default;
3859 memset (method_slots, 0, sizeof (method_slots_default));
3861 handle_parent:
3862 mono_class_setup_methods (klass);
3863 mono_class_setup_vtable (klass);
3864 if (mono_class_has_failure (klass))
3865 goto loader_error;
3867 iter = NULL;
3868 while ((method = mono_class_get_methods (klass, &iter))) {
3869 match = 0;
3870 if (method->slot != -1) {
3871 g_assert (method->slot < nslots);
3872 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3873 continue;
3874 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3875 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3878 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3879 continue;
3880 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3881 if (bflags & BFLAGS_Public)
3882 match++;
3883 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3884 match++;
3886 if (!match)
3887 continue;
3888 match = 0;
3889 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3890 if (bflags & BFLAGS_Static)
3891 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3892 match++;
3893 } else {
3894 if (bflags & BFLAGS_Instance)
3895 match++;
3898 if (!match)
3899 continue;
3901 if (name != NULL) {
3902 if (compare_func (name, method->name))
3903 continue;
3906 match = 0;
3907 g_ptr_array_add (array, method);
3909 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3910 goto handle_parent;
3911 if (method_slots != method_slots_default)
3912 g_free (method_slots);
3914 return array;
3916 loader_error:
3917 if (method_slots != method_slots_default)
3918 g_free (method_slots);
3919 g_ptr_array_free (array, TRUE);
3921 g_assert (mono_class_has_failure (klass));
3922 mono_error_set_for_class_failure (error, klass);
3923 return NULL;
3926 ICALL_EXPORT GPtrArray*
3927 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3929 MonoError error;
3930 GPtrArray *method_array;
3931 MonoClass *klass;
3933 klass = mono_class_from_mono_type (type->type);
3934 if (type->type->byref) {
3935 return g_ptr_array_new ();
3938 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3939 mono_error_set_pending_exception (&error);
3940 return method_array;
3943 ICALL_EXPORT GPtrArray*
3944 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3946 MonoClass *startklass, *klass;
3947 MonoMethod *method;
3948 int match;
3949 gpointer iter = NULL;
3950 GPtrArray *res_array;
3951 MonoError error;
3953 if (type->type->byref) {
3954 return g_ptr_array_new ();
3957 klass = startklass = mono_class_from_mono_type (type->type);
3959 mono_class_setup_methods (klass);
3960 if (mono_class_has_failure (klass)) {
3961 mono_error_init (&error);
3962 mono_error_set_for_class_failure (&error, klass);
3963 mono_error_set_pending_exception (&error);
3964 return NULL;
3967 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3969 iter = NULL;
3970 while ((method = mono_class_get_methods (klass, &iter))) {
3971 match = 0;
3972 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3973 continue;
3974 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3975 if (bflags & BFLAGS_Public)
3976 match++;
3977 } else {
3978 if (bflags & BFLAGS_NonPublic)
3979 match++;
3981 if (!match)
3982 continue;
3983 match = 0;
3984 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3985 if (bflags & BFLAGS_Static)
3986 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3987 match++;
3988 } else {
3989 if (bflags & BFLAGS_Instance)
3990 match++;
3993 if (!match)
3994 continue;
3995 g_ptr_array_add (res_array, method);
3998 return res_array;
4001 static guint
4002 property_hash (gconstpointer data)
4004 MonoProperty *prop = (MonoProperty*)data;
4006 return g_str_hash (prop->name);
4009 static gboolean
4010 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4012 if (method1->slot != -1 && method1->slot == method2->slot)
4013 return TRUE;
4015 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4016 if (method1->is_inflated)
4017 method1 = ((MonoMethodInflated*) method1)->declaring;
4018 if (method2->is_inflated)
4019 method2 = ((MonoMethodInflated*) method2)->declaring;
4022 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4025 static gboolean
4026 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4028 // Properties are hide-by-name-and-signature
4029 if (!g_str_equal (prop1->name, prop2->name))
4030 return FALSE;
4032 /* If we see a property in a generic method, we want to
4033 compare the generic signatures, not the inflated signatures
4034 because we might conflate two properties that were
4035 distinct:
4037 class Foo<T,U> {
4038 public T this[T t] { getter { return t; } } // method 1
4039 public U this[U u] { getter { return u; } } // method 2
4042 If we see int Foo<int,int>::Item[int] we need to know if
4043 the indexer came from method 1 or from method 2, and we
4044 shouldn't conflate them. (Bugzilla 36283)
4046 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4047 return FALSE;
4049 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4050 return FALSE;
4052 return TRUE;
4055 static gboolean
4056 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4058 if (!accessor)
4059 return FALSE;
4061 return method_nonpublic (accessor, start_klass);
4064 ICALL_EXPORT GPtrArray*
4065 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4067 MonoError error;
4068 MonoClass *startklass, *klass;
4069 MonoMethod *method;
4070 MonoProperty *prop;
4071 int match;
4072 guint32 flags;
4073 int (*compare_func) (const char *s1, const char *s2) = NULL;
4074 gpointer iter;
4075 GHashTable *properties = NULL;
4076 GPtrArray *res_array;
4078 if (type->type->byref) {
4079 return g_ptr_array_new ();
4082 mono_error_init (&error);
4084 klass = startklass = mono_class_from_mono_type (type->type);
4086 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4088 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4090 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4091 handle_parent:
4092 mono_class_setup_methods (klass);
4093 mono_class_setup_vtable (klass);
4094 if (mono_class_has_failure (klass)) {
4095 mono_error_set_for_class_failure (&error, klass);
4096 goto loader_error;
4099 iter = NULL;
4100 while ((prop = mono_class_get_properties (klass, &iter))) {
4101 match = 0;
4102 method = prop->get;
4103 if (!method)
4104 method = prop->set;
4105 if (method)
4106 flags = method->flags;
4107 else
4108 flags = 0;
4109 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4110 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4111 if (bflags & BFLAGS_Public)
4112 match++;
4113 } else if (bflags & BFLAGS_NonPublic) {
4114 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4115 property_accessor_nonpublic(prop->set, startklass == klass)) {
4116 match++;
4119 if (!match)
4120 continue;
4121 match = 0;
4122 if (flags & METHOD_ATTRIBUTE_STATIC) {
4123 if (bflags & BFLAGS_Static)
4124 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4125 match++;
4126 } else {
4127 if (bflags & BFLAGS_Instance)
4128 match++;
4131 if (!match)
4132 continue;
4133 match = 0;
4135 if (propname != NULL && compare_func (propname, prop->name))
4136 continue;
4138 if (g_hash_table_lookup (properties, prop))
4139 continue;
4141 g_ptr_array_add (res_array, prop);
4143 g_hash_table_insert (properties, prop, prop);
4145 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4146 goto handle_parent;
4148 g_hash_table_destroy (properties);
4150 return res_array;
4153 loader_error:
4154 if (properties)
4155 g_hash_table_destroy (properties);
4156 g_ptr_array_free (res_array, TRUE);
4158 mono_error_set_pending_exception (&error);
4160 return NULL;
4163 static guint
4164 event_hash (gconstpointer data)
4166 MonoEvent *event = (MonoEvent*)data;
4168 return g_str_hash (event->name);
4171 static gboolean
4172 event_equal (MonoEvent *event1, MonoEvent *event2)
4174 // Events are hide-by-name
4175 return g_str_equal (event1->name, event2->name);
4178 ICALL_EXPORT GPtrArray*
4179 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4181 MonoError error;
4182 MonoClass *startklass, *klass;
4183 MonoMethod *method;
4184 MonoEvent *event;
4185 int match;
4186 gpointer iter;
4187 int (*compare_func) (const char *s1, const char *s2) = NULL;
4188 GHashTable *events = NULL;
4189 GPtrArray *res_array;
4191 if (type->type->byref) {
4192 return g_ptr_array_new ();
4195 mono_error_init (&error);
4197 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4199 res_array = g_ptr_array_sized_new (4);
4201 klass = startklass = mono_class_from_mono_type (type->type);
4203 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4204 handle_parent:
4205 mono_class_setup_methods (klass);
4206 mono_class_setup_vtable (klass);
4207 if (mono_class_has_failure (klass)) {
4208 mono_error_set_for_class_failure (&error, klass);
4209 goto failure;
4212 iter = NULL;
4213 while ((event = mono_class_get_events (klass, &iter))) {
4214 match = 0;
4215 method = event->add;
4216 if (!method)
4217 method = event->remove;
4218 if (!method)
4219 method = event->raise;
4220 if (method) {
4221 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4222 if (bflags & BFLAGS_Public)
4223 match++;
4224 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4225 if (bflags & BFLAGS_NonPublic)
4226 match++;
4229 else
4230 if (bflags & BFLAGS_NonPublic)
4231 match ++;
4232 if (!match)
4233 continue;
4234 match = 0;
4235 if (method) {
4236 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4237 if (bflags & BFLAGS_Static)
4238 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4239 match++;
4240 } else {
4241 if (bflags & BFLAGS_Instance)
4242 match++;
4245 else
4246 if (bflags & BFLAGS_Instance)
4247 match ++;
4248 if (!match)
4249 continue;
4251 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4252 continue;
4254 if (g_hash_table_lookup (events, event))
4255 continue;
4257 g_ptr_array_add (res_array, event);
4259 g_hash_table_insert (events, event, event);
4261 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4262 goto handle_parent;
4264 g_hash_table_destroy (events);
4266 return res_array;
4268 failure:
4269 if (events != NULL)
4270 g_hash_table_destroy (events);
4272 g_ptr_array_free (res_array, TRUE);
4274 mono_error_set_pending_exception (&error);
4275 return NULL;
4278 ICALL_EXPORT GPtrArray *
4279 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4281 MonoClass *klass;
4282 int match;
4283 MonoClass *nested;
4284 gpointer iter;
4285 GPtrArray *res_array;
4287 if (type->type->byref) {
4288 return g_ptr_array_new ();
4291 klass = mono_class_from_mono_type (type->type);
4294 * If a nested type is generic, return its generic type definition.
4295 * Note that this means that the return value is essentially the set
4296 * of nested types of the generic type definition of @klass.
4298 * A note in MSDN claims that a generic type definition can have
4299 * nested types that aren't generic. In any case, the container of that
4300 * nested type would be the generic type definition.
4302 if (mono_class_is_ginst (klass))
4303 klass = mono_class_get_generic_class (klass)->container_class;
4305 res_array = g_ptr_array_new ();
4307 iter = NULL;
4308 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4309 match = 0;
4310 if ((mono_class_get_flags (nested) & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4311 if (bflags & BFLAGS_Public)
4312 match++;
4313 } else {
4314 if (bflags & BFLAGS_NonPublic)
4315 match++;
4317 if (!match)
4318 continue;
4320 if (str != NULL && strcmp (nested->name, str))
4321 continue;
4323 g_ptr_array_add (res_array, &nested->byval_arg);
4326 return res_array;
4329 ICALL_EXPORT MonoReflectionType*
4330 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4332 MonoError error;
4333 MonoReflectionType *ret;
4334 gchar *str;
4335 MonoType *type = NULL;
4336 MonoTypeNameParse info;
4337 gboolean type_resolve;
4339 /* On MS.NET, this does not fire a TypeResolve event */
4340 type_resolve = TRUE;
4341 str = mono_string_to_utf8_checked (name, &error);
4342 if (mono_error_set_pending_exception (&error))
4343 return NULL;
4344 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4345 if (!mono_reflection_parse_type (str, &info)) {
4346 g_free (str);
4347 mono_reflection_free_type_info (&info);
4348 if (throwOnError) {
4349 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4350 return NULL;
4352 /*g_print ("failed parse\n");*/
4353 return NULL;
4356 if (info.assembly.name) {
4357 g_free (str);
4358 mono_reflection_free_type_info (&info);
4359 if (throwOnError) {
4360 /* 1.0 and 2.0 throw different exceptions */
4361 if (mono_defaults.generic_ilist_class)
4362 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4363 else
4364 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4365 return NULL;
4367 return NULL;
4370 if (module != NULL) {
4371 if (module->image) {
4372 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4373 if (!is_ok (&error)) {
4374 g_free (str);
4375 mono_reflection_free_type_info (&info);
4376 mono_error_set_pending_exception (&error);
4377 return NULL;
4379 } else
4380 type = NULL;
4382 else
4383 if (assembly_is_dynamic (assembly->assembly)) {
4384 /* Enumerate all modules */
4385 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4386 int i;
4388 type = NULL;
4389 if (abuilder->modules) {
4390 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4391 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4392 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4393 if (!is_ok (&error)) {
4394 g_free (str);
4395 mono_reflection_free_type_info (&info);
4396 mono_error_set_pending_exception (&error);
4397 return NULL;
4399 if (type)
4400 break;
4404 if (!type && abuilder->loaded_modules) {
4405 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4406 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4407 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4408 if (!is_ok (&error)) {
4409 g_free (str);
4410 mono_reflection_free_type_info (&info);
4411 mono_error_set_pending_exception (&error);
4412 return NULL;
4414 if (type)
4415 break;
4419 else {
4420 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4421 if (!is_ok (&error)) {
4422 g_free (str);
4423 mono_reflection_free_type_info (&info);
4424 mono_error_set_pending_exception (&error);
4425 return NULL;
4428 g_free (str);
4429 mono_reflection_free_type_info (&info);
4430 if (!type) {
4431 MonoException *e = NULL;
4433 if (throwOnError)
4434 e = mono_get_exception_type_load (name, NULL);
4436 if (e != NULL)
4437 mono_set_pending_exception (e);
4438 return NULL;
4441 if (type->type == MONO_TYPE_CLASS) {
4442 MonoClass *klass = mono_type_get_class (type);
4444 /* need to report exceptions ? */
4445 if (throwOnError && mono_class_has_failure (klass)) {
4446 /* report SecurityException (or others) that occured when loading the assembly */
4447 mono_error_set_for_class_failure (&error, klass);
4448 mono_error_set_pending_exception (&error);
4449 return NULL;
4453 /* g_print ("got it\n"); */
4454 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4455 mono_error_set_pending_exception (&error);
4457 return ret;
4460 static gboolean
4461 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4463 gchar *content;
4464 gchar *shadow_ini_file;
4465 gsize len;
4467 /* Check for shadow-copied assembly */
4468 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4469 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4470 content = NULL;
4471 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4472 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4473 if (content) {
4474 g_free (content);
4475 content = NULL;
4478 g_free (shadow_ini_file);
4479 if (content != NULL) {
4480 if (*filename)
4481 g_free (*filename);
4482 *filename = content;
4483 return TRUE;
4486 return FALSE;
4489 ICALL_EXPORT MonoString *
4490 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4492 MonoDomain *domain = mono_object_domain (assembly);
4493 MonoAssembly *mass = assembly->assembly;
4494 MonoString *res = NULL;
4495 gchar *uri;
4496 gchar *absolute;
4497 gchar *dirname;
4499 if (g_path_is_absolute (mass->image->name)) {
4500 absolute = g_strdup (mass->image->name);
4501 dirname = g_path_get_dirname (absolute);
4502 } else {
4503 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4504 dirname = g_strdup (mass->basedir);
4507 replace_shadow_path (domain, dirname, &absolute);
4508 g_free (dirname);
4510 mono_icall_make_platform_path (absolute);
4512 if (escaped) {
4513 uri = g_filename_to_uri (absolute, NULL, NULL);
4514 } else {
4515 const gchar *prepend = mono_icall_get_file_path_prefix (absolute);
4516 uri = g_strconcat (prepend, absolute, NULL);
4519 if (uri) {
4520 res = mono_string_new (domain, uri);
4521 g_free (uri);
4523 g_free (absolute);
4524 return res;
4527 ICALL_EXPORT MonoBoolean
4528 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4530 MonoAssembly *mass = assembly->assembly;
4532 return mass->in_gac;
4535 ICALL_EXPORT MonoReflectionAssembly*
4536 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4538 MonoError error;
4539 gchar *name;
4540 MonoAssembly *res;
4541 MonoImageOpenStatus status;
4542 MonoReflectionAssembly* result = NULL;
4544 name = mono_string_to_utf8_checked (mname, &error);
4545 if (mono_error_set_pending_exception (&error))
4546 return NULL;
4547 res = mono_assembly_load_with_partial_name (name, &status);
4549 g_free (name);
4551 if (res == NULL)
4552 return NULL;
4553 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4554 if (!result)
4555 mono_error_set_pending_exception (&error);
4556 return result;
4559 ICALL_EXPORT MonoStringHandle
4560 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4562 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4563 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4564 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4567 ICALL_EXPORT MonoBoolean
4568 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4570 return assembly->assembly->ref_only;
4573 ICALL_EXPORT MonoStringHandle
4574 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4576 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4577 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4579 return mono_string_new_handle (domain, assembly->image->version, error);
4582 ICALL_EXPORT MonoReflectionMethod*
4583 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4585 MonoError error;
4586 MonoReflectionMethod *res = NULL;
4587 MonoMethod *method;
4589 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4591 if (!token)
4592 return NULL;
4593 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4594 if (!mono_error_ok (&error))
4595 goto leave;
4597 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4599 leave:
4600 if (!mono_error_ok (&error))
4601 mono_error_set_pending_exception (&error);
4602 return res;
4605 ICALL_EXPORT MonoReflectionModule*
4606 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4608 MonoError error;
4609 MonoReflectionModule *result = NULL;
4610 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4611 if (!mono_error_ok (&error))
4612 mono_error_set_pending_exception (&error);
4613 return result;
4616 ICALL_EXPORT MonoArray*
4617 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4619 MonoError error;
4620 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4621 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4622 if (mono_error_set_pending_exception (&error))
4623 return NULL;
4624 int i;
4625 const char *val;
4627 for (i = 0; i < table->rows; ++i) {
4628 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4629 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4631 return result;
4634 ICALL_EXPORT MonoStringHandle
4635 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4637 int i;
4638 guint8 aotid_sum = 0;
4639 MonoDomain* domain = mono_domain_get ();
4641 if (!domain->entry_assembly || !domain->entry_assembly->image)
4642 return NULL;
4644 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4646 for (i = 0; i < 16; ++i)
4647 aotid_sum |= (*aotid)[i];
4649 if (aotid_sum == 0)
4650 return NULL;
4652 gchar *guid = mono_guid_to_string((guint8*) aotid);
4653 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4654 g_free (guid);
4655 return res;
4658 static MonoObject*
4659 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4661 static MonoMethod *create_version = NULL;
4662 MonoObject *result;
4663 gpointer args [4];
4665 mono_error_init (error);
4668 if (!create_version) {
4669 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4670 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4671 g_assert (create_version);
4672 mono_method_desc_free (desc);
4675 args [0] = &major;
4676 args [1] = &minor;
4677 args [2] = &build;
4678 args [3] = &revision;
4679 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4680 return_val_if_nok (error, NULL);
4682 mono_runtime_invoke_checked (create_version, result, args, error);
4683 return_val_if_nok (error, NULL);
4685 return result;
4688 ICALL_EXPORT MonoArray*
4689 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4691 MonoError error;
4692 MonoArray *result;
4693 MonoDomain *domain = mono_object_domain (assembly);
4694 int i, count = 0;
4695 static MonoMethod *create_culture = NULL;
4696 MonoImage *image = assembly->assembly->image;
4697 MonoTableInfo *t;
4698 MonoObject *o;
4700 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4701 count = t->rows;
4703 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4704 if (mono_error_set_pending_exception (&error))
4705 return NULL;
4708 if (count > 0 && !create_culture) {
4709 MonoMethodDesc *desc = mono_method_desc_new (
4710 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4711 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4712 g_assert (create_culture);
4713 mono_method_desc_free (desc);
4716 for (i = 0; i < count; i++) {
4717 MonoObject *version;
4718 MonoReflectionAssemblyName *aname;
4719 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4721 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4723 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4724 domain, mono_class_get_assembly_name_class (), &error);
4725 if (mono_error_set_pending_exception (&error))
4726 return NULL;
4728 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4730 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4731 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4732 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4733 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4734 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4735 aname->versioncompat = 1; /* SameMachine (default) */
4736 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4738 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4739 if (mono_error_set_pending_exception (&error))
4740 return NULL;
4742 MONO_OBJECT_SETREF (aname, version, version);
4744 if (create_culture) {
4745 gpointer args [2];
4746 MonoBoolean assembly_ref = 1;
4747 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4748 args [1] = &assembly_ref;
4750 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4751 if (mono_error_set_pending_exception (&error))
4752 return NULL;
4754 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4757 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4758 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4759 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4761 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4762 /* public key token isn't copied - the class library will
4763 automatically generate it from the public key if required */
4764 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4765 if (mono_error_set_pending_exception (&error))
4766 return NULL;
4768 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4769 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4770 } else {
4771 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4772 if (mono_error_set_pending_exception (&error))
4773 return NULL;
4775 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4776 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4778 } else {
4779 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4780 if (mono_error_set_pending_exception (&error))
4781 return NULL;
4783 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4786 /* note: this function doesn't return the codebase on purpose (i.e. it can
4787 be used under partial trust as path information isn't present). */
4789 mono_array_setref (result, i, aname);
4791 return result;
4794 /* move this in some file in mono/util/ */
4795 static char *
4796 g_concat_dir_and_file (const char *dir, const char *file)
4798 g_return_val_if_fail (dir != NULL, NULL);
4799 g_return_val_if_fail (file != NULL, NULL);
4802 * If the directory name doesn't have a / on the end, we need
4803 * to add one so we get a proper path to the file
4805 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4806 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4807 else
4808 return g_strconcat (dir, file, NULL);
4811 ICALL_EXPORT void *
4812 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4814 MonoError error;
4815 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4816 guint32 i;
4817 guint32 cols [MONO_MANIFEST_SIZE];
4818 guint32 impl, file_idx;
4819 const char *val;
4820 MonoImage *module;
4822 char *n = mono_string_to_utf8_checked (name, &error);
4823 if (mono_error_set_pending_exception (&error))
4824 return NULL;
4826 for (i = 0; i < table->rows; ++i) {
4827 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4828 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4829 if (strcmp (val, n) == 0)
4830 break;
4832 g_free (n);
4833 if (i == table->rows)
4834 return NULL;
4835 /* FIXME */
4836 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4837 if (impl) {
4839 * this code should only be called after obtaining the
4840 * ResourceInfo and handling the other cases.
4842 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4843 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4845 module = mono_image_load_file_for_image_checked (assembly->assembly->image, file_idx, &error);
4846 if (mono_error_set_pending_exception (&error) || !module)
4847 return NULL;
4849 else
4850 module = assembly->assembly->image;
4853 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4854 if (mono_error_set_pending_exception (&error))
4855 return NULL;
4856 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4858 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4861 ICALL_EXPORT gboolean
4862 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4864 MonoError error;
4865 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4866 int i;
4867 guint32 cols [MONO_MANIFEST_SIZE];
4868 guint32 file_cols [MONO_FILE_SIZE];
4869 const char *val;
4870 char *n;
4872 n = mono_string_to_utf8_checked (name, &error);
4873 if (mono_error_set_pending_exception (&error))
4874 return FALSE;
4875 for (i = 0; i < table->rows; ++i) {
4876 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4877 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4878 if (strcmp (val, n) == 0)
4879 break;
4881 g_free (n);
4882 if (i == table->rows)
4883 return FALSE;
4885 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4886 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4888 else {
4889 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4890 case MONO_IMPLEMENTATION_FILE:
4891 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4892 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4893 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4894 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4895 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4896 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4897 info->location = 0;
4898 else
4899 info->location = RESOURCE_LOCATION_EMBEDDED;
4900 break;
4902 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4903 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4904 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4905 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4906 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4907 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4908 g_free (msg);
4909 mono_set_pending_exception (ex);
4910 return FALSE;
4912 MonoReflectionAssembly *assm_obj;
4913 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4914 if (!assm_obj) {
4915 mono_error_set_pending_exception (&error);
4916 return FALSE;
4918 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4920 /* Obtain info recursively */
4921 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4922 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4923 break;
4925 case MONO_IMPLEMENTATION_EXP_TYPE:
4926 g_assert_not_reached ();
4927 break;
4931 return TRUE;
4934 ICALL_EXPORT MonoObject*
4935 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4937 MonoError error;
4938 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4939 MonoArray *result = NULL;
4940 int i, count;
4941 const char *val;
4942 char *n;
4944 /* check hash if needed */
4945 if (name) {
4946 n = mono_string_to_utf8_checked (name, &error);
4947 if (mono_error_set_pending_exception (&error))
4948 return NULL;
4950 for (i = 0; i < table->rows; ++i) {
4951 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4952 if (strcmp (val, n) == 0) {
4953 MonoString *fn;
4954 g_free (n);
4955 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4956 fn = mono_string_new (mono_object_domain (assembly), n);
4957 g_free (n);
4958 return (MonoObject*)fn;
4961 g_free (n);
4962 return NULL;
4965 count = 0;
4966 for (i = 0; i < table->rows; ++i) {
4967 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4968 count ++;
4971 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4972 if (mono_error_set_pending_exception (&error))
4973 return NULL;
4976 count = 0;
4977 for (i = 0; i < table->rows; ++i) {
4978 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4979 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4980 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4981 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4982 g_free (n);
4983 count ++;
4986 return (MonoObject*)result;
4989 ICALL_EXPORT MonoArray*
4990 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4992 MonoError error;
4993 MonoDomain *domain = mono_domain_get();
4994 MonoArray *res;
4995 MonoClass *klass;
4996 int i, j, file_count = 0;
4997 MonoImage **modules;
4998 guint32 module_count, real_module_count;
4999 MonoTableInfo *table;
5000 guint32 cols [MONO_FILE_SIZE];
5001 MonoImage *image = assembly->assembly->image;
5003 g_assert (image != NULL);
5004 g_assert (!assembly_is_dynamic (assembly->assembly));
5006 table = &image->tables [MONO_TABLE_FILE];
5007 file_count = table->rows;
5009 modules = image->modules;
5010 module_count = image->module_count;
5012 real_module_count = 0;
5013 for (i = 0; i < module_count; ++i)
5014 if (modules [i])
5015 real_module_count ++;
5017 klass = mono_class_get_module_class ();
5018 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5019 if (mono_error_set_pending_exception (&error))
5020 return NULL;
5022 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5023 if (mono_error_set_pending_exception (&error))
5024 return NULL;
5026 mono_array_setref (res, 0, image_obj);
5027 j = 1;
5028 for (i = 0; i < module_count; ++i)
5029 if (modules [i]) {
5030 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5031 if (mono_error_set_pending_exception (&error))
5032 return NULL;
5033 mono_array_setref (res, j, rm);
5034 ++j;
5037 for (i = 0; i < file_count; ++i, ++j) {
5038 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5039 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5040 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5041 if (mono_error_set_pending_exception (&error))
5042 return NULL;
5043 mono_array_setref (res, j, rm);
5045 else {
5046 MonoImage *m = mono_image_load_file_for_image_checked (image, i + 1, &error);
5047 if (mono_error_set_pending_exception (&error))
5048 return NULL;
5049 if (!m) {
5050 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5051 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5052 return NULL;
5054 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5055 if (mono_error_set_pending_exception (&error))
5056 return NULL;
5057 mono_array_setref (res, j, rm);
5061 return res;
5064 ICALL_EXPORT MonoReflectionMethod*
5065 ves_icall_GetCurrentMethod (void)
5067 MonoReflectionMethod *res = NULL;
5068 MonoError error;
5070 MonoMethod *m = mono_method_get_last_managed ();
5072 if (!m) {
5073 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5074 return NULL;
5077 while (m->is_inflated)
5078 m = ((MonoMethodInflated*)m)->declaring;
5080 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5081 mono_error_set_pending_exception (&error);
5082 return res;
5086 static MonoMethod*
5087 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5089 int offset = -1, i;
5090 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5091 MonoError error;
5092 MonoMethod *result;
5093 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5094 //method is inflated, we should inflate it on the other class
5095 MonoGenericContext ctx;
5096 ctx.method_inst = inflated->context.method_inst;
5097 ctx.class_inst = inflated->context.class_inst;
5098 if (mono_class_is_ginst (klass))
5099 ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
5100 else if (mono_class_is_gtd (klass))
5101 ctx.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
5102 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5103 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5104 return result;
5107 mono_class_setup_methods (method->klass);
5108 if (mono_class_has_failure (method->klass))
5109 return NULL;
5110 for (i = 0; i < method->klass->method.count; ++i) {
5111 if (method->klass->methods [i] == method) {
5112 offset = i;
5113 break;
5116 mono_class_setup_methods (klass);
5117 if (mono_class_has_failure (klass))
5118 return NULL;
5119 g_assert (offset >= 0 && offset < klass->method.count);
5120 return klass->methods [offset];
5123 ICALL_EXPORT MonoReflectionMethod*
5124 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5126 MonoReflectionMethod *res = NULL;
5127 MonoError error;
5128 MonoClass *klass;
5129 if (type && generic_check) {
5130 klass = mono_class_from_mono_type (type);
5131 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5132 return NULL;
5134 if (method->klass != klass) {
5135 method = mono_method_get_equivalent_method (method, klass);
5136 if (!method)
5137 return NULL;
5139 } else if (type)
5140 klass = mono_class_from_mono_type (type);
5141 else
5142 klass = method->klass;
5143 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5144 mono_error_set_pending_exception (&error);
5145 return res;
5148 ICALL_EXPORT MonoReflectionMethodBody*
5149 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5151 MonoError error;
5152 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5153 mono_error_set_pending_exception (&error);
5154 return result;
5157 ICALL_EXPORT MonoReflectionAssembly*
5158 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5160 MonoError error;
5161 MonoReflectionAssembly *result;
5162 MonoMethod *dest = NULL;
5164 mono_stack_walk_no_il (get_executing, &dest);
5165 g_assert (dest);
5166 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5167 if (!result)
5168 mono_error_set_pending_exception (&error);
5169 return result;
5173 ICALL_EXPORT MonoReflectionAssembly*
5174 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5176 MonoError error;
5177 MonoReflectionAssembly *result;
5178 MonoDomain* domain = mono_domain_get ();
5180 if (!domain->entry_assembly)
5181 return NULL;
5183 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5184 if (!result)
5185 mono_error_set_pending_exception (&error);
5186 return result;
5189 ICALL_EXPORT MonoReflectionAssembly*
5190 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5192 MonoError error;
5193 MonoMethod *m;
5194 MonoMethod *dest;
5195 MonoReflectionAssembly *result;
5197 dest = NULL;
5198 mono_stack_walk_no_il (get_executing, &dest);
5199 m = dest;
5200 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5201 if (!dest)
5202 dest = m;
5203 if (!m) {
5204 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5205 return NULL;
5207 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5208 if (!result)
5209 mono_error_set_pending_exception (&error);
5210 return result;
5213 ICALL_EXPORT MonoStringHandle
5214 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5215 gboolean assembly_qualified, MonoError *error)
5217 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5218 MonoType *type = MONO_HANDLE_RAW (object)->type;
5219 MonoTypeNameFormat format;
5220 MonoStringHandle res;
5221 gchar *name;
5223 if (full_name)
5224 format = assembly_qualified ?
5225 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5226 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5227 else
5228 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5230 name = mono_type_get_name_full (type, format);
5231 if (!name)
5232 return NULL_HANDLE_STRING;
5234 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5235 g_free (name);
5236 return NULL_HANDLE_STRING;
5239 res = mono_string_new_handle (domain, name, error);
5240 g_free (name);
5242 return res;
5245 ICALL_EXPORT int
5246 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5248 MonoError error;
5249 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5251 mono_class_init_checked (klass, &error);
5252 mono_error_set_pending_exception (&error);
5253 return mono_security_core_clr_class_level (klass);
5256 ICALL_EXPORT int
5257 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5259 MonoClassField *field = rfield->field;
5260 return mono_security_core_clr_field_level (field, TRUE);
5263 ICALL_EXPORT int
5264 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5266 MonoMethod *method = rfield->method;
5267 return mono_security_core_clr_method_level (method, TRUE);
5270 static void
5271 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token, MonoError *error)
5273 static MonoMethod *create_culture = NULL;
5274 MonoObject *obj;
5275 gpointer args [2];
5276 guint32 pkey_len;
5277 const char *pkey_ptr;
5278 gchar *codebase;
5279 MonoBoolean assembly_ref = 0;
5281 mono_error_init (error);
5283 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5284 aname->major = name->major;
5285 aname->minor = name->minor;
5286 aname->build = name->build;
5287 aname->flags = name->flags;
5288 aname->revision = name->revision;
5289 aname->hashalg = name->hash_alg;
5290 aname->versioncompat = 1; /* SameMachine (default) */
5291 aname->processor_architecture = name->arch;
5293 if (by_default_version) {
5294 MonoObject *version;
5296 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5297 return_if_nok (error);
5299 MONO_OBJECT_SETREF (aname, version, version);
5302 codebase = NULL;
5303 if (absolute != NULL && *absolute != '\0') {
5304 gchar *result;
5306 codebase = g_strdup (absolute);
5308 mono_icall_make_platform_path (codebase);
5310 const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
5312 result = g_strconcat (prepend, codebase, NULL);
5313 g_free (codebase);
5314 codebase = result;
5317 if (codebase) {
5318 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5319 g_free (codebase);
5322 if (!create_culture) {
5323 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5324 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5325 g_assert (create_culture);
5326 mono_method_desc_free (desc);
5329 if (name->culture) {
5330 args [0] = mono_string_new (domain, name->culture);
5331 args [1] = &assembly_ref;
5333 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5334 return_if_nok (error);
5336 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5339 if (name->public_key) {
5340 pkey_ptr = (char*)name->public_key;
5341 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5343 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5344 return_if_nok (error);
5345 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5346 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5347 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5348 } else if (default_publickey) {
5349 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5350 return_if_nok (error);
5351 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5352 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5355 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5356 if (name->public_key_token [0]) {
5357 int i, j;
5358 char *p;
5360 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5361 return_if_nok (error);
5363 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5364 p = mono_array_addr (keyToken, char, 0);
5366 for (i = 0, j = 0; i < 8; i++) {
5367 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5368 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5369 p++;
5371 } else if (default_token) {
5372 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5373 return_if_nok (error);
5374 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5378 ICALL_EXPORT MonoString *
5379 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5381 MonoDomain *domain = mono_object_domain (assembly);
5382 MonoAssembly *mass = assembly->assembly;
5383 MonoString *res;
5384 gchar *name;
5386 name = mono_stringify_assembly_name (&mass->aname);
5387 res = mono_string_new (domain, name);
5388 g_free (name);
5390 return res;
5393 ICALL_EXPORT MonoAssemblyName *
5394 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5396 return &mass->aname;
5399 ICALL_EXPORT void
5400 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5402 MonoError error;
5403 char *filename;
5404 MonoImageOpenStatus status = MONO_IMAGE_OK;
5405 gboolean res;
5406 MonoImage *image;
5407 MonoAssemblyName name;
5408 char *dirname;
5410 filename = mono_string_to_utf8_checked (fname, &error);
5411 if (mono_error_set_pending_exception (&error))
5412 return;
5414 dirname = g_path_get_dirname (filename);
5415 replace_shadow_path (mono_domain_get (), dirname, &filename);
5416 g_free (dirname);
5418 image = mono_image_open (filename, &status);
5420 if (!image){
5421 MonoException *exc;
5423 g_free (filename);
5424 if (status == MONO_IMAGE_IMAGE_INVALID)
5425 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5426 else
5427 exc = mono_get_exception_file_not_found2 (NULL, fname);
5428 mono_set_pending_exception (exc);
5429 return;
5432 res = mono_assembly_fill_assembly_name (image, &name);
5433 if (!res) {
5434 mono_image_close (image);
5435 g_free (filename);
5436 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5437 return;
5440 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5441 mono_error_set_pending_exception (&error);
5443 mono_image_close (image);
5444 g_free (filename);
5447 ICALL_EXPORT MonoBoolean
5448 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5449 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5451 MonoBoolean result = FALSE;
5452 MonoDeclSecurityEntry entry;
5454 /* SecurityAction.RequestMinimum */
5455 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5456 *minimum = entry.blob;
5457 *minLength = entry.size;
5458 result = TRUE;
5460 /* SecurityAction.RequestOptional */
5461 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5462 *optional = entry.blob;
5463 *optLength = entry.size;
5464 result = TRUE;
5466 /* SecurityAction.RequestRefuse */
5467 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5468 *refused = entry.blob;
5469 *refLength = entry.size;
5470 result = TRUE;
5473 return result;
5476 static gboolean
5477 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5479 guint32 attrs, visibility;
5480 do {
5481 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5482 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5483 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5484 return FALSE;
5486 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5488 return TRUE;
5491 static MonoArray*
5492 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5494 MonoReflectionType *rt;
5495 MonoArray *res;
5496 MonoClass *klass;
5497 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5498 int i, count;
5500 mono_error_init (error);
5502 /* we start the count from 1 because we skip the special type <Module> */
5503 if (exportedOnly) {
5504 count = 0;
5505 for (i = 1; i < tdef->rows; ++i) {
5506 if (mono_module_type_is_visible (tdef, image, i + 1))
5507 count++;
5509 } else {
5510 count = tdef->rows - 1;
5512 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5513 return_val_if_nok (error, NULL);
5514 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5515 return_val_if_nok (error, NULL);
5516 count = 0;
5517 for (i = 1; i < tdef->rows; ++i) {
5518 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5519 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5521 if (klass) {
5522 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5523 return_val_if_nok (error, NULL);
5525 mono_array_setref (res, count, rt);
5526 } else {
5527 MonoException *ex = mono_error_convert_to_exception (error);
5528 mono_array_setref (*exceptions, count, ex);
5530 count++;
5534 return res;
5537 ICALL_EXPORT MonoArray*
5538 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5540 MonoError error;
5541 MonoArray *res = NULL;
5542 MonoArray *exceptions = NULL;
5543 MonoImage *image = NULL;
5544 MonoTableInfo *table = NULL;
5545 MonoDomain *domain;
5546 GList *list = NULL;
5547 int i, len, ex_count;
5549 domain = mono_object_domain (assembly);
5551 g_assert (!assembly_is_dynamic (assembly->assembly));
5552 image = assembly->assembly->image;
5553 table = &image->tables [MONO_TABLE_FILE];
5554 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5555 if (mono_error_set_pending_exception (&error))
5556 return NULL;
5558 /* Append data from all modules in the assembly */
5559 for (i = 0; i < table->rows; ++i) {
5560 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5561 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, &error);
5562 if (mono_error_set_pending_exception (&error))
5563 return NULL;
5564 if (loaded_image) {
5565 MonoArray *ex2;
5566 MonoArray *res2;
5568 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5569 if (mono_error_set_pending_exception (&error))
5570 return NULL;
5573 /* Append the new types to the end of the array */
5574 if (mono_array_length (res2) > 0) {
5575 guint32 len1, len2;
5576 MonoArray *res3, *ex3;
5578 len1 = mono_array_length (res);
5579 len2 = mono_array_length (res2);
5581 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5582 if (mono_error_set_pending_exception (&error))
5583 return NULL;
5584 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5585 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5586 res = res3;
5588 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5589 if (mono_error_set_pending_exception (&error))
5590 return NULL;
5591 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5592 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5593 exceptions = ex3;
5599 /* the ReflectionTypeLoadException must have all the types (Types property),
5600 * NULL replacing types which throws an exception. The LoaderException must
5601 * contain all exceptions for NULL items.
5604 len = mono_array_length (res);
5606 ex_count = 0;
5607 for (i = 0; i < len; i++) {
5608 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5609 MonoClass *klass;
5611 if (t) {
5612 klass = mono_type_get_class (t->type);
5613 if ((klass != NULL) && mono_class_has_failure (klass)) {
5614 /* keep the class in the list */
5615 list = g_list_append (list, klass);
5616 /* and replace Type with NULL */
5617 mono_array_setref (res, i, NULL);
5619 } else {
5620 ex_count ++;
5624 if (list || ex_count) {
5625 GList *tmp = NULL;
5626 MonoException *exc = NULL;
5627 MonoArray *exl = NULL;
5628 int j, length = g_list_length (list) + ex_count;
5630 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5631 if (mono_error_set_pending_exception (&error)) {
5632 g_list_free (list);
5633 return NULL;
5635 /* Types for which mono_class_get_checked () succeeded */
5636 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5637 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5638 mono_array_setref (exl, i, exc);
5640 /* Types for which it don't */
5641 for (j = 0; j < mono_array_length (exceptions); ++j) {
5642 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5643 if (exc) {
5644 g_assert (i < length);
5645 mono_array_setref (exl, i, exc);
5646 i ++;
5649 g_list_free (list);
5650 list = NULL;
5652 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5653 if (!is_ok (&error)) {
5654 mono_error_set_pending_exception (&error);
5655 return NULL;
5657 mono_set_pending_exception (exc);
5658 return NULL;
5661 return res;
5664 ICALL_EXPORT void
5665 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5667 mono_assembly_name_free (aname);
5670 ICALL_EXPORT gboolean
5671 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5673 *is_version_definited = *is_token_defined = FALSE;
5675 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5678 ICALL_EXPORT MonoReflectionType*
5679 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5681 MonoError error;
5682 MonoReflectionType *ret;
5683 MonoDomain *domain = mono_object_domain (module);
5684 MonoClass *klass;
5686 g_assert (module->image);
5688 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5689 /* These images do not have a global type */
5690 return NULL;
5692 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5693 if (!mono_error_ok (&error)) {
5694 mono_error_set_pending_exception (&error);
5695 return NULL;
5698 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5699 if (!mono_error_ok (&error)) {
5700 mono_error_set_pending_exception (&error);
5701 return NULL;
5704 return ret;
5707 ICALL_EXPORT void
5708 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5710 /*if (module->image)
5711 mono_image_close (module->image);*/
5714 ICALL_EXPORT MonoStringHandle
5715 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5717 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5718 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5720 g_assert (image);
5721 return mono_string_new_handle (domain, image->guid, error);
5724 #ifndef HOST_WIN32
5725 static inline gpointer
5726 mono_icall_module_get_hinstance (MonoReflectionModule *module)
5728 return (gpointer) (-1);
5730 #endif /* HOST_WIN32 */
5732 ICALL_EXPORT gpointer
5733 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5735 return mono_icall_module_get_hinstance (module);
5738 ICALL_EXPORT void
5739 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5741 if (image_is_dynamic (image)) {
5742 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5743 *pe_kind = dyn->pe_kind;
5744 *machine = dyn->machine;
5746 else {
5747 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5748 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5752 ICALL_EXPORT gint32
5753 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5755 return (image->md_version_major << 16) | (image->md_version_minor);
5758 ICALL_EXPORT MonoArray*
5759 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5761 MonoError error;
5762 MonoArray *exceptions;
5763 int i;
5765 if (!module->image) {
5766 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5767 mono_error_set_pending_exception (&error);
5768 return arr;
5769 } else {
5770 MonoArray *res;
5772 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5773 if (mono_error_set_pending_exception (&error))
5774 return NULL;
5776 for (i = 0; i < mono_array_length (exceptions); ++i) {
5777 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5778 if (ex) {
5779 mono_set_pending_exception (ex);
5780 return NULL;
5783 return res;
5787 static gboolean
5788 mono_memberref_is_method (MonoImage *image, guint32 token)
5790 if (!image_is_dynamic (image)) {
5791 guint32 cols [MONO_MEMBERREF_SIZE];
5792 const char *sig;
5793 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5794 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5795 mono_metadata_decode_blob_size (sig, &sig);
5796 return (*sig != 0x6);
5797 } else {
5798 MonoError error;
5799 MonoClass *handle_class;
5801 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5802 mono_error_cleanup (&error); /* just probing, ignore error */
5803 return FALSE;
5806 return mono_defaults.methodhandle_class == handle_class;
5810 static void
5811 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5813 if (type_args)
5814 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5815 mono_array_addr (type_args, MonoType*, 0));
5816 else
5817 context->class_inst = NULL;
5818 if (method_args)
5819 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5820 mono_array_addr (method_args, MonoType*, 0));
5821 else
5822 context->method_inst = NULL;
5825 ICALL_EXPORT MonoType*
5826 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5828 MonoClass *klass;
5829 int table = mono_metadata_token_table (token);
5830 int index = mono_metadata_token_index (token);
5831 MonoGenericContext context;
5832 MonoError error;
5834 *resolve_error = ResolveTokenError_Other;
5836 /* Validate token */
5837 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5838 (table != MONO_TABLE_TYPESPEC)) {
5839 *resolve_error = ResolveTokenError_BadTable;
5840 return NULL;
5843 if (image_is_dynamic (image)) {
5844 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5845 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5846 mono_error_cleanup (&error);
5847 return klass ? &klass->byval_arg : NULL;
5850 init_generic_context_from_args (&context, type_args, method_args);
5851 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5852 mono_error_cleanup (&error);
5853 return klass ? &klass->byval_arg : NULL;
5856 if ((index <= 0) || (index > image->tables [table].rows)) {
5857 *resolve_error = ResolveTokenError_OutOfRange;
5858 return NULL;
5861 init_generic_context_from_args (&context, type_args, method_args);
5862 klass = mono_class_get_checked (image, token, &error);
5863 if (klass)
5864 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5865 if (!mono_error_ok (&error)) {
5866 mono_error_set_pending_exception (&error);
5867 return NULL;
5870 if (klass)
5871 return &klass->byval_arg;
5872 else
5873 return NULL;
5876 ICALL_EXPORT MonoMethod*
5877 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5879 MonoError error;
5880 int table = mono_metadata_token_table (token);
5881 int index = mono_metadata_token_index (token);
5882 MonoGenericContext context;
5883 MonoMethod *method;
5885 *resolve_error = ResolveTokenError_Other;
5887 /* Validate token */
5888 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5889 (table != MONO_TABLE_MEMBERREF)) {
5890 *resolve_error = ResolveTokenError_BadTable;
5891 return NULL;
5894 if (image_is_dynamic (image)) {
5895 if (table == MONO_TABLE_METHOD) {
5896 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5897 mono_error_cleanup (&error);
5898 return method;
5901 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5902 *resolve_error = ResolveTokenError_BadTable;
5903 return NULL;
5906 init_generic_context_from_args (&context, type_args, method_args);
5907 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5908 mono_error_cleanup (&error);
5909 return method;
5912 if ((index <= 0) || (index > image->tables [table].rows)) {
5913 *resolve_error = ResolveTokenError_OutOfRange;
5914 return NULL;
5916 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5917 *resolve_error = ResolveTokenError_BadTable;
5918 return NULL;
5921 init_generic_context_from_args (&context, type_args, method_args);
5922 method = mono_get_method_checked (image, token, NULL, &context, &error);
5923 mono_error_set_pending_exception (&error);
5925 return method;
5928 ICALL_EXPORT MonoString*
5929 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5931 MonoError error;
5932 int index = mono_metadata_token_index (token);
5934 *resolve_error = ResolveTokenError_Other;
5936 /* Validate token */
5937 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5938 *resolve_error = ResolveTokenError_BadTable;
5939 return NULL;
5942 if (image_is_dynamic (image)) {
5943 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5944 mono_error_cleanup (&error);
5945 return result;
5948 if ((index <= 0) || (index >= image->heap_us.size)) {
5949 *resolve_error = ResolveTokenError_OutOfRange;
5950 return NULL;
5953 /* FIXME: What to do if the index points into the middle of a string ? */
5955 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5956 mono_error_set_pending_exception (&error);
5957 return result;
5960 ICALL_EXPORT MonoClassField*
5961 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5963 MonoError error;
5964 MonoClass *klass;
5965 int table = mono_metadata_token_table (token);
5966 int index = mono_metadata_token_index (token);
5967 MonoGenericContext context;
5968 MonoClassField *field;
5970 *resolve_error = ResolveTokenError_Other;
5972 /* Validate token */
5973 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5974 *resolve_error = ResolveTokenError_BadTable;
5975 return NULL;
5978 if (image_is_dynamic (image)) {
5979 if (table == MONO_TABLE_FIELD) {
5980 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5981 mono_error_cleanup (&error);
5982 return field;
5985 if (mono_memberref_is_method (image, token)) {
5986 *resolve_error = ResolveTokenError_BadTable;
5987 return NULL;
5990 init_generic_context_from_args (&context, type_args, method_args);
5991 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5992 mono_error_cleanup (&error);
5993 return field;
5996 if ((index <= 0) || (index > image->tables [table].rows)) {
5997 *resolve_error = ResolveTokenError_OutOfRange;
5998 return NULL;
6000 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6001 *resolve_error = ResolveTokenError_BadTable;
6002 return NULL;
6005 init_generic_context_from_args (&context, type_args, method_args);
6006 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6007 mono_error_set_pending_exception (&error);
6009 return field;
6013 ICALL_EXPORT MonoObject*
6014 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6016 MonoError merror;
6017 MonoObject *ret;
6018 int table = mono_metadata_token_table (token);
6020 *error = ResolveTokenError_Other;
6022 switch (table) {
6023 case MONO_TABLE_TYPEDEF:
6024 case MONO_TABLE_TYPEREF:
6025 case MONO_TABLE_TYPESPEC: {
6026 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6027 if (t) {
6028 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6029 mono_error_set_pending_exception (&merror);
6031 return ret;
6033 else
6034 return NULL;
6036 case MONO_TABLE_METHOD:
6037 case MONO_TABLE_METHODSPEC: {
6038 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6039 if (m) {
6040 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6041 mono_error_set_pending_exception (&merror);
6043 return ret;
6044 } else
6045 return NULL;
6047 case MONO_TABLE_FIELD: {
6048 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6049 if (f) {
6050 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6051 mono_error_set_pending_exception (&merror);
6052 return ret;
6054 else
6055 return NULL;
6057 case MONO_TABLE_MEMBERREF:
6058 if (mono_memberref_is_method (image, token)) {
6059 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6060 if (m) {
6061 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6062 mono_error_set_pending_exception (&merror);
6064 return ret;
6065 } else
6066 return NULL;
6068 else {
6069 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6070 if (f) {
6071 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6072 mono_error_set_pending_exception (&merror);
6073 return ret;
6075 else
6076 return NULL;
6078 break;
6080 default:
6081 *error = ResolveTokenError_BadTable;
6084 return NULL;
6087 ICALL_EXPORT MonoArray*
6088 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6090 MonoError error;
6091 int table = mono_metadata_token_table (token);
6092 int idx = mono_metadata_token_index (token);
6093 MonoTableInfo *tables = image->tables;
6094 guint32 sig, len;
6095 const char *ptr;
6096 MonoArray *res;
6098 *resolve_error = ResolveTokenError_OutOfRange;
6100 /* FIXME: Support other tables ? */
6101 if (table != MONO_TABLE_STANDALONESIG)
6102 return NULL;
6104 if (image_is_dynamic (image))
6105 return NULL;
6107 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6108 return NULL;
6110 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6112 ptr = mono_metadata_blob_heap (image, sig);
6113 len = mono_metadata_decode_blob_size (ptr, &ptr);
6115 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6116 if (mono_error_set_pending_exception (&error))
6117 return NULL;
6118 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6119 return res;
6122 ICALL_EXPORT MonoBoolean
6123 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6125 MonoType *type;
6126 MonoBoolean res;
6128 type = t->type;
6129 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6131 return res;
6134 static void
6135 check_for_invalid_type (MonoClass *klass, MonoError *error)
6137 char *name;
6139 mono_error_init (error);
6141 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6142 return;
6144 name = mono_type_get_full_name (klass);
6145 mono_error_set_type_load_name (error, name, g_strdup (""), "");
6147 ICALL_EXPORT MonoReflectionType *
6148 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6150 MonoError error;
6151 MonoReflectionType *ret;
6152 MonoClass *klass, *aklass;
6154 klass = mono_class_from_mono_type (type->type);
6155 check_for_invalid_type (klass, &error);
6156 if (mono_error_set_pending_exception (&error))
6157 return NULL;
6159 if (rank == 0) //single dimentional array
6160 aklass = mono_array_class_get (klass, 1);
6161 else
6162 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6164 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6165 mono_error_set_pending_exception (&error);
6167 return ret;
6170 ICALL_EXPORT MonoReflectionType *
6171 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6173 MonoError error;
6174 MonoReflectionType *ret;
6175 MonoClass *klass;
6177 klass = mono_class_from_mono_type (type->type);
6178 mono_class_init_checked (klass, &error);
6179 if (mono_error_set_pending_exception (&error))
6180 return NULL;
6182 check_for_invalid_type (klass, &error);
6183 if (mono_error_set_pending_exception (&error))
6184 return NULL;
6186 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6187 mono_error_set_pending_exception (&error);
6189 return ret;
6192 ICALL_EXPORT MonoReflectionType *
6193 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6195 MonoError error;
6196 MonoReflectionType *ret;
6197 MonoClass *klass, *pklass;
6199 klass = mono_class_from_mono_type (type->type);
6200 mono_class_init_checked (klass, &error);
6201 if (mono_error_set_pending_exception (&error))
6202 return NULL;
6203 check_for_invalid_type (klass, &error);
6204 if (mono_error_set_pending_exception (&error))
6205 return NULL;
6207 pklass = mono_ptr_class_get (type->type);
6209 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6210 mono_error_set_pending_exception (&error);
6212 return ret;
6215 ICALL_EXPORT MonoObject *
6216 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6217 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6219 MonoError error;
6220 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6221 MonoObject *delegate;
6222 gpointer func;
6223 MonoMethod *method = info->method;
6224 MonoMethodSignature *sig = mono_method_signature(method);
6226 mono_class_init_checked (delegate_class, &error);
6227 if (mono_error_set_pending_exception (&error))
6228 return NULL;
6230 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6231 /* FIXME improve this exception message */
6232 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6233 __func__,
6234 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6235 mono_error_set_pending_exception (&error);
6236 return NULL;
6239 if (mono_security_core_clr_enabled ()) {
6240 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6241 if (throwOnBindFailure)
6242 mono_error_set_pending_exception (&error);
6243 else
6244 mono_error_cleanup (&error);
6245 return NULL;
6249 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6250 if (!method->is_inflated) {
6251 mono_set_pending_exception(mono_get_exception_argument("method", " Cannot bind to the target method because its signature differs from that of the delegate type"));
6252 return NULL;
6256 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6257 if (mono_error_set_pending_exception (&error))
6258 return NULL;
6260 if (method_is_dynamic (method)) {
6261 /* Creating a trampoline would leak memory */
6262 func = mono_compile_method_checked (method, &error);
6263 if (mono_error_set_pending_exception (&error))
6264 return NULL;
6265 } else {
6266 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6267 method = mono_object_get_virtual_method (target, method);
6268 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6269 if (mono_error_set_pending_exception (&error))
6270 return NULL;
6271 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6274 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6275 if (mono_error_set_pending_exception (&error))
6276 return NULL;
6277 return delegate;
6280 ICALL_EXPORT MonoMulticastDelegate *
6281 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6283 MonoError error;
6284 MonoMulticastDelegate *ret;
6286 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6288 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6289 if (mono_error_set_pending_exception (&error))
6290 return NULL;
6292 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6294 return ret;
6297 ICALL_EXPORT MonoReflectionMethod*
6298 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6300 MonoReflectionMethod *ret = NULL;
6301 MonoError error;
6302 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6303 mono_error_set_pending_exception (&error);
6304 return ret;
6307 /* System.Buffer */
6309 static inline gint32
6310 mono_array_get_byte_length (MonoArray *array)
6312 MonoClass *klass;
6313 int length;
6314 int i;
6316 klass = array->obj.vtable->klass;
6318 if (array->bounds == NULL)
6319 length = array->max_length;
6320 else {
6321 length = 1;
6322 for (i = 0; i < klass->rank; ++ i)
6323 length *= array->bounds [i].length;
6326 switch (klass->element_class->byval_arg.type) {
6327 case MONO_TYPE_I1:
6328 case MONO_TYPE_U1:
6329 case MONO_TYPE_BOOLEAN:
6330 return length;
6331 case MONO_TYPE_I2:
6332 case MONO_TYPE_U2:
6333 case MONO_TYPE_CHAR:
6334 return length << 1;
6335 case MONO_TYPE_I4:
6336 case MONO_TYPE_U4:
6337 case MONO_TYPE_R4:
6338 return length << 2;
6339 case MONO_TYPE_I:
6340 case MONO_TYPE_U:
6341 return length * sizeof (gpointer);
6342 case MONO_TYPE_I8:
6343 case MONO_TYPE_U8:
6344 case MONO_TYPE_R8:
6345 return length << 3;
6346 default:
6347 return -1;
6351 ICALL_EXPORT gint32
6352 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6354 return mono_array_get_byte_length (array);
6357 ICALL_EXPORT gint8
6358 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6360 return mono_array_get (array, gint8, idx);
6363 ICALL_EXPORT void
6364 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6366 mono_array_set (array, gint8, idx, value);
6369 ICALL_EXPORT MonoBoolean
6370 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6372 guint8 *src_buf, *dest_buf;
6374 if (count < 0) {
6375 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6376 return FALSE;
6379 g_assert (count >= 0);
6381 /* This is called directly from the class libraries without going through the managed wrapper */
6382 MONO_CHECK_ARG_NULL (src, FALSE);
6383 MONO_CHECK_ARG_NULL (dest, FALSE);
6385 /* watch out for integer overflow */
6386 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6387 return FALSE;
6389 src_buf = (guint8 *)src->vector + src_offset;
6390 dest_buf = (guint8 *)dest->vector + dest_offset;
6392 if (src != dest)
6393 memcpy (dest_buf, src_buf, count);
6394 else
6395 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6397 return TRUE;
6400 #ifndef DISABLE_REMOTING
6401 ICALL_EXPORT MonoObject *
6402 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6404 MonoError error;
6405 MonoDomain *domain = mono_object_domain (this_obj);
6406 MonoObject *res;
6407 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6408 MonoTransparentProxy *tp;
6409 MonoType *type;
6410 MonoClass *klass;
6412 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6413 if (mono_error_set_pending_exception (&error))
6414 return NULL;
6416 tp = (MonoTransparentProxy*) res;
6418 MONO_OBJECT_SETREF (tp, rp, rp);
6419 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6420 klass = mono_class_from_mono_type (type);
6422 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6423 mono_class_setup_vtable (klass);
6424 if (mono_class_has_failure (klass)) {
6425 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6426 return NULL;
6429 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6430 if (mono_error_set_pending_exception (&error))
6431 return NULL;
6432 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6433 if (mono_error_set_pending_exception (&error))
6434 return NULL;
6436 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6437 if (mono_error_set_pending_exception (&error))
6438 return NULL;
6439 return res;
6442 ICALL_EXPORT MonoReflectionType *
6443 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6445 MonoError error;
6446 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6447 mono_error_set_pending_exception (&error);
6449 return ret;
6451 #endif
6453 /* System.Environment */
6455 MonoString*
6456 ves_icall_System_Environment_get_UserName (void)
6458 /* using glib is more portable */
6459 return mono_string_new (mono_domain_get (), g_get_user_name ());
6462 #ifndef HOST_WIN32
6463 static MonoString *
6464 mono_icall_get_machine_name (void)
6466 #if !defined(DISABLE_SOCKETS)
6467 MonoString *result;
6468 char *buf;
6469 int n;
6470 #if defined _SC_HOST_NAME_MAX
6471 n = sysconf (_SC_HOST_NAME_MAX);
6472 if (n == -1)
6473 #endif
6474 n = 512;
6475 buf = g_malloc (n+1);
6477 if (gethostname (buf, n) == 0){
6478 buf [n] = 0;
6479 result = mono_string_new (mono_domain_get (), buf);
6480 } else
6481 result = NULL;
6482 g_free (buf);
6484 return result;
6485 #else
6486 return mono_string_new (mono_domain_get (), "mono");
6487 #endif
6489 #endif /* !HOST_WIN32 */
6491 ICALL_EXPORT MonoString *
6492 ves_icall_System_Environment_get_MachineName (void)
6494 return mono_icall_get_machine_name ();
6497 #ifndef HOST_WIN32
6498 static inline int
6499 mono_icall_get_platform (void)
6501 #if defined(__MACH__)
6502 /* OSX */
6504 // Notice that the value is hidden from user code, and only exposed
6505 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6506 // define and making assumptions based on Unix/128/4 values before there
6507 // was a MacOS define. Lots of code would assume that not-Unix meant
6508 // Windows, but in this case, it would be OSX.
6510 return 6;
6511 #else
6512 /* Unix */
6513 return 4;
6514 #endif
6516 #endif /* !HOST_WIN32 */
6518 ICALL_EXPORT int
6519 ves_icall_System_Environment_get_Platform (void)
6521 return mono_icall_get_platform ();
6524 #ifndef HOST_WIN32
6525 static inline MonoString *
6526 mono_icall_get_new_line (void)
6528 return mono_string_new (mono_domain_get (), "\n");
6530 #endif /* !HOST_WIN32 */
6532 ICALL_EXPORT MonoString *
6533 ves_icall_System_Environment_get_NewLine (void)
6535 return mono_icall_get_new_line ();
6538 #ifndef HOST_WIN32
6539 static inline MonoBoolean
6540 mono_icall_is_64bit_os (void)
6542 #if SIZEOF_VOID_P == 8
6543 return TRUE;
6544 #else
6545 #if defined(HAVE_SYS_UTSNAME_H)
6546 struct utsname name;
6548 if (uname (&name) >= 0) {
6549 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6551 #endif
6552 return FALSE;
6553 #endif
6555 #endif /* !HOST_WIN32 */
6557 ICALL_EXPORT MonoBoolean
6558 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6560 return mono_icall_is_64bit_os ();
6563 ICALL_EXPORT MonoStringHandle
6564 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6566 const gchar *value;
6568 if (utf8_name == NULL)
6569 return NULL_HANDLE_STRING;
6571 value = g_getenv (utf8_name);
6573 if (value == 0)
6574 return NULL_HANDLE_STRING;
6576 return mono_string_new_handle (mono_domain_get (), value, error);
6580 * There is no standard way to get at environ.
6582 #ifndef _MSC_VER
6583 #ifndef __MINGW32_VERSION
6584 #if defined(__APPLE__)
6585 #if defined (TARGET_OSX)
6586 /* Apple defines this in crt_externs.h but doesn't provide that header for
6587 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6588 * in fact exist on all implementations (so far)
6590 gchar ***_NSGetEnviron(void);
6591 #define environ (*_NSGetEnviron())
6592 #else
6593 static char *mono_environ[1] = { NULL };
6594 #define environ mono_environ
6595 #endif /* defined (TARGET_OSX) */
6596 #else
6597 extern
6598 char **environ;
6599 #endif
6600 #endif
6601 #endif
6603 ICALL_EXPORT MonoArray *
6604 ves_icall_System_Environment_GetCoomandLineArgs (void)
6606 MonoError error;
6607 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6608 mono_error_set_pending_exception (&error);
6609 return result;
6612 #ifndef HOST_WIN32
6613 static MonoArray *
6614 mono_icall_get_environment_variable_names (void)
6616 MonoError error;
6617 MonoArray *names;
6618 MonoDomain *domain;
6619 MonoString *str;
6620 gchar **e, **parts;
6621 int n;
6623 n = 0;
6624 for (e = environ; *e != 0; ++ e)
6625 ++ n;
6627 domain = mono_domain_get ();
6628 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6629 if (mono_error_set_pending_exception (&error))
6630 return NULL;
6632 n = 0;
6633 for (e = environ; *e != 0; ++ e) {
6634 parts = g_strsplit (*e, "=", 2);
6635 if (*parts != 0) {
6636 str = mono_string_new (domain, *parts);
6637 mono_array_setref (names, n, str);
6640 g_strfreev (parts);
6642 ++ n;
6645 return names;
6647 #endif /* !HOST_WIN32 */
6649 ICALL_EXPORT MonoArray *
6650 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6652 return mono_icall_get_environment_variable_names ();
6655 #ifndef HOST_WIN32
6656 static void
6657 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
6659 gchar *utf8_name, *utf8_value;
6660 MonoError error;
6662 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6663 if (mono_error_set_pending_exception (&error))
6664 return;
6666 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6667 g_unsetenv (utf8_name);
6668 g_free (utf8_name);
6669 return;
6672 utf8_value = mono_string_to_utf8_checked (value, &error);
6673 if (!mono_error_ok (&error)) {
6674 g_free (utf8_name);
6675 mono_error_set_pending_exception (&error);
6676 return;
6678 g_setenv (utf8_name, utf8_value, TRUE);
6680 g_free (utf8_name);
6681 g_free (utf8_value);
6683 #endif /* !HOST_WIN32 */
6685 ICALL_EXPORT void
6686 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6688 mono_icall_set_environment_variable (name, value);
6691 ICALL_EXPORT void
6692 ves_icall_System_Environment_Exit (int result)
6694 mono_environment_exitcode_set (result);
6696 /* FIXME: There are some cleanup hangs that should be worked out, but
6697 * if the program is going to exit, everything will be cleaned up when
6698 * NaCl exits anyway.
6700 #ifndef __native_client__
6701 if (!mono_runtime_try_shutdown ())
6702 mono_thread_exit ();
6704 /* Suspend all managed threads since the runtime is going away */
6705 mono_thread_suspend_all_other_threads ();
6707 mono_runtime_quit ();
6708 #endif
6710 /* we may need to do some cleanup here... */
6711 exit (result);
6714 ICALL_EXPORT MonoStringHandle
6715 ves_icall_System_Environment_GetGacPath (MonoError *error)
6717 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6720 #ifndef HOST_WIN32
6721 static inline MonoString *
6722 mono_icall_get_windows_folder_path (int folder)
6724 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6725 return mono_string_new (mono_domain_get (), "");
6727 #endif /* !HOST_WIN32 */
6729 ICALL_EXPORT MonoString*
6730 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6732 return mono_icall_get_windows_folder_path (folder);
6735 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
6736 static MonoArray *
6737 mono_icall_get_logical_drives (void)
6739 MonoError error;
6740 gunichar2 buf [256], *ptr, *dname;
6741 gunichar2 *u16;
6742 guint initial_size = 127, size = 128;
6743 gint ndrives;
6744 MonoArray *result;
6745 MonoString *drivestr;
6746 MonoDomain *domain = mono_domain_get ();
6747 gint len;
6749 buf [0] = '\0';
6750 ptr = buf;
6752 while (size > initial_size) {
6753 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6754 if (size > initial_size) {
6755 if (ptr != buf)
6756 g_free (ptr);
6757 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6758 initial_size = size;
6759 size++;
6763 /* Count strings */
6764 dname = ptr;
6765 ndrives = 0;
6766 do {
6767 while (*dname++);
6768 ndrives++;
6769 } while (*dname);
6771 dname = ptr;
6772 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6773 if (mono_error_set_pending_exception (&error))
6774 goto leave;
6776 ndrives = 0;
6777 do {
6778 len = 0;
6779 u16 = dname;
6780 while (*u16) { u16++; len ++; }
6781 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6782 if (mono_error_set_pending_exception (&error))
6783 goto leave;
6785 mono_array_setref (result, ndrives++, drivestr);
6786 while (*dname++);
6787 } while (*dname);
6789 leave:
6790 if (ptr != buf)
6791 g_free (ptr);
6793 return result;
6795 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
6797 ICALL_EXPORT MonoArray *
6798 ves_icall_System_Environment_GetLogicalDrives (void)
6800 return mono_icall_get_logical_drives ();
6803 ICALL_EXPORT MonoString *
6804 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6806 MonoError error;
6807 gunichar2 volume_name [MAX_PATH + 1];
6809 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6810 return NULL;
6811 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6812 mono_error_set_pending_exception (&error);
6813 return result;
6816 ICALL_EXPORT MonoStringHandle
6817 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6819 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6822 static const char *encodings [] = {
6823 (char *) 1,
6824 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6825 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6826 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6827 (char *) 2,
6828 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6829 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6830 "x_unicode_2_0_utf_7",
6831 (char *) 3,
6832 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6833 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6834 (char *) 4,
6835 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6836 "iso_10646_ucs2",
6837 (char *) 5,
6838 "unicodefffe", "utf_16be",
6839 (char *) 6,
6840 "iso_8859_1",
6841 (char *) 0
6845 * Returns the internal codepage, if the value of "int_code_page" is
6846 * 1 at entry, and we can not compute a suitable code page number,
6847 * returns the code page as a string
6849 ICALL_EXPORT MonoString*
6850 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6852 const char *cset;
6853 const char *p;
6854 char *c;
6855 char *codepage = NULL;
6856 int code;
6857 int want_name = *int_code_page;
6858 int i;
6860 *int_code_page = -1;
6862 g_get_charset (&cset);
6863 c = codepage = g_strdup (cset);
6864 for (c = codepage; *c; c++){
6865 if (isascii (*c) && isalpha (*c))
6866 *c = tolower (*c);
6867 if (*c == '-')
6868 *c = '_';
6870 /* g_print ("charset: %s\n", cset); */
6872 /* handle some common aliases */
6873 p = encodings [0];
6874 code = 0;
6875 for (i = 0; p != 0; ){
6876 if ((gsize) p < 7){
6877 code = (gssize) p;
6878 p = encodings [++i];
6879 continue;
6881 if (strcmp (p, codepage) == 0){
6882 *int_code_page = code;
6883 break;
6885 p = encodings [++i];
6888 if (strstr (codepage, "utf_8") != NULL)
6889 *int_code_page |= 0x10000000;
6890 g_free (codepage);
6892 if (want_name && *int_code_page == -1)
6893 return mono_string_new (mono_domain_get (), cset);
6894 else
6895 return NULL;
6898 ICALL_EXPORT MonoBoolean
6899 ves_icall_System_Environment_get_HasShutdownStarted (void)
6901 if (mono_runtime_is_shutting_down ())
6902 return TRUE;
6904 if (mono_domain_is_unloading (mono_domain_get ()))
6905 return TRUE;
6907 return FALSE;
6910 #ifndef HOST_WIN32
6911 static inline void
6912 mono_icall_broadcast_setting_change (void)
6914 return;
6916 #endif /* !HOST_WIN32 */
6918 ICALL_EXPORT void
6919 ves_icall_System_Environment_BroadcastSettingChange (void)
6921 mono_icall_broadcast_setting_change ();
6924 ICALL_EXPORT
6925 gint32
6926 ves_icall_System_Environment_get_TickCount (void)
6928 /* this will overflow after ~24 days */
6929 return (gint32) (mono_msec_boottime () & 0xffffffff);
6932 ICALL_EXPORT gint32
6933 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6935 return 9;
6938 #ifndef DISABLE_REMOTING
6939 ICALL_EXPORT MonoBoolean
6940 ves_icall_IsTransparentProxy (MonoObject *proxy)
6942 if (!proxy)
6943 return 0;
6945 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6946 return 1;
6948 return 0;
6951 ICALL_EXPORT MonoReflectionMethod *
6952 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6953 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6955 MonoReflectionMethod *ret = NULL;
6956 MonoError error;
6958 MonoClass *klass;
6959 MonoMethod *method;
6960 MonoMethod **vtable;
6961 MonoMethod *res = NULL;
6963 MONO_CHECK_ARG_NULL (rtype, NULL);
6964 MONO_CHECK_ARG_NULL (rmethod, NULL);
6966 method = rmethod->method;
6967 klass = mono_class_from_mono_type (rtype->type);
6968 mono_class_init_checked (klass, &error);
6969 if (mono_error_set_pending_exception (&error))
6970 return NULL;
6972 if (MONO_CLASS_IS_INTERFACE (klass))
6973 return NULL;
6975 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6976 return NULL;
6978 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6979 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6980 return rmethod;
6981 else
6982 return NULL;
6985 mono_class_setup_vtable (klass);
6986 vtable = klass->vtable;
6988 if (mono_class_is_interface (method->klass)) {
6989 gboolean variance_used = FALSE;
6990 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6991 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6992 if (offs >= 0)
6993 res = vtable [offs + method->slot];
6994 } else {
6995 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6996 return NULL;
6998 if (method->slot != -1)
6999 res = vtable [method->slot];
7002 if (!res)
7003 return NULL;
7005 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7006 mono_error_set_pending_exception (&error);
7007 return ret;
7010 ICALL_EXPORT void
7011 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7013 MonoError error;
7014 MonoClass *klass;
7015 MonoVTable* vtable;
7017 klass = mono_class_from_mono_type (type->type);
7018 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7019 if (!is_ok (&error)) {
7020 mono_error_set_pending_exception (&error);
7021 return;
7024 mono_vtable_set_is_remote (vtable, enable);
7027 #else /* DISABLE_REMOTING */
7029 ICALL_EXPORT void
7030 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7032 g_assert_not_reached ();
7035 #endif
7037 ICALL_EXPORT MonoObject *
7038 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7040 MonoError error;
7041 MonoClass *klass;
7042 MonoDomain *domain;
7043 MonoObject *ret;
7045 domain = mono_object_domain (type);
7046 klass = mono_class_from_mono_type (type->type);
7047 mono_class_init_checked (klass, &error);
7048 if (mono_error_set_pending_exception (&error))
7049 return NULL;
7051 if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
7052 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7053 return NULL;
7056 if (klass->rank >= 1) {
7057 g_assert (klass->rank == 1);
7058 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7059 mono_error_set_pending_exception (&error);
7060 return ret;
7061 } else {
7062 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7063 if (!is_ok (&error)) {
7064 mono_error_set_pending_exception (&error);
7065 return NULL;
7067 /* Bypass remoting object creation check */
7068 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7069 mono_error_set_pending_exception (&error);
7071 return ret;
7075 ICALL_EXPORT MonoStringHandle
7076 ves_icall_System_IO_get_temp_path (MonoError *error)
7078 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7081 #ifndef PLATFORM_NO_DRIVEINFO
7082 ICALL_EXPORT MonoBoolean
7083 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7084 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7085 gint32 *error)
7087 gboolean result;
7088 ULARGE_INTEGER wapi_free_bytes_avail;
7089 ULARGE_INTEGER wapi_total_number_of_bytes;
7090 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7092 *error = ERROR_SUCCESS;
7093 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7094 &wapi_total_number_of_free_bytes);
7096 if (result) {
7097 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7098 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7099 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7100 } else {
7101 *free_bytes_avail = 0;
7102 *total_number_of_bytes = 0;
7103 *total_number_of_free_bytes = 0;
7104 *error = GetLastError ();
7107 return result;
7110 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
7111 static inline guint32
7112 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
7114 return GetDriveType (mono_string_chars (root_path_name));
7116 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
7118 ICALL_EXPORT guint32
7119 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7121 return mono_icall_drive_info_get_drive_type (root_path_name);
7124 #endif /* PLATFORM_NO_DRIVEINFO */
7126 ICALL_EXPORT gpointer
7127 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7129 MonoError error;
7130 gpointer result = mono_compile_method_checked (method, &error);
7131 mono_error_set_pending_exception (&error);
7132 return result;
7135 ICALL_EXPORT MonoString *
7136 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7138 MonoString *mcpath;
7139 gchar *path;
7141 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7143 mono_icall_make_platform_path (path);
7145 mcpath = mono_string_new (mono_domain_get (), path);
7146 g_free (path);
7148 return mcpath;
7151 /* this is an icall */
7152 static MonoString *
7153 get_bundled_app_config (void)
7155 MonoError error;
7156 const gchar *app_config;
7157 MonoDomain *domain;
7158 MonoString *file;
7159 gchar *config_file_name, *config_file_path;
7160 gsize len, config_file_path_length, config_ext_length;
7161 gchar *module;
7163 domain = mono_domain_get ();
7164 file = domain->setup->configuration_file;
7165 if (!file || file->length == 0)
7166 return NULL;
7168 // Retrieve config file and remove the extension
7169 config_file_name = mono_string_to_utf8_checked (file, &error);
7170 if (mono_error_set_pending_exception (&error))
7171 return NULL;
7172 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7173 if (!config_file_path)
7174 config_file_path = config_file_name;
7176 config_file_path_length = strlen (config_file_path);
7177 config_ext_length = strlen (".config");
7178 if (config_file_path_length <= config_ext_length)
7179 return NULL;
7181 len = config_file_path_length - config_ext_length;
7182 module = (gchar *)g_malloc0 (len + 1);
7183 memcpy (module, config_file_path, len);
7184 // Get the config file from the module name
7185 app_config = mono_config_string_for_assembly_file (module);
7186 // Clean-up
7187 g_free (module);
7188 if (config_file_name != config_file_path)
7189 g_free (config_file_name);
7190 g_free (config_file_path);
7192 if (!app_config)
7193 return NULL;
7195 return mono_string_new (mono_domain_get (), app_config);
7198 static MonoStringHandle
7199 get_bundled_machine_config (MonoError *error)
7201 const gchar *machine_config;
7203 machine_config = mono_get_machine_config ();
7205 if (!machine_config)
7206 return NULL_HANDLE_STRING;
7208 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7211 ICALL_EXPORT MonoStringHandle
7212 ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
7214 return get_bundled_machine_config (error);
7218 ICALL_EXPORT MonoStringHandle
7219 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7221 return get_bundled_machine_config (error);
7224 ICALL_EXPORT MonoStringHandle
7225 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7227 return get_bundled_machine_config (error);
7231 ICALL_EXPORT MonoString *
7232 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7234 MonoString *ipath;
7235 gchar *path;
7237 path = g_path_get_dirname (mono_get_config_dir ());
7239 mono_icall_make_platform_path (path);
7241 ipath = mono_string_new (mono_domain_get (), path);
7242 g_free (path);
7244 return ipath;
7247 ICALL_EXPORT gboolean
7248 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7250 MonoPEResourceDataEntry *entry;
7251 MonoImage *image;
7253 if (!assembly || !result || !size)
7254 return FALSE;
7256 *result = NULL;
7257 *size = 0;
7258 image = assembly->assembly->image;
7259 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7260 if (!entry)
7261 return FALSE;
7263 *result = mono_image_rva_map (image, entry->rde_data_offset);
7264 if (!(*result)) {
7265 g_free (entry);
7266 return FALSE;
7268 *size = entry->rde_size;
7269 g_free (entry);
7270 return TRUE;
7273 ICALL_EXPORT MonoBoolean
7274 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7276 return mono_is_debugger_attached ();
7279 ICALL_EXPORT MonoBoolean
7280 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7282 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7283 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7284 else
7285 return FALSE;
7288 ICALL_EXPORT void
7289 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7291 if (mono_get_runtime_callbacks ()->debug_log)
7292 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7295 #ifndef HOST_WIN32
7296 static inline void
7297 mono_icall_write_windows_debug_string (MonoString *message)
7299 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7301 #endif /* !HOST_WIN32 */
7303 ICALL_EXPORT void
7304 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7306 mono_icall_write_windows_debug_string (message);
7309 /* Only used for value types */
7310 ICALL_EXPORT MonoObject *
7311 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7313 MonoError error;
7314 MonoObject *result;
7315 MonoClass *klass;
7316 MonoDomain *domain;
7318 domain = mono_object_domain (type);
7319 klass = mono_class_from_mono_type (type->type);
7320 mono_class_init_checked (klass, &error);
7321 if (mono_error_set_pending_exception (&error))
7322 return NULL;
7324 if (mono_class_is_nullable (klass))
7325 /* No arguments -> null */
7326 return NULL;
7328 result = mono_object_new_checked (domain, klass, &error);
7329 mono_error_set_pending_exception (&error);
7330 return result;
7333 ICALL_EXPORT MonoReflectionMethod *
7334 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7336 MonoReflectionMethod *ret = NULL;
7337 MonoError error;
7339 MonoClass *klass, *parent;
7340 MonoGenericContext *generic_inst = NULL;
7341 MonoMethod *method = m->method;
7342 MonoMethod *result = NULL;
7343 int slot;
7345 if (method->klass == NULL)
7346 return m;
7348 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7349 MONO_CLASS_IS_INTERFACE (method->klass) ||
7350 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7351 return m;
7353 slot = mono_method_get_vtable_slot (method);
7354 if (slot == -1)
7355 return m;
7357 klass = method->klass;
7358 if (mono_class_is_ginst (klass)) {
7359 generic_inst = mono_class_get_context (klass);
7360 klass = mono_class_get_generic_class (klass)->container_class;
7363 retry:
7364 if (definition) {
7365 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7366 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7367 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7368 or klass is the generic container class and generic_inst is the instantiation.
7370 when we go to the parent, if the parent is an open constructed type, we need to
7371 replace the type parameters by the definitions from the generic_inst, and then take it
7372 apart again into the klass and the generic_inst.
7374 For cases like this:
7375 class C<T> : B<T, int> {
7376 public override void Foo () { ... }
7378 class B<U,V> : A<HashMap<U,V>> {
7379 public override void Foo () { ... }
7381 class A<X> {
7382 public virtual void Foo () { ... }
7385 if at each iteration the parent isn't open, we can skip inflating it. if at some
7386 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7387 NULL;
7389 MonoGenericContext *parent_inst = NULL;
7390 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7391 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7392 if (!mono_error_ok (&error)) {
7393 mono_error_set_pending_exception (&error);
7394 return NULL;
7397 if (mono_class_is_ginst (parent)) {
7398 parent_inst = mono_class_get_context (parent);
7399 parent = mono_class_get_generic_class (parent)->container_class;
7402 mono_class_setup_vtable (parent);
7403 if (parent->vtable_size <= slot)
7404 break;
7405 klass = parent;
7406 generic_inst = parent_inst;
7408 } else {
7409 klass = klass->parent;
7410 if (!klass)
7411 return m;
7412 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7413 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7414 if (!mono_error_ok (&error)) {
7415 mono_error_set_pending_exception (&error);
7416 return NULL;
7419 generic_inst = NULL;
7421 if (mono_class_is_ginst (klass)) {
7422 generic_inst = mono_class_get_context (klass);
7423 klass = mono_class_get_generic_class (klass)->container_class;
7428 if (generic_inst) {
7429 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7430 if (!mono_error_ok (&error)) {
7431 mono_error_set_pending_exception (&error);
7432 return NULL;
7436 if (klass == method->klass)
7437 return m;
7439 /*This is possible if definition == FALSE.
7440 * Do it here to be really sure we don't read invalid memory.
7442 if (slot >= klass->vtable_size)
7443 return m;
7445 mono_class_setup_vtable (klass);
7447 result = klass->vtable [slot];
7448 if (result == NULL) {
7449 /* It is an abstract method */
7450 gboolean found = FALSE;
7451 gpointer iter = NULL;
7452 while ((result = mono_class_get_methods (klass, &iter))) {
7453 if (result->slot == slot) {
7454 found = TRUE;
7455 break;
7458 /* found might be FALSE if we looked in an abstract class
7459 * that doesn't override an abstract method of its
7460 * parent:
7461 * abstract class Base {
7462 * public abstract void Foo ();
7464 * abstract class Derived : Base { }
7465 * class Child : Derived {
7466 * public override void Foo () { }
7469 * if m was Child.Foo and we ask for the base method,
7470 * then we get here with klass == Derived and found == FALSE
7472 /* but it shouldn't be the case that if we're looking
7473 * for the definition and didn't find a result; the
7474 * loop above should've taken us as far as we could
7475 * go! */
7476 g_assert (!(definition && !found));
7477 if (!found)
7478 goto retry;
7481 g_assert (result != NULL);
7483 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7484 mono_error_set_pending_exception (&error);
7485 return ret;
7488 ICALL_EXPORT MonoString*
7489 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7491 MonoMethod *method = m->method;
7493 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7494 return m->name;
7497 ICALL_EXPORT void
7498 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7500 iter->sig = *(MonoMethodSignature**)argsp;
7502 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7503 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7505 iter->next_arg = 0;
7506 /* FIXME: it's not documented what start is exactly... */
7507 if (start) {
7508 iter->args = start;
7509 } else {
7510 iter->args = argsp + sizeof (gpointer);
7512 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7514 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7517 ICALL_EXPORT MonoTypedRef
7518 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7520 guint32 i, arg_size;
7521 gint32 align;
7522 MonoTypedRef res;
7524 i = iter->sig->sentinelpos + iter->next_arg;
7526 g_assert (i < iter->sig->param_count);
7528 res.type = iter->sig->params [i];
7529 res.klass = mono_class_from_mono_type (res.type);
7530 arg_size = mono_type_stack_size (res.type, &align);
7531 #if defined(__arm__) || defined(__mips__)
7532 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7533 #endif
7534 res.value = iter->args;
7535 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7536 /* Values are stored as 8 byte register sized objects, but 'value'
7537 * is dereferenced as a pointer in other routines.
7539 res.value = (char*)res.value + 4;
7540 #endif
7541 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7542 if (arg_size <= sizeof (gpointer)) {
7543 int dummy;
7544 int padding = arg_size - mono_type_size (res.type, &dummy);
7545 res.value = (guint8*)res.value + padding;
7547 #endif
7548 iter->args = (char*)iter->args + arg_size;
7549 iter->next_arg++;
7551 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7553 return res;
7556 ICALL_EXPORT MonoTypedRef
7557 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7559 guint32 i, arg_size;
7560 gint32 align;
7561 MonoTypedRef res;
7563 i = iter->sig->sentinelpos + iter->next_arg;
7565 g_assert (i < iter->sig->param_count);
7567 while (i < iter->sig->param_count) {
7568 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7569 continue;
7570 res.type = iter->sig->params [i];
7571 res.klass = mono_class_from_mono_type (res.type);
7572 /* FIXME: endianess issue... */
7573 arg_size = mono_type_stack_size (res.type, &align);
7574 #if defined(__arm__) || defined(__mips__)
7575 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7576 #endif
7577 res.value = iter->args;
7578 iter->args = (char*)iter->args + arg_size;
7579 iter->next_arg++;
7580 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7581 return res;
7583 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7585 res.type = NULL;
7586 res.value = NULL;
7587 res.klass = NULL;
7588 return res;
7591 ICALL_EXPORT MonoType*
7592 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7594 gint i;
7596 i = iter->sig->sentinelpos + iter->next_arg;
7598 g_assert (i < iter->sig->param_count);
7600 return iter->sig->params [i];
7603 ICALL_EXPORT MonoObject*
7604 mono_TypedReference_ToObject (MonoTypedRef* tref)
7606 MonoError error;
7607 MonoObject *result = NULL;
7608 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7609 MonoObject** objp = (MonoObject **)tref->value;
7610 return *objp;
7613 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7614 mono_error_set_pending_exception (&error);
7615 return result;
7618 ICALL_EXPORT MonoTypedRef
7619 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7621 MonoTypedRef res;
7622 MonoReflectionField *f;
7623 MonoClass *klass;
7624 MonoType *ftype = NULL;
7625 guint8 *p = NULL;
7626 int i;
7628 memset (&res, 0, sizeof (res));
7630 g_assert (fields);
7631 g_assert (mono_array_length (fields) > 0);
7633 klass = target->vtable->klass;
7635 for (i = 0; i < mono_array_length (fields); ++i) {
7636 f = mono_array_get (fields, MonoReflectionField*, i);
7637 if (f == NULL) {
7638 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7639 return res;
7641 if (f->field->parent != klass) {
7642 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7643 return res;
7645 if (i == 0)
7646 p = (guint8*)target + f->field->offset;
7647 else
7648 p += f->field->offset - sizeof (MonoObject);
7649 klass = mono_class_from_mono_type (f->field->type);
7650 ftype = f->field->type;
7653 res.type = ftype;
7654 res.klass = mono_class_from_mono_type (ftype);
7655 res.value = p;
7657 return res;
7660 static void
7661 prelink_method (MonoMethod *method, MonoError *error)
7663 const char *exc_class, *exc_arg;
7665 mono_error_init (error);
7666 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7667 return;
7668 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7669 if (exc_class) {
7670 mono_error_set_exception_instance (error,
7671 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7672 return;
7674 /* create the wrapper, too? */
7677 ICALL_EXPORT void
7678 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7680 MonoError error;
7682 prelink_method (method->method, &error);
7683 mono_error_set_pending_exception (&error);
7686 ICALL_EXPORT void
7687 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7689 MonoError error;
7690 MonoClass *klass = mono_class_from_mono_type (type->type);
7691 MonoMethod* m;
7692 gpointer iter = NULL;
7694 mono_class_init_checked (klass, &error);
7695 if (mono_error_set_pending_exception (&error))
7696 return;
7698 while ((m = mono_class_get_methods (klass, &iter))) {
7699 prelink_method (m, &error);
7700 if (mono_error_set_pending_exception (&error))
7701 return;
7705 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7706 ICALL_EXPORT void
7707 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7708 gint32 const **exponents,
7709 gunichar2 const **digitLowerTable,
7710 gunichar2 const **digitUpperTable,
7711 gint64 const **tenPowersList,
7712 gint32 const **decHexDigits)
7714 *mantissas = Formatter_MantissaBitsTable;
7715 *exponents = Formatter_TensExponentTable;
7716 *digitLowerTable = Formatter_DigitLowerTable;
7717 *digitUpperTable = Formatter_DigitUpperTable;
7718 *tenPowersList = Formatter_TenPowersList;
7719 *decHexDigits = Formatter_DecHexDigits;
7723 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7724 * and avoid useless allocations.
7726 static MonoArray*
7727 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7729 MonoReflectionType *rt;
7730 MonoArray *res;
7731 int i, count = 0;
7733 mono_error_init (error);
7734 for (i = 0; i < type->num_mods; ++i) {
7735 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7736 count++;
7738 if (!count)
7739 return NULL;
7740 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7741 return_val_if_nok (error, NULL);
7742 count = 0;
7743 for (i = 0; i < type->num_mods; ++i) {
7744 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7745 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7746 return_val_if_nok (error, NULL);
7748 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7749 return_val_if_nok (error, NULL);
7751 mono_array_setref (res, count, rt);
7752 count++;
7755 return res;
7758 ICALL_EXPORT MonoArray*
7759 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7761 MonoError error;
7762 MonoType *type = param->ClassImpl->type;
7763 MonoClass *member_class = mono_object_class (param->MemberImpl);
7764 MonoMethod *method = NULL;
7765 MonoImage *image;
7766 int pos;
7767 MonoMethodSignature *sig;
7768 MonoArray *res;
7770 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7771 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7772 method = rmethod->method;
7773 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7774 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7775 if (!(method = prop->property->get))
7776 method = prop->property->set;
7777 g_assert (method);
7778 } else {
7779 char *type_name = mono_type_get_full_name (member_class);
7780 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7781 MonoException *ex = mono_get_exception_not_supported (msg);
7782 g_free (type_name);
7783 g_free (msg);
7784 mono_set_pending_exception (ex);
7785 return NULL;
7788 image = method->klass->image;
7789 pos = param->PositionImpl;
7790 sig = mono_method_signature (method);
7791 if (pos == -1)
7792 type = sig->ret;
7793 else
7794 type = sig->params [pos];
7796 res = type_array_from_modifiers (image, type, optional, &error);
7797 mono_error_set_pending_exception (&error);
7798 return res;
7801 static MonoType*
7802 get_property_type (MonoProperty *prop)
7804 MonoMethodSignature *sig;
7805 if (prop->get) {
7806 sig = mono_method_signature (prop->get);
7807 return sig->ret;
7808 } else if (prop->set) {
7809 sig = mono_method_signature (prop->set);
7810 return sig->params [sig->param_count - 1];
7812 return NULL;
7815 ICALL_EXPORT MonoArray*
7816 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7818 MonoError error;
7819 MonoType *type = get_property_type (property->property);
7820 MonoImage *image = property->klass->image;
7821 MonoArray *res;
7823 if (!type)
7824 return NULL;
7825 res = type_array_from_modifiers (image, type, optional, &error);
7826 mono_error_set_pending_exception (&error);
7827 return res;
7831 *Construct a MonoType suited to be used to decode a constant blob object.
7833 * @type is the target type which will be constructed
7834 * @blob_type is the blob type, for example, that comes from the constant table
7835 * @real_type is the expected constructed type.
7837 static void
7838 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7840 type->type = blob_type;
7841 type->data.klass = NULL;
7842 if (blob_type == MONO_TYPE_CLASS)
7843 type->data.klass = mono_defaults.object_class;
7844 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7845 /* For enums, we need to use the base type */
7846 type->type = MONO_TYPE_VALUETYPE;
7847 type->data.klass = mono_class_from_mono_type (real_type);
7848 } else
7849 type->data.klass = mono_class_from_mono_type (real_type);
7852 ICALL_EXPORT MonoObject*
7853 property_info_get_default_value (MonoReflectionProperty *property)
7855 MonoError error;
7856 MonoType blob_type;
7857 MonoProperty *prop = property->property;
7858 MonoType *type = get_property_type (prop);
7859 MonoDomain *domain = mono_object_domain (property);
7860 MonoTypeEnum def_type;
7861 const char *def_value;
7862 MonoObject *o;
7864 mono_class_init (prop->parent);
7866 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7867 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7868 return NULL;
7871 def_value = mono_class_get_property_default_value (prop, &def_type);
7873 mono_type_from_blob_type (&blob_type, def_type, type);
7874 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7876 mono_error_set_pending_exception (&error);
7877 return o;
7880 ICALL_EXPORT MonoBoolean
7881 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7883 MonoError error;
7884 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7885 MonoCustomAttrInfo *cinfo;
7886 gboolean found;
7888 mono_class_init_checked (attr_class, &error);
7889 if (mono_error_set_pending_exception (&error))
7890 return FALSE;
7892 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7893 if (!is_ok (&error)) {
7894 mono_error_set_pending_exception (&error);
7895 return FALSE;
7897 if (!cinfo)
7898 return FALSE;
7899 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7900 if (!cinfo->cached)
7901 mono_custom_attrs_free (cinfo);
7902 return found;
7905 ICALL_EXPORT MonoArray*
7906 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7908 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7909 MonoArray *res;
7910 MonoError error;
7912 if (attr_class) {
7913 mono_class_init_checked (attr_class, &error);
7914 if (mono_error_set_pending_exception (&error))
7915 return NULL;
7918 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7919 if (!mono_error_ok (&error)) {
7920 mono_error_set_pending_exception (&error);
7921 return NULL;
7924 return res;
7927 ICALL_EXPORT MonoArray*
7928 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7930 MonoError error;
7931 MonoArray *result;
7932 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7933 mono_error_set_pending_exception (&error);
7934 return result;
7938 ICALL_EXPORT MonoString*
7939 ves_icall_Mono_Runtime_GetDisplayName (void)
7941 char *info;
7942 MonoString *display_name;
7944 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7945 display_name = mono_string_new (mono_domain_get (), info);
7946 g_free (info);
7947 return display_name;
7950 ICALL_EXPORT MonoString*
7951 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7953 MonoError error;
7954 MonoString *message;
7955 guint32 ret;
7956 gunichar2 buf[256];
7958 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7959 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7960 buf, 255, NULL);
7961 if (ret == 0) {
7962 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7963 } else {
7964 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7965 if (mono_error_set_pending_exception (&error))
7966 return NULL;
7969 return message;
7972 #ifndef HOST_WIN32
7973 static inline gint32
7974 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
7976 return WAIT_TIMEOUT;
7978 #endif /* !HOST_WIN32 */
7980 ICALL_EXPORT gint32
7981 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7983 return mono_icall_wait_for_input_idle (handle, milliseconds);
7986 ICALL_EXPORT gint32
7987 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7989 return mono_process_current_pid ();
7992 ICALL_EXPORT MonoBoolean
7993 ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
7995 #if HAVE_BTLS
7996 return TRUE;
7997 #else
7998 return FALSE;
7999 #endif
8002 #ifndef DISABLE_COM
8004 ICALL_EXPORT int
8005 ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoException* ex)
8007 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented."));
8008 return 0;
8011 ICALL_EXPORT MonoObject*
8012 ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObject* type)
8014 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented."));
8015 return NULL;
8018 ICALL_EXPORT void*
8019 ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObject* obj)
8021 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented."));
8022 return NULL;
8025 ICALL_EXPORT MonoObject*
8026 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo()
8028 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."));
8029 return NULL;
8032 ICALL_EXPORT MonoBoolean
8033 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException(int error, MonoString* message, void* languageException)
8035 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented."));
8036 return FALSE;
8039 ICALL_EXPORT void
8040 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError(MonoObject* error)
8042 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented."));
8045 ICALL_EXPORT int
8046 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoString* sourceString, int length, void** hstring)
8048 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented."));
8049 return 0;
8052 ICALL_EXPORT int
8053 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring)
8055 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented."));
8056 return 0;
8059 ICALL_EXPORT mono_unichar2*
8060 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length)
8062 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented."));
8063 return NULL;
8066 #endif
8069 #ifndef DISABLE_ICALL_TABLES
8071 #define ICALL_TYPE(id,name,first)
8072 #define ICALL(id,name,func) Icall_ ## id,
8073 #define HANDLES(inner) inner
8075 enum {
8076 #include "metadata/icall-def.h"
8077 Icall_last
8080 #undef ICALL_TYPE
8081 #undef ICALL
8082 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8083 #define ICALL(id,name,func)
8084 #undef HANDLES
8085 #define HANDLES(inner) inner
8086 enum {
8087 #include "metadata/icall-def.h"
8088 Icall_type_num
8091 #undef ICALL_TYPE
8092 #undef ICALL
8093 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8094 #define ICALL(id,name,func)
8095 #undef HANDLES
8096 #define HANDLES(inner) inner
8097 typedef struct {
8098 guint16 first_icall;
8099 } IcallTypeDesc;
8101 static const IcallTypeDesc
8102 icall_type_descs [] = {
8103 #include "metadata/icall-def.h"
8104 {Icall_last}
8107 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8109 #undef HANDLES
8110 #define HANDLES(inner) inner
8111 #undef ICALL_TYPE
8112 #define ICALL_TYPE(id,name,first)
8113 #undef ICALL
8115 #ifdef HAVE_ARRAY_ELEM_INIT
8116 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8117 #define MSGSTRFIELD1(line) str##line
8119 static const struct msgstrtn_t {
8120 #define ICALL(id,name,func)
8121 #undef ICALL_TYPE
8122 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8123 #include "metadata/icall-def.h"
8124 #undef ICALL_TYPE
8125 } icall_type_names_str = {
8126 #define ICALL_TYPE(id,name,first) (name),
8127 #include "metadata/icall-def.h"
8128 #undef ICALL_TYPE
8130 static const guint16 icall_type_names_idx [] = {
8131 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8132 #include "metadata/icall-def.h"
8133 #undef ICALL_TYPE
8135 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8137 static const struct msgstr_t {
8138 #undef ICALL
8139 #define ICALL_TYPE(id,name,first)
8140 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8141 #include "metadata/icall-def.h"
8142 #undef ICALL
8143 } icall_names_str = {
8144 #define ICALL(id,name,func) (name),
8145 #include "metadata/icall-def.h"
8146 #undef ICALL
8148 static const guint16 icall_names_idx [] = {
8149 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8150 #include "metadata/icall-def.h"
8151 #undef ICALL
8153 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8155 #else
8157 #undef ICALL_TYPE
8158 #undef ICALL
8159 #define ICALL_TYPE(id,name,first) name,
8160 #define ICALL(id,name,func)
8161 static const char* const
8162 icall_type_names [] = {
8163 #include "metadata/icall-def.h"
8164 NULL
8167 #define icall_type_name_get(id) (icall_type_names [(id)])
8169 #undef ICALL_TYPE
8170 #undef ICALL
8171 #define ICALL_TYPE(id,name,first)
8172 #define ICALL(id,name,func) name,
8173 static const char* const
8174 icall_names [] = {
8175 #include "metadata/icall-def.h"
8176 NULL
8178 #define icall_name_get(id) icall_names [(id)]
8180 #endif /* !HAVE_ARRAY_ELEM_INIT */
8182 #undef HANDLES
8183 #define HANDLES(inner) inner
8184 #undef ICALL_TYPE
8185 #undef ICALL
8186 #define ICALL_TYPE(id,name,first)
8187 #define ICALL(id,name,func) func,
8188 static const gconstpointer
8189 icall_functions [] = {
8190 #include "metadata/icall-def.h"
8191 NULL
8194 #ifdef ENABLE_ICALL_SYMBOL_MAP
8195 #undef HANDLES
8196 #define HANDLES(inner) inner
8197 #undef ICALL_TYPE
8198 #undef ICALL
8199 #define ICALL_TYPE(id,name,first)
8200 #define ICALL(id,name,func) #func,
8201 static const gconstpointer
8202 icall_symbols [] = {
8203 #include "metadata/icall-def.h"
8204 NULL
8206 #endif
8208 #undef ICALL_TYPE
8209 #undef ICALL
8210 #define ICALL_TYPE(id,name,first)
8211 #define ICALL(id,name,func) 0,
8212 #undef HANDLES
8213 #define HANDLES(inner) 1,
8214 static const guchar
8215 icall_uses_handles [] = {
8216 #include "metadata/icall-def.h"
8217 #undef ICALL
8218 #undef HANDLES
8221 #endif /* DISABLE_ICALL_TABLES */
8223 static mono_mutex_t icall_mutex;
8224 static GHashTable *icall_hash = NULL;
8225 static GHashTable *jit_icall_hash_name = NULL;
8226 static GHashTable *jit_icall_hash_addr = NULL;
8228 void
8229 mono_icall_init (void)
8231 #ifndef DISABLE_ICALL_TABLES
8232 int i = 0;
8234 /* check that tables are sorted: disable in release */
8235 if (TRUE) {
8236 int j;
8237 const char *prev_class = NULL;
8238 const char *prev_method;
8240 for (i = 0; i < Icall_type_num; ++i) {
8241 const IcallTypeDesc *desc;
8242 int num_icalls;
8243 prev_method = NULL;
8244 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8245 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8246 prev_class = icall_type_name_get (i);
8247 desc = &icall_type_descs [i];
8248 num_icalls = icall_desc_num_icalls (desc);
8249 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8250 for (j = 0; j < num_icalls; ++j) {
8251 const char *methodn = icall_name_get (desc->first_icall + j);
8252 if (prev_method && strcmp (prev_method, methodn) >= 0)
8253 g_print ("method %s should come before method %s\n", methodn, prev_method);
8254 prev_method = methodn;
8258 #endif
8260 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8261 mono_os_mutex_init (&icall_mutex);
8264 static void
8265 mono_icall_lock (void)
8267 mono_locks_os_acquire (&icall_mutex, IcallLock);
8270 static void
8271 mono_icall_unlock (void)
8273 mono_locks_os_release (&icall_mutex, IcallLock);
8276 void
8277 mono_icall_cleanup (void)
8279 g_hash_table_destroy (icall_hash);
8280 g_hash_table_destroy (jit_icall_hash_name);
8281 g_hash_table_destroy (jit_icall_hash_addr);
8282 mono_os_mutex_destroy (&icall_mutex);
8286 * mono_add_internal_call:
8287 * @name: method specification to surface to the managed world
8288 * @method: pointer to a C method to invoke when the method is called
8290 * This method surfaces the C function pointed by @method as a method
8291 * that has been surfaced in managed code with the method specified in
8292 * @name as an internal call.
8294 * Internal calls are surfaced to all app domains loaded and they are
8295 * accessibly by a type with the specified name.
8297 * You must provide a fully qualified type name, that is namespaces
8298 * and type name, followed by a colon and the method name, with an
8299 * optional signature to bind.
8301 * For example, the following are all valid declarations:
8303 * "MyApp.Services.ScriptService:Accelerate"
8304 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8306 * You use method parameters in cases where there might be more than
8307 * one surface method to managed code. That way you can register different
8308 * internal calls for different method overloads.
8310 * The internal calls are invoked with no marshalling. This means that .NET
8311 * types like System.String are exposed as `MonoString *` parameters. This is
8312 * different than the way that strings are surfaced in P/Invoke.
8314 * For more information on how the parameters are marshalled, see the
8315 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8316 * page.
8318 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8319 * reference for more information on the format of method descriptions.
8321 void
8322 mono_add_internal_call (const char *name, gconstpointer method)
8324 mono_icall_lock ();
8326 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8328 mono_icall_unlock ();
8331 #ifndef DISABLE_ICALL_TABLES
8333 #ifdef HAVE_ARRAY_ELEM_INIT
8334 static int
8335 compare_method_imap (const void *key, const void *elem)
8337 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8338 return strcmp (key, method_name);
8341 static gsize
8342 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8344 const guint16 *nameslot = (const guint16 *)mono_binary_search (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
8345 if (!nameslot)
8346 return -1;
8347 return (nameslot - &icall_names_idx [0]);
8350 static gboolean
8351 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8353 gsize slotnum = find_slot_icall (imap, name);
8354 if (slotnum == -1)
8355 return FALSE;
8356 return (gboolean)icall_uses_handles [slotnum];
8359 static gpointer
8360 find_method_icall (const IcallTypeDesc *imap, const char *name)
8362 gsize slotnum = find_slot_icall (imap, name);
8363 if (slotnum == -1)
8364 return NULL;
8365 return (gpointer)icall_functions [slotnum];
8368 static int
8369 compare_class_imap (const void *key, const void *elem)
8371 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8372 return strcmp (key, class_name);
8375 static const IcallTypeDesc*
8376 find_class_icalls (const char *name)
8378 const guint16 *nameslot = (const guint16 *)mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
8379 if (!nameslot)
8380 return NULL;
8381 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8384 #else /* HAVE_ARRAY_ELEM_INIT */
8386 static int
8387 compare_method_imap (const void *key, const void *elem)
8389 const char** method_name = (const char**)elem;
8390 return strcmp (key, *method_name);
8393 static gsize
8394 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8396 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8397 if (!nameslot)
8398 return -1;
8399 return nameslot - icall_names;
8402 static gpointer
8403 find_method_icall (const IcallTypeDesc *imap, const char *name)
8405 gsize slotnum = find_slot_icall (imap, name);
8406 if (slotnum == -1)
8407 return NULL;
8408 return (gpointer)icall_functions [slotnum];
8411 static gboolean
8412 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8414 gsize slotnum = find_slot_icall (imap, name);
8415 if (slotnum == -1)
8416 return FALSE;
8417 return (gboolean)icall_uses_handles [slotnum];
8420 static int
8421 compare_class_imap (const void *key, const void *elem)
8423 const char** class_name = (const char**)elem;
8424 return strcmp (key, *class_name);
8427 static const IcallTypeDesc*
8428 find_class_icalls (const char *name)
8430 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8431 if (!nameslot)
8432 return NULL;
8433 return &icall_type_descs [nameslot - icall_type_names];
8436 #endif /* HAVE_ARRAY_ELEM_INIT */
8438 #endif /* DISABLE_ICALL_TABLES */
8441 * we should probably export this as an helper (handle nested types).
8442 * Returns the number of chars written in buf.
8444 static int
8445 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8447 int nspacelen, cnamelen;
8448 nspacelen = strlen (klass->name_space);
8449 cnamelen = strlen (klass->name);
8450 if (nspacelen + cnamelen + 2 > bufsize)
8451 return 0;
8452 if (nspacelen) {
8453 memcpy (buf, klass->name_space, nspacelen);
8454 buf [nspacelen ++] = '.';
8456 memcpy (buf + nspacelen, klass->name, cnamelen);
8457 buf [nspacelen + cnamelen] = 0;
8458 return nspacelen + cnamelen;
8461 #ifdef DISABLE_ICALL_TABLES
8462 static void
8463 no_icall_table (void)
8465 g_assert_not_reached ();
8467 #endif
8470 * mono_lookup_internal_call_full:
8471 * @method: the method to look up
8472 * @uses_handles: out argument if method needs handles around managed objects.
8474 * Returns a pointer to the icall code for the given method. If
8475 * uses_handles is not NULL, it will be set to TRUE if the method
8476 * needs managed objects wrapped using the infrastructure in handle.h
8478 * If the method is not found, warns and returns NULL.
8480 gpointer
8481 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8483 char *sigstart;
8484 char *tmpsig;
8485 char mname [2048];
8486 int typelen = 0, mlen, siglen;
8487 gpointer res;
8488 #ifndef DISABLE_ICALL_TABLES
8489 const IcallTypeDesc *imap = NULL;
8490 #endif
8492 g_assert (method != NULL);
8494 if (method->is_inflated)
8495 method = ((MonoMethodInflated *) method)->declaring;
8497 if (method->klass->nested_in) {
8498 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8499 if (!pos)
8500 return NULL;
8502 mname [pos++] = '/';
8503 mname [pos] = 0;
8505 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8506 if (!typelen)
8507 return NULL;
8509 typelen += pos;
8510 } else {
8511 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8512 if (!typelen)
8513 return NULL;
8516 #ifndef DISABLE_ICALL_TABLES
8517 imap = find_class_icalls (mname);
8518 #endif
8520 mname [typelen] = ':';
8521 mname [typelen + 1] = ':';
8523 mlen = strlen (method->name);
8524 memcpy (mname + typelen + 2, method->name, mlen);
8525 sigstart = mname + typelen + 2 + mlen;
8526 *sigstart = 0;
8528 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8529 siglen = strlen (tmpsig);
8530 if (typelen + mlen + siglen + 6 > sizeof (mname))
8531 return NULL;
8532 sigstart [0] = '(';
8533 memcpy (sigstart + 1, tmpsig, siglen);
8534 sigstart [siglen + 1] = ')';
8535 sigstart [siglen + 2] = 0;
8536 g_free (tmpsig);
8538 mono_icall_lock ();
8540 res = g_hash_table_lookup (icall_hash, mname);
8541 if (res) {
8542 if (uses_handles)
8543 *uses_handles = FALSE;
8544 mono_icall_unlock ();;
8545 return res;
8547 /* try without signature */
8548 *sigstart = 0;
8549 res = g_hash_table_lookup (icall_hash, mname);
8550 if (res) {
8551 if (uses_handles)
8552 *uses_handles = FALSE;
8553 mono_icall_unlock ();
8554 return res;
8557 #ifdef DISABLE_ICALL_TABLES
8558 mono_icall_unlock ();
8559 /* Fail only when the result is actually used */
8560 /* mono_marshal_get_native_wrapper () depends on this */
8561 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8562 return ves_icall_System_String_ctor_RedirectToCreateString;
8563 else
8564 return no_icall_table;
8565 #else
8566 /* it wasn't found in the static call tables */
8567 if (!imap) {
8568 if (uses_handles)
8569 *uses_handles = FALSE;
8570 mono_icall_unlock ();
8571 return NULL;
8573 res = find_method_icall (imap, sigstart - mlen);
8574 if (res) {
8575 if (uses_handles)
8576 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8577 mono_icall_unlock ();
8578 return res;
8580 /* try _with_ signature */
8581 *sigstart = '(';
8582 res = find_method_icall (imap, sigstart - mlen);
8583 if (res) {
8584 if (uses_handles)
8585 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8586 mono_icall_unlock ();
8587 return res;
8590 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8591 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8592 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8593 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8594 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");
8595 g_print ("If you see other errors or faults after this message they are probably related\n");
8596 g_print ("and you need to fix your mono install first.\n");
8598 mono_icall_unlock ();
8600 return NULL;
8601 #endif
8604 gpointer
8605 mono_lookup_internal_call (MonoMethod *method)
8607 return mono_lookup_internal_call_full (method, NULL);
8610 #ifdef ENABLE_ICALL_SYMBOL_MAP
8611 static int
8612 func_cmp (gconstpointer key, gconstpointer p)
8614 return (gsize)key - (gsize)*(gsize*)p;
8616 #endif
8619 * mono_lookup_icall_symbol:
8621 * Given the icall METHOD, returns its C symbol.
8623 const char*
8624 mono_lookup_icall_symbol (MonoMethod *m)
8626 #ifdef DISABLE_ICALL_TABLES
8627 g_assert_not_reached ();
8628 return NULL;
8629 #else
8630 #ifdef ENABLE_ICALL_SYMBOL_MAP
8631 gpointer func;
8632 int i;
8633 gpointer slot;
8634 static gconstpointer *functions_sorted;
8635 static const char**symbols_sorted;
8636 static gboolean inited;
8638 if (!inited) {
8639 gboolean changed;
8641 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8642 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8643 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8644 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8645 /* Bubble sort the two arrays */
8646 changed = TRUE;
8647 while (changed) {
8648 changed = FALSE;
8649 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8650 if (functions_sorted [i] > functions_sorted [i + 1]) {
8651 gconstpointer tmp;
8653 tmp = functions_sorted [i];
8654 functions_sorted [i] = functions_sorted [i + 1];
8655 functions_sorted [i + 1] = tmp;
8656 tmp = symbols_sorted [i];
8657 symbols_sorted [i] = symbols_sorted [i + 1];
8658 symbols_sorted [i + 1] = tmp;
8659 changed = TRUE;
8665 func = mono_lookup_internal_call (m);
8666 if (!func)
8667 return NULL;
8668 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8669 if (!slot)
8670 return NULL;
8671 g_assert (slot);
8672 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8673 #else
8674 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8675 g_assert_not_reached ();
8676 return 0;
8677 #endif
8678 #endif
8681 static MonoType*
8682 type_from_typename (char *type_name)
8684 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8686 if (!strcmp (type_name, "int"))
8687 klass = mono_defaults.int_class;
8688 else if (!strcmp (type_name, "ptr"))
8689 klass = mono_defaults.int_class;
8690 else if (!strcmp (type_name, "void"))
8691 klass = mono_defaults.void_class;
8692 else if (!strcmp (type_name, "int32"))
8693 klass = mono_defaults.int32_class;
8694 else if (!strcmp (type_name, "uint32"))
8695 klass = mono_defaults.uint32_class;
8696 else if (!strcmp (type_name, "int8"))
8697 klass = mono_defaults.sbyte_class;
8698 else if (!strcmp (type_name, "uint8"))
8699 klass = mono_defaults.byte_class;
8700 else if (!strcmp (type_name, "int16"))
8701 klass = mono_defaults.int16_class;
8702 else if (!strcmp (type_name, "uint16"))
8703 klass = mono_defaults.uint16_class;
8704 else if (!strcmp (type_name, "long"))
8705 klass = mono_defaults.int64_class;
8706 else if (!strcmp (type_name, "ulong"))
8707 klass = mono_defaults.uint64_class;
8708 else if (!strcmp (type_name, "float"))
8709 klass = mono_defaults.single_class;
8710 else if (!strcmp (type_name, "double"))
8711 klass = mono_defaults.double_class;
8712 else if (!strcmp (type_name, "object"))
8713 klass = mono_defaults.object_class;
8714 else if (!strcmp (type_name, "obj"))
8715 klass = mono_defaults.object_class;
8716 else if (!strcmp (type_name, "string"))
8717 klass = mono_defaults.string_class;
8718 else if (!strcmp (type_name, "bool"))
8719 klass = mono_defaults.boolean_class;
8720 else if (!strcmp (type_name, "boolean"))
8721 klass = mono_defaults.boolean_class;
8722 else {
8723 g_error ("%s", type_name);
8724 g_assert_not_reached ();
8726 return &klass->byval_arg;
8730 * LOCKING: Take the corlib image lock.
8732 MonoMethodSignature*
8733 mono_create_icall_signature (const char *sigstr)
8735 gchar **parts;
8736 int i, len;
8737 gchar **tmp;
8738 MonoMethodSignature *res, *res2;
8739 MonoImage *corlib = mono_defaults.corlib;
8741 mono_image_lock (corlib);
8742 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8743 mono_image_unlock (corlib);
8745 if (res)
8746 return res;
8748 parts = g_strsplit (sigstr, " ", 256);
8750 tmp = parts;
8751 len = 0;
8752 while (*tmp) {
8753 len ++;
8754 tmp ++;
8757 res = mono_metadata_signature_alloc (corlib, len - 1);
8758 res->pinvoke = 1;
8760 #ifdef HOST_WIN32
8762 * Under windows, the default pinvoke calling convention is STDCALL but
8763 * we need CDECL.
8765 res->call_convention = MONO_CALL_C;
8766 #endif
8768 res->ret = type_from_typename (parts [0]);
8769 for (i = 1; i < len; ++i) {
8770 res->params [i - 1] = type_from_typename (parts [i]);
8773 g_strfreev (parts);
8775 mono_image_lock (corlib);
8776 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8777 if (res2)
8778 res = res2; /*Value is allocated in the image pool*/
8779 else
8780 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8781 mono_image_unlock (corlib);
8783 return res;
8786 MonoJitICallInfo *
8787 mono_find_jit_icall_by_name (const char *name)
8789 MonoJitICallInfo *info;
8790 g_assert (jit_icall_hash_name);
8792 mono_icall_lock ();
8793 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8794 mono_icall_unlock ();
8795 return info;
8798 MonoJitICallInfo *
8799 mono_find_jit_icall_by_addr (gconstpointer addr)
8801 MonoJitICallInfo *info;
8802 g_assert (jit_icall_hash_addr);
8804 mono_icall_lock ();
8805 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8806 mono_icall_unlock ();
8808 return info;
8812 * mono_get_jit_icall_info:
8814 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8815 * caller should access it while holding the icall lock.
8817 GHashTable*
8818 mono_get_jit_icall_info (void)
8820 return jit_icall_hash_name;
8824 * mono_lookup_jit_icall_symbol:
8826 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8828 const char*
8829 mono_lookup_jit_icall_symbol (const char *name)
8831 MonoJitICallInfo *info;
8832 const char *res = NULL;
8834 mono_icall_lock ();
8835 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8836 if (info)
8837 res = info->c_symbol;
8838 mono_icall_unlock ();
8839 return res;
8842 void
8843 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8845 mono_icall_lock ();
8846 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8847 mono_icall_unlock ();
8851 * If NO_RAISE is set, that means the icall is not calling mono_raise_exception () directly or indirectly. The JIT might be able to call these
8852 * icalls without wrappers in some cases.
8854 MonoJitICallInfo *
8855 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8857 MonoJitICallInfo *info;
8859 g_assert (func);
8860 g_assert (name);
8862 mono_icall_lock ();
8864 if (!jit_icall_hash_name) {
8865 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8866 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8869 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8870 g_warning ("jit icall already defined \"%s\"\n", name);
8871 g_assert_not_reached ();
8874 info = g_new0 (MonoJitICallInfo, 1);
8876 info->name = name;
8877 info->func = func;
8878 info->sig = sig;
8879 info->c_symbol = c_symbol;
8880 info->no_raise = no_raise;
8882 if (is_save) {
8883 info->wrapper = func;
8884 } else {
8885 info->wrapper = NULL;
8888 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8889 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8891 mono_icall_unlock ();
8892 return info;
8895 MonoJitICallInfo *
8896 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8898 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);