[runtime] MonoError-ize mono_compile_method
[mono-project.git] / mono / metadata / icall.c
blob3a47c3286ee772462fe9bb2714535c84f47f6f14
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 (HOST_WIN32)
32 #include <stdlib.h>
33 #endif
34 #if defined (HAVE_WCHAR_H)
35 #include <wchar.h>
36 #endif
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
99 #include <windows.h>
100 #include <shlobj.h>
101 #endif
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
107 #endif
109 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
121 static MonoArray*
122 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType *type)
127 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
130 static void
131 mono_class_init_checked (MonoClass *klass, MonoError *error)
133 mono_error_init (error);
135 if (!mono_class_init (klass))
136 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
139 ICALL_EXPORT MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
142 MonoError error;
143 MonoClass *ac;
144 gint32 esize;
145 gpointer *ea;
146 MonoObject *result = NULL;
148 ac = (MonoClass *)arr->obj.vtable->klass;
150 esize = mono_array_element_size (ac);
151 ea = (gpointer*)((char*)arr->vector + (pos * esize));
153 if (ac->element_class->valuetype) {
154 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
155 mono_error_set_pending_exception (&error);
156 } else
157 result = (MonoObject *)*ea;
158 return result;
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
164 MonoClass *ac, *ic;
165 MonoArray *io;
166 gint32 i, pos, *ind;
168 MONO_CHECK_ARG_NULL (idxs, NULL);
170 io = idxs;
171 ic = (MonoClass *)io->obj.vtable->klass;
173 ac = (MonoClass *)arr->obj.vtable->klass;
175 g_assert (ic->rank == 1);
176 if (io->bounds != NULL || io->max_length != ac->rank) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
178 return NULL;
181 ind = (gint32 *)io->vector;
183 if (arr->bounds == NULL) {
184 if (*ind < 0 || *ind >= arr->max_length) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
186 return NULL;
189 return ves_icall_System_Array_GetValueImpl (arr, *ind);
192 for (i = 0; i < ac->rank; i++) {
193 if ((ind [i] < arr->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
196 return NULL;
200 pos = ind [0] - arr->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos * arr->bounds [i].length + ind [i] -
203 arr->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (arr, pos);
208 ICALL_EXPORT void
209 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
211 MonoError error;
212 MonoClass *ac, *vc, *ec;
213 gint32 esize, vsize;
214 gpointer *ea, *va;
215 int et, vt;
217 guint64 u64 = 0;
218 gint64 i64 = 0;
219 gdouble r64 = 0;
221 mono_error_init (&error);
223 if (value)
224 vc = value->vtable->klass;
225 else
226 vc = NULL;
228 ac = arr->obj.vtable->klass;
229 ec = ac->element_class;
231 esize = mono_array_element_size (ac);
232 ea = (gpointer*)((char*)arr->vector + (pos * esize));
233 va = (gpointer*)((char*)value + sizeof (MonoObject));
235 if (mono_class_is_nullable (ec)) {
236 mono_nullable_init ((guint8*)ea, value, ec);
237 return;
240 if (!value) {
241 mono_gc_bzero_atomic (ea, esize);
242 return;
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
248 return; \
249 }G_STMT_END
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
255 return; \
257 }G_STMT_END
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
262 return; \
263 }G_STMT_END
265 /* Check element (destination) type. */
266 switch (ec->byval_arg.type) {
267 case MONO_TYPE_STRING:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_STRING:
270 break;
271 default:
272 INVALID_CAST;
274 break;
275 case MONO_TYPE_BOOLEAN:
276 switch (vc->byval_arg.type) {
277 case MONO_TYPE_BOOLEAN:
278 break;
279 case MONO_TYPE_CHAR:
280 case MONO_TYPE_U1:
281 case MONO_TYPE_U2:
282 case MONO_TYPE_U4:
283 case MONO_TYPE_U8:
284 case MONO_TYPE_I1:
285 case MONO_TYPE_I2:
286 case MONO_TYPE_I4:
287 case MONO_TYPE_I8:
288 case MONO_TYPE_R4:
289 case MONO_TYPE_R8:
290 NO_WIDENING_CONVERSION;
291 default:
292 INVALID_CAST;
294 break;
295 default:
296 break;
299 if (!ec->valuetype) {
300 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
301 if (mono_error_set_pending_exception (&error))
302 return;
303 if (!castOk)
304 INVALID_CAST;
305 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
306 return;
309 if (mono_object_isinst_checked (value, ec, &error)) {
310 if (ec->has_references)
311 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
312 else
313 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
314 return;
316 if (mono_error_set_pending_exception (&error))
317 return;
319 if (!vc->valuetype)
320 INVALID_CAST;
322 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
324 et = ec->byval_arg.type;
325 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
326 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
328 vt = vc->byval_arg.type;
329 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
330 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
333 switch (vt) { \
334 case MONO_TYPE_U1: \
335 case MONO_TYPE_U2: \
336 case MONO_TYPE_U4: \
337 case MONO_TYPE_U8: \
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
341 return; \
342 /* You can't assign a signed value to an unsigned array. */ \
343 case MONO_TYPE_I1: \
344 case MONO_TYPE_I2: \
345 case MONO_TYPE_I4: \
346 case MONO_TYPE_I8: \
347 /* You can't assign a floating point number to an integer array. */ \
348 case MONO_TYPE_R4: \
349 case MONO_TYPE_R8: \
350 NO_WIDENING_CONVERSION; \
352 }G_STMT_END
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
355 switch (vt) { \
356 case MONO_TYPE_I1: \
357 case MONO_TYPE_I2: \
358 case MONO_TYPE_I4: \
359 case MONO_TYPE_I8: \
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
362 return; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
365 case MONO_TYPE_U1: \
366 case MONO_TYPE_U2: \
367 case MONO_TYPE_U4: \
368 case MONO_TYPE_U8: \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
372 return; \
373 /* You can't assign a floating point number to an integer array. */ \
374 case MONO_TYPE_R4: \
375 case MONO_TYPE_R8: \
376 NO_WIDENING_CONVERSION; \
378 }G_STMT_END
380 #define ASSIGN_REAL(etype) G_STMT_START{\
381 switch (vt) { \
382 case MONO_TYPE_R4: \
383 case MONO_TYPE_R8: \
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
386 return; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
389 case MONO_TYPE_I1: \
390 case MONO_TYPE_I2: \
391 case MONO_TYPE_I4: \
392 case MONO_TYPE_I8: \
393 *(etype *) ea = (etype) i64; \
394 return; \
395 case MONO_TYPE_U1: \
396 case MONO_TYPE_U2: \
397 case MONO_TYPE_U4: \
398 case MONO_TYPE_U8: \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
401 return; \
403 }G_STMT_END
405 switch (vt) {
406 case MONO_TYPE_U1:
407 u64 = *(guint8 *) va;
408 break;
409 case MONO_TYPE_U2:
410 u64 = *(guint16 *) va;
411 break;
412 case MONO_TYPE_U4:
413 u64 = *(guint32 *) va;
414 break;
415 case MONO_TYPE_U8:
416 u64 = *(guint64 *) va;
417 break;
418 case MONO_TYPE_I1:
419 i64 = *(gint8 *) va;
420 break;
421 case MONO_TYPE_I2:
422 i64 = *(gint16 *) va;
423 break;
424 case MONO_TYPE_I4:
425 i64 = *(gint32 *) va;
426 break;
427 case MONO_TYPE_I8:
428 i64 = *(gint64 *) va;
429 break;
430 case MONO_TYPE_R4:
431 r64 = *(gfloat *) va;
432 break;
433 case MONO_TYPE_R8:
434 r64 = *(gdouble *) va;
435 break;
436 case MONO_TYPE_CHAR:
437 u64 = *(guint16 *) va;
438 break;
439 case MONO_TYPE_BOOLEAN:
440 /* Boolean is only compatible with itself. */
441 switch (et) {
442 case MONO_TYPE_CHAR:
443 case MONO_TYPE_U1:
444 case MONO_TYPE_U2:
445 case MONO_TYPE_U4:
446 case MONO_TYPE_U8:
447 case MONO_TYPE_I1:
448 case MONO_TYPE_I2:
449 case MONO_TYPE_I4:
450 case MONO_TYPE_I8:
451 case MONO_TYPE_R4:
452 case MONO_TYPE_R8:
453 NO_WIDENING_CONVERSION;
454 default:
455 INVALID_CAST;
457 break;
460 /* If we can't do a direct copy, let's try a widening conversion. */
461 switch (et) {
462 case MONO_TYPE_CHAR:
463 ASSIGN_UNSIGNED (guint16);
464 case MONO_TYPE_U1:
465 ASSIGN_UNSIGNED (guint8);
466 case MONO_TYPE_U2:
467 ASSIGN_UNSIGNED (guint16);
468 case MONO_TYPE_U4:
469 ASSIGN_UNSIGNED (guint32);
470 case MONO_TYPE_U8:
471 ASSIGN_UNSIGNED (guint64);
472 case MONO_TYPE_I1:
473 ASSIGN_SIGNED (gint8);
474 case MONO_TYPE_I2:
475 ASSIGN_SIGNED (gint16);
476 case MONO_TYPE_I4:
477 ASSIGN_SIGNED (gint32);
478 case MONO_TYPE_I8:
479 ASSIGN_SIGNED (gint64);
480 case MONO_TYPE_R4:
481 ASSIGN_REAL (gfloat);
482 case MONO_TYPE_R8:
483 ASSIGN_REAL (gdouble);
486 INVALID_CAST;
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
488 return;
490 #undef INVALID_CAST
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
494 #undef ASSIGN_SIGNED
495 #undef ASSIGN_REAL
498 ICALL_EXPORT void
499 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
500 MonoArray *idxs)
502 MonoClass *ac, *ic;
503 gint32 i, pos, *ind;
505 MONO_CHECK_ARG_NULL (idxs,);
507 ic = idxs->obj.vtable->klass;
508 ac = arr->obj.vtable->klass;
510 g_assert (ic->rank == 1);
511 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
513 return;
516 ind = (gint32 *)idxs->vector;
518 if (arr->bounds == NULL) {
519 if (*ind < 0 || *ind >= arr->max_length) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
521 return;
524 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
525 return;
528 for (i = 0; i < ac->rank; i++)
529 if ((ind [i] < arr->bounds [i].lower_bound) ||
530 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
532 return;
535 pos = ind [0] - arr->bounds [0].lower_bound;
536 for (i = 1; i < ac->rank; i++)
537 pos = pos * arr->bounds [i].length + ind [i] -
538 arr->bounds [i].lower_bound;
540 ves_icall_System_Array_SetValueImpl (arr, value, pos);
543 ICALL_EXPORT MonoArray *
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
546 MonoError error;
547 MonoClass *aklass, *klass;
548 MonoArray *array;
549 uintptr_t *sizes, i;
550 gboolean bounded = FALSE;
552 MONO_CHECK_ARG_NULL (type, NULL);
553 MONO_CHECK_ARG_NULL (lengths, NULL);
555 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
556 if (bounds)
557 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
559 for (i = 0; i < mono_array_length (lengths); i++) {
560 if (mono_array_get (lengths, gint32, i) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
562 return NULL;
566 klass = mono_class_from_mono_type (type->type);
567 mono_class_init_checked (klass, &error);
568 if (mono_error_set_pending_exception (&error))
569 return NULL;
571 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
573 bounded = TRUE;
574 else
575 bounded = FALSE;
577 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
579 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
580 for (i = 0; i < aklass->rank; ++i) {
581 sizes [i] = mono_array_get (lengths, guint32, i);
582 if (bounds)
583 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
584 else
585 sizes [i + aklass->rank] = 0;
588 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
589 mono_error_set_pending_exception (&error);
591 return array;
594 ICALL_EXPORT MonoArray *
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
597 MonoError error;
598 MonoClass *aklass, *klass;
599 MonoArray *array;
600 uintptr_t *sizes, i;
601 gboolean bounded = FALSE;
603 MONO_CHECK_ARG_NULL (type, NULL);
604 MONO_CHECK_ARG_NULL (lengths, NULL);
606 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
607 if (bounds)
608 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
610 for (i = 0; i < mono_array_length (lengths); i++) {
611 if ((mono_array_get (lengths, gint64, i) < 0) ||
612 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
614 return NULL;
618 klass = mono_class_from_mono_type (type->type);
619 mono_class_init_checked (klass, &error);
620 if (mono_error_set_pending_exception (&error))
621 return NULL;
623 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
625 bounded = TRUE;
626 else
627 bounded = FALSE;
629 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
631 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
632 for (i = 0; i < aklass->rank; ++i) {
633 sizes [i] = mono_array_get (lengths, guint64, i);
634 if (bounds)
635 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
636 else
637 sizes [i + aklass->rank] = 0;
640 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
641 mono_error_set_pending_exception (&error);
643 return array;
646 ICALL_EXPORT gint32
647 ves_icall_System_Array_GetRank (MonoObject *arr)
649 return arr->vtable->klass->rank;
652 ICALL_EXPORT gint32
653 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
655 gint32 rank = arr->obj.vtable->klass->rank;
656 uintptr_t length;
658 if ((dimension < 0) || (dimension >= rank)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
660 return 0;
663 if (arr->bounds == NULL)
664 length = arr->max_length;
665 else
666 length = arr->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
671 return 0;
673 #endif
674 return length;
677 ICALL_EXPORT gint64
678 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
680 gint32 rank = arr->obj.vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
684 return 0;
687 if (arr->bounds == NULL)
688 return arr->max_length;
690 return arr->bounds [dimension].length;
693 ICALL_EXPORT gint32
694 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
696 gint32 rank = arr->obj.vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
700 return 0;
703 if (arr->bounds == NULL)
704 return 0;
706 return arr->bounds [dimension].lower_bound;
709 ICALL_EXPORT void
710 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
712 int sz = mono_array_element_size (mono_object_class (arr));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
716 ICALL_EXPORT MonoArray*
717 ves_icall_System_Array_Clone (MonoArray *arr)
719 MonoError error;
720 MonoArray *result = mono_array_clone_checked (arr, &error);
721 mono_error_set_pending_exception (&error);
722 return result;
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
728 int element_size;
729 void * dest_addr;
730 void * source_addr;
731 MonoVTable *src_vtable;
732 MonoVTable *dest_vtable;
733 MonoClass *src_class;
734 MonoClass *dest_class;
736 src_vtable = source->obj.vtable;
737 dest_vtable = dest->obj.vtable;
739 if (src_vtable->rank != dest_vtable->rank)
740 return FALSE;
742 if (source->bounds || dest->bounds)
743 return FALSE;
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx + length > mono_array_length_fast (dest)) ||
747 (source_idx + length > mono_array_length_fast (source)))
748 return FALSE;
750 src_class = src_vtable->klass->element_class;
751 dest_class = dest_vtable->klass->element_class;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
758 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
760 if (src_class == mono_defaults.object_class && dest_class->valuetype)
761 return FALSE;
763 /* Check if we're copying a char[] <==> (u)short[] */
764 if (src_class != dest_class) {
765 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
766 return FALSE;
768 /* 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. */
769 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
770 return FALSE;
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
778 } else {
779 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
780 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
782 } else {
783 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
786 return TRUE;
789 ICALL_EXPORT void
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
792 MonoClass *ac;
793 gint32 esize;
794 gpointer *ea;
796 ac = (MonoClass *)arr->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)arr->vector + (pos * esize));
801 mono_gc_memmove_atomic (value, ea, esize);
804 ICALL_EXPORT void
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
807 MonoClass *ac, *ec;
808 gint32 esize;
809 gpointer *ea;
811 ac = (MonoClass *)arr->obj.vtable->klass;
812 ec = ac->element_class;
814 esize = mono_array_element_size (ac);
815 ea = (gpointer*)((char*)arr->vector + (pos * esize));
817 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
818 g_assert (esize == sizeof (gpointer));
819 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
820 } else {
821 g_assert (ec->inited);
822 g_assert (esize == mono_class_value_size (ec, NULL));
823 if (ec->has_references)
824 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
825 else
826 mono_gc_memmove_atomic (ea, value, esize);
830 ICALL_EXPORT void
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
833 MonoClass *klass = array->obj.vtable->klass;
834 guint32 size = mono_array_element_size (klass);
835 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
836 int align;
837 const char *field_data;
839 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_set_pending_exception (exc);
843 return;
846 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
847 MonoException *exc = mono_get_exception_argument("field_handle",
848 "Field doesn't have an RVA");
849 mono_set_pending_exception (exc);
850 return;
853 size *= array->max_length;
854 field_data = mono_field_get_data (field_handle);
856 if (size > mono_type_size (field_handle->type, &align)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field not large enough to fill array");
859 mono_set_pending_exception (exc);
860 return;
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
864 #define SWAP(n) { \
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
867 int i, \
868 nEnt = (size / sizeof(guint ## n)); \
870 for (i = 0; i < nEnt; i++) { \
871 data[i] = read ## n (&src[i]); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
878 case MONO_TYPE_CHAR:
879 case MONO_TYPE_I2:
880 case MONO_TYPE_U2:
881 SWAP (16);
882 break;
883 case MONO_TYPE_I4:
884 case MONO_TYPE_U4:
885 case MONO_TYPE_R4:
886 SWAP (32);
887 break;
888 case MONO_TYPE_I8:
889 case MONO_TYPE_U8:
890 case MONO_TYPE_R8:
891 SWAP (64);
892 break;
893 default:
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
895 break;
897 #else
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
899 #endif
902 ICALL_EXPORT gint
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
905 return offsetof (MonoString, chars);
908 ICALL_EXPORT MonoObject *
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
911 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
912 return obj;
913 else {
914 MonoError error;
915 MonoObject *ret = mono_object_clone_checked (obj, &error);
916 mono_error_set_pending_exception (&error);
918 return ret;
922 ICALL_EXPORT void
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
925 MonoError error;
926 MonoClass *klass;
927 MonoVTable *vtable;
929 MONO_CHECK_ARG_NULL (handle,);
931 klass = mono_class_from_mono_type (handle);
932 MONO_CHECK_ARG (handle, klass,);
934 if (klass->generic_container)
935 return;
937 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
940 return;
943 /* This will call the type constructor */
944 if (!mono_runtime_class_init_full (vtable, &error))
945 mono_error_set_pending_exception (&error);
948 ICALL_EXPORT void
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
951 MonoError error;
953 mono_image_check_for_module_cctor (image);
954 if (image->has_module_cctor) {
955 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
956 if (!mono_error_ok (&error)) {
957 mono_error_set_pending_exception (&error);
958 return;
960 /*It's fine to raise the exception here*/
961 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
962 if (!is_ok (&error)) {
963 mono_error_set_pending_exception (&error);
964 return;
966 if (!mono_runtime_class_init_full (vtable, &error))
967 mono_error_set_pending_exception (&error);
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
974 guint8 *stack_addr;
975 guint8 *current;
976 size_t stack_size;
977 /* later make this configurable and per-arch */
978 int min_size = 4096 * 4 * sizeof (void*);
979 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
980 /* if we have no info we are optimistic and assume there is enough room */
981 if (!stack_addr)
982 return TRUE;
983 #ifdef HOST_WIN32
984 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
985 // to the current sp
986 return TRUE;
987 #endif
988 current = (guint8 *)&stack_addr;
989 if (current > stack_addr) {
990 if ((current - stack_addr) < min_size)
991 return FALSE;
992 } else {
993 if (current - (stack_addr - stack_size) < min_size)
994 return FALSE;
996 return TRUE;
999 ICALL_EXPORT MonoObject *
1000 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1002 MonoError error;
1003 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1004 mono_error_set_pending_exception (&error);
1006 return ret;
1009 ICALL_EXPORT gint32
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1012 MonoError error;
1013 MonoClass *klass;
1014 MonoObject **values = NULL;
1015 MonoObject *o;
1016 int count = 0;
1017 gint32 result = (int)(gsize)mono_defaults.int32_class;
1018 MonoClassField* field;
1019 gpointer iter;
1021 klass = mono_object_class (this_obj);
1023 if (mono_class_num_fields (klass) == 0)
1024 return result;
1027 * Compute the starting value of the hashcode for fields of primitive
1028 * types, and return the remaining fields in an array to the managed side.
1029 * This way, we can avoid costly reflection operations in managed code.
1031 iter = NULL;
1032 while ((field = mono_class_get_fields (klass, &iter))) {
1033 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1034 continue;
1035 if (mono_field_is_deleted (field))
1036 continue;
1037 /* FIXME: Add more types */
1038 switch (field->type->type) {
1039 case MONO_TYPE_I4:
1040 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1041 break;
1042 case MONO_TYPE_STRING: {
1043 MonoString *s;
1044 s = *(MonoString**)((guint8*)this_obj + field->offset);
1045 if (s != NULL)
1046 result ^= mono_string_hash (s);
1047 break;
1049 default:
1050 if (!values)
1051 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1052 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1053 if (!is_ok (&error)) {
1054 mono_error_set_pending_exception (&error);
1055 return 0;
1057 values [count++] = o;
1061 if (values) {
1062 int i;
1063 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1064 if (mono_error_set_pending_exception (&error))
1065 return 0;
1066 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1067 for (i = 0; i < count; ++i)
1068 mono_array_setref (*fields, i, values [i]);
1069 } else {
1070 *fields = NULL;
1072 return result;
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1078 MonoError error;
1079 MonoClass *klass;
1080 MonoObject **values = NULL;
1081 MonoObject *o;
1082 MonoClassField* field;
1083 gpointer iter;
1084 int count = 0;
1086 MONO_CHECK_ARG_NULL (that, FALSE);
1088 if (this_obj->vtable != that->vtable)
1089 return FALSE;
1091 klass = mono_object_class (this_obj);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1100 * managed code.
1102 *fields = NULL;
1103 iter = NULL;
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1106 continue;
1107 if (mono_field_is_deleted (field))
1108 continue;
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1111 case MONO_TYPE_U1:
1112 case MONO_TYPE_I1:
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1115 return FALSE;
1116 break;
1117 case MONO_TYPE_U2:
1118 case MONO_TYPE_I2:
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1121 return FALSE;
1122 break;
1123 case MONO_TYPE_U4:
1124 case MONO_TYPE_I4:
1125 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1126 return FALSE;
1127 break;
1128 case MONO_TYPE_U8:
1129 case MONO_TYPE_I8:
1130 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1131 return FALSE;
1132 break;
1133 case MONO_TYPE_R4:
1134 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1135 return FALSE;
1136 break;
1137 case MONO_TYPE_R8:
1138 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1139 return FALSE;
1140 break;
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1148 if (s1 == s2)
1149 break;
1150 if ((s1 == NULL) || (s2 == NULL))
1151 return FALSE;
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1154 if (s1len != s2len)
1155 return FALSE;
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1158 return FALSE;
1159 break;
1161 default:
1162 if (!values)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1165 if (!is_ok (&error)) {
1166 mono_error_set_pending_exception (&error);
1167 return FALSE;
1169 values [count++] = o;
1170 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1171 if (!is_ok (&error)) {
1172 mono_error_set_pending_exception (&error);
1173 return FALSE;
1175 values [count++] = o;
1178 if (klass->enumtype)
1179 /* enums only have one non-static field */
1180 break;
1183 if (values) {
1184 int i;
1185 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1186 if (mono_error_set_pending_exception (&error))
1187 return FALSE;
1188 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1189 for (i = 0; i < count; ++i)
1190 mono_array_setref_fast (*fields, i, values [i]);
1191 return FALSE;
1192 } else {
1193 return TRUE;
1197 ICALL_EXPORT MonoReflectionType *
1198 ves_icall_System_Object_GetType (MonoObject *obj)
1200 MonoError error;
1201 MonoReflectionType *ret;
1202 #ifndef DISABLE_REMOTING
1203 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1204 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1205 else
1206 #endif
1207 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1209 mono_error_set_pending_exception (&error);
1210 return ret;
1213 ICALL_EXPORT void
1214 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1216 mtype->type = &obj->vtable->klass->byval_arg;
1217 g_assert (mtype->type->type);
1220 ICALL_EXPORT gint32
1221 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1223 MONO_CHECK_ARG_NULL (obj, 0);
1225 MonoError error;
1226 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1227 mono_error_set_pending_exception (&error);
1228 return result;
1231 ICALL_EXPORT gint32
1232 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1233 MonoReflectionMethod *method,
1234 MonoArray *opt_param_types)
1236 MONO_CHECK_ARG_NULL (method, 0);
1238 MonoError error;
1239 gint32 result = mono_image_create_method_token (
1240 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1241 mono_error_set_pending_exception (&error);
1242 return result;
1245 ICALL_EXPORT void
1246 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1248 MonoError error;
1249 mono_image_create_pefile (mb, file, &error);
1250 mono_error_set_pending_exception (&error);
1253 ICALL_EXPORT void
1254 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1256 MonoError error;
1257 mono_image_build_metadata (mb, &error);
1258 mono_error_set_pending_exception (&error);
1261 ICALL_EXPORT void
1262 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1264 mono_image_register_token (mb->dynamic_image, token, obj);
1267 ICALL_EXPORT MonoObject*
1268 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1270 MonoObject *obj;
1272 mono_loader_lock ();
1273 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1274 mono_loader_unlock ();
1276 return obj;
1279 ICALL_EXPORT MonoReflectionModule*
1280 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1282 MonoError error;
1283 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1284 mono_error_set_pending_exception (&error);
1285 return result;
1289 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1290 * @tb: a TypeBuilder object
1292 * (icall)
1293 * Creates the generic class after all generic parameters have been added.
1295 ICALL_EXPORT void
1296 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1298 MonoError error;
1299 (void) mono_reflection_create_generic_class (tb, &error);
1300 mono_error_set_pending_exception (&error);
1303 #ifndef DISABLE_REFLECTION_EMIT
1304 ICALL_EXPORT MonoArray*
1305 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1307 MonoError error;
1308 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1309 mono_error_set_pending_exception (&error);
1310 return result;
1312 #endif
1314 static gboolean
1315 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1317 MonoMethod **dest = (MonoMethod **)data;
1319 /* skip unmanaged frames */
1320 if (!managed)
1321 return FALSE;
1323 if (!(*dest)) {
1324 if (!strcmp (m->klass->name_space, "System.Reflection"))
1325 return FALSE;
1326 *dest = m;
1327 return TRUE;
1329 return FALSE;
1332 static gboolean
1333 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1335 MonoMethod **dest = (MonoMethod **)data;
1337 /* skip unmanaged frames */
1338 if (!managed)
1339 return FALSE;
1341 if (m->wrapper_type != MONO_WRAPPER_NONE)
1342 return FALSE;
1344 if (m == *dest) {
1345 *dest = NULL;
1346 return FALSE;
1349 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1350 return FALSE;
1352 if (!(*dest)) {
1353 *dest = m;
1354 return TRUE;
1356 return FALSE;
1359 static gboolean
1360 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1362 MonoMethod **dest = (MonoMethod **)data;
1364 /* skip unmanaged frames */
1365 if (!managed)
1366 return FALSE;
1368 if (m->wrapper_type != MONO_WRAPPER_NONE)
1369 return FALSE;
1371 if (m == *dest) {
1372 *dest = NULL;
1373 return FALSE;
1376 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1377 || (!strcmp (m->klass->name_space, "System"))))
1378 return FALSE;
1380 if (!(*dest)) {
1381 *dest = m;
1382 return TRUE;
1384 return FALSE;
1387 static MonoReflectionType *
1388 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1390 MonoMethod *m, *dest;
1392 MonoType *type = NULL;
1393 MonoAssembly *assembly = NULL;
1394 gboolean type_resolve = FALSE;
1395 MonoImage *rootimage = NULL;
1397 mono_error_init (error);
1400 * We must compute the calling assembly as type loading must happen under a metadata context.
1401 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1402 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1404 m = mono_method_get_last_managed ();
1405 dest = m;
1406 if (m && m->klass->image != mono_defaults.corlib) {
1407 /* Happens with inlining */
1408 } else {
1409 /* Ugly hack: type_from_parsed_name is called from
1410 * System.Type.internal_from_name, which is called most
1411 * directly from System.Type.GetType(string,bool,bool) but
1412 * also indirectly from places such as
1413 * System.Type.GetType(string,func,func) (via
1414 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1415 * so we need to skip over all of those to find the true caller.
1417 * It would be nice if we had stack marks.
1419 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1420 if (!dest)
1421 dest = m;
1425 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1426 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1427 * to crash. This only seems to happen in some strange remoting
1428 * scenarios and I was unable to figure out what's happening there.
1429 * Dec 10, 2005 - Martin.
1432 if (dest) {
1433 assembly = dest->klass->image->assembly;
1434 type_resolve = TRUE;
1435 rootimage = assembly->image;
1436 } else {
1437 g_warning (G_STRLOC);
1440 if (info->assembly.name)
1441 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1443 if (assembly) {
1444 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1445 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1446 return_val_if_nok (error, NULL);
1449 // XXXX - aleksey -
1450 // Say we're looking for System.Generic.Dict<int, Local>
1451 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1452 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1453 // is messed up when we go to construct the Local as the type arg...
1455 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1456 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1457 if (!info->assembly.name && !type) {
1458 /* try mscorlib */
1459 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1460 return_val_if_nok (error, NULL);
1462 if (assembly && !type && type_resolve) {
1463 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1464 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1465 return_val_if_nok (error, NULL);
1468 if (!type)
1469 return NULL;
1471 return mono_type_get_object_checked (mono_domain_get (), type, error);
1474 ICALL_EXPORT MonoReflectionType*
1475 ves_icall_System_Type_internal_from_name (MonoString *name,
1476 MonoBoolean throwOnError,
1477 MonoBoolean ignoreCase)
1479 MonoError error;
1480 char *str = mono_string_to_utf8 (name);
1481 MonoTypeNameParse info;
1482 MonoReflectionType *type;
1483 gboolean parsedOk;
1485 parsedOk = mono_reflection_parse_type (str, &info);
1487 /* mono_reflection_parse_type() mangles the string */
1488 if (!parsedOk) {
1489 mono_reflection_free_type_info (&info);
1490 if (throwOnError) {
1491 mono_error_init (&error);
1492 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1493 mono_error_set_pending_exception (&error);
1495 g_free (str);
1496 return NULL;
1499 type = type_from_parsed_name (&info, ignoreCase, &error);
1501 mono_reflection_free_type_info (&info);
1502 g_free (str);
1504 if (!mono_error_ok (&error)) {
1505 if (throwOnError)
1506 mono_error_set_pending_exception (&error);
1507 else
1508 mono_error_cleanup (&error);
1509 return NULL;
1512 if (type == NULL){
1513 MonoException *e = NULL;
1515 if (throwOnError)
1516 e = mono_get_exception_type_load (name, NULL);
1518 if (e) {
1519 mono_set_pending_exception (e);
1520 return NULL;
1524 return type;
1528 ICALL_EXPORT MonoReflectionType*
1529 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1531 MonoError error;
1532 MonoReflectionType *ret;
1533 MonoDomain *domain = mono_domain_get ();
1535 ret = mono_type_get_object_checked (domain, handle, &error);
1536 mono_error_set_pending_exception (&error);
1538 return ret;
1541 /* System.TypeCode */
1542 typedef enum {
1543 TYPECODE_EMPTY,
1544 TYPECODE_OBJECT,
1545 TYPECODE_DBNULL,
1546 TYPECODE_BOOLEAN,
1547 TYPECODE_CHAR,
1548 TYPECODE_SBYTE,
1549 TYPECODE_BYTE,
1550 TYPECODE_INT16,
1551 TYPECODE_UINT16,
1552 TYPECODE_INT32,
1553 TYPECODE_UINT32,
1554 TYPECODE_INT64,
1555 TYPECODE_UINT64,
1556 TYPECODE_SINGLE,
1557 TYPECODE_DOUBLE,
1558 TYPECODE_DECIMAL,
1559 TYPECODE_DATETIME,
1560 TYPECODE_STRING = 18
1561 } TypeCode;
1563 ICALL_EXPORT guint32
1564 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1566 int t = type->type->type;
1568 if (type->type->byref)
1569 return TYPECODE_OBJECT;
1571 handle_enum:
1572 switch (t) {
1573 case MONO_TYPE_VOID:
1574 return TYPECODE_OBJECT;
1575 case MONO_TYPE_BOOLEAN:
1576 return TYPECODE_BOOLEAN;
1577 case MONO_TYPE_U1:
1578 return TYPECODE_BYTE;
1579 case MONO_TYPE_I1:
1580 return TYPECODE_SBYTE;
1581 case MONO_TYPE_U2:
1582 return TYPECODE_UINT16;
1583 case MONO_TYPE_I2:
1584 return TYPECODE_INT16;
1585 case MONO_TYPE_CHAR:
1586 return TYPECODE_CHAR;
1587 case MONO_TYPE_PTR:
1588 case MONO_TYPE_U:
1589 case MONO_TYPE_I:
1590 return TYPECODE_OBJECT;
1591 case MONO_TYPE_U4:
1592 return TYPECODE_UINT32;
1593 case MONO_TYPE_I4:
1594 return TYPECODE_INT32;
1595 case MONO_TYPE_U8:
1596 return TYPECODE_UINT64;
1597 case MONO_TYPE_I8:
1598 return TYPECODE_INT64;
1599 case MONO_TYPE_R4:
1600 return TYPECODE_SINGLE;
1601 case MONO_TYPE_R8:
1602 return TYPECODE_DOUBLE;
1603 case MONO_TYPE_VALUETYPE: {
1604 MonoClass *klass = type->type->data.klass;
1606 if (klass->enumtype) {
1607 t = mono_class_enum_basetype (klass)->type;
1608 goto handle_enum;
1609 } else if (mono_is_corlib_image (klass->image)) {
1610 if (strcmp (klass->name_space, "System") == 0) {
1611 if (strcmp (klass->name, "Decimal") == 0)
1612 return TYPECODE_DECIMAL;
1613 else if (strcmp (klass->name, "DateTime") == 0)
1614 return TYPECODE_DATETIME;
1617 return TYPECODE_OBJECT;
1619 case MONO_TYPE_STRING:
1620 return TYPECODE_STRING;
1621 case MONO_TYPE_SZARRAY:
1622 case MONO_TYPE_ARRAY:
1623 case MONO_TYPE_OBJECT:
1624 case MONO_TYPE_VAR:
1625 case MONO_TYPE_MVAR:
1626 case MONO_TYPE_TYPEDBYREF:
1627 return TYPECODE_OBJECT;
1628 case MONO_TYPE_CLASS:
1630 MonoClass *klass = type->type->data.klass;
1631 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1632 if (strcmp (klass->name, "DBNull") == 0)
1633 return TYPECODE_DBNULL;
1636 return TYPECODE_OBJECT;
1637 case MONO_TYPE_GENERICINST:
1638 return TYPECODE_OBJECT;
1639 default:
1640 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1642 return 0;
1645 static gboolean
1646 mono_type_is_primitive (MonoType *type)
1648 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1649 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1652 static MonoType*
1653 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1655 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1656 return mono_class_enum_basetype (type->data.klass);
1657 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1658 return mono_class_enum_basetype (type->data.generic_class->container_class);
1659 return type;
1662 ICALL_EXPORT guint32
1663 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1665 MonoClass *klass;
1666 MonoClass *klassc;
1668 g_assert (type != NULL);
1670 klass = mono_class_from_mono_type (type->type);
1671 klassc = mono_class_from_mono_type (c->type);
1673 if (type->type->byref ^ c->type->byref)
1674 return FALSE;
1676 if (type->type->byref) {
1677 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1678 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1680 klass = mono_class_from_mono_type (t);
1681 klassc = mono_class_from_mono_type (ot);
1683 if (mono_type_is_primitive (t)) {
1684 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1685 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1686 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1687 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1688 return t->type == ot->type;
1689 } else {
1690 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1691 return FALSE;
1693 if (klass->valuetype)
1694 return klass == klassc;
1695 return klass->valuetype == klassc->valuetype;
1698 return mono_class_is_assignable_from (klass, klassc);
1701 ICALL_EXPORT guint32
1702 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1704 MonoError error;
1705 MonoClass *klass = mono_class_from_mono_type (type->type);
1706 mono_class_init_checked (klass, &error);
1707 if (!is_ok (&error)) {
1708 mono_error_set_pending_exception (&error);
1709 return FALSE;
1711 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1712 mono_error_set_pending_exception (&error);
1713 return result;
1716 ICALL_EXPORT guint32
1717 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1719 MonoClass *klass = mono_class_from_mono_type (type->type);
1720 return klass->flags;
1723 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1724 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1726 MonoError error;
1727 MonoClass *klass = field->field->parent;
1728 MonoMarshalType *info;
1729 MonoType *ftype;
1730 int i;
1732 if (klass->generic_container ||
1733 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1734 return NULL;
1736 ftype = mono_field_get_type (field->field);
1737 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1738 return NULL;
1740 info = mono_marshal_load_type_info (klass);
1742 for (i = 0; i < info->num_fields; ++i) {
1743 if (info->fields [i].field == field->field) {
1744 if (!info->fields [i].mspec)
1745 return NULL;
1746 else {
1747 MonoReflectionMarshalAsAttribute* obj;
1748 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1749 if (!mono_error_ok (&error))
1750 mono_error_set_pending_exception (&error);
1751 return obj;
1756 return NULL;
1759 ICALL_EXPORT MonoReflectionField*
1760 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1762 MonoError error;
1763 gboolean found = FALSE;
1764 MonoClass *klass;
1765 MonoClass *k;
1767 g_assert (handle);
1769 if (!type) {
1770 klass = handle->parent;
1771 } else {
1772 klass = mono_class_from_mono_type (type);
1774 /* Check that the field belongs to the class */
1775 for (k = klass; k; k = k->parent) {
1776 if (k == handle->parent) {
1777 found = TRUE;
1778 break;
1782 if (!found)
1783 /* The managed code will throw the exception */
1784 return NULL;
1787 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1788 mono_error_set_pending_exception (&error);
1789 return result;
1792 ICALL_EXPORT MonoArray*
1793 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1795 MonoError error;
1796 MonoType *type = mono_field_get_type_checked (field->field, &error);
1797 MonoArray *res;
1799 if (!mono_error_ok (&error)) {
1800 mono_error_set_pending_exception (&error);
1801 return NULL;
1804 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1805 mono_error_set_pending_exception (&error);
1806 return res;
1809 ICALL_EXPORT int
1810 vell_icall_get_method_attributes (MonoMethod *method)
1812 return method->flags;
1815 ICALL_EXPORT void
1816 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1818 MonoError error;
1819 MonoReflectionType *rt;
1820 MonoDomain *domain = mono_domain_get ();
1821 MonoMethodSignature* sig;
1823 sig = mono_method_signature_checked (method, &error);
1824 if (!mono_error_ok (&error)) {
1825 mono_error_set_pending_exception (&error);
1826 return;
1829 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1830 if (!mono_error_ok (&error)) {
1831 mono_error_set_pending_exception (&error);
1832 return;
1835 MONO_STRUCT_SETREF (info, parent, rt);
1837 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1838 if (!mono_error_ok (&error)) {
1839 mono_error_set_pending_exception (&error);
1840 return;
1843 MONO_STRUCT_SETREF (info, ret, rt);
1845 info->attrs = method->flags;
1846 info->implattrs = method->iflags;
1847 if (sig->call_convention == MONO_CALL_DEFAULT)
1848 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1849 else {
1850 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1851 info->callconv = 2;
1852 else
1853 info->callconv = 1;
1855 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1858 ICALL_EXPORT MonoArray*
1859 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1861 MonoError error;
1862 MonoDomain *domain = mono_domain_get ();
1864 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1865 mono_error_set_pending_exception (&error);
1866 return result;
1869 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1870 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1872 MonoError error;
1873 MonoDomain *domain = mono_domain_get ();
1874 MonoReflectionMarshalAsAttribute* res = NULL;
1875 MonoMarshalSpec **mspecs;
1876 int i;
1878 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1879 mono_method_get_marshal_info (method, mspecs);
1881 if (mspecs [0]) {
1882 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1883 if (!mono_error_ok (&error)) {
1884 mono_error_set_pending_exception (&error);
1885 return NULL;
1889 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1890 if (mspecs [i])
1891 mono_metadata_free_marshal_spec (mspecs [i]);
1892 g_free (mspecs);
1894 return res;
1897 ICALL_EXPORT gint32
1898 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1900 MonoClass *parent = field->field->parent;
1901 if (!parent->size_inited)
1902 mono_class_init (parent);
1903 mono_class_setup_fields_locking (parent);
1905 return field->field->offset - sizeof (MonoObject);
1908 ICALL_EXPORT MonoReflectionType*
1909 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1911 MonoError error;
1912 MonoReflectionType *ret;
1913 MonoClass *parent;
1915 parent = declaring? field->field->parent: field->klass;
1917 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1918 mono_error_set_pending_exception (&error);
1920 return ret;
1924 ICALL_EXPORT MonoObject *
1925 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1927 MonoError error;
1928 MonoClass *fklass = field->klass;
1929 MonoClassField *cf = field->field;
1930 MonoDomain *domain = mono_object_domain (field);
1932 if (fklass->image->assembly->ref_only) {
1933 mono_set_pending_exception (mono_get_exception_invalid_operation (
1934 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1935 return NULL;
1938 if (mono_security_core_clr_enabled () &&
1939 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1940 mono_error_set_pending_exception (&error);
1941 return NULL;
1944 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1945 mono_error_set_pending_exception (&error);
1946 return result;
1949 ICALL_EXPORT void
1950 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1952 MonoError error;
1953 MonoClassField *cf = field->field;
1954 MonoType *type;
1955 gchar *v;
1957 if (field->klass->image->assembly->ref_only) {
1958 mono_set_pending_exception (mono_get_exception_invalid_operation (
1959 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1960 return;
1963 if (mono_security_core_clr_enabled () &&
1964 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1965 mono_error_set_pending_exception (&error);
1966 return;
1969 type = mono_field_get_type_checked (cf, &error);
1970 if (!mono_error_ok (&error)) {
1971 mono_error_set_pending_exception (&error);
1972 return;
1975 v = (gchar *) value;
1976 if (!type->byref) {
1977 switch (type->type) {
1978 case MONO_TYPE_U1:
1979 case MONO_TYPE_I1:
1980 case MONO_TYPE_BOOLEAN:
1981 case MONO_TYPE_U2:
1982 case MONO_TYPE_I2:
1983 case MONO_TYPE_CHAR:
1984 case MONO_TYPE_U:
1985 case MONO_TYPE_I:
1986 case MONO_TYPE_U4:
1987 case MONO_TYPE_I4:
1988 case MONO_TYPE_R4:
1989 case MONO_TYPE_U8:
1990 case MONO_TYPE_I8:
1991 case MONO_TYPE_R8:
1992 case MONO_TYPE_VALUETYPE:
1993 case MONO_TYPE_PTR:
1994 if (v != NULL)
1995 v += sizeof (MonoObject);
1996 break;
1997 case MONO_TYPE_STRING:
1998 case MONO_TYPE_OBJECT:
1999 case MONO_TYPE_CLASS:
2000 case MONO_TYPE_ARRAY:
2001 case MONO_TYPE_SZARRAY:
2002 /* Do nothing */
2003 break;
2004 case MONO_TYPE_GENERICINST: {
2005 MonoGenericClass *gclass = type->data.generic_class;
2006 g_assert (!gclass->context.class_inst->is_open);
2008 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2009 MonoClass *nklass = mono_class_from_mono_type (type);
2010 MonoObject *nullable;
2013 * Convert the boxed vtype into a Nullable structure.
2014 * This is complicated by the fact that Nullables have
2015 * a variable structure.
2017 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2018 if (!mono_error_ok (&error)) {
2019 mono_error_set_pending_exception (&error);
2020 return;
2023 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2025 v = (gchar *)mono_object_unbox (nullable);
2027 else
2028 if (gclass->container_class->valuetype && (v != NULL))
2029 v += sizeof (MonoObject);
2030 break;
2032 default:
2033 g_error ("type 0x%x not handled in "
2034 "ves_icall_FieldInfo_SetValueInternal", type->type);
2035 return;
2039 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2040 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2041 if (!is_ok (&error)) {
2042 mono_error_set_pending_exception (&error);
2043 return;
2045 if (!vtable->initialized) {
2046 if (!mono_runtime_class_init_full (vtable, &error)) {
2047 mono_error_set_pending_exception (&error);
2048 return;
2051 mono_field_static_set_value (vtable, cf, v);
2052 } else {
2053 mono_field_set_value (obj, cf, v);
2057 ICALL_EXPORT void
2058 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2060 MonoClassField *f;
2062 g_assert (field);
2063 g_assert (obj);
2064 g_assert (value);
2066 f = field->field;
2067 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2068 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2069 return;
2072 if (MONO_TYPE_IS_REFERENCE (f->type))
2073 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2074 else
2075 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2078 ICALL_EXPORT MonoObject *
2079 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2081 MonoObject *o = NULL;
2082 MonoClassField *field = rfield->field;
2083 MonoClass *klass;
2084 MonoDomain *domain = mono_object_domain (rfield);
2085 gchar *v;
2086 MonoTypeEnum def_type;
2087 const char *def_value;
2088 MonoType *t;
2089 MonoError error;
2091 mono_class_init (field->parent);
2093 t = mono_field_get_type_checked (field, &error);
2094 if (!mono_error_ok (&error)) {
2095 mono_error_set_pending_exception (&error);
2096 return NULL;
2099 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2100 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2101 return NULL;
2104 if (image_is_dynamic (field->parent->image)) {
2105 MonoClass *klass = field->parent;
2106 int fidx = field - klass->fields;
2108 g_assert (fidx >= 0 && fidx < klass->field.count);
2109 g_assert (klass->ext);
2110 g_assert (klass->ext->field_def_values);
2111 def_type = klass->ext->field_def_values [fidx].def_type;
2112 def_value = klass->ext->field_def_values [fidx].data;
2113 if (def_type == MONO_TYPE_END) {
2114 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2115 return NULL;
2117 } else {
2118 def_value = mono_class_get_field_default_value (field, &def_type);
2119 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2120 if (!def_value) {
2121 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2122 return NULL;
2126 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2127 switch (def_type) {
2128 case MONO_TYPE_U1:
2129 case MONO_TYPE_I1:
2130 case MONO_TYPE_BOOLEAN:
2131 case MONO_TYPE_U2:
2132 case MONO_TYPE_I2:
2133 case MONO_TYPE_CHAR:
2134 case MONO_TYPE_U:
2135 case MONO_TYPE_I:
2136 case MONO_TYPE_U4:
2137 case MONO_TYPE_I4:
2138 case MONO_TYPE_R4:
2139 case MONO_TYPE_U8:
2140 case MONO_TYPE_I8:
2141 case MONO_TYPE_R8: {
2142 MonoType *t;
2144 /* boxed value type */
2145 t = g_new0 (MonoType, 1);
2146 t->type = def_type;
2147 klass = mono_class_from_mono_type (t);
2148 g_free (t);
2149 o = mono_object_new_checked (domain, klass, &error);
2150 if (!mono_error_ok (&error)) {
2151 mono_error_set_pending_exception (&error);
2152 return NULL;
2154 v = ((gchar *) o) + sizeof (MonoObject);
2155 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2156 if (mono_error_set_pending_exception (&error))
2157 return NULL;
2158 break;
2160 case MONO_TYPE_STRING:
2161 case MONO_TYPE_CLASS:
2162 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2163 if (mono_error_set_pending_exception (&error))
2164 return NULL;
2165 break;
2166 default:
2167 g_assert_not_reached ();
2170 return o;
2173 ICALL_EXPORT MonoReflectionType*
2174 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2176 MonoError error;
2177 MonoReflectionType *ret;
2178 MonoType *type;
2180 type = mono_field_get_type_checked (ref_field->field, &error);
2181 if (!mono_error_ok (&error)) {
2182 mono_error_set_pending_exception (&error);
2183 return NULL;
2186 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2187 if (!mono_error_ok (&error)) {
2188 mono_error_set_pending_exception (&error);
2189 return NULL;
2192 return ret;
2195 /* From MonoProperty.cs */
2196 typedef enum {
2197 PInfo_Attributes = 1,
2198 PInfo_GetMethod = 1 << 1,
2199 PInfo_SetMethod = 1 << 2,
2200 PInfo_ReflectedType = 1 << 3,
2201 PInfo_DeclaringType = 1 << 4,
2202 PInfo_Name = 1 << 5
2203 } PInfo;
2205 ICALL_EXPORT void
2206 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2208 MonoError error;
2209 MonoReflectionType *rt;
2210 MonoReflectionMethod *rm;
2211 MonoDomain *domain = mono_object_domain (property);
2212 const MonoProperty *pproperty = property->property;
2214 if ((req_info & PInfo_ReflectedType) != 0) {
2215 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2216 if (mono_error_set_pending_exception (&error))
2217 return;
2219 MONO_STRUCT_SETREF (info, parent, rt);
2221 if ((req_info & PInfo_DeclaringType) != 0) {
2222 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2223 if (mono_error_set_pending_exception (&error))
2224 return;
2226 MONO_STRUCT_SETREF (info, declaring_type, rt);
2229 if ((req_info & PInfo_Name) != 0)
2230 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2232 if ((req_info & PInfo_Attributes) != 0)
2233 info->attrs = pproperty->attrs;
2235 if ((req_info & PInfo_GetMethod) != 0) {
2236 if (pproperty->get &&
2237 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2238 pproperty->get->klass == property->klass)) {
2239 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2240 if (mono_error_set_pending_exception (&error))
2241 return;
2242 } else {
2243 rm = NULL;
2246 MONO_STRUCT_SETREF (info, get, rm);
2248 if ((req_info & PInfo_SetMethod) != 0) {
2249 if (pproperty->set &&
2250 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2251 pproperty->set->klass == property->klass)) {
2252 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2253 if (mono_error_set_pending_exception (&error))
2254 return;
2255 } else {
2256 rm = NULL;
2259 MONO_STRUCT_SETREF (info, set, rm);
2262 * There may be other methods defined for properties, though, it seems they are not exposed
2263 * in the reflection API
2267 ICALL_EXPORT void
2268 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2270 MonoError error;
2271 MonoReflectionType *rt;
2272 MonoReflectionMethod *rm;
2273 MonoDomain *domain = mono_object_domain (event);
2275 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2276 if (mono_error_set_pending_exception (&error))
2277 return;
2279 MONO_STRUCT_SETREF (info, reflected_type, rt);
2281 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2282 if (mono_error_set_pending_exception (&error))
2283 return;
2285 MONO_STRUCT_SETREF (info, declaring_type, rt);
2287 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2288 info->attrs = event->event->attrs;
2290 if (event->event->add) {
2291 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2292 if (mono_error_set_pending_exception (&error))
2293 return;
2294 } else {
2295 rm = NULL;
2298 MONO_STRUCT_SETREF (info, add_method, rm);
2300 if (event->event->remove) {
2301 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2302 if (mono_error_set_pending_exception (&error))
2303 return;
2304 } else {
2305 rm = NULL;
2308 MONO_STRUCT_SETREF (info, remove_method, rm);
2310 if (event->event->raise) {
2311 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2312 if (mono_error_set_pending_exception (&error))
2313 return;
2314 } else {
2315 rm = NULL;
2318 MONO_STRUCT_SETREF (info, raise_method, rm);
2320 #ifndef MONO_SMALL_CONFIG
2321 if (event->event->other) {
2322 int i, n = 0;
2323 while (event->event->other [n])
2324 n++;
2325 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2326 if (mono_error_set_pending_exception (&error))
2327 return;
2328 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2330 for (i = 0; i < n; i++) {
2331 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2332 if (mono_error_set_pending_exception (&error))
2333 return;
2334 mono_array_setref (info->other_methods, i, rm);
2337 #endif
2340 static void
2341 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2343 int i;
2344 MonoClass *ic;
2346 mono_class_setup_interfaces (klass, error);
2347 if (!mono_error_ok (error))
2348 return;
2350 for (i = 0; i < klass->interface_count; i++) {
2351 ic = klass->interfaces [i];
2352 g_hash_table_insert (ifaces, ic, ic);
2354 collect_interfaces (ic, ifaces, error);
2355 if (!mono_error_ok (error))
2356 return;
2360 typedef struct {
2361 MonoArray *iface_array;
2362 MonoGenericContext *context;
2363 MonoError *error;
2364 MonoDomain *domain;
2365 int next_idx;
2366 } FillIfaceArrayData;
2368 static void
2369 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2371 MonoReflectionType *rt;
2372 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2373 MonoClass *ic = (MonoClass *)key;
2374 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2376 if (!mono_error_ok (data->error))
2377 return;
2379 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2380 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2381 if (!mono_error_ok (data->error))
2382 return;
2385 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2386 if (!mono_error_ok (data->error))
2387 return;
2389 mono_array_setref (data->iface_array, data->next_idx++, rt);
2391 if (inflated)
2392 mono_metadata_free_type (inflated);
2395 static guint
2396 get_interfaces_hash (gconstpointer v1)
2398 MonoClass *k = (MonoClass*)v1;
2400 return k->type_token;
2403 ICALL_EXPORT MonoArray*
2404 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2406 MonoError error;
2407 MonoClass *klass = mono_class_from_mono_type (type->type);
2408 MonoClass *parent;
2409 FillIfaceArrayData data = { 0 };
2410 int len;
2412 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2414 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2415 data.context = mono_class_get_context (klass);
2416 klass = klass->generic_class->container_class;
2419 for (parent = klass; parent; parent = parent->parent) {
2420 mono_class_setup_interfaces (parent, &error);
2421 if (!mono_error_ok (&error))
2422 goto fail;
2423 collect_interfaces (parent, iface_hash, &error);
2424 if (!mono_error_ok (&error))
2425 goto fail;
2428 data.error = &error;
2429 data.domain = mono_object_domain (type);
2431 len = g_hash_table_size (iface_hash);
2432 if (len == 0) {
2433 g_hash_table_destroy (iface_hash);
2434 if (!data.domain->empty_types) {
2435 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0, &error);
2436 if (!is_ok (&error))
2437 goto fail;
2439 return data.domain->empty_types;
2442 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len, &error);
2443 if (!is_ok (&error))
2444 goto fail;
2445 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2446 if (!mono_error_ok (&error))
2447 goto fail;
2449 g_hash_table_destroy (iface_hash);
2450 return data.iface_array;
2452 fail:
2453 g_hash_table_destroy (iface_hash);
2454 mono_error_set_pending_exception (&error);
2455 return NULL;
2458 ICALL_EXPORT void
2459 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2461 gboolean variance_used;
2462 MonoClass *klass = mono_class_from_mono_type (type->type);
2463 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2464 MonoReflectionMethod *member;
2465 MonoMethod* method;
2466 gpointer iter;
2467 int i = 0, len, ioffset;
2468 MonoDomain *domain;
2469 MonoError error;
2471 mono_class_init_checked (klass, &error);
2472 if (mono_error_set_pending_exception (&error))
2473 return;
2474 mono_class_init_checked (iclass, &error);
2475 if (mono_error_set_pending_exception (&error))
2476 return;
2478 mono_class_setup_vtable (klass);
2480 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2481 if (ioffset == -1)
2482 return;
2484 len = mono_class_num_methods (iclass);
2485 domain = mono_object_domain (type);
2486 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2487 if (mono_error_set_pending_exception (&error))
2488 return;
2489 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2490 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2491 if (mono_error_set_pending_exception (&error))
2492 return;
2493 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2494 iter = NULL;
2495 while ((method = mono_class_get_methods (iclass, &iter))) {
2496 member = mono_method_get_object_checked (domain, method, iclass, &error);
2497 if (mono_error_set_pending_exception (&error))
2498 return;
2499 mono_array_setref (*methods, i, member);
2500 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2501 if (mono_error_set_pending_exception (&error))
2502 return;
2503 mono_array_setref (*targets, i, member);
2505 i ++;
2509 ICALL_EXPORT void
2510 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2512 MonoError error;
2513 MonoClass *klass = mono_class_from_mono_type (type->type);
2515 mono_class_init_checked (klass, &error);
2516 if (mono_error_set_pending_exception (&error))
2517 return;
2519 if (image_is_dynamic (klass->image)) {
2520 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2521 *packing = tb->packing_size;
2522 *size = tb->class_size;
2523 } else {
2524 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2528 ICALL_EXPORT MonoReflectionType*
2529 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2531 MonoError error;
2532 MonoReflectionType *ret;
2533 MonoClass *klass;
2535 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2536 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2537 mono_error_set_pending_exception (&error);
2538 return ret;
2541 klass = mono_class_from_mono_type (type->type);
2542 mono_class_init_checked (klass, &error);
2543 if (mono_error_set_pending_exception (&error))
2544 return NULL;
2547 // GetElementType should only return a type for:
2548 // Array Pointer PassedByRef
2549 if (type->type->byref)
2550 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2551 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2552 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2553 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2554 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2555 else
2556 return NULL;
2558 mono_error_set_pending_exception (&error);
2560 return ret;
2563 ICALL_EXPORT MonoReflectionType*
2564 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2566 MonoError error;
2567 MonoReflectionType *ret;
2569 if (type->type->byref)
2570 return NULL;
2572 MonoClass *klass = mono_class_from_mono_type (type->type);
2573 if (!klass->parent)
2574 return NULL;
2576 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2577 mono_error_set_pending_exception (&error);
2579 return ret;
2582 ICALL_EXPORT MonoBoolean
2583 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2585 return type->type->type == MONO_TYPE_PTR;
2588 ICALL_EXPORT MonoBoolean
2589 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2591 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)));
2594 ICALL_EXPORT MonoBoolean
2595 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2597 return type->type->byref;
2600 ICALL_EXPORT MonoBoolean
2601 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2603 MonoError error;
2604 MonoClass *klass = mono_class_from_mono_type (type->type);
2605 mono_class_init_checked (klass, &error);
2606 if (mono_error_set_pending_exception (&error))
2607 return FALSE;
2609 return mono_class_is_com_object (klass);
2612 ICALL_EXPORT guint32
2613 ves_icall_reflection_get_token (MonoObject* obj)
2615 MonoError error;
2616 guint32 result = mono_reflection_get_token_checked (obj, &error);
2617 mono_error_set_pending_exception (&error);
2618 return result;
2621 ICALL_EXPORT MonoReflectionModule*
2622 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2624 MonoError error;
2625 MonoReflectionModule *result = NULL;
2626 MonoClass *klass = mono_class_from_mono_type (type->type);
2627 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2628 mono_error_set_pending_exception (&error);
2629 return result;
2632 ICALL_EXPORT MonoReflectionAssembly*
2633 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2635 MonoError error;
2636 MonoDomain *domain = mono_domain_get ();
2637 MonoClass *klass = mono_class_from_mono_type (type->type);
2638 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2639 mono_error_set_pending_exception (&error);
2640 return result;
2643 ICALL_EXPORT MonoReflectionType*
2644 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2646 MonoError error;
2647 MonoReflectionType *ret;
2648 MonoDomain *domain = mono_domain_get ();
2649 MonoClass *klass;
2651 if (type->type->byref)
2652 return NULL;
2653 if (type->type->type == MONO_TYPE_VAR) {
2654 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2655 klass = param ? param->owner.klass : NULL;
2656 } else if (type->type->type == MONO_TYPE_MVAR) {
2657 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2658 klass = param ? param->owner.method->klass : NULL;
2659 } else {
2660 klass = mono_class_from_mono_type (type->type)->nested_in;
2663 if (!klass)
2664 return NULL;
2666 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2667 mono_error_set_pending_exception (&error);
2669 return ret;
2672 ICALL_EXPORT MonoString*
2673 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2675 MonoDomain *domain = mono_domain_get ();
2676 MonoClass *klass = mono_class_from_mono_type (type->type);
2678 if (type->type->byref) {
2679 char *n = g_strdup_printf ("%s&", klass->name);
2680 MonoString *res = mono_string_new (domain, n);
2682 g_free (n);
2684 return res;
2685 } else {
2686 return mono_string_new (domain, klass->name);
2690 ICALL_EXPORT MonoString*
2691 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2693 MonoDomain *domain = mono_domain_get ();
2694 MonoClass *klass = mono_class_from_mono_type (type->type);
2696 while (klass->nested_in)
2697 klass = klass->nested_in;
2699 if (klass->name_space [0] == '\0')
2700 return NULL;
2701 else
2702 return mono_string_new (domain, klass->name_space);
2705 ICALL_EXPORT gint32
2706 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2708 MonoClass *klass;
2710 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2711 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2712 return 0;
2715 klass = mono_class_from_mono_type (type->type);
2717 return klass->rank;
2720 static MonoArray*
2721 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2723 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2726 ICALL_EXPORT MonoArray*
2727 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2729 MonoError error;
2730 MonoReflectionType *rt;
2731 MonoArray *res;
2732 MonoClass *klass, *pklass;
2733 MonoDomain *domain = mono_object_domain (type);
2734 int i;
2736 klass = mono_class_from_mono_type (type->type);
2738 if (klass->generic_container) {
2739 MonoGenericContainer *container = klass->generic_container;
2740 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2741 if (mono_error_set_pending_exception (&error))
2742 return NULL;
2743 for (i = 0; i < container->type_argc; ++i) {
2744 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2746 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2747 if (mono_error_set_pending_exception (&error))
2748 return NULL;
2750 mono_array_setref (res, i, rt);
2752 } else if (klass->generic_class) {
2753 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2754 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2755 if (mono_error_set_pending_exception (&error))
2756 return NULL;
2757 for (i = 0; i < inst->type_argc; ++i) {
2758 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2759 if (mono_error_set_pending_exception (&error))
2760 return NULL;
2762 mono_array_setref (res, i, rt);
2764 } else {
2765 res = NULL;
2767 return res;
2770 ICALL_EXPORT gboolean
2771 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2773 MonoClass *klass;
2775 if (!IS_MONOTYPE (type))
2776 return FALSE;
2778 if (type->type->byref)
2779 return FALSE;
2781 klass = mono_class_from_mono_type (type->type);
2782 return klass->generic_container != NULL;
2785 ICALL_EXPORT MonoReflectionType*
2786 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2788 MonoError error;
2789 MonoReflectionType *ret;
2790 MonoClass *klass;
2792 if (type->type->byref)
2793 return NULL;
2795 klass = mono_class_from_mono_type (type->type);
2797 if (klass->generic_container) {
2798 return type; /* check this one */
2800 if (klass->generic_class) {
2801 MonoClass *generic_class = klass->generic_class->container_class;
2802 gpointer tb;
2804 tb = mono_class_get_ref_info (generic_class);
2806 if (generic_class->wastypebuilder && tb)
2807 return (MonoReflectionType *)tb;
2808 else {
2809 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2810 mono_error_set_pending_exception (&error);
2812 return ret;
2815 return NULL;
2818 ICALL_EXPORT MonoReflectionType*
2819 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2821 MonoError error;
2822 MonoReflectionType *ret;
2823 MonoClass *klass;
2824 MonoType *geninst, **types;
2825 int i, count;
2827 g_assert (IS_MONOTYPE (type));
2828 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2829 if (mono_error_set_pending_exception (&error))
2830 return NULL;
2832 count = mono_array_length (type_array);
2833 types = g_new0 (MonoType *, count);
2835 for (i = 0; i < count; i++) {
2836 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2837 types [i] = t->type;
2840 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2841 g_free (types);
2842 if (!geninst) {
2843 mono_error_set_pending_exception (&error);
2844 return NULL;
2847 klass = mono_class_from_mono_type (geninst);
2849 /*we might inflate to the GTD*/
2850 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2851 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2852 return NULL;
2855 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2856 mono_error_set_pending_exception (&error);
2858 return ret;
2861 ICALL_EXPORT gboolean
2862 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2864 MonoClass *klass;
2866 if (!IS_MONOTYPE (type))
2867 return FALSE;
2869 if (type->type->byref)
2870 return FALSE;
2872 klass = mono_class_from_mono_type (type->type);
2873 return klass->generic_class != NULL || klass->generic_container != NULL;
2876 ICALL_EXPORT gint32
2877 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2879 if (!IS_MONOTYPE (type))
2880 return -1;
2882 if (is_generic_parameter (type->type))
2883 return mono_type_get_generic_param_num (type->type);
2884 return -1;
2887 ICALL_EXPORT GenericParameterAttributes
2888 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2890 g_assert (IS_MONOTYPE (type));
2891 g_assert (is_generic_parameter (type->type));
2892 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2895 ICALL_EXPORT MonoArray *
2896 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2898 MonoError error;
2899 MonoReflectionType *rt;
2900 MonoGenericParamInfo *param_info;
2901 MonoDomain *domain;
2902 MonoClass **ptr;
2903 MonoArray *res;
2904 int i, count;
2906 g_assert (IS_MONOTYPE (type));
2908 domain = mono_object_domain (type);
2909 param_info = mono_generic_param_info (type->type->data.generic_param);
2910 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2913 res = mono_array_new_checked (domain, mono_defaults.monotype_class, count, &error);
2914 if (mono_error_set_pending_exception (&error))
2915 return NULL;
2916 for (i = 0; i < count; i++) {
2917 rt = mono_type_get_object_checked (domain, &param_info->constraints [i]->byval_arg, &error);
2918 if (mono_error_set_pending_exception (&error))
2919 return NULL;
2921 mono_array_setref (res, i, rt);
2925 return res;
2928 ICALL_EXPORT MonoBoolean
2929 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2931 return is_generic_parameter (type->type);
2934 ICALL_EXPORT MonoBoolean
2935 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2937 return is_generic_parameter (tb->type.type);
2940 ICALL_EXPORT void
2941 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2942 MonoReflectionType *t)
2944 enumtype->type = t->type;
2947 ICALL_EXPORT MonoReflectionMethod*
2948 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2949 MonoReflectionMethod* generic)
2951 MonoDomain *domain;
2952 MonoClass *klass;
2953 MonoMethod *method;
2954 gpointer iter;
2955 MonoError error;
2956 MonoReflectionMethod *ret = NULL;
2958 domain = ((MonoObject *)type)->vtable->domain;
2960 klass = mono_class_from_mono_type (type->type);
2961 mono_class_init_checked (klass, &error);
2962 if (mono_error_set_pending_exception (&error))
2963 return NULL;
2965 iter = NULL;
2966 while ((method = mono_class_get_methods (klass, &iter))) {
2967 if (method->token == generic->method->token) {
2968 ret = mono_method_get_object_checked (domain, method, klass, &error);
2969 if (mono_error_set_pending_exception (&error))
2970 return NULL;
2974 return ret;
2977 ICALL_EXPORT MonoReflectionMethod *
2978 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2980 MonoMethod *method;
2981 MonoType *type = ref_type->type;
2982 MonoError error;
2983 MonoReflectionMethod *ret = NULL;
2985 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2986 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2987 return NULL;
2989 if (type->type == MONO_TYPE_VAR)
2990 return NULL;
2992 method = mono_type_get_generic_param_owner (type)->owner.method;
2993 g_assert (method);
2995 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2996 if (!mono_error_ok (&error))
2997 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2998 return ret;
3001 ICALL_EXPORT MonoBoolean
3002 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3004 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3005 return FALSE;
3008 ICALL_EXPORT MonoBoolean
3009 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3011 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3012 return FALSE;
3015 ICALL_EXPORT void
3016 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3018 MonoDomain *domain = mono_domain_get ();
3019 MonoImage *image = method->method->klass->image;
3020 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3021 MonoTableInfo *tables = image->tables;
3022 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3023 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3024 guint32 im_cols [MONO_IMPLMAP_SIZE];
3025 guint32 scope_token;
3026 const char *import = NULL;
3027 const char *scope = NULL;
3029 if (image_is_dynamic (image)) {
3030 MonoReflectionMethodAux *method_aux =
3031 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3032 if (method_aux) {
3033 import = method_aux->dllentry;
3034 scope = method_aux->dll;
3037 if (!import || !scope) {
3038 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3039 return;
3042 else {
3043 if (piinfo->implmap_idx) {
3044 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3046 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3047 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3048 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3049 scope = mono_metadata_string_heap (image, scope_token);
3053 *flags = piinfo->piflags;
3054 *entry_point = mono_string_new (domain, import);
3055 *dll_name = mono_string_new (domain, scope);
3058 ICALL_EXPORT MonoReflectionMethod *
3059 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3061 MonoMethodInflated *imethod;
3062 MonoMethod *result;
3063 MonoReflectionMethod *ret = NULL;
3064 MonoError error;
3066 if (method->method->is_generic)
3067 return method;
3069 if (!method->method->is_inflated)
3070 return NULL;
3072 imethod = (MonoMethodInflated *) method->method;
3074 result = imethod->declaring;
3075 /* Not a generic method. */
3076 if (!result->is_generic)
3077 return NULL;
3079 if (image_is_dynamic (method->method->klass->image)) {
3080 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3081 MonoReflectionMethod *res;
3084 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3085 * the dynamic case as well ?
3087 mono_image_lock ((MonoImage*)image);
3088 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3089 mono_image_unlock ((MonoImage*)image);
3091 if (res)
3092 return res;
3095 if (imethod->context.class_inst) {
3096 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3097 /*Generic methods gets the context of the GTD.*/
3098 if (mono_class_get_context (klass)) {
3099 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3100 if (!mono_error_ok (&error))
3101 goto leave;
3105 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3106 leave:
3107 if (!mono_error_ok (&error))
3108 mono_error_set_pending_exception (&error);
3109 return ret;
3112 ICALL_EXPORT gboolean
3113 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3115 return mono_method_signature (method->method)->generic_param_count != 0;
3118 ICALL_EXPORT gboolean
3119 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3121 return method->method->is_generic;
3124 ICALL_EXPORT MonoArray*
3125 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3127 MonoError error;
3128 MonoReflectionType *rt;
3129 MonoArray *res;
3130 MonoDomain *domain;
3131 int count, i;
3133 domain = mono_object_domain (method);
3135 if (method->method->is_inflated) {
3136 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3138 if (inst) {
3139 count = inst->type_argc;
3140 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3141 if (mono_error_set_pending_exception (&error))
3142 return NULL;
3144 for (i = 0; i < count; i++) {
3145 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3146 if (mono_error_set_pending_exception (&error))
3147 return NULL;
3149 mono_array_setref (res, i, rt);
3152 return res;
3156 count = mono_method_signature (method->method)->generic_param_count;
3157 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3158 if (mono_error_set_pending_exception (&error))
3159 return NULL;
3161 for (i = 0; i < count; i++) {
3162 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3163 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3164 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3166 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3167 if (mono_error_set_pending_exception (&error))
3168 return NULL;
3170 mono_array_setref (res, i, rt);
3173 return res;
3176 ICALL_EXPORT MonoObject *
3177 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3179 MonoError error;
3181 * Invoke from reflection is supposed to always be a virtual call (the API
3182 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3183 * greater flexibility.
3185 MonoMethod *m = method->method;
3186 MonoMethodSignature *sig = mono_method_signature (m);
3187 MonoImage *image;
3188 int pcount;
3189 void *obj = this_arg;
3191 *exc = NULL;
3193 if (mono_security_core_clr_enabled () &&
3194 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3195 mono_error_set_pending_exception (&error);
3196 return NULL;
3199 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3200 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3201 mono_error_cleanup (&error); /* FIXME does this make sense? */
3202 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3203 return NULL;
3206 if (this_arg) {
3207 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3208 if (!is_ok (&error)) {
3209 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3210 return NULL;
3212 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3213 char *target_name = mono_type_get_full_name (m->klass);
3214 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3215 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3216 g_free (msg);
3217 g_free (target_name);
3218 g_free (this_name);
3219 return NULL;
3221 m = mono_object_get_virtual_method (this_arg, m);
3222 /* must pass the pointer to the value for valuetype methods */
3223 if (m->klass->valuetype)
3224 obj = mono_object_unbox (this_arg);
3225 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3226 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3227 return NULL;
3231 if (sig->ret->byref) {
3232 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"));
3233 return NULL;
3236 pcount = params? mono_array_length (params): 0;
3237 if (pcount != sig->param_count) {
3238 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3239 return NULL;
3242 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3243 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."));
3244 return NULL;
3247 image = m->klass->image;
3248 if (image->assembly->ref_only) {
3249 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."));
3250 return NULL;
3253 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3254 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3255 return NULL;
3258 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3259 MonoArray *arr;
3260 int i;
3261 uintptr_t *lengths;
3262 intptr_t *lower_bounds;
3263 pcount = mono_array_length (params);
3264 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3265 /* Note: the synthetized array .ctors have int32 as argument type */
3266 for (i = 0; i < pcount; ++i)
3267 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3269 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3270 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3271 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3272 if (!mono_error_ok (&error)) {
3273 mono_error_set_pending_exception (&error);
3274 return NULL;
3277 for (i = 0; i < mono_array_length (arr); ++i) {
3278 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3279 if (!mono_error_ok (&error)) {
3280 mono_error_set_pending_exception (&error);
3281 return NULL;
3283 mono_array_setref_fast (arr, i, subarray);
3285 return (MonoObject*)arr;
3288 if (m->klass->rank == pcount) {
3289 /* Only lengths provided. */
3290 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3291 if (!mono_error_ok (&error)) {
3292 mono_error_set_pending_exception (&error);
3293 return NULL;
3296 return (MonoObject*)arr;
3297 } else {
3298 g_assert (pcount == (m->klass->rank * 2));
3299 /* The arguments are lower-bound-length pairs */
3300 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3302 for (i = 0; i < pcount / 2; ++i) {
3303 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3304 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3307 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3308 if (!mono_error_ok (&error)) {
3309 mono_error_set_pending_exception (&error);
3310 return NULL;
3313 return (MonoObject*)arr;
3316 return mono_runtime_invoke_array (m, obj, params, NULL);
3319 #ifndef DISABLE_REMOTING
3320 ICALL_EXPORT MonoObject *
3321 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3323 MonoError error;
3324 MonoDomain *domain = mono_object_domain (method);
3325 MonoMethod *m = method->method;
3326 MonoMethodSignature *sig = mono_method_signature (m);
3327 MonoArray *out_args;
3328 MonoObject *result;
3329 int i, j, outarg_count = 0;
3331 if (m->klass == mono_defaults.object_class) {
3332 if (!strcmp (m->name, "FieldGetter")) {
3333 MonoClass *k = this_arg->vtable->klass;
3334 MonoString *name;
3335 char *str;
3337 /* If this is a proxy, then it must be a CBO */
3338 if (k == mono_defaults.transparent_proxy_class) {
3339 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3340 this_arg = tp->rp->unwrapped_server;
3341 g_assert (this_arg);
3342 k = this_arg->vtable->klass;
3345 name = mono_array_get (params, MonoString *, 1);
3346 str = mono_string_to_utf8 (name);
3348 do {
3349 MonoClassField* field = mono_class_get_field_from_name (k, str);
3350 if (field) {
3351 g_free (str);
3352 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3353 if (field_klass->valuetype) {
3354 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3355 if (mono_error_set_pending_exception (&error))
3356 return NULL;
3357 } else
3358 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3360 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3361 if (mono_error_set_pending_exception (&error))
3362 return NULL;
3363 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3364 mono_array_setref (out_args, 0, result);
3365 return NULL;
3367 k = k->parent;
3368 } while (k);
3370 g_free (str);
3371 g_assert_not_reached ();
3373 } else if (!strcmp (m->name, "FieldSetter")) {
3374 MonoClass *k = this_arg->vtable->klass;
3375 MonoString *name;
3376 guint32 size;
3377 gint32 align;
3378 char *str;
3380 /* If this is a proxy, then it must be a CBO */
3381 if (k == mono_defaults.transparent_proxy_class) {
3382 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3383 this_arg = tp->rp->unwrapped_server;
3384 g_assert (this_arg);
3385 k = this_arg->vtable->klass;
3388 name = mono_array_get (params, MonoString *, 1);
3389 str = mono_string_to_utf8 (name);
3391 do {
3392 MonoClassField* field = mono_class_get_field_from_name (k, str);
3393 if (field) {
3394 g_free (str);
3395 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3396 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3398 if (field_klass->valuetype) {
3399 size = mono_type_size (field->type, &align);
3400 g_assert (size == mono_class_value_size (field_klass, NULL));
3401 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3402 } else {
3403 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3406 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3407 if (mono_error_set_pending_exception (&error))
3408 return NULL;
3409 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3411 return NULL;
3414 k = k->parent;
3415 } while (k);
3417 g_free (str);
3418 g_assert_not_reached ();
3423 for (i = 0; i < mono_array_length (params); i++) {
3424 if (sig->params [i]->byref)
3425 outarg_count++;
3428 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3429 if (mono_error_set_pending_exception (&error))
3430 return NULL;
3432 /* handle constructors only for objects already allocated */
3433 if (!strcmp (method->method->name, ".ctor"))
3434 g_assert (this_arg);
3436 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3437 g_assert (!method->method->klass->valuetype);
3438 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3440 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3441 if (sig->params [i]->byref) {
3442 gpointer arg;
3443 arg = mono_array_get (params, gpointer, i);
3444 mono_array_setref (out_args, j, arg);
3445 j++;
3449 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3451 return result;
3453 #endif
3455 static guint64
3456 read_enum_value (const char *mem, int type)
3458 switch (type) {
3459 case MONO_TYPE_BOOLEAN:
3460 case MONO_TYPE_U1:
3461 return *(guint8*)mem;
3462 case MONO_TYPE_I1:
3463 return *(gint8*)mem;
3464 case MONO_TYPE_CHAR:
3465 case MONO_TYPE_U2:
3466 return read16 (mem);
3467 case MONO_TYPE_I2:
3468 return (gint16) read16 (mem);
3469 case MONO_TYPE_U4:
3470 return read32 (mem);
3471 case MONO_TYPE_I4:
3472 return (gint32) read32 (mem);
3473 case MONO_TYPE_U8:
3474 case MONO_TYPE_I8:
3475 return read64 (mem);
3476 default:
3477 g_assert_not_reached ();
3479 return 0;
3482 static void
3483 write_enum_value (char *mem, int type, guint64 value)
3485 switch (type) {
3486 case MONO_TYPE_U1:
3487 case MONO_TYPE_I1: {
3488 guint8 *p = (guint8*)mem;
3489 *p = value;
3490 break;
3492 case MONO_TYPE_U2:
3493 case MONO_TYPE_I2:
3494 case MONO_TYPE_CHAR: {
3495 guint16 *p = (guint16 *)mem;
3496 *p = value;
3497 break;
3499 case MONO_TYPE_U4:
3500 case MONO_TYPE_I4: {
3501 guint32 *p = (guint32 *)mem;
3502 *p = value;
3503 break;
3505 case MONO_TYPE_U8:
3506 case MONO_TYPE_I8: {
3507 guint64 *p = (guint64 *)mem;
3508 *p = value;
3509 break;
3511 default:
3512 g_assert_not_reached ();
3514 return;
3517 ICALL_EXPORT MonoObject *
3518 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3520 MonoError error;
3521 MonoDomain *domain;
3522 MonoClass *enumc;
3523 MonoObject *res;
3524 MonoType *etype;
3526 domain = mono_object_domain (enumType);
3527 enumc = mono_class_from_mono_type (enumType->type);
3529 mono_class_init_checked (enumc, &error);
3530 if (mono_error_set_pending_exception (&error))
3531 return NULL;
3533 etype = mono_class_enum_basetype (enumc);
3535 res = mono_object_new_checked (domain, enumc, &error);
3536 if (mono_error_set_pending_exception (&error))
3537 return NULL;
3538 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3540 return res;
3543 ICALL_EXPORT MonoBoolean
3544 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3546 int size = mono_class_value_size (a->vtable->klass, NULL);
3547 guint64 a_val = 0, b_val = 0;
3549 memcpy (&a_val, mono_object_unbox (a), size);
3550 memcpy (&b_val, mono_object_unbox (b), size);
3552 return (a_val & b_val) == b_val;
3555 ICALL_EXPORT MonoObject *
3556 ves_icall_System_Enum_get_value (MonoObject *eobj)
3558 MonoError error;
3559 MonoObject *res;
3560 MonoClass *enumc;
3561 gpointer dst;
3562 gpointer src;
3563 int size;
3565 if (!eobj)
3566 return NULL;
3568 g_assert (eobj->vtable->klass->enumtype);
3570 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3571 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3572 if (mono_error_set_pending_exception (&error))
3573 return NULL;
3574 dst = (char *)res + sizeof (MonoObject);
3575 src = (char *)eobj + sizeof (MonoObject);
3576 size = mono_class_value_size (enumc, NULL);
3578 memcpy (dst, src, size);
3580 return res;
3583 ICALL_EXPORT MonoReflectionType *
3584 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3586 MonoError error;
3587 MonoReflectionType *ret;
3588 MonoType *etype;
3589 MonoClass *klass;
3591 klass = mono_class_from_mono_type (type->type);
3592 mono_class_init_checked (klass, &error);
3593 if (mono_error_set_pending_exception (&error))
3594 return NULL;
3596 etype = mono_class_enum_basetype (klass);
3597 if (!etype) {
3598 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3599 return NULL;
3602 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3603 mono_error_set_pending_exception (&error);
3605 return ret;
3608 ICALL_EXPORT int
3609 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3611 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3612 gpointer odata = (char *)other + sizeof (MonoObject);
3613 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3614 g_assert (basetype);
3616 if (other == NULL)
3617 return 1;
3619 if (eobj->vtable->klass != other->vtable->klass)
3620 return 2;
3622 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3623 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3624 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3625 if (me == other) \
3626 return 0; \
3627 return me > other ? 1 : -1; \
3628 } while (0)
3630 switch (basetype->type) {
3631 case MONO_TYPE_U1:
3632 COMPARE_ENUM_VALUES (guint8);
3633 case MONO_TYPE_I1:
3634 COMPARE_ENUM_VALUES (gint8);
3635 case MONO_TYPE_CHAR:
3636 case MONO_TYPE_U2:
3637 COMPARE_ENUM_VALUES (guint16);
3638 case MONO_TYPE_I2:
3639 COMPARE_ENUM_VALUES (gint16);
3640 case MONO_TYPE_U4:
3641 COMPARE_ENUM_VALUES (guint32);
3642 case MONO_TYPE_I4:
3643 COMPARE_ENUM_VALUES (gint32);
3644 case MONO_TYPE_U8:
3645 COMPARE_ENUM_VALUES (guint64);
3646 case MONO_TYPE_I8:
3647 COMPARE_ENUM_VALUES (gint64);
3648 default:
3649 break;
3651 #undef COMPARE_ENUM_VALUES
3652 /* indicates that the enum was of an unsupported unerlying type */
3653 return 3;
3656 ICALL_EXPORT int
3657 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3659 gpointer data = (char *)eobj + sizeof (MonoObject);
3660 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3661 g_assert (basetype);
3663 switch (basetype->type) {
3664 case MONO_TYPE_I1: {
3665 gint8 value = *((gint8*)data);
3666 return ((int)value ^ (int)value << 8);
3668 case MONO_TYPE_U1:
3669 return *((guint8*)data);
3670 case MONO_TYPE_CHAR:
3671 case MONO_TYPE_U2:
3672 return *((guint16*)data);
3674 case MONO_TYPE_I2: {
3675 gint16 value = *((gint16*)data);
3676 return ((int)(guint16)value | (((int)value) << 16));
3678 case MONO_TYPE_U4:
3679 return *((guint32*)data);
3680 case MONO_TYPE_I4:
3681 return *((gint32*)data);
3682 case MONO_TYPE_U8:
3683 case MONO_TYPE_I8: {
3684 gint64 value = *((gint64*)data);
3685 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3687 default:
3688 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3690 return 0;
3693 ICALL_EXPORT MonoBoolean
3694 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3696 MonoError error;
3697 MonoDomain *domain = mono_object_domain (type);
3698 MonoClass *enumc = mono_class_from_mono_type (type->type);
3699 guint j = 0, nvalues;
3700 gpointer iter;
3701 MonoClassField *field;
3702 int base_type;
3703 guint64 field_value, previous_value = 0;
3704 gboolean sorted = TRUE;
3706 mono_class_init_checked (enumc, &error);
3707 if (mono_error_set_pending_exception (&error))
3708 return FALSE;
3711 if (!enumc->enumtype) {
3712 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3713 return TRUE;
3716 base_type = mono_class_enum_basetype (enumc)->type;
3718 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3719 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3720 if (mono_error_set_pending_exception (&error))
3721 return FALSE;
3722 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3723 if (mono_error_set_pending_exception (&error))
3724 return FALSE;
3726 iter = NULL;
3727 while ((field = mono_class_get_fields (enumc, &iter))) {
3728 const char *p;
3729 MonoTypeEnum def_type;
3731 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3732 continue;
3733 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3734 continue;
3735 if (mono_field_is_deleted (field))
3736 continue;
3737 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3739 p = mono_class_get_field_default_value (field, &def_type);
3740 /* len = */ mono_metadata_decode_blob_size (p, &p);
3742 field_value = read_enum_value (p, base_type);
3743 mono_array_set (*values, guint64, j, field_value);
3745 if (previous_value > field_value)
3746 sorted = FALSE;
3748 previous_value = field_value;
3749 ++j;
3752 return sorted;
3755 enum {
3756 BFLAGS_IgnoreCase = 1,
3757 BFLAGS_DeclaredOnly = 2,
3758 BFLAGS_Instance = 4,
3759 BFLAGS_Static = 8,
3760 BFLAGS_Public = 0x10,
3761 BFLAGS_NonPublic = 0x20,
3762 BFLAGS_FlattenHierarchy = 0x40,
3763 BFLAGS_InvokeMethod = 0x100,
3764 BFLAGS_CreateInstance = 0x200,
3765 BFLAGS_GetField = 0x400,
3766 BFLAGS_SetField = 0x800,
3767 BFLAGS_GetProperty = 0x1000,
3768 BFLAGS_SetProperty = 0x2000,
3769 BFLAGS_ExactBinding = 0x10000,
3770 BFLAGS_SuppressChangeType = 0x20000,
3771 BFLAGS_OptionalParamBinding = 0x40000
3774 ICALL_EXPORT MonoArray*
3775 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3777 MonoError error;
3778 MonoDomain *domain;
3779 MonoClass *startklass, *klass, *refklass;
3780 MonoArray *res;
3781 MonoObject *member;
3782 int i, match;
3783 gpointer iter;
3784 char *utf8_name = NULL;
3785 int (*compare_func) (const char *s1, const char *s2) = NULL;
3786 MonoClassField *field;
3787 MonoPtrArray tmp_array;
3789 domain = ((MonoObject *)type)->vtable->domain;
3790 if (type->type->byref) {
3791 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3792 mono_error_set_pending_exception (&error);
3793 return result;
3796 klass = startklass = mono_class_from_mono_type (type->type);
3797 refklass = mono_class_from_mono_type (reftype->type);
3799 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3801 handle_parent:
3802 if (mono_class_has_failure (klass)) {
3803 mono_ptr_array_destroy (tmp_array);
3804 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3805 return NULL;
3808 iter = NULL;
3809 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3810 guint32 flags = mono_field_get_flags (field);
3811 match = 0;
3812 if (mono_field_is_deleted_with_flags (field, flags))
3813 continue;
3814 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3815 if (bflags & BFLAGS_Public)
3816 match++;
3817 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3818 if (bflags & BFLAGS_NonPublic) {
3819 match++;
3822 if (!match)
3823 continue;
3824 match = 0;
3825 if (flags & FIELD_ATTRIBUTE_STATIC) {
3826 if (bflags & BFLAGS_Static)
3827 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3828 match++;
3829 } else {
3830 if (bflags & BFLAGS_Instance)
3831 match++;
3834 if (!match)
3835 continue;
3837 if (name != NULL) {
3838 if (utf8_name == NULL) {
3839 utf8_name = mono_string_to_utf8 (name);
3840 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3843 if (compare_func (mono_field_get_name (field), utf8_name))
3844 continue;
3847 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3848 if (!mono_error_ok (&error))
3849 goto fail;
3850 mono_ptr_array_append (tmp_array, member);
3852 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3853 goto handle_parent;
3855 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
3856 if (!is_ok (&error))
3857 goto fail;
3859 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3860 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3862 mono_ptr_array_destroy (tmp_array);
3864 if (utf8_name != NULL)
3865 g_free (utf8_name);
3867 return res;
3868 fail:
3869 mono_ptr_array_destroy (tmp_array);
3870 mono_error_set_pending_exception (&error);
3871 return NULL;
3874 static gboolean
3875 method_nonpublic (MonoMethod* method, gboolean start_klass)
3877 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3878 case METHOD_ATTRIBUTE_ASSEM:
3879 return (start_klass || mono_defaults.generic_ilist_class);
3880 case METHOD_ATTRIBUTE_PRIVATE:
3881 return start_klass;
3882 case METHOD_ATTRIBUTE_PUBLIC:
3883 return FALSE;
3884 default:
3885 return TRUE;
3889 GPtrArray*
3890 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3892 GPtrArray *array;
3893 MonoClass *startklass;
3894 MonoMethod *method;
3895 gpointer iter;
3896 int match, nslots;
3897 /*FIXME, use MonoBitSet*/
3898 guint32 method_slots_default [8];
3899 guint32 *method_slots = NULL;
3900 int (*compare_func) (const char *s1, const char *s2) = NULL;
3902 array = g_ptr_array_new ();
3903 startklass = klass;
3904 *ex = NULL;
3906 if (name != NULL)
3907 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3909 /* An optimization for calls made from Delegate:CreateDelegate () */
3910 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3911 method = mono_get_delegate_invoke (klass);
3912 g_assert (method);
3914 g_ptr_array_add (array, method);
3915 return array;
3918 mono_class_setup_methods (klass);
3919 mono_class_setup_vtable (klass);
3920 if (mono_class_has_failure (klass))
3921 goto loader_error;
3923 if (is_generic_parameter (&klass->byval_arg))
3924 nslots = mono_class_get_vtable_size (klass->parent);
3925 else
3926 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3927 if (nslots >= sizeof (method_slots_default) * 8) {
3928 method_slots = g_new0 (guint32, nslots / 32 + 1);
3929 } else {
3930 method_slots = method_slots_default;
3931 memset (method_slots, 0, sizeof (method_slots_default));
3933 handle_parent:
3934 mono_class_setup_methods (klass);
3935 mono_class_setup_vtable (klass);
3936 if (mono_class_has_failure (klass))
3937 goto loader_error;
3939 iter = NULL;
3940 while ((method = mono_class_get_methods (klass, &iter))) {
3941 match = 0;
3942 if (method->slot != -1) {
3943 g_assert (method->slot < nslots);
3944 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3945 continue;
3946 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3947 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3950 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3951 continue;
3952 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3953 if (bflags & BFLAGS_Public)
3954 match++;
3955 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3956 match++;
3958 if (!match)
3959 continue;
3960 match = 0;
3961 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3962 if (bflags & BFLAGS_Static)
3963 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3964 match++;
3965 } else {
3966 if (bflags & BFLAGS_Instance)
3967 match++;
3970 if (!match)
3971 continue;
3973 if (name != NULL) {
3974 if (compare_func (name, method->name))
3975 continue;
3978 match = 0;
3979 g_ptr_array_add (array, method);
3981 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3982 goto handle_parent;
3983 if (method_slots != method_slots_default)
3984 g_free (method_slots);
3986 return array;
3988 loader_error:
3989 if (method_slots != method_slots_default)
3990 g_free (method_slots);
3991 g_ptr_array_free (array, TRUE);
3993 if (mono_class_has_failure (klass)) {
3994 *ex = mono_class_get_exception_for_failure (klass);
3995 } else {
3996 *ex = mono_get_exception_execution_engine ("Unknown error");
3998 return NULL;
4001 ICALL_EXPORT MonoArray*
4002 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4004 static MonoClass *MethodInfo_array;
4005 MonoError error;
4006 MonoDomain *domain;
4007 MonoArray *res;
4008 MonoVTable *array_vtable;
4009 MonoException *ex = NULL;
4010 const char *mname = NULL;
4011 GPtrArray *method_array;
4012 MonoClass *klass, *refklass;
4013 int i;
4015 mono_error_init (&error);
4017 if (!MethodInfo_array) {
4018 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
4019 mono_memory_barrier ();
4020 MethodInfo_array = klass;
4023 klass = mono_class_from_mono_type (type->type);
4024 refklass = mono_class_from_mono_type (reftype->type);
4025 domain = ((MonoObject *)type)->vtable->domain;
4026 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
4027 if (!is_ok (&error)) {
4028 mono_error_set_pending_exception (&error);
4029 return NULL;
4031 if (type->type->byref) {
4032 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4033 mono_error_set_pending_exception (&error);
4035 return res;
4038 if (name)
4039 mname = mono_string_to_utf8 (name);
4041 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4042 g_free ((char*)mname);
4043 if (ex) {
4044 mono_set_pending_exception (ex);
4045 return NULL;
4048 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4049 if (!mono_error_ok (&error)) {
4050 mono_error_set_pending_exception (&error);
4051 return NULL;
4054 for (i = 0; i < method_array->len; ++i) {
4055 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4056 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4057 if (!mono_error_ok (&error))
4058 goto failure;
4059 mono_array_setref (res, i, rm);
4062 failure:
4063 g_ptr_array_free (method_array, TRUE);
4064 if (!mono_error_ok (&error))
4065 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4066 return res;
4069 ICALL_EXPORT MonoArray*
4070 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4072 MonoDomain *domain;
4073 MonoClass *startklass, *klass, *refklass;
4074 MonoArray *res = NULL;
4075 MonoMethod *method;
4076 MonoObject *member;
4077 int i, match;
4078 gpointer iter = NULL;
4079 MonoPtrArray tmp_array;
4080 MonoError error;
4082 domain = ((MonoObject *)type)->vtable->domain;
4083 if (type->type->byref) {
4084 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4085 mono_error_set_pending_exception (&error);
4086 return res;
4089 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4092 klass = startklass = mono_class_from_mono_type (type->type);
4093 refklass = mono_class_from_mono_type (reftype->type);
4095 mono_class_setup_methods (klass);
4096 if (mono_class_has_failure (klass)) {
4097 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4098 goto leave;
4101 iter = NULL;
4102 while ((method = mono_class_get_methods (klass, &iter))) {
4103 match = 0;
4104 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4105 continue;
4106 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4107 if (bflags & BFLAGS_Public)
4108 match++;
4109 } else {
4110 if (bflags & BFLAGS_NonPublic)
4111 match++;
4113 if (!match)
4114 continue;
4115 match = 0;
4116 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4117 if (bflags & BFLAGS_Static)
4118 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4119 match++;
4120 } else {
4121 if (bflags & BFLAGS_Instance)
4122 match++;
4125 if (!match)
4126 continue;
4127 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4128 if (mono_error_set_pending_exception (&error))
4129 goto leave;
4131 mono_ptr_array_append (tmp_array, member);
4134 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4135 if (mono_error_set_pending_exception (&error))
4136 goto leave;
4138 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4139 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4141 leave:
4142 mono_ptr_array_destroy (tmp_array);
4144 return res;
4147 static guint
4148 property_hash (gconstpointer data)
4150 MonoProperty *prop = (MonoProperty*)data;
4152 return g_str_hash (prop->name);
4155 static gboolean
4156 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
4158 if (method1->is_inflated)
4159 method1 = ((MonoMethodInflated*) method1)->declaring;
4160 if (method2->is_inflated)
4161 method2 = ((MonoMethodInflated*) method2)->declaring;
4163 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4166 static gboolean
4167 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4169 // Properties are hide-by-name-and-signature
4170 if (!g_str_equal (prop1->name, prop2->name))
4171 return FALSE;
4173 /* If we see a property in a generic method, we want to
4174 compare the generic signatures, not the inflated signatures
4175 because we might conflate two properties that were
4176 distinct:
4178 class Foo<T,U> {
4179 public T this[T t] { getter { return t; } } // method 1
4180 public U this[U u] { getter { return u; } } // method 2
4183 If we see int Foo<int,int>::Item[int] we need to know if
4184 the indexer came from method 1 or from method 2, and we
4185 shouldn't conflate them. (Bugzilla 36283)
4187 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4188 return FALSE;
4190 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4191 return FALSE;
4193 return TRUE;
4196 static gboolean
4197 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4199 if (!accessor)
4200 return FALSE;
4202 return method_nonpublic (accessor, start_klass);
4205 ICALL_EXPORT MonoArray*
4206 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4208 MonoError error;
4209 MonoDomain *domain;
4210 MonoClass *startklass, *klass;
4211 MonoArray *res;
4212 MonoMethod *method;
4213 MonoProperty *prop;
4214 int i, match;
4215 guint32 flags;
4216 gchar *propname = NULL;
4217 int (*compare_func) (const char *s1, const char *s2) = NULL;
4218 gpointer iter;
4219 GHashTable *properties = NULL;
4220 MonoPtrArray tmp_array;
4222 mono_error_init (&error);
4224 domain = ((MonoObject *)type)->vtable->domain;
4225 if (type->type->byref) {
4226 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4227 mono_error_set_pending_exception (&error);
4228 return res;
4231 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4233 klass = startklass = mono_class_from_mono_type (type->type);
4235 if (name != NULL) {
4236 propname = mono_string_to_utf8 (name);
4237 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4240 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4241 handle_parent:
4242 mono_class_setup_methods (klass);
4243 mono_class_setup_vtable (klass);
4244 if (mono_class_has_failure (klass))
4245 goto loader_error;
4247 iter = NULL;
4248 while ((prop = mono_class_get_properties (klass, &iter))) {
4249 match = 0;
4250 method = prop->get;
4251 if (!method)
4252 method = prop->set;
4253 if (method)
4254 flags = method->flags;
4255 else
4256 flags = 0;
4257 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4258 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4259 if (bflags & BFLAGS_Public)
4260 match++;
4261 } else if (bflags & BFLAGS_NonPublic) {
4262 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4263 property_accessor_nonpublic(prop->set, startklass == klass)) {
4264 match++;
4267 if (!match)
4268 continue;
4269 match = 0;
4270 if (flags & METHOD_ATTRIBUTE_STATIC) {
4271 if (bflags & BFLAGS_Static)
4272 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4273 match++;
4274 } else {
4275 if (bflags & BFLAGS_Instance)
4276 match++;
4279 if (!match)
4280 continue;
4281 match = 0;
4283 if (name != NULL) {
4284 if (compare_func (propname, prop->name))
4285 continue;
4288 if (g_hash_table_lookup (properties, prop))
4289 continue;
4291 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4292 if (!pr)
4293 goto failure;
4294 mono_ptr_array_append (tmp_array, pr);
4296 g_hash_table_insert (properties, prop, prop);
4298 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4299 goto handle_parent;
4301 g_hash_table_destroy (properties);
4302 g_free (propname);
4304 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4305 if (!is_ok (&error))
4306 goto failure;
4307 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4308 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4310 mono_ptr_array_destroy (tmp_array);
4312 return res;
4316 loader_error:
4317 if (mono_class_has_failure (klass)) {
4318 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4321 failure:
4322 if (properties)
4323 g_hash_table_destroy (properties);
4324 if (name)
4325 g_free (propname);
4326 mono_ptr_array_destroy (tmp_array);
4328 mono_error_set_pending_exception (&error);
4330 return NULL;
4333 static guint
4334 event_hash (gconstpointer data)
4336 MonoEvent *event = (MonoEvent*)data;
4338 return g_str_hash (event->name);
4341 static gboolean
4342 event_equal (MonoEvent *event1, MonoEvent *event2)
4344 // Events are hide-by-name
4345 return g_str_equal (event1->name, event2->name);
4348 ICALL_EXPORT MonoArray*
4349 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4351 MonoError error;
4352 MonoDomain *domain;
4353 MonoClass *startklass, *klass;
4354 MonoArray *res;
4355 MonoMethod *method;
4356 MonoEvent *event;
4357 int i, match;
4358 gpointer iter;
4359 char *utf8_name = NULL;
4360 int (*compare_func) (const char *s1, const char *s2) = NULL;
4361 GHashTable *events = NULL;
4362 MonoPtrArray tmp_array;
4364 mono_error_init (&error);
4366 domain = mono_object_domain (type);
4367 if (type->type->byref) {
4368 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4369 mono_error_set_pending_exception (&error);
4370 return res;
4373 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4375 klass = startklass = mono_class_from_mono_type (type->type);
4377 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4378 handle_parent:
4379 mono_class_setup_methods (klass);
4380 mono_class_setup_vtable (klass);
4381 if (mono_class_has_failure (klass))
4382 goto loader_error;
4384 iter = NULL;
4385 while ((event = mono_class_get_events (klass, &iter))) {
4386 match = 0;
4387 method = event->add;
4388 if (!method)
4389 method = event->remove;
4390 if (!method)
4391 method = event->raise;
4392 if (method) {
4393 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4394 if (bflags & BFLAGS_Public)
4395 match++;
4396 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4397 if (bflags & BFLAGS_NonPublic)
4398 match++;
4401 else
4402 if (bflags & BFLAGS_NonPublic)
4403 match ++;
4404 if (!match)
4405 continue;
4406 match = 0;
4407 if (method) {
4408 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4409 if (bflags & BFLAGS_Static)
4410 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4411 match++;
4412 } else {
4413 if (bflags & BFLAGS_Instance)
4414 match++;
4417 else
4418 if (bflags & BFLAGS_Instance)
4419 match ++;
4420 if (!match)
4421 continue;
4423 if (name != NULL) {
4424 if (utf8_name == NULL) {
4425 utf8_name = mono_string_to_utf8 (name);
4426 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4429 if (compare_func (event->name, utf8_name))
4430 continue;
4433 if (g_hash_table_lookup (events, event))
4434 continue;
4436 MonoReflectionEvent *ev_obj;
4437 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4438 if (!ev_obj)
4439 goto failure;
4440 mono_ptr_array_append (tmp_array, ev_obj);
4442 g_hash_table_insert (events, event, event);
4444 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4445 goto handle_parent;
4447 g_hash_table_destroy (events);
4449 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4450 if (!is_ok (&error))
4451 goto failure;
4453 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4454 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4456 mono_ptr_array_destroy (tmp_array);
4458 if (utf8_name != NULL)
4459 g_free (utf8_name);
4461 return res;
4463 loader_error:
4464 if (mono_class_has_failure (klass)) {
4465 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4468 failure:
4470 if (events != NULL)
4471 g_hash_table_destroy (events);
4472 if (utf8_name != NULL)
4473 g_free (utf8_name);
4475 mono_ptr_array_destroy (tmp_array);
4477 mono_error_set_pending_exception (&error);
4478 return NULL;
4481 ICALL_EXPORT MonoArray*
4482 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4484 MonoError error;
4485 MonoReflectionType *rt;
4486 MonoDomain *domain;
4487 MonoClass *klass;
4488 MonoArray *res = NULL;
4489 int i, match;
4490 MonoClass *nested;
4491 gpointer iter;
4492 char *str = NULL;
4493 MonoPtrArray tmp_array;
4495 mono_error_init (&error);
4497 domain = ((MonoObject *)type)->vtable->domain;
4498 if (type->type->byref) {
4499 MonoArray *result = mono_array_new_cached (domain, mono_defaults.monotype_class, 0, &error);
4500 mono_error_set_pending_exception (&error);
4501 return result;
4503 klass = mono_class_from_mono_type (type->type);
4506 * If a nested type is generic, return its generic type definition.
4507 * Note that this means that the return value is essentially the set
4508 * of nested types of the generic type definition of @klass.
4510 * A note in MSDN claims that a generic type definition can have
4511 * nested types that aren't generic. In any case, the container of that
4512 * nested type would be the generic type definition.
4514 if (klass->generic_class)
4515 klass = klass->generic_class->container_class;
4517 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4518 iter = NULL;
4519 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4520 match = 0;
4521 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4522 if (bflags & BFLAGS_Public)
4523 match++;
4524 } else {
4525 if (bflags & BFLAGS_NonPublic)
4526 match++;
4528 if (!match)
4529 continue;
4531 if (name != NULL) {
4532 if (str == NULL) {
4533 str = mono_string_to_utf8 (name);
4534 mono_identifier_unescape_type_name_chars (str);
4537 if (strcmp (nested->name, str))
4538 continue;
4541 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4542 if (!is_ok (&error))
4543 goto leave;
4545 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4548 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array), &error);
4549 if (!is_ok (&error))
4550 goto leave;
4552 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4553 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4555 leave:
4556 mono_ptr_array_destroy (tmp_array);
4558 g_free (str);
4560 mono_error_set_pending_exception (&error);
4561 return res;
4564 ICALL_EXPORT MonoReflectionType*
4565 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4567 MonoError error;
4568 MonoReflectionType *ret;
4569 gchar *str;
4570 MonoType *type = NULL;
4571 MonoTypeNameParse info;
4572 gboolean type_resolve;
4574 /* On MS.NET, this does not fire a TypeResolve event */
4575 type_resolve = TRUE;
4576 str = mono_string_to_utf8 (name);
4577 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4578 if (!mono_reflection_parse_type (str, &info)) {
4579 g_free (str);
4580 mono_reflection_free_type_info (&info);
4581 if (throwOnError) {
4582 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4583 return NULL;
4585 /*g_print ("failed parse\n");*/
4586 return NULL;
4589 if (info.assembly.name) {
4590 g_free (str);
4591 mono_reflection_free_type_info (&info);
4592 if (throwOnError) {
4593 /* 1.0 and 2.0 throw different exceptions */
4594 if (mono_defaults.generic_ilist_class)
4595 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4596 else
4597 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4598 return NULL;
4600 return NULL;
4603 if (module != NULL) {
4604 if (module->image) {
4605 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4606 if (!is_ok (&error)) {
4607 g_free (str);
4608 mono_reflection_free_type_info (&info);
4609 mono_error_set_pending_exception (&error);
4610 return NULL;
4612 } else
4613 type = NULL;
4615 else
4616 if (assembly_is_dynamic (assembly->assembly)) {
4617 /* Enumerate all modules */
4618 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4619 int i;
4621 type = NULL;
4622 if (abuilder->modules) {
4623 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4624 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4625 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4626 if (!is_ok (&error)) {
4627 g_free (str);
4628 mono_reflection_free_type_info (&info);
4629 mono_error_set_pending_exception (&error);
4630 return NULL;
4632 if (type)
4633 break;
4637 if (!type && abuilder->loaded_modules) {
4638 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4639 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4640 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4641 if (!is_ok (&error)) {
4642 g_free (str);
4643 mono_reflection_free_type_info (&info);
4644 mono_error_set_pending_exception (&error);
4645 return NULL;
4647 if (type)
4648 break;
4652 else {
4653 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4654 if (!is_ok (&error)) {
4655 g_free (str);
4656 mono_reflection_free_type_info (&info);
4657 mono_error_set_pending_exception (&error);
4658 return NULL;
4661 g_free (str);
4662 mono_reflection_free_type_info (&info);
4663 if (!type) {
4664 MonoException *e = NULL;
4666 if (throwOnError)
4667 e = mono_get_exception_type_load (name, NULL);
4669 if (e != NULL)
4670 mono_set_pending_exception (e);
4671 return NULL;
4674 if (type->type == MONO_TYPE_CLASS) {
4675 MonoClass *klass = mono_type_get_class (type);
4677 /* need to report exceptions ? */
4678 if (throwOnError && mono_class_has_failure (klass)) {
4679 /* report SecurityException (or others) that occured when loading the assembly */
4680 MonoException *exc = mono_class_get_exception_for_failure (klass);
4681 mono_set_pending_exception (exc);
4682 return NULL;
4686 /* g_print ("got it\n"); */
4687 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4688 mono_error_set_pending_exception (&error);
4690 return ret;
4693 static gboolean
4694 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4696 gchar *content;
4697 gchar *shadow_ini_file;
4698 gsize len;
4700 /* Check for shadow-copied assembly */
4701 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4702 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4703 content = NULL;
4704 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4705 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4706 if (content) {
4707 g_free (content);
4708 content = NULL;
4711 g_free (shadow_ini_file);
4712 if (content != NULL) {
4713 if (*filename)
4714 g_free (*filename);
4715 *filename = content;
4716 return TRUE;
4719 return FALSE;
4722 ICALL_EXPORT MonoString *
4723 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4725 MonoDomain *domain = mono_object_domain (assembly);
4726 MonoAssembly *mass = assembly->assembly;
4727 MonoString *res = NULL;
4728 gchar *uri;
4729 gchar *absolute;
4730 gchar *dirname;
4732 if (g_path_is_absolute (mass->image->name)) {
4733 absolute = g_strdup (mass->image->name);
4734 dirname = g_path_get_dirname (absolute);
4735 } else {
4736 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4737 dirname = g_strdup (mass->basedir);
4740 replace_shadow_path (domain, dirname, &absolute);
4741 g_free (dirname);
4742 #if HOST_WIN32
4744 gint i;
4745 for (i = strlen (absolute) - 1; i >= 0; i--)
4746 if (absolute [i] == '\\')
4747 absolute [i] = '/';
4749 #endif
4750 if (escaped) {
4751 uri = g_filename_to_uri (absolute, NULL, NULL);
4752 } else {
4753 const char *prepend = "file://";
4754 #if HOST_WIN32
4755 if (*absolute == '/' && *(absolute + 1) == '/') {
4756 prepend = "file:";
4757 } else {
4758 prepend = "file:///";
4760 #endif
4761 uri = g_strconcat (prepend, absolute, NULL);
4764 if (uri) {
4765 res = mono_string_new (domain, uri);
4766 g_free (uri);
4768 g_free (absolute);
4769 return res;
4772 ICALL_EXPORT MonoBoolean
4773 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4775 MonoAssembly *mass = assembly->assembly;
4777 return mass->in_gac;
4780 ICALL_EXPORT MonoReflectionAssembly*
4781 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4783 MonoError error;
4784 gchar *name;
4785 MonoAssembly *res;
4786 MonoImageOpenStatus status;
4787 MonoReflectionAssembly* result = NULL;
4789 name = mono_string_to_utf8 (mname);
4790 res = mono_assembly_load_with_partial_name (name, &status);
4792 g_free (name);
4794 if (res == NULL)
4795 return NULL;
4796 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4797 if (!result)
4798 mono_error_set_pending_exception (&error);
4799 return result;
4802 ICALL_EXPORT MonoString *
4803 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4805 MonoDomain *domain = mono_object_domain (assembly);
4806 MonoString *res;
4808 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4810 return res;
4813 ICALL_EXPORT MonoBoolean
4814 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4816 return assembly->assembly->ref_only;
4819 ICALL_EXPORT MonoString *
4820 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4822 MonoDomain *domain = mono_object_domain (assembly);
4824 return mono_string_new (domain, assembly->assembly->image->version);
4827 ICALL_EXPORT MonoReflectionMethod*
4828 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4830 MonoError error;
4831 MonoReflectionMethod *res = NULL;
4832 MonoMethod *method;
4834 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4836 if (!token)
4837 return NULL;
4838 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4839 if (!mono_error_ok (&error))
4840 goto leave;
4842 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4844 leave:
4845 if (!mono_error_ok (&error))
4846 mono_error_set_pending_exception (&error);
4847 return res;
4850 ICALL_EXPORT MonoReflectionModule*
4851 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4853 MonoError error;
4854 MonoReflectionModule *result = NULL;
4855 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4856 if (!mono_error_ok (&error))
4857 mono_error_set_pending_exception (&error);
4858 return result;
4861 ICALL_EXPORT MonoArray*
4862 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4864 MonoError error;
4865 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4866 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4867 if (mono_error_set_pending_exception (&error))
4868 return NULL;
4869 int i;
4870 const char *val;
4872 for (i = 0; i < table->rows; ++i) {
4873 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4874 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4876 return result;
4879 static MonoObject*
4880 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4882 static MonoMethod *create_version = NULL;
4883 MonoObject *result;
4884 gpointer args [4];
4886 mono_error_init (error);
4889 if (!create_version) {
4890 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4891 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4892 g_assert (create_version);
4893 mono_method_desc_free (desc);
4896 args [0] = &major;
4897 args [1] = &minor;
4898 args [2] = &build;
4899 args [3] = &revision;
4900 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4901 return_val_if_nok (error, NULL);
4903 mono_runtime_invoke_checked (create_version, result, args, error);
4904 return_val_if_nok (error, NULL);
4906 return result;
4909 ICALL_EXPORT MonoArray*
4910 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4912 MonoError error;
4913 MonoArray *result;
4914 MonoDomain *domain = mono_object_domain (assembly);
4915 int i, count = 0;
4916 static MonoMethod *create_culture = NULL;
4917 MonoImage *image = assembly->assembly->image;
4918 MonoTableInfo *t;
4919 MonoObject *o;
4921 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4922 count = t->rows;
4924 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4925 if (mono_error_set_pending_exception (&error))
4926 return NULL;
4929 if (count > 0 && !create_culture) {
4930 MonoMethodDesc *desc = mono_method_desc_new (
4931 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4932 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4933 g_assert (create_culture);
4934 mono_method_desc_free (desc);
4937 for (i = 0; i < count; i++) {
4938 MonoObject *version;
4939 MonoReflectionAssemblyName *aname;
4940 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4942 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4944 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4945 domain, mono_class_get_assembly_name_class (), &error);
4946 if (mono_error_set_pending_exception (&error))
4947 return NULL;
4949 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4951 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4952 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4953 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4954 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4955 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4956 aname->versioncompat = 1; /* SameMachine (default) */
4957 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4959 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4960 if (mono_error_set_pending_exception (&error))
4961 return NULL;
4963 MONO_OBJECT_SETREF (aname, version, version);
4965 if (create_culture) {
4966 gpointer args [2];
4967 MonoBoolean assembly_ref = 1;
4968 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4969 args [1] = &assembly_ref;
4971 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4972 if (mono_error_set_pending_exception (&error))
4973 return NULL;
4975 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4978 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4979 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4980 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4982 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4983 /* public key token isn't copied - the class library will
4984 automatically generate it from the public key if required */
4985 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4986 if (mono_error_set_pending_exception (&error))
4987 return NULL;
4989 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4990 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4991 } else {
4992 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4993 if (mono_error_set_pending_exception (&error))
4994 return NULL;
4996 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4997 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4999 } else {
5000 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5001 if (mono_error_set_pending_exception (&error))
5002 return NULL;
5004 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5007 /* note: this function doesn't return the codebase on purpose (i.e. it can
5008 be used under partial trust as path information isn't present). */
5010 mono_array_setref (result, i, aname);
5012 return result;
5015 /* move this in some file in mono/util/ */
5016 static char *
5017 g_concat_dir_and_file (const char *dir, const char *file)
5019 g_return_val_if_fail (dir != NULL, NULL);
5020 g_return_val_if_fail (file != NULL, NULL);
5023 * If the directory name doesn't have a / on the end, we need
5024 * to add one so we get a proper path to the file
5026 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5027 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5028 else
5029 return g_strconcat (dir, file, NULL);
5032 ICALL_EXPORT void *
5033 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5035 MonoError error;
5036 char *n = mono_string_to_utf8 (name);
5037 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5038 guint32 i;
5039 guint32 cols [MONO_MANIFEST_SIZE];
5040 guint32 impl, file_idx;
5041 const char *val;
5042 MonoImage *module;
5044 for (i = 0; i < table->rows; ++i) {
5045 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5046 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5047 if (strcmp (val, n) == 0)
5048 break;
5050 g_free (n);
5051 if (i == table->rows)
5052 return NULL;
5053 /* FIXME */
5054 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5055 if (impl) {
5057 * this code should only be called after obtaining the
5058 * ResourceInfo and handling the other cases.
5060 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5061 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5063 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5064 if (!module)
5065 return NULL;
5067 else
5068 module = assembly->assembly->image;
5071 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5072 if (mono_error_set_pending_exception (&error))
5073 return NULL;
5074 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5076 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5079 ICALL_EXPORT gboolean
5080 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5082 MonoError error;
5083 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5084 int i;
5085 guint32 cols [MONO_MANIFEST_SIZE];
5086 guint32 file_cols [MONO_FILE_SIZE];
5087 const char *val;
5088 char *n;
5090 n = mono_string_to_utf8 (name);
5091 for (i = 0; i < table->rows; ++i) {
5092 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5093 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5094 if (strcmp (val, n) == 0)
5095 break;
5097 g_free (n);
5098 if (i == table->rows)
5099 return FALSE;
5101 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5102 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5104 else {
5105 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5106 case MONO_IMPLEMENTATION_FILE:
5107 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5108 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5109 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5110 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5111 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5112 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5113 info->location = 0;
5114 else
5115 info->location = RESOURCE_LOCATION_EMBEDDED;
5116 break;
5118 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5119 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5120 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5121 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5122 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5123 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5124 g_free (msg);
5125 mono_set_pending_exception (ex);
5126 return FALSE;
5128 MonoReflectionAssembly *assm_obj;
5129 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5130 if (!assm_obj) {
5131 mono_error_set_pending_exception (&error);
5132 return FALSE;
5134 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5136 /* Obtain info recursively */
5137 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5138 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5139 break;
5141 case MONO_IMPLEMENTATION_EXP_TYPE:
5142 g_assert_not_reached ();
5143 break;
5147 return TRUE;
5150 ICALL_EXPORT MonoObject*
5151 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5153 MonoError error;
5154 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5155 MonoArray *result = NULL;
5156 int i, count;
5157 const char *val;
5158 char *n;
5160 /* check hash if needed */
5161 if (name) {
5162 n = mono_string_to_utf8 (name);
5163 for (i = 0; i < table->rows; ++i) {
5164 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5165 if (strcmp (val, n) == 0) {
5166 MonoString *fn;
5167 g_free (n);
5168 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5169 fn = mono_string_new (mono_object_domain (assembly), n);
5170 g_free (n);
5171 return (MonoObject*)fn;
5174 g_free (n);
5175 return NULL;
5178 count = 0;
5179 for (i = 0; i < table->rows; ++i) {
5180 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5181 count ++;
5184 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5185 if (mono_error_set_pending_exception (&error))
5186 return NULL;
5189 count = 0;
5190 for (i = 0; i < table->rows; ++i) {
5191 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5192 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5193 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5194 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5195 g_free (n);
5196 count ++;
5199 return (MonoObject*)result;
5202 ICALL_EXPORT MonoArray*
5203 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5205 MonoError error;
5206 MonoDomain *domain = mono_domain_get();
5207 MonoArray *res;
5208 MonoClass *klass;
5209 int i, j, file_count = 0;
5210 MonoImage **modules;
5211 guint32 module_count, real_module_count;
5212 MonoTableInfo *table;
5213 guint32 cols [MONO_FILE_SIZE];
5214 MonoImage *image = assembly->assembly->image;
5216 g_assert (image != NULL);
5217 g_assert (!assembly_is_dynamic (assembly->assembly));
5219 table = &image->tables [MONO_TABLE_FILE];
5220 file_count = table->rows;
5222 modules = image->modules;
5223 module_count = image->module_count;
5225 real_module_count = 0;
5226 for (i = 0; i < module_count; ++i)
5227 if (modules [i])
5228 real_module_count ++;
5230 klass = mono_class_get_module_class ();
5231 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5232 if (mono_error_set_pending_exception (&error))
5233 return NULL;
5235 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5236 if (mono_error_set_pending_exception (&error))
5237 return NULL;
5239 mono_array_setref (res, 0, image_obj);
5240 j = 1;
5241 for (i = 0; i < module_count; ++i)
5242 if (modules [i]) {
5243 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5244 if (mono_error_set_pending_exception (&error))
5245 return NULL;
5246 mono_array_setref (res, j, rm);
5247 ++j;
5250 for (i = 0; i < file_count; ++i, ++j) {
5251 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5252 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5253 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5254 if (mono_error_set_pending_exception (&error))
5255 return NULL;
5256 mono_array_setref (res, j, rm);
5258 else {
5259 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5260 if (!m) {
5261 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5262 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5263 return NULL;
5265 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5266 if (mono_error_set_pending_exception (&error))
5267 return NULL;
5268 mono_array_setref (res, j, rm);
5272 return res;
5275 ICALL_EXPORT MonoReflectionMethod*
5276 ves_icall_GetCurrentMethod (void)
5278 MonoReflectionMethod *res = NULL;
5279 MonoError error;
5281 MonoMethod *m = mono_method_get_last_managed ();
5283 if (!m) {
5284 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5285 return NULL;
5288 while (m->is_inflated)
5289 m = ((MonoMethodInflated*)m)->declaring;
5291 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5292 mono_error_set_pending_exception (&error);
5293 return res;
5297 static MonoMethod*
5298 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5300 int offset = -1, i;
5301 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5302 MonoError error;
5303 MonoMethod *result;
5304 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5305 //method is inflated, we should inflate it on the other class
5306 MonoGenericContext ctx;
5307 ctx.method_inst = inflated->context.method_inst;
5308 ctx.class_inst = inflated->context.class_inst;
5309 if (klass->generic_class)
5310 ctx.class_inst = klass->generic_class->context.class_inst;
5311 else if (klass->generic_container)
5312 ctx.class_inst = klass->generic_container->context.class_inst;
5313 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5314 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5315 return result;
5318 mono_class_setup_methods (method->klass);
5319 if (mono_class_has_failure (method->klass))
5320 return NULL;
5321 for (i = 0; i < method->klass->method.count; ++i) {
5322 if (method->klass->methods [i] == method) {
5323 offset = i;
5324 break;
5327 mono_class_setup_methods (klass);
5328 if (mono_class_has_failure (klass))
5329 return NULL;
5330 g_assert (offset >= 0 && offset < klass->method.count);
5331 return klass->methods [offset];
5334 ICALL_EXPORT MonoReflectionMethod*
5335 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5337 MonoReflectionMethod *res = NULL;
5338 MonoError error;
5339 MonoClass *klass;
5340 if (type) {
5341 klass = mono_class_from_mono_type (type);
5342 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5343 return NULL;
5344 if (method->klass != klass) {
5345 method = mono_method_get_equivalent_method (method, klass);
5346 if (!method)
5347 return NULL;
5349 } else
5350 klass = method->klass;
5351 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5352 mono_error_set_pending_exception (&error);
5353 return res;
5356 ICALL_EXPORT MonoReflectionMethodBody*
5357 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5359 MonoError error;
5360 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5361 mono_error_set_pending_exception (&error);
5362 return result;
5365 ICALL_EXPORT MonoReflectionAssembly*
5366 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5368 MonoError error;
5369 MonoReflectionAssembly *result;
5370 MonoMethod *dest = NULL;
5372 mono_stack_walk_no_il (get_executing, &dest);
5373 g_assert (dest);
5374 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5375 if (!result)
5376 mono_error_set_pending_exception (&error);
5377 return result;
5381 ICALL_EXPORT MonoReflectionAssembly*
5382 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5384 MonoError error;
5385 MonoReflectionAssembly *result;
5386 MonoDomain* domain = mono_domain_get ();
5388 if (!domain->entry_assembly)
5389 return NULL;
5391 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5392 if (!result)
5393 mono_error_set_pending_exception (&error);
5394 return result;
5397 ICALL_EXPORT MonoReflectionAssembly*
5398 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5400 MonoError error;
5401 MonoMethod *m;
5402 MonoMethod *dest;
5403 MonoReflectionAssembly *result;
5405 dest = NULL;
5406 mono_stack_walk_no_il (get_executing, &dest);
5407 m = dest;
5408 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5409 if (!dest)
5410 dest = m;
5411 if (!m) {
5412 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5413 return NULL;
5415 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5416 if (!result)
5417 mono_error_set_pending_exception (&error);
5418 return result;
5421 ICALL_EXPORT MonoString *
5422 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5423 gboolean assembly_qualified)
5425 MonoDomain *domain = mono_object_domain (object);
5426 MonoTypeNameFormat format;
5427 MonoString *res;
5428 gchar *name;
5430 if (full_name)
5431 format = assembly_qualified ?
5432 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5433 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5434 else
5435 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5437 name = mono_type_get_name_full (object->type, format);
5438 if (!name)
5439 return NULL;
5441 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5442 g_free (name);
5443 return NULL;
5446 res = mono_string_new (domain, name);
5447 g_free (name);
5449 return res;
5452 ICALL_EXPORT int
5453 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5455 MonoError error;
5456 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5458 mono_class_init_checked (klass, &error);
5459 mono_error_set_pending_exception (&error);
5460 return mono_security_core_clr_class_level (klass);
5463 ICALL_EXPORT int
5464 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5466 MonoClassField *field = rfield->field;
5467 return mono_security_core_clr_field_level (field, TRUE);
5470 ICALL_EXPORT int
5471 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5473 MonoMethod *method = rfield->method;
5474 return mono_security_core_clr_method_level (method, TRUE);
5477 static void
5478 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)
5480 static MonoMethod *create_culture = NULL;
5481 MonoObject *obj;
5482 gpointer args [2];
5483 guint32 pkey_len;
5484 const char *pkey_ptr;
5485 gchar *codebase;
5486 MonoBoolean assembly_ref = 0;
5488 mono_error_init (error);
5490 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5491 aname->major = name->major;
5492 aname->minor = name->minor;
5493 aname->build = name->build;
5494 aname->flags = name->flags;
5495 aname->revision = name->revision;
5496 aname->hashalg = name->hash_alg;
5497 aname->versioncompat = 1; /* SameMachine (default) */
5498 aname->processor_architecture = name->arch;
5500 if (by_default_version) {
5501 MonoObject *version;
5503 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5504 return_if_nok (error);
5506 MONO_OBJECT_SETREF (aname, version, version);
5509 codebase = NULL;
5510 if (absolute != NULL && *absolute != '\0') {
5511 const gchar *prepend = "file://";
5512 gchar *result;
5514 codebase = g_strdup (absolute);
5516 #if HOST_WIN32
5518 gint i;
5519 for (i = strlen (codebase) - 1; i >= 0; i--)
5520 if (codebase [i] == '\\')
5521 codebase [i] = '/';
5523 if (*codebase == '/' && *(codebase + 1) == '/') {
5524 prepend = "file:";
5525 } else {
5526 prepend = "file:///";
5529 #endif
5530 result = g_strconcat (prepend, codebase, NULL);
5531 g_free (codebase);
5532 codebase = result;
5535 if (codebase) {
5536 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5537 g_free (codebase);
5540 if (!create_culture) {
5541 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5542 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5543 g_assert (create_culture);
5544 mono_method_desc_free (desc);
5547 if (name->culture) {
5548 args [0] = mono_string_new (domain, name->culture);
5549 args [1] = &assembly_ref;
5551 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5552 return_if_nok (error);
5554 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5557 if (name->public_key) {
5558 pkey_ptr = (char*)name->public_key;
5559 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5561 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5562 return_if_nok (error);
5563 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5564 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5565 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5566 } else if (default_publickey) {
5567 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5568 return_if_nok (error);
5569 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5570 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5573 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5574 if (name->public_key_token [0]) {
5575 int i, j;
5576 char *p;
5578 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5579 return_if_nok (error);
5581 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5582 p = mono_array_addr (keyToken, char, 0);
5584 for (i = 0, j = 0; i < 8; i++) {
5585 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5586 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5587 p++;
5589 } else if (default_token) {
5590 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5591 return_if_nok (error);
5592 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5596 ICALL_EXPORT MonoString *
5597 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5599 MonoDomain *domain = mono_object_domain (assembly);
5600 MonoAssembly *mass = assembly->assembly;
5601 MonoString *res;
5602 gchar *name;
5604 name = mono_stringify_assembly_name (&mass->aname);
5605 res = mono_string_new (domain, name);
5606 g_free (name);
5608 return res;
5611 ICALL_EXPORT void
5612 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5614 MonoError error;
5615 gchar *absolute;
5616 MonoAssembly *mass = assembly->assembly;
5618 if (g_path_is_absolute (mass->image->name)) {
5619 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5620 mono_error_set_pending_exception (&error);
5621 return;
5623 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5625 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5626 mono_error_set_pending_exception (&error);
5628 g_free (absolute);
5631 ICALL_EXPORT void
5632 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5634 MonoError error;
5635 char *filename;
5636 MonoImageOpenStatus status = MONO_IMAGE_OK;
5637 gboolean res;
5638 MonoImage *image;
5639 MonoAssemblyName name;
5640 char *dirname;
5642 filename = mono_string_to_utf8 (fname);
5644 dirname = g_path_get_dirname (filename);
5645 replace_shadow_path (mono_domain_get (), dirname, &filename);
5646 g_free (dirname);
5648 image = mono_image_open (filename, &status);
5650 if (!image){
5651 MonoException *exc;
5653 g_free (filename);
5654 if (status == MONO_IMAGE_IMAGE_INVALID)
5655 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5656 else
5657 exc = mono_get_exception_file_not_found2 (NULL, fname);
5658 mono_set_pending_exception (exc);
5659 return;
5662 res = mono_assembly_fill_assembly_name (image, &name);
5663 if (!res) {
5664 mono_image_close (image);
5665 g_free (filename);
5666 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5667 return;
5670 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5671 mono_error_set_pending_exception (&error);
5673 mono_image_close (image);
5674 g_free (filename);
5677 ICALL_EXPORT MonoBoolean
5678 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5679 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5681 MonoBoolean result = FALSE;
5682 MonoDeclSecurityEntry entry;
5684 /* SecurityAction.RequestMinimum */
5685 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5686 *minimum = entry.blob;
5687 *minLength = entry.size;
5688 result = TRUE;
5690 /* SecurityAction.RequestOptional */
5691 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5692 *optional = entry.blob;
5693 *optLength = entry.size;
5694 result = TRUE;
5696 /* SecurityAction.RequestRefuse */
5697 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5698 *refused = entry.blob;
5699 *refLength = entry.size;
5700 result = TRUE;
5703 return result;
5706 static gboolean
5707 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5709 guint32 attrs, visibility;
5710 do {
5711 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5712 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5713 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5714 return FALSE;
5716 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5718 return TRUE;
5721 static MonoArray*
5722 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5724 MonoReflectionType *rt;
5725 MonoArray *res;
5726 MonoClass *klass;
5727 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5728 int i, count;
5730 mono_error_init (error);
5732 /* we start the count from 1 because we skip the special type <Module> */
5733 if (exportedOnly) {
5734 count = 0;
5735 for (i = 1; i < tdef->rows; ++i) {
5736 if (mono_module_type_is_visible (tdef, image, i + 1))
5737 count++;
5739 } else {
5740 count = tdef->rows - 1;
5742 res = mono_array_new_checked (domain, mono_defaults.monotype_class, count, error);
5743 return_val_if_nok (error, NULL);
5744 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5745 return_val_if_nok (error, NULL);
5746 count = 0;
5747 for (i = 1; i < tdef->rows; ++i) {
5748 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5749 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5751 if (klass) {
5752 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5753 return_val_if_nok (error, NULL);
5755 mono_array_setref (res, count, rt);
5756 } else {
5757 MonoException *ex = mono_error_convert_to_exception (error);
5758 mono_array_setref (*exceptions, count, ex);
5760 count++;
5764 return res;
5767 ICALL_EXPORT MonoArray*
5768 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5770 MonoError error;
5771 MonoArray *res = NULL;
5772 MonoArray *exceptions = NULL;
5773 MonoImage *image = NULL;
5774 MonoTableInfo *table = NULL;
5775 MonoDomain *domain;
5776 GList *list = NULL;
5777 int i, len, ex_count;
5779 domain = mono_object_domain (assembly);
5781 g_assert (!assembly_is_dynamic (assembly->assembly));
5782 image = assembly->assembly->image;
5783 table = &image->tables [MONO_TABLE_FILE];
5784 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5785 if (mono_error_set_pending_exception (&error))
5786 return NULL;
5788 /* Append data from all modules in the assembly */
5789 for (i = 0; i < table->rows; ++i) {
5790 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5791 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5792 if (loaded_image) {
5793 MonoArray *ex2;
5794 MonoArray *res2;
5796 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5797 if (mono_error_set_pending_exception (&error))
5798 return NULL;
5801 /* Append the new types to the end of the array */
5802 if (mono_array_length (res2) > 0) {
5803 guint32 len1, len2;
5804 MonoArray *res3, *ex3;
5806 len1 = mono_array_length (res);
5807 len2 = mono_array_length (res2);
5809 res3 = mono_array_new_checked (domain, mono_defaults.monotype_class, len1 + len2, &error);
5810 if (mono_error_set_pending_exception (&error))
5811 return NULL;
5812 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5813 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5814 res = res3;
5816 ex3 = mono_array_new_checked (domain, mono_defaults.monotype_class, len1 + len2, &error);
5817 if (mono_error_set_pending_exception (&error))
5818 return NULL;
5819 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5820 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5821 exceptions = ex3;
5827 /* the ReflectionTypeLoadException must have all the types (Types property),
5828 * NULL replacing types which throws an exception. The LoaderException must
5829 * contain all exceptions for NULL items.
5832 len = mono_array_length (res);
5834 ex_count = 0;
5835 for (i = 0; i < len; i++) {
5836 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5837 MonoClass *klass;
5839 if (t) {
5840 klass = mono_type_get_class (t->type);
5841 if ((klass != NULL) && mono_class_has_failure (klass)) {
5842 /* keep the class in the list */
5843 list = g_list_append (list, klass);
5844 /* and replace Type with NULL */
5845 mono_array_setref (res, i, NULL);
5847 } else {
5848 ex_count ++;
5852 if (list || ex_count) {
5853 GList *tmp = NULL;
5854 MonoException *exc = NULL;
5855 MonoArray *exl = NULL;
5856 int j, length = g_list_length (list) + ex_count;
5858 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5859 if (mono_error_set_pending_exception (&error)) {
5860 g_list_free (list);
5861 return NULL;
5863 /* Types for which mono_class_get_checked () succeeded */
5864 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5865 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5866 mono_array_setref (exl, i, exc);
5868 /* Types for which it don't */
5869 for (j = 0; j < mono_array_length (exceptions); ++j) {
5870 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5871 if (exc) {
5872 g_assert (i < length);
5873 mono_array_setref (exl, i, exc);
5874 i ++;
5877 g_list_free (list);
5878 list = NULL;
5880 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5881 if (!is_ok (&error)) {
5882 mono_error_set_pending_exception (&error);
5883 return NULL;
5885 mono_set_pending_exception (exc);
5886 return NULL;
5889 return res;
5892 ICALL_EXPORT gboolean
5893 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5895 MonoError error;
5896 MonoAssemblyName aname;
5897 MonoDomain *domain = mono_object_domain (name);
5898 char *val;
5899 gboolean is_version_defined;
5900 gboolean is_token_defined;
5902 aname.public_key = NULL;
5903 val = mono_string_to_utf8 (assname);
5904 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5905 g_free ((guint8*) aname.public_key);
5906 g_free (val);
5907 return FALSE;
5910 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5911 mono_error_set_pending_exception (&error);
5913 mono_assembly_name_free (&aname);
5914 g_free ((guint8*) aname.public_key);
5915 g_free (val);
5917 return TRUE;
5920 ICALL_EXPORT MonoReflectionType*
5921 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5923 MonoError error;
5924 MonoReflectionType *ret;
5925 MonoDomain *domain = mono_object_domain (module);
5926 MonoClass *klass;
5928 g_assert (module->image);
5930 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5931 /* These images do not have a global type */
5932 return NULL;
5934 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5935 if (!mono_error_ok (&error)) {
5936 mono_error_set_pending_exception (&error);
5937 return NULL;
5940 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5941 if (!mono_error_ok (&error)) {
5942 mono_error_set_pending_exception (&error);
5943 return NULL;
5946 return ret;
5949 ICALL_EXPORT void
5950 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5952 /*if (module->image)
5953 mono_image_close (module->image);*/
5956 ICALL_EXPORT MonoString*
5957 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5959 MonoDomain *domain = mono_object_domain (module);
5961 g_assert (module->image);
5962 return mono_string_new (domain, module->image->guid);
5965 ICALL_EXPORT gpointer
5966 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5968 #ifdef HOST_WIN32
5969 if (module->image && module->image->is_module_handle)
5970 return module->image->raw_data;
5971 #endif
5973 return (gpointer) (-1);
5976 ICALL_EXPORT void
5977 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5979 if (image_is_dynamic (image)) {
5980 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5981 *pe_kind = dyn->pe_kind;
5982 *machine = dyn->machine;
5984 else {
5985 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5986 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5990 ICALL_EXPORT gint32
5991 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5993 return (image->md_version_major << 16) | (image->md_version_minor);
5996 ICALL_EXPORT MonoArray*
5997 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5999 MonoError error;
6000 MonoArray *exceptions;
6001 int i;
6003 if (!module->image) {
6004 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.monotype_class, 0, &error);
6005 mono_error_set_pending_exception (&error);
6006 return arr;
6007 } else {
6008 MonoArray *res;
6010 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6011 if (mono_error_set_pending_exception (&error))
6012 return NULL;
6014 for (i = 0; i < mono_array_length (exceptions); ++i) {
6015 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6016 if (ex) {
6017 mono_set_pending_exception (ex);
6018 return NULL;
6021 return res;
6025 static gboolean
6026 mono_memberref_is_method (MonoImage *image, guint32 token)
6028 if (!image_is_dynamic (image)) {
6029 guint32 cols [MONO_MEMBERREF_SIZE];
6030 const char *sig;
6031 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6032 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6033 mono_metadata_decode_blob_size (sig, &sig);
6034 return (*sig != 0x6);
6035 } else {
6036 MonoError error;
6037 MonoClass *handle_class;
6039 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6040 mono_error_cleanup (&error); /* just probing, ignore error */
6041 return FALSE;
6044 return mono_defaults.methodhandle_class == handle_class;
6048 static void
6049 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6051 if (type_args)
6052 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6053 mono_array_addr (type_args, MonoType*, 0));
6054 else
6055 context->class_inst = NULL;
6056 if (method_args)
6057 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6058 mono_array_addr (method_args, MonoType*, 0));
6059 else
6060 context->method_inst = NULL;
6063 ICALL_EXPORT MonoType*
6064 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6066 MonoClass *klass;
6067 int table = mono_metadata_token_table (token);
6068 int index = mono_metadata_token_index (token);
6069 MonoGenericContext context;
6070 MonoError error;
6072 *resolve_error = ResolveTokenError_Other;
6074 /* Validate token */
6075 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6076 (table != MONO_TABLE_TYPESPEC)) {
6077 *resolve_error = ResolveTokenError_BadTable;
6078 return NULL;
6081 if (image_is_dynamic (image)) {
6082 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6083 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6084 mono_error_cleanup (&error);
6085 return klass ? &klass->byval_arg : NULL;
6088 init_generic_context_from_args (&context, type_args, method_args);
6089 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6090 mono_error_cleanup (&error);
6091 return klass ? &klass->byval_arg : NULL;
6094 if ((index <= 0) || (index > image->tables [table].rows)) {
6095 *resolve_error = ResolveTokenError_OutOfRange;
6096 return NULL;
6099 init_generic_context_from_args (&context, type_args, method_args);
6100 klass = mono_class_get_checked (image, token, &error);
6101 if (klass)
6102 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6103 if (!mono_error_ok (&error)) {
6104 mono_error_set_pending_exception (&error);
6105 return NULL;
6108 if (klass)
6109 return &klass->byval_arg;
6110 else
6111 return NULL;
6114 ICALL_EXPORT MonoMethod*
6115 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6117 MonoError error;
6118 int table = mono_metadata_token_table (token);
6119 int index = mono_metadata_token_index (token);
6120 MonoGenericContext context;
6121 MonoMethod *method;
6123 *resolve_error = ResolveTokenError_Other;
6125 /* Validate token */
6126 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6127 (table != MONO_TABLE_MEMBERREF)) {
6128 *resolve_error = ResolveTokenError_BadTable;
6129 return NULL;
6132 if (image_is_dynamic (image)) {
6133 if (table == MONO_TABLE_METHOD) {
6134 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6135 mono_error_cleanup (&error);
6136 return method;
6139 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6140 *resolve_error = ResolveTokenError_BadTable;
6141 return NULL;
6144 init_generic_context_from_args (&context, type_args, method_args);
6145 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6146 mono_error_cleanup (&error);
6147 return method;
6150 if ((index <= 0) || (index > image->tables [table].rows)) {
6151 *resolve_error = ResolveTokenError_OutOfRange;
6152 return NULL;
6154 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6155 *resolve_error = ResolveTokenError_BadTable;
6156 return NULL;
6159 init_generic_context_from_args (&context, type_args, method_args);
6160 method = mono_get_method_checked (image, token, NULL, &context, &error);
6161 mono_error_set_pending_exception (&error);
6163 return method;
6166 ICALL_EXPORT MonoString*
6167 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6169 MonoError error;
6170 int index = mono_metadata_token_index (token);
6172 *resolve_error = ResolveTokenError_Other;
6174 /* Validate token */
6175 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6176 *resolve_error = ResolveTokenError_BadTable;
6177 return NULL;
6180 if (image_is_dynamic (image)) {
6181 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6182 mono_error_cleanup (&error);
6183 return result;
6186 if ((index <= 0) || (index >= image->heap_us.size)) {
6187 *resolve_error = ResolveTokenError_OutOfRange;
6188 return NULL;
6191 /* FIXME: What to do if the index points into the middle of a string ? */
6193 return mono_ldstr (mono_domain_get (), image, index);
6196 ICALL_EXPORT MonoClassField*
6197 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6199 MonoError error;
6200 MonoClass *klass;
6201 int table = mono_metadata_token_table (token);
6202 int index = mono_metadata_token_index (token);
6203 MonoGenericContext context;
6204 MonoClassField *field;
6206 *resolve_error = ResolveTokenError_Other;
6208 /* Validate token */
6209 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6210 *resolve_error = ResolveTokenError_BadTable;
6211 return NULL;
6214 if (image_is_dynamic (image)) {
6215 if (table == MONO_TABLE_FIELD) {
6216 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6217 mono_error_cleanup (&error);
6218 return field;
6221 if (mono_memberref_is_method (image, token)) {
6222 *resolve_error = ResolveTokenError_BadTable;
6223 return NULL;
6226 init_generic_context_from_args (&context, type_args, method_args);
6227 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6228 mono_error_cleanup (&error);
6229 return field;
6232 if ((index <= 0) || (index > image->tables [table].rows)) {
6233 *resolve_error = ResolveTokenError_OutOfRange;
6234 return NULL;
6236 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6237 *resolve_error = ResolveTokenError_BadTable;
6238 return NULL;
6241 init_generic_context_from_args (&context, type_args, method_args);
6242 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6243 mono_error_set_pending_exception (&error);
6245 return field;
6249 ICALL_EXPORT MonoObject*
6250 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6252 MonoError merror;
6253 MonoObject *ret;
6254 int table = mono_metadata_token_table (token);
6256 *error = ResolveTokenError_Other;
6258 switch (table) {
6259 case MONO_TABLE_TYPEDEF:
6260 case MONO_TABLE_TYPEREF:
6261 case MONO_TABLE_TYPESPEC: {
6262 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6263 if (t) {
6264 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6265 mono_error_set_pending_exception (&merror);
6267 return ret;
6269 else
6270 return NULL;
6272 case MONO_TABLE_METHOD:
6273 case MONO_TABLE_METHODSPEC: {
6274 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6275 if (m) {
6276 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6277 mono_error_set_pending_exception (&merror);
6279 return ret;
6280 } else
6281 return NULL;
6283 case MONO_TABLE_FIELD: {
6284 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6285 if (f) {
6286 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6287 mono_error_set_pending_exception (&merror);
6288 return ret;
6290 else
6291 return NULL;
6293 case MONO_TABLE_MEMBERREF:
6294 if (mono_memberref_is_method (image, token)) {
6295 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6296 if (m) {
6297 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6298 mono_error_set_pending_exception (&merror);
6300 return ret;
6301 } else
6302 return NULL;
6304 else {
6305 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6306 if (f) {
6307 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6308 mono_error_set_pending_exception (&merror);
6309 return ret;
6311 else
6312 return NULL;
6314 break;
6316 default:
6317 *error = ResolveTokenError_BadTable;
6320 return NULL;
6323 ICALL_EXPORT MonoArray*
6324 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6326 MonoError error;
6327 int table = mono_metadata_token_table (token);
6328 int idx = mono_metadata_token_index (token);
6329 MonoTableInfo *tables = image->tables;
6330 guint32 sig, len;
6331 const char *ptr;
6332 MonoArray *res;
6334 *resolve_error = ResolveTokenError_OutOfRange;
6336 /* FIXME: Support other tables ? */
6337 if (table != MONO_TABLE_STANDALONESIG)
6338 return NULL;
6340 if (image_is_dynamic (image))
6341 return NULL;
6343 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6344 return NULL;
6346 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6348 ptr = mono_metadata_blob_heap (image, sig);
6349 len = mono_metadata_decode_blob_size (ptr, &ptr);
6351 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6352 if (mono_error_set_pending_exception (&error))
6353 return NULL;
6354 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6355 return res;
6358 ICALL_EXPORT MonoReflectionType*
6359 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6361 MonoError error;
6362 MonoReflectionType *ret;
6363 MonoClass *klass;
6364 int isbyref = 0, rank;
6365 char *str = mono_string_to_utf8 (smodifiers);
6366 char *p;
6368 klass = mono_class_from_mono_type (tb->type.type);
6369 p = str;
6370 /* logic taken from mono_reflection_parse_type(): keep in sync */
6371 while (*p) {
6372 switch (*p) {
6373 case '&':
6374 if (isbyref) { /* only one level allowed by the spec */
6375 g_free (str);
6376 return NULL;
6378 isbyref = 1;
6379 p++;
6381 g_free (str);
6383 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6384 mono_error_set_pending_exception (&error);
6386 return ret;
6387 case '*':
6388 klass = mono_ptr_class_get (&klass->byval_arg);
6389 mono_class_init (klass);
6390 p++;
6391 break;
6392 case '[':
6393 rank = 1;
6394 p++;
6395 while (*p) {
6396 if (*p == ']')
6397 break;
6398 if (*p == ',')
6399 rank++;
6400 else if (*p != '*') { /* '*' means unknown lower bound */
6401 g_free (str);
6402 return NULL;
6404 ++p;
6406 if (*p != ']') {
6407 g_free (str);
6408 return NULL;
6410 p++;
6411 klass = mono_array_class_get (klass, rank);
6412 mono_class_init (klass);
6413 break;
6414 default:
6415 break;
6419 g_free (str);
6421 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6422 mono_error_set_pending_exception (&error);
6424 return ret;
6427 ICALL_EXPORT MonoBoolean
6428 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6430 MonoType *type;
6431 MonoBoolean res;
6433 type = t->type;
6434 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6436 return res;
6439 static void
6440 check_for_invalid_type (MonoClass *klass, MonoError *error)
6442 char *name;
6443 MonoString *str;
6445 mono_error_init (error);
6447 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6448 return;
6450 name = mono_type_get_full_name (klass);
6451 str = mono_string_new (mono_domain_get (), name);
6452 g_free (name);
6453 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6456 ICALL_EXPORT MonoReflectionType *
6457 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6459 MonoError error;
6460 MonoReflectionType *ret;
6461 MonoClass *klass, *aklass;
6463 klass = mono_class_from_mono_type (type->type);
6464 check_for_invalid_type (klass, &error);
6465 mono_error_set_pending_exception (&error);
6467 if (rank == 0) //single dimentional array
6468 aklass = mono_array_class_get (klass, 1);
6469 else
6470 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6472 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6473 mono_error_set_pending_exception (&error);
6475 return ret;
6478 ICALL_EXPORT MonoReflectionType *
6479 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6481 MonoError error;
6482 MonoReflectionType *ret;
6483 MonoClass *klass;
6485 klass = mono_class_from_mono_type (type->type);
6486 mono_class_init_checked (klass, &error);
6487 if (mono_error_set_pending_exception (&error))
6488 return NULL;
6490 check_for_invalid_type (klass, &error);
6491 if (mono_error_set_pending_exception (&error))
6492 return NULL;
6494 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6495 mono_error_set_pending_exception (&error);
6497 return ret;
6500 ICALL_EXPORT MonoReflectionType *
6501 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6503 MonoError error;
6504 MonoReflectionType *ret;
6505 MonoClass *klass, *pklass;
6507 klass = mono_class_from_mono_type (type->type);
6508 mono_class_init_checked (klass, &error);
6509 if (mono_error_set_pending_exception (&error))
6510 return NULL;
6511 check_for_invalid_type (klass, &error);
6512 if (mono_error_set_pending_exception (&error))
6513 return NULL;
6515 pklass = mono_ptr_class_get (type->type);
6517 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6518 mono_error_set_pending_exception (&error);
6520 return ret;
6523 ICALL_EXPORT MonoObject *
6524 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6525 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6527 MonoError error;
6528 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6529 MonoObject *delegate;
6530 gpointer func;
6531 MonoMethod *method = info->method;
6533 mono_class_init_checked (delegate_class, &error);
6534 if (mono_error_set_pending_exception (&error))
6535 return NULL;
6537 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6538 /* FIXME improve this exception message */
6539 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6540 __func__,
6541 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6542 mono_error_set_pending_exception (&error);
6543 return NULL;
6546 if (mono_security_core_clr_enabled ()) {
6547 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6548 if (throwOnBindFailure)
6549 mono_error_set_pending_exception (&error);
6550 else
6551 mono_error_cleanup (&error);
6552 return NULL;
6556 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6557 if (mono_error_set_pending_exception (&error))
6558 return NULL;
6560 if (method_is_dynamic (method)) {
6561 /* Creating a trampoline would leak memory */
6562 func = mono_compile_method_checked (method, &error);
6563 if (mono_error_set_pending_exception (&error))
6564 return NULL;
6565 } else {
6566 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6567 method = mono_object_get_virtual_method (target, method);
6568 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6569 if (mono_error_set_pending_exception (&error))
6570 return NULL;
6571 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6574 mono_delegate_ctor_with_method (delegate, target, func, method);
6576 return delegate;
6579 ICALL_EXPORT MonoMulticastDelegate *
6580 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6582 MonoError error;
6583 MonoMulticastDelegate *ret;
6585 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6587 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6588 if (mono_error_set_pending_exception (&error))
6589 return NULL;
6591 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6593 return ret;
6596 ICALL_EXPORT MonoReflectionMethod*
6597 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6599 MonoReflectionMethod *ret = NULL;
6600 MonoError error;
6601 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6602 mono_error_set_pending_exception (&error);
6603 return ret;
6606 /* System.Buffer */
6608 static inline gint32
6609 mono_array_get_byte_length (MonoArray *array)
6611 MonoClass *klass;
6612 int length;
6613 int i;
6615 klass = array->obj.vtable->klass;
6617 if (array->bounds == NULL)
6618 length = array->max_length;
6619 else {
6620 length = 1;
6621 for (i = 0; i < klass->rank; ++ i)
6622 length *= array->bounds [i].length;
6625 switch (klass->element_class->byval_arg.type) {
6626 case MONO_TYPE_I1:
6627 case MONO_TYPE_U1:
6628 case MONO_TYPE_BOOLEAN:
6629 return length;
6630 case MONO_TYPE_I2:
6631 case MONO_TYPE_U2:
6632 case MONO_TYPE_CHAR:
6633 return length << 1;
6634 case MONO_TYPE_I4:
6635 case MONO_TYPE_U4:
6636 case MONO_TYPE_R4:
6637 return length << 2;
6638 case MONO_TYPE_I:
6639 case MONO_TYPE_U:
6640 return length * sizeof (gpointer);
6641 case MONO_TYPE_I8:
6642 case MONO_TYPE_U8:
6643 case MONO_TYPE_R8:
6644 return length << 3;
6645 default:
6646 return -1;
6650 ICALL_EXPORT gint32
6651 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6653 return mono_array_get_byte_length (array);
6656 ICALL_EXPORT gint8
6657 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6659 return mono_array_get (array, gint8, idx);
6662 ICALL_EXPORT void
6663 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6665 mono_array_set (array, gint8, idx, value);
6668 ICALL_EXPORT MonoBoolean
6669 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6671 guint8 *src_buf, *dest_buf;
6673 if (count < 0) {
6674 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6675 return FALSE;
6678 g_assert (count >= 0);
6680 /* This is called directly from the class libraries without going through the managed wrapper */
6681 MONO_CHECK_ARG_NULL (src, FALSE);
6682 MONO_CHECK_ARG_NULL (dest, FALSE);
6684 /* watch out for integer overflow */
6685 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6686 return FALSE;
6688 src_buf = (guint8 *)src->vector + src_offset;
6689 dest_buf = (guint8 *)dest->vector + dest_offset;
6691 if (src != dest)
6692 memcpy (dest_buf, src_buf, count);
6693 else
6694 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6696 return TRUE;
6699 #ifndef DISABLE_REMOTING
6700 ICALL_EXPORT MonoObject *
6701 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6703 MonoError error;
6704 MonoDomain *domain = mono_object_domain (this_obj);
6705 MonoObject *res;
6706 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6707 MonoTransparentProxy *tp;
6708 MonoType *type;
6709 MonoClass *klass;
6711 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6712 if (mono_error_set_pending_exception (&error))
6713 return NULL;
6715 tp = (MonoTransparentProxy*) res;
6717 MONO_OBJECT_SETREF (tp, rp, rp);
6718 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6719 klass = mono_class_from_mono_type (type);
6721 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6722 mono_class_setup_vtable (klass);
6723 if (mono_class_has_failure (klass)) {
6724 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6725 return NULL;
6728 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6729 if (!is_ok (&error)) {
6730 mono_error_set_pending_exception (&error);
6731 return NULL;
6733 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6734 if (!is_ok (&error)) {
6735 mono_error_set_pending_exception (&error);
6736 return NULL;
6739 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6740 return res;
6743 ICALL_EXPORT MonoReflectionType *
6744 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6746 MonoError error;
6747 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6748 mono_error_set_pending_exception (&error);
6750 return ret;
6752 #endif
6754 /* System.Environment */
6756 MonoString*
6757 ves_icall_System_Environment_get_UserName (void)
6759 /* using glib is more portable */
6760 return mono_string_new (mono_domain_get (), g_get_user_name ());
6764 ICALL_EXPORT MonoString *
6765 ves_icall_System_Environment_get_MachineName (void)
6767 #if defined (HOST_WIN32)
6768 gunichar2 *buf;
6769 guint32 len;
6770 MonoString *result;
6772 len = MAX_COMPUTERNAME_LENGTH + 1;
6773 buf = g_new (gunichar2, len);
6775 result = NULL;
6776 if (GetComputerName (buf, (PDWORD) &len)) {
6777 MonoError error;
6778 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6779 mono_error_set_pending_exception (&error);
6782 g_free (buf);
6783 return result;
6784 #elif !defined(DISABLE_SOCKETS)
6785 MonoString *result;
6786 char *buf;
6787 int n;
6788 #if defined _SC_HOST_NAME_MAX
6789 n = sysconf (_SC_HOST_NAME_MAX);
6790 if (n == -1)
6791 #endif
6792 n = 512;
6793 buf = g_malloc (n+1);
6795 if (gethostname (buf, n) == 0){
6796 buf [n] = 0;
6797 result = mono_string_new (mono_domain_get (), buf);
6798 } else
6799 result = NULL;
6800 g_free (buf);
6802 return result;
6803 #else
6804 return mono_string_new (mono_domain_get (), "mono");
6805 #endif
6808 ICALL_EXPORT int
6809 ves_icall_System_Environment_get_Platform (void)
6811 #if defined (TARGET_WIN32)
6812 /* Win32NT */
6813 return 2;
6814 #elif defined(__MACH__)
6815 /* OSX */
6817 // Notice that the value is hidden from user code, and only exposed
6818 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6819 // define and making assumptions based on Unix/128/4 values before there
6820 // was a MacOS define. Lots of code would assume that not-Unix meant
6821 // Windows, but in this case, it would be OSX.
6823 return 6;
6824 #else
6825 /* Unix */
6826 return 4;
6827 #endif
6830 ICALL_EXPORT MonoString *
6831 ves_icall_System_Environment_get_NewLine (void)
6833 #if defined (HOST_WIN32)
6834 return mono_string_new (mono_domain_get (), "\r\n");
6835 #else
6836 return mono_string_new (mono_domain_get (), "\n");
6837 #endif
6840 ICALL_EXPORT MonoBoolean
6841 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6843 #if SIZEOF_VOID_P == 8
6844 return TRUE;
6845 #else
6846 #ifdef HOST_WIN32
6847 gboolean isWow64Process = FALSE;
6848 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6849 return (MonoBoolean)isWow64Process;
6851 #elif defined(HAVE_SYS_UTSNAME_H)
6852 struct utsname name;
6854 if (uname (&name) >= 0) {
6855 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6857 #endif
6858 return FALSE;
6859 #endif
6862 ICALL_EXPORT MonoString *
6863 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6865 const gchar *value;
6866 gchar *utf8_name;
6868 if (name == NULL)
6869 return NULL;
6871 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6872 value = g_getenv (utf8_name);
6874 g_free (utf8_name);
6876 if (value == 0)
6877 return NULL;
6879 return mono_string_new (mono_domain_get (), value);
6883 * There is no standard way to get at environ.
6885 #ifndef _MSC_VER
6886 #ifndef __MINGW32_VERSION
6887 #if defined(__APPLE__)
6888 #if defined (TARGET_OSX)
6889 /* Apple defines this in crt_externs.h but doesn't provide that header for
6890 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6891 * in fact exist on all implementations (so far)
6893 gchar ***_NSGetEnviron(void);
6894 #define environ (*_NSGetEnviron())
6895 #else
6896 static char *mono_environ[1] = { NULL };
6897 #define environ mono_environ
6898 #endif /* defined (TARGET_OSX) */
6899 #else
6900 extern
6901 char **environ;
6902 #endif
6903 #endif
6904 #endif
6906 ICALL_EXPORT MonoArray *
6907 ves_icall_System_Environment_GetCoomandLineArgs (void)
6909 MonoError error;
6910 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6911 mono_error_set_pending_exception (&error);
6912 return result;
6915 ICALL_EXPORT MonoArray *
6916 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6918 #ifdef HOST_WIN32
6919 MonoError error;
6920 MonoArray *names;
6921 MonoDomain *domain;
6922 MonoString *str;
6923 WCHAR* env_strings;
6924 WCHAR* env_string;
6925 WCHAR* equal_str;
6926 int n = 0;
6928 env_strings = GetEnvironmentStrings();
6930 if (env_strings) {
6931 env_string = env_strings;
6932 while (*env_string != '\0') {
6933 /* weird case that MS seems to skip */
6934 if (*env_string != '=')
6935 n++;
6936 while (*env_string != '\0')
6937 env_string++;
6938 env_string++;
6942 domain = mono_domain_get ();
6943 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6944 if (mono_error_set_pending_exception (&error))
6945 return NULL;
6947 if (env_strings) {
6948 n = 0;
6949 env_string = env_strings;
6950 while (*env_string != '\0') {
6951 /* weird case that MS seems to skip */
6952 if (*env_string != '=') {
6953 equal_str = wcschr(env_string, '=');
6954 g_assert(equal_str);
6955 MonoError error;
6956 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6957 if (mono_error_set_pending_exception (&error))
6958 return NULL;
6960 mono_array_setref (names, n, str);
6961 n++;
6963 while (*env_string != '\0')
6964 env_string++;
6965 env_string++;
6968 FreeEnvironmentStrings (env_strings);
6971 return names;
6973 #else
6974 MonoError error;
6975 MonoArray *names;
6976 MonoDomain *domain;
6977 MonoString *str;
6978 gchar **e, **parts;
6979 int n;
6981 n = 0;
6982 for (e = environ; *e != 0; ++ e)
6983 ++ n;
6985 domain = mono_domain_get ();
6986 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6987 if (mono_error_set_pending_exception (&error))
6988 return NULL;
6990 n = 0;
6991 for (e = environ; *e != 0; ++ e) {
6992 parts = g_strsplit (*e, "=", 2);
6993 if (*parts != 0) {
6994 str = mono_string_new (domain, *parts);
6995 mono_array_setref (names, n, str);
6998 g_strfreev (parts);
7000 ++ n;
7003 return names;
7004 #endif
7008 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
7010 #if !GLIB_CHECK_VERSION(2,4,0)
7011 #define g_setenv(a,b,c) setenv(a,b,c)
7012 #define g_unsetenv(a) unsetenv(a)
7013 #endif
7015 ICALL_EXPORT void
7016 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7018 #ifdef HOST_WIN32
7019 gunichar2 *utf16_name, *utf16_value;
7020 #else
7021 gchar *utf8_name, *utf8_value;
7022 MonoError error;
7023 #endif
7025 #ifdef HOST_WIN32
7026 utf16_name = mono_string_to_utf16 (name);
7027 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7028 SetEnvironmentVariable (utf16_name, NULL);
7029 g_free (utf16_name);
7030 return;
7033 utf16_value = mono_string_to_utf16 (value);
7035 SetEnvironmentVariable (utf16_name, utf16_value);
7037 g_free (utf16_name);
7038 g_free (utf16_value);
7039 #else
7040 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
7042 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7043 g_unsetenv (utf8_name);
7044 g_free (utf8_name);
7045 return;
7048 utf8_value = mono_string_to_utf8_checked (value, &error);
7049 if (!mono_error_ok (&error)) {
7050 g_free (utf8_name);
7051 mono_error_set_pending_exception (&error);
7052 return;
7054 g_setenv (utf8_name, utf8_value, TRUE);
7056 g_free (utf8_name);
7057 g_free (utf8_value);
7058 #endif
7061 ICALL_EXPORT void
7062 ves_icall_System_Environment_Exit (int result)
7064 mono_environment_exitcode_set (result);
7066 /* FIXME: There are some cleanup hangs that should be worked out, but
7067 * if the program is going to exit, everything will be cleaned up when
7068 * NaCl exits anyway.
7070 #ifndef __native_client__
7071 if (!mono_runtime_try_shutdown ())
7072 mono_thread_exit ();
7074 /* Suspend all managed threads since the runtime is going away */
7075 mono_thread_suspend_all_other_threads ();
7077 mono_runtime_quit ();
7078 #endif
7080 /* we may need to do some cleanup here... */
7081 exit (result);
7084 ICALL_EXPORT MonoString*
7085 ves_icall_System_Environment_GetGacPath (void)
7087 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7090 ICALL_EXPORT MonoString*
7091 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7093 #if defined (HOST_WIN32)
7094 #ifndef CSIDL_FLAG_CREATE
7095 #define CSIDL_FLAG_CREATE 0x8000
7096 #endif
7098 WCHAR path [MAX_PATH];
7099 /* Create directory if no existing */
7100 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7101 int len = 0;
7102 while (path [len])
7103 ++ len;
7104 MonoError error;
7105 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7106 mono_error_set_pending_exception (&error);
7107 return res;
7109 #else
7110 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7111 #endif
7112 return mono_string_new (mono_domain_get (), "");
7115 ICALL_EXPORT MonoArray *
7116 ves_icall_System_Environment_GetLogicalDrives (void)
7118 MonoError error;
7119 gunichar2 buf [256], *ptr, *dname;
7120 gunichar2 *u16;
7121 guint initial_size = 127, size = 128;
7122 gint ndrives;
7123 MonoArray *result;
7124 MonoString *drivestr;
7125 MonoDomain *domain = mono_domain_get ();
7126 gint len;
7128 buf [0] = '\0';
7129 ptr = buf;
7131 while (size > initial_size) {
7132 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7133 if (size > initial_size) {
7134 if (ptr != buf)
7135 g_free (ptr);
7136 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7137 initial_size = size;
7138 size++;
7142 /* Count strings */
7143 dname = ptr;
7144 ndrives = 0;
7145 do {
7146 while (*dname++);
7147 ndrives++;
7148 } while (*dname);
7150 dname = ptr;
7151 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7152 if (mono_error_set_pending_exception (&error))
7153 goto leave;
7155 ndrives = 0;
7156 do {
7157 len = 0;
7158 u16 = dname;
7159 while (*u16) { u16++; len ++; }
7160 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7161 if (mono_error_set_pending_exception (&error))
7162 goto leave;
7164 mono_array_setref (result, ndrives++, drivestr);
7165 while (*dname++);
7166 } while (*dname);
7168 leave:
7169 if (ptr != buf)
7170 g_free (ptr);
7172 return result;
7175 ICALL_EXPORT MonoString *
7176 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7178 MonoError error;
7179 gunichar2 volume_name [MAX_PATH + 1];
7181 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7182 return NULL;
7183 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7184 mono_error_set_pending_exception (&error);
7185 return result;
7188 ICALL_EXPORT MonoString *
7189 ves_icall_System_Environment_InternalGetHome (void)
7191 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7194 static const char *encodings [] = {
7195 (char *) 1,
7196 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7197 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7198 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7199 (char *) 2,
7200 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7201 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7202 "x_unicode_2_0_utf_7",
7203 (char *) 3,
7204 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7205 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7206 (char *) 4,
7207 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7208 "iso_10646_ucs2",
7209 (char *) 5,
7210 "unicodefffe", "utf_16be",
7211 (char *) 6,
7212 "iso_8859_1",
7213 (char *) 0
7217 * Returns the internal codepage, if the value of "int_code_page" is
7218 * 1 at entry, and we can not compute a suitable code page number,
7219 * returns the code page as a string
7221 ICALL_EXPORT MonoString*
7222 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7224 const char *cset;
7225 const char *p;
7226 char *c;
7227 char *codepage = NULL;
7228 int code;
7229 int want_name = *int_code_page;
7230 int i;
7232 *int_code_page = -1;
7234 g_get_charset (&cset);
7235 c = codepage = strdup (cset);
7236 for (c = codepage; *c; c++){
7237 if (isascii (*c) && isalpha (*c))
7238 *c = tolower (*c);
7239 if (*c == '-')
7240 *c = '_';
7242 /* g_print ("charset: %s\n", cset); */
7244 /* handle some common aliases */
7245 p = encodings [0];
7246 code = 0;
7247 for (i = 0; p != 0; ){
7248 if ((gsize) p < 7){
7249 code = (gssize) p;
7250 p = encodings [++i];
7251 continue;
7253 if (strcmp (p, codepage) == 0){
7254 *int_code_page = code;
7255 break;
7257 p = encodings [++i];
7260 if (strstr (codepage, "utf_8") != NULL)
7261 *int_code_page |= 0x10000000;
7262 free (codepage);
7264 if (want_name && *int_code_page == -1)
7265 return mono_string_new (mono_domain_get (), cset);
7266 else
7267 return NULL;
7270 ICALL_EXPORT MonoBoolean
7271 ves_icall_System_Environment_get_HasShutdownStarted (void)
7273 if (mono_runtime_is_shutting_down ())
7274 return TRUE;
7276 if (mono_domain_is_unloading (mono_domain_get ()))
7277 return TRUE;
7279 return FALSE;
7282 ICALL_EXPORT void
7283 ves_icall_System_Environment_BroadcastSettingChange (void)
7285 #ifdef HOST_WIN32
7286 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7287 #endif
7290 ICALL_EXPORT
7291 gint32
7292 ves_icall_System_Environment_get_TickCount (void)
7294 /* this will overflow after ~24 days */
7295 return (gint32) (mono_msec_boottime () & 0xffffffff);
7298 ICALL_EXPORT gint32
7299 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7301 return 9;
7304 ICALL_EXPORT void
7305 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7306 MonoReflectionMethod *method,
7307 MonoArray *out_args)
7309 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7312 #ifndef DISABLE_REMOTING
7313 ICALL_EXPORT MonoBoolean
7314 ves_icall_IsTransparentProxy (MonoObject *proxy)
7316 if (!proxy)
7317 return 0;
7319 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7320 return 1;
7322 return 0;
7325 ICALL_EXPORT MonoReflectionMethod *
7326 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7327 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7329 MonoReflectionMethod *ret = NULL;
7330 MonoError error;
7332 MonoClass *klass;
7333 MonoMethod *method;
7334 MonoMethod **vtable;
7335 MonoMethod *res = NULL;
7337 MONO_CHECK_ARG_NULL (rtype, NULL);
7338 MONO_CHECK_ARG_NULL (rmethod, NULL);
7340 method = rmethod->method;
7341 klass = mono_class_from_mono_type (rtype->type);
7342 mono_class_init_checked (klass, &error);
7343 if (mono_error_set_pending_exception (&error))
7344 return NULL;
7346 if (MONO_CLASS_IS_INTERFACE (klass))
7347 return NULL;
7349 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7350 return NULL;
7352 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7353 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7354 return rmethod;
7355 else
7356 return NULL;
7359 mono_class_setup_vtable (klass);
7360 vtable = klass->vtable;
7362 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7363 gboolean variance_used = FALSE;
7364 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7365 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7366 if (offs >= 0)
7367 res = vtable [offs + method->slot];
7368 } else {
7369 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7370 return NULL;
7372 if (method->slot != -1)
7373 res = vtable [method->slot];
7376 if (!res)
7377 return NULL;
7379 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7380 mono_error_set_pending_exception (&error);
7381 return ret;
7384 ICALL_EXPORT void
7385 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7387 MonoError error;
7388 MonoClass *klass;
7389 MonoVTable* vtable;
7391 klass = mono_class_from_mono_type (type->type);
7392 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7393 if (!is_ok (&error)) {
7394 mono_error_set_pending_exception (&error);
7395 return;
7398 mono_vtable_set_is_remote (vtable, enable);
7401 #else /* DISABLE_REMOTING */
7403 ICALL_EXPORT void
7404 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7406 g_assert_not_reached ();
7409 #endif
7411 ICALL_EXPORT MonoObject *
7412 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7414 MonoError error;
7415 MonoClass *klass;
7416 MonoDomain *domain;
7417 MonoObject *ret;
7419 domain = mono_object_domain (type);
7420 klass = mono_class_from_mono_type (type->type);
7421 mono_class_init_checked (klass, &error);
7422 if (mono_error_set_pending_exception (&error))
7423 return NULL;
7425 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7426 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7427 return NULL;
7430 if (klass->rank >= 1) {
7431 g_assert (klass->rank == 1);
7432 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7433 mono_error_set_pending_exception (&error);
7434 return ret;
7435 } else {
7436 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7437 if (!is_ok (&error)) {
7438 mono_error_set_pending_exception (&error);
7439 return NULL;
7441 /* Bypass remoting object creation check */
7442 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7443 mono_error_set_pending_exception (&error);
7445 return ret;
7449 ICALL_EXPORT MonoString *
7450 ves_icall_System_IO_get_temp_path (void)
7452 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7455 #ifndef PLATFORM_NO_DRIVEINFO
7456 ICALL_EXPORT MonoBoolean
7457 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7458 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7459 gint32 *error)
7461 gboolean result;
7462 ULARGE_INTEGER wapi_free_bytes_avail;
7463 ULARGE_INTEGER wapi_total_number_of_bytes;
7464 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7466 *error = ERROR_SUCCESS;
7467 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7468 &wapi_total_number_of_free_bytes);
7470 if (result) {
7471 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7472 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7473 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7474 } else {
7475 *free_bytes_avail = 0;
7476 *total_number_of_bytes = 0;
7477 *total_number_of_free_bytes = 0;
7478 *error = GetLastError ();
7481 return result;
7484 ICALL_EXPORT guint32
7485 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7487 return GetDriveType (mono_string_chars (root_path_name));
7489 #endif
7491 ICALL_EXPORT gpointer
7492 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7494 MonoError error;
7495 gpointer result = mono_compile_method_checked (method, &error);
7496 mono_error_set_pending_exception (&error);
7497 return result;
7500 ICALL_EXPORT MonoString *
7501 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7503 MonoString *mcpath;
7504 gchar *path;
7506 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7508 #if defined (HOST_WIN32)
7509 /* Avoid mixing '/' and '\\' */
7511 gint i;
7512 for (i = strlen (path) - 1; i >= 0; i--)
7513 if (path [i] == '/')
7514 path [i] = '\\';
7516 #endif
7517 mcpath = mono_string_new (mono_domain_get (), path);
7518 g_free (path);
7520 return mcpath;
7523 static MonoString *
7524 get_bundled_app_config (void)
7526 const gchar *app_config;
7527 MonoDomain *domain;
7528 MonoString *file;
7529 gchar *config_file_name, *config_file_path;
7530 gsize len, config_file_path_length, config_ext_length;
7531 gchar *module;
7533 domain = mono_domain_get ();
7534 file = domain->setup->configuration_file;
7535 if (!file || file->length == 0)
7536 return NULL;
7538 // Retrieve config file and remove the extension
7539 config_file_name = mono_string_to_utf8 (file);
7540 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7541 if (!config_file_path)
7542 config_file_path = config_file_name;
7544 config_file_path_length = strlen (config_file_path);
7545 config_ext_length = strlen (".config");
7546 if (config_file_path_length <= config_ext_length)
7547 return NULL;
7549 len = config_file_path_length - config_ext_length;
7550 module = (gchar *)g_malloc0 (len + 1);
7551 memcpy (module, config_file_path, len);
7552 // Get the config file from the module name
7553 app_config = mono_config_string_for_assembly_file (module);
7554 // Clean-up
7555 g_free (module);
7556 if (config_file_name != config_file_path)
7557 g_free (config_file_name);
7558 g_free (config_file_path);
7560 if (!app_config)
7561 return NULL;
7563 return mono_string_new (mono_domain_get (), app_config);
7566 static MonoString *
7567 get_bundled_machine_config (void)
7569 const gchar *machine_config;
7571 machine_config = mono_get_machine_config ();
7573 if (!machine_config)
7574 return NULL;
7576 return mono_string_new (mono_domain_get (), machine_config);
7579 ICALL_EXPORT MonoString *
7580 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7582 MonoString *ipath;
7583 gchar *path;
7585 path = g_path_get_dirname (mono_get_config_dir ());
7587 #if defined (HOST_WIN32)
7588 /* Avoid mixing '/' and '\\' */
7590 gint i;
7591 for (i = strlen (path) - 1; i >= 0; i--)
7592 if (path [i] == '/')
7593 path [i] = '\\';
7595 #endif
7596 ipath = mono_string_new (mono_domain_get (), path);
7597 g_free (path);
7599 return ipath;
7602 ICALL_EXPORT gboolean
7603 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7605 MonoPEResourceDataEntry *entry;
7606 MonoImage *image;
7608 if (!assembly || !result || !size)
7609 return FALSE;
7611 *result = NULL;
7612 *size = 0;
7613 image = assembly->assembly->image;
7614 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7615 if (!entry)
7616 return FALSE;
7618 *result = mono_image_rva_map (image, entry->rde_data_offset);
7619 if (!(*result)) {
7620 g_free (entry);
7621 return FALSE;
7623 *size = entry->rde_size;
7624 g_free (entry);
7625 return TRUE;
7628 ICALL_EXPORT MonoBoolean
7629 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7631 return mono_is_debugger_attached ();
7634 ICALL_EXPORT MonoBoolean
7635 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7637 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7638 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7639 else
7640 return FALSE;
7643 ICALL_EXPORT void
7644 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7646 if (mono_get_runtime_callbacks ()->debug_log)
7647 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7650 ICALL_EXPORT void
7651 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7653 #if defined (HOST_WIN32)
7654 OutputDebugString (mono_string_chars (message));
7655 #else
7656 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7657 #endif
7660 /* Only used for value types */
7661 ICALL_EXPORT MonoObject *
7662 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7664 MonoError error;
7665 MonoObject *result;
7666 MonoClass *klass;
7667 MonoDomain *domain;
7669 domain = mono_object_domain (type);
7670 klass = mono_class_from_mono_type (type->type);
7671 mono_class_init_checked (klass, &error);
7672 if (mono_error_set_pending_exception (&error))
7673 return NULL;
7675 if (mono_class_is_nullable (klass))
7676 /* No arguments -> null */
7677 return NULL;
7679 result = mono_object_new_checked (domain, klass, &error);
7680 mono_error_set_pending_exception (&error);
7681 return result;
7684 ICALL_EXPORT MonoReflectionMethod *
7685 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7687 MonoReflectionMethod *ret = NULL;
7688 MonoError error;
7690 MonoClass *klass, *parent;
7691 MonoGenericContext *generic_inst = NULL;
7692 MonoMethod *method = m->method;
7693 MonoMethod *result = NULL;
7694 int slot;
7696 if (method->klass == NULL)
7697 return m;
7699 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7700 MONO_CLASS_IS_INTERFACE (method->klass) ||
7701 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7702 return m;
7704 slot = mono_method_get_vtable_slot (method);
7705 if (slot == -1)
7706 return m;
7708 klass = method->klass;
7709 if (klass->generic_class) {
7710 generic_inst = mono_class_get_context (klass);
7711 klass = klass->generic_class->container_class;
7714 if (definition) {
7715 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7716 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7717 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7718 or klass is the generic container class and generic_inst is the instantiation.
7720 when we go to the parent, if the parent is an open constructed type, we need to
7721 replace the type parameters by the definitions from the generic_inst, and then take it
7722 apart again into the klass and the generic_inst.
7724 For cases like this:
7725 class C<T> : B<T, int> {
7726 public override void Foo () { ... }
7728 class B<U,V> : A<HashMap<U,V>> {
7729 public override void Foo () { ... }
7731 class A<X> {
7732 public virtual void Foo () { ... }
7735 if at each iteration the parent isn't open, we can skip inflating it. if at some
7736 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7737 NULL;
7739 MonoGenericContext *parent_inst = NULL;
7740 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7741 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7742 if (!mono_error_ok (&error)) {
7743 mono_error_set_pending_exception (&error);
7744 return NULL;
7747 if (parent->generic_class) {
7748 parent_inst = mono_class_get_context (parent);
7749 parent = parent->generic_class->container_class;
7752 mono_class_setup_vtable (parent);
7753 if (parent->vtable_size <= slot)
7754 break;
7755 klass = parent;
7756 generic_inst = parent_inst;
7758 } else {
7759 klass = klass->parent;
7760 if (!klass)
7761 return m;
7762 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7763 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7764 if (!mono_error_ok (&error)) {
7765 mono_error_set_pending_exception (&error);
7766 return NULL;
7769 generic_inst = NULL;
7771 if (klass->generic_class) {
7772 generic_inst = mono_class_get_context (klass);
7773 klass = klass->generic_class->container_class;
7778 if (generic_inst) {
7779 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7780 if (!mono_error_ok (&error)) {
7781 mono_error_set_pending_exception (&error);
7782 return NULL;
7786 if (klass == method->klass)
7787 return m;
7789 /*This is possible if definition == FALSE.
7790 * Do it here to be really sure we don't read invalid memory.
7792 if (slot >= klass->vtable_size)
7793 return m;
7795 mono_class_setup_vtable (klass);
7797 result = klass->vtable [slot];
7798 if (result == NULL) {
7799 /* It is an abstract method */
7800 gpointer iter = NULL;
7801 while ((result = mono_class_get_methods (klass, &iter)))
7802 if (result->slot == slot)
7803 break;
7806 if (result == NULL)
7807 return m;
7809 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7810 mono_error_set_pending_exception (&error);
7811 return ret;
7814 ICALL_EXPORT MonoString*
7815 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7817 MonoMethod *method = m->method;
7819 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7820 return m->name;
7823 ICALL_EXPORT void
7824 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7826 iter->sig = *(MonoMethodSignature**)argsp;
7828 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7829 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7831 iter->next_arg = 0;
7832 /* FIXME: it's not documented what start is exactly... */
7833 if (start) {
7834 iter->args = start;
7835 } else {
7836 iter->args = argsp + sizeof (gpointer);
7838 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7840 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7843 ICALL_EXPORT MonoTypedRef
7844 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7846 guint32 i, arg_size;
7847 gint32 align;
7848 MonoTypedRef res;
7850 i = iter->sig->sentinelpos + iter->next_arg;
7852 g_assert (i < iter->sig->param_count);
7854 res.type = iter->sig->params [i];
7855 res.klass = mono_class_from_mono_type (res.type);
7856 arg_size = mono_type_stack_size (res.type, &align);
7857 #if defined(__arm__) || defined(__mips__)
7858 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7859 #endif
7860 res.value = iter->args;
7861 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7862 /* Values are stored as 8 byte register sized objects, but 'value'
7863 * is dereferenced as a pointer in other routines.
7865 res.value = (char*)res.value + 4;
7866 #endif
7867 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7868 if (arg_size <= sizeof (gpointer)) {
7869 int dummy;
7870 int padding = arg_size - mono_type_size (res.type, &dummy);
7871 res.value = (guint8*)res.value + padding;
7873 #endif
7874 iter->args = (char*)iter->args + arg_size;
7875 iter->next_arg++;
7877 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7879 return res;
7882 ICALL_EXPORT MonoTypedRef
7883 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7885 guint32 i, arg_size;
7886 gint32 align;
7887 MonoTypedRef res;
7889 i = iter->sig->sentinelpos + iter->next_arg;
7891 g_assert (i < iter->sig->param_count);
7893 while (i < iter->sig->param_count) {
7894 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7895 continue;
7896 res.type = iter->sig->params [i];
7897 res.klass = mono_class_from_mono_type (res.type);
7898 /* FIXME: endianess issue... */
7899 arg_size = mono_type_stack_size (res.type, &align);
7900 #if defined(__arm__) || defined(__mips__)
7901 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7902 #endif
7903 res.value = iter->args;
7904 iter->args = (char*)iter->args + arg_size;
7905 iter->next_arg++;
7906 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7907 return res;
7909 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7911 res.type = NULL;
7912 res.value = NULL;
7913 res.klass = NULL;
7914 return res;
7917 ICALL_EXPORT MonoType*
7918 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7920 gint i;
7922 i = iter->sig->sentinelpos + iter->next_arg;
7924 g_assert (i < iter->sig->param_count);
7926 return iter->sig->params [i];
7929 ICALL_EXPORT MonoObject*
7930 mono_TypedReference_ToObject (MonoTypedRef* tref)
7932 MonoError error;
7933 MonoObject *result = NULL;
7934 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7935 MonoObject** objp = (MonoObject **)tref->value;
7936 return *objp;
7939 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7940 mono_error_set_pending_exception (&error);
7941 return result;
7944 ICALL_EXPORT MonoTypedRef
7945 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7947 MonoTypedRef res;
7948 MonoReflectionField *f;
7949 MonoClass *klass;
7950 MonoType *ftype = NULL;
7951 guint8 *p = NULL;
7952 int i;
7954 memset (&res, 0, sizeof (res));
7956 g_assert (fields);
7957 g_assert (mono_array_length (fields) > 0);
7959 klass = target->vtable->klass;
7961 for (i = 0; i < mono_array_length (fields); ++i) {
7962 f = mono_array_get (fields, MonoReflectionField*, i);
7963 if (f == NULL) {
7964 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7965 return res;
7967 if (f->field->parent != klass) {
7968 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7969 return res;
7971 if (i == 0)
7972 p = (guint8*)target + f->field->offset;
7973 else
7974 p += f->field->offset - sizeof (MonoObject);
7975 klass = mono_class_from_mono_type (f->field->type);
7976 ftype = f->field->type;
7979 res.type = ftype;
7980 res.klass = mono_class_from_mono_type (ftype);
7981 res.value = p;
7983 return res;
7986 static void
7987 prelink_method (MonoMethod *method, MonoError *error)
7989 const char *exc_class, *exc_arg;
7991 mono_error_init (error);
7992 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7993 return;
7994 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7995 if (exc_class) {
7996 mono_error_set_exception_instance (error,
7997 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7998 return;
8000 /* create the wrapper, too? */
8003 ICALL_EXPORT void
8004 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8006 MonoError error;
8008 prelink_method (method->method, &error);
8009 mono_error_set_pending_exception (&error);
8012 ICALL_EXPORT void
8013 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8015 MonoError error;
8016 MonoClass *klass = mono_class_from_mono_type (type->type);
8017 MonoMethod* m;
8018 gpointer iter = NULL;
8020 mono_class_init_checked (klass, &error);
8021 if (mono_error_set_pending_exception (&error))
8022 return;
8024 while ((m = mono_class_get_methods (klass, &iter))) {
8025 prelink_method (m, &error);
8026 if (mono_error_set_pending_exception (&error))
8027 return;
8031 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8032 ICALL_EXPORT void
8033 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8034 gint32 const **exponents,
8035 gunichar2 const **digitLowerTable,
8036 gunichar2 const **digitUpperTable,
8037 gint64 const **tenPowersList,
8038 gint32 const **decHexDigits)
8040 *mantissas = Formatter_MantissaBitsTable;
8041 *exponents = Formatter_TensExponentTable;
8042 *digitLowerTable = Formatter_DigitLowerTable;
8043 *digitUpperTable = Formatter_DigitUpperTable;
8044 *tenPowersList = Formatter_TenPowersList;
8045 *decHexDigits = Formatter_DecHexDigits;
8049 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8050 * and avoid useless allocations.
8052 static MonoArray*
8053 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8055 MonoReflectionType *rt;
8056 MonoArray *res;
8057 int i, count = 0;
8059 mono_error_init (error);
8060 for (i = 0; i < type->num_mods; ++i) {
8061 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8062 count++;
8064 if (!count)
8065 return NULL;
8066 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8067 return_val_if_nok (error, NULL);
8068 count = 0;
8069 for (i = 0; i < type->num_mods; ++i) {
8070 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8071 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8072 return_val_if_nok (error, NULL);
8074 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8075 return_val_if_nok (error, NULL);
8077 mono_array_setref (res, count, rt);
8078 count++;
8081 return res;
8084 ICALL_EXPORT MonoArray*
8085 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8087 MonoError error;
8088 MonoType *type = param->ClassImpl->type;
8089 MonoClass *member_class = mono_object_class (param->MemberImpl);
8090 MonoMethod *method = NULL;
8091 MonoImage *image;
8092 int pos;
8093 MonoMethodSignature *sig;
8094 MonoArray *res;
8096 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8097 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8098 method = rmethod->method;
8099 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8100 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8101 if (!(method = prop->property->get))
8102 method = prop->property->set;
8103 g_assert (method);
8104 } else {
8105 char *type_name = mono_type_get_full_name (member_class);
8106 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8107 MonoException *ex = mono_get_exception_not_supported (msg);
8108 g_free (type_name);
8109 g_free (msg);
8110 mono_set_pending_exception (ex);
8111 return NULL;
8114 image = method->klass->image;
8115 pos = param->PositionImpl;
8116 sig = mono_method_signature (method);
8117 if (pos == -1)
8118 type = sig->ret;
8119 else
8120 type = sig->params [pos];
8122 res = type_array_from_modifiers (image, type, optional, &error);
8123 mono_error_set_pending_exception (&error);
8124 return res;
8127 static MonoType*
8128 get_property_type (MonoProperty *prop)
8130 MonoMethodSignature *sig;
8131 if (prop->get) {
8132 sig = mono_method_signature (prop->get);
8133 return sig->ret;
8134 } else if (prop->set) {
8135 sig = mono_method_signature (prop->set);
8136 return sig->params [sig->param_count - 1];
8138 return NULL;
8141 ICALL_EXPORT MonoArray*
8142 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8144 MonoError error;
8145 MonoType *type = get_property_type (property->property);
8146 MonoImage *image = property->klass->image;
8147 MonoArray *res;
8149 if (!type)
8150 return NULL;
8151 res = type_array_from_modifiers (image, type, optional, &error);
8152 mono_error_set_pending_exception (&error);
8153 return res;
8157 *Construct a MonoType suited to be used to decode a constant blob object.
8159 * @type is the target type which will be constructed
8160 * @blob_type is the blob type, for example, that comes from the constant table
8161 * @real_type is the expected constructed type.
8163 static void
8164 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8166 type->type = blob_type;
8167 type->data.klass = NULL;
8168 if (blob_type == MONO_TYPE_CLASS)
8169 type->data.klass = mono_defaults.object_class;
8170 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8171 /* For enums, we need to use the base type */
8172 type->type = MONO_TYPE_VALUETYPE;
8173 type->data.klass = mono_class_from_mono_type (real_type);
8174 } else
8175 type->data.klass = mono_class_from_mono_type (real_type);
8178 ICALL_EXPORT MonoObject*
8179 property_info_get_default_value (MonoReflectionProperty *property)
8181 MonoError error;
8182 MonoType blob_type;
8183 MonoProperty *prop = property->property;
8184 MonoType *type = get_property_type (prop);
8185 MonoDomain *domain = mono_object_domain (property);
8186 MonoTypeEnum def_type;
8187 const char *def_value;
8188 MonoObject *o;
8190 mono_class_init (prop->parent);
8192 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8193 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8194 return NULL;
8197 def_value = mono_class_get_property_default_value (prop, &def_type);
8199 mono_type_from_blob_type (&blob_type, def_type, type);
8200 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8202 mono_error_set_pending_exception (&error);
8203 return o;
8206 ICALL_EXPORT MonoBoolean
8207 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8209 MonoError error;
8210 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8211 MonoCustomAttrInfo *cinfo;
8212 gboolean found;
8214 mono_class_init_checked (attr_class, &error);
8215 if (mono_error_set_pending_exception (&error))
8216 return FALSE;
8218 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8219 if (!is_ok (&error)) {
8220 mono_error_set_pending_exception (&error);
8221 return FALSE;
8223 if (!cinfo)
8224 return FALSE;
8225 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8226 if (!cinfo->cached)
8227 mono_custom_attrs_free (cinfo);
8228 return found;
8231 ICALL_EXPORT MonoArray*
8232 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8234 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8235 MonoArray *res;
8236 MonoError error;
8238 if (attr_class) {
8239 mono_class_init_checked (attr_class, &error);
8240 if (mono_error_set_pending_exception (&error))
8241 return NULL;
8244 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8245 if (!mono_error_ok (&error)) {
8246 mono_error_set_pending_exception (&error);
8247 return NULL;
8250 return res;
8253 ICALL_EXPORT MonoArray*
8254 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8256 MonoError error;
8257 MonoArray *result;
8258 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8259 mono_error_set_pending_exception (&error);
8260 return result;
8264 ICALL_EXPORT MonoString*
8265 ves_icall_Mono_Runtime_GetDisplayName (void)
8267 char *info;
8268 MonoString *display_name;
8270 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8271 display_name = mono_string_new (mono_domain_get (), info);
8272 g_free (info);
8273 return display_name;
8276 ICALL_EXPORT MonoString*
8277 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8279 MonoError error;
8280 MonoString *message;
8281 guint32 ret;
8282 gunichar2 buf[256];
8284 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8285 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8286 buf, 255, NULL);
8287 if (ret == 0) {
8288 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8289 } else {
8290 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8291 if (mono_error_set_pending_exception (&error))
8292 return NULL;
8295 return message;
8298 ICALL_EXPORT gpointer
8299 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8301 return GetCurrentProcess ();
8304 ICALL_EXPORT MonoBoolean
8305 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8307 return GetExitCodeProcess (handle, (guint32*) exitcode);
8310 ICALL_EXPORT MonoBoolean
8311 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8313 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8314 return CloseHandle (handle);
8315 #else
8316 return CloseProcess (handle);
8317 #endif
8320 ICALL_EXPORT MonoBoolean
8321 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8323 return TerminateProcess (handle, exitcode);
8326 ICALL_EXPORT gint32
8327 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8329 return WaitForInputIdle (handle, milliseconds);
8332 ICALL_EXPORT MonoBoolean
8333 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8335 return GetProcessWorkingSetSize (handle, min, max);
8338 ICALL_EXPORT MonoBoolean
8339 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8341 return SetProcessWorkingSetSize (handle, min, max);
8344 ICALL_EXPORT MonoBoolean
8345 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8347 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8350 ICALL_EXPORT gint32
8351 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8353 return mono_process_current_pid ();
8356 ICALL_EXPORT gint32
8357 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8359 return GetPriorityClass (handle);
8362 ICALL_EXPORT MonoBoolean
8363 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8365 return SetPriorityClass (handle, priorityClass);
8368 #ifndef DISABLE_ICALL_TABLES
8370 #define ICALL_TYPE(id,name,first)
8371 #define ICALL(id,name,func) Icall_ ## id,
8373 enum {
8374 #include "metadata/icall-def.h"
8375 Icall_last
8378 #undef ICALL_TYPE
8379 #undef ICALL
8380 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8381 #define ICALL(id,name,func)
8382 enum {
8383 #include "metadata/icall-def.h"
8384 Icall_type_num
8387 #undef ICALL_TYPE
8388 #undef ICALL
8389 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8390 #define ICALL(id,name,func)
8391 typedef struct {
8392 guint16 first_icall;
8393 } IcallTypeDesc;
8395 static const IcallTypeDesc
8396 icall_type_descs [] = {
8397 #include "metadata/icall-def.h"
8398 {Icall_last}
8401 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8403 #undef ICALL_TYPE
8404 #define ICALL_TYPE(id,name,first)
8405 #undef ICALL
8407 #ifdef HAVE_ARRAY_ELEM_INIT
8408 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8409 #define MSGSTRFIELD1(line) str##line
8411 static const struct msgstrtn_t {
8412 #define ICALL(id,name,func)
8413 #undef ICALL_TYPE
8414 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8415 #include "metadata/icall-def.h"
8416 #undef ICALL_TYPE
8417 } icall_type_names_str = {
8418 #define ICALL_TYPE(id,name,first) (name),
8419 #include "metadata/icall-def.h"
8420 #undef ICALL_TYPE
8422 static const guint16 icall_type_names_idx [] = {
8423 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8424 #include "metadata/icall-def.h"
8425 #undef ICALL_TYPE
8427 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8429 static const struct msgstr_t {
8430 #undef ICALL
8431 #define ICALL_TYPE(id,name,first)
8432 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8433 #include "metadata/icall-def.h"
8434 #undef ICALL
8435 } icall_names_str = {
8436 #define ICALL(id,name,func) (name),
8437 #include "metadata/icall-def.h"
8438 #undef ICALL
8440 static const guint16 icall_names_idx [] = {
8441 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8442 #include "metadata/icall-def.h"
8443 #undef ICALL
8445 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8447 #else
8449 #undef ICALL_TYPE
8450 #undef ICALL
8451 #define ICALL_TYPE(id,name,first) name,
8452 #define ICALL(id,name,func)
8453 static const char* const
8454 icall_type_names [] = {
8455 #include "metadata/icall-def.h"
8456 NULL
8459 #define icall_type_name_get(id) (icall_type_names [(id)])
8461 #undef ICALL_TYPE
8462 #undef ICALL
8463 #define ICALL_TYPE(id,name,first)
8464 #define ICALL(id,name,func) name,
8465 static const char* const
8466 icall_names [] = {
8467 #include "metadata/icall-def.h"
8468 NULL
8470 #define icall_name_get(id) icall_names [(id)]
8472 #endif /* !HAVE_ARRAY_ELEM_INIT */
8474 #undef ICALL_TYPE
8475 #undef ICALL
8476 #define ICALL_TYPE(id,name,first)
8477 #define ICALL(id,name,func) func,
8478 static const gconstpointer
8479 icall_functions [] = {
8480 #include "metadata/icall-def.h"
8481 NULL
8484 #ifdef ENABLE_ICALL_SYMBOL_MAP
8485 #undef ICALL_TYPE
8486 #undef ICALL
8487 #define ICALL_TYPE(id,name,first)
8488 #define ICALL(id,name,func) #func,
8489 static const gconstpointer
8490 icall_symbols [] = {
8491 #include "metadata/icall-def.h"
8492 NULL
8494 #endif
8496 #endif /* DISABLE_ICALL_TABLES */
8498 static mono_mutex_t icall_mutex;
8499 static GHashTable *icall_hash = NULL;
8500 static GHashTable *jit_icall_hash_name = NULL;
8501 static GHashTable *jit_icall_hash_addr = NULL;
8503 void
8504 mono_icall_init (void)
8506 #ifndef DISABLE_ICALL_TABLES
8507 int i = 0;
8509 /* check that tables are sorted: disable in release */
8510 if (TRUE) {
8511 int j;
8512 const char *prev_class = NULL;
8513 const char *prev_method;
8515 for (i = 0; i < Icall_type_num; ++i) {
8516 const IcallTypeDesc *desc;
8517 int num_icalls;
8518 prev_method = NULL;
8519 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8520 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8521 prev_class = icall_type_name_get (i);
8522 desc = &icall_type_descs [i];
8523 num_icalls = icall_desc_num_icalls (desc);
8524 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8525 for (j = 0; j < num_icalls; ++j) {
8526 const char *methodn = icall_name_get (desc->first_icall + j);
8527 if (prev_method && strcmp (prev_method, methodn) >= 0)
8528 g_print ("method %s should come before method %s\n", methodn, prev_method);
8529 prev_method = methodn;
8533 #endif
8535 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8536 mono_os_mutex_init (&icall_mutex);
8539 static void
8540 mono_icall_lock (void)
8542 mono_locks_os_acquire (&icall_mutex, IcallLock);
8545 static void
8546 mono_icall_unlock (void)
8548 mono_locks_os_release (&icall_mutex, IcallLock);
8551 void
8552 mono_icall_cleanup (void)
8554 g_hash_table_destroy (icall_hash);
8555 g_hash_table_destroy (jit_icall_hash_name);
8556 g_hash_table_destroy (jit_icall_hash_addr);
8557 mono_os_mutex_destroy (&icall_mutex);
8561 * mono_add_internal_call:
8562 * @name: method specification to surface to the managed world
8563 * @method: pointer to a C method to invoke when the method is called
8565 * This method surfaces the C function pointed by @method as a method
8566 * that has been surfaced in managed code with the method specified in
8567 * @name as an internal call.
8569 * Internal calls are surfaced to all app domains loaded and they are
8570 * accessibly by a type with the specified name.
8572 * You must provide a fully qualified type name, that is namespaces
8573 * and type name, followed by a colon and the method name, with an
8574 * optional signature to bind.
8576 * For example, the following are all valid declarations:
8578 * "MyApp.Services.ScriptService:Accelerate"
8579 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8581 * You use method parameters in cases where there might be more than
8582 * one surface method to managed code. That way you can register different
8583 * internal calls for different method overloads.
8585 * The internal calls are invoked with no marshalling. This means that .NET
8586 * types like System.String are exposed as `MonoString *` parameters. This is
8587 * different than the way that strings are surfaced in P/Invoke.
8589 * For more information on how the parameters are marshalled, see the
8590 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8591 * page.
8593 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8594 * reference for more information on the format of method descriptions.
8596 void
8597 mono_add_internal_call (const char *name, gconstpointer method)
8599 mono_icall_lock ();
8601 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8603 mono_icall_unlock ();
8606 #ifndef DISABLE_ICALL_TABLES
8608 #ifdef HAVE_ARRAY_ELEM_INIT
8609 static int
8610 compare_method_imap (const void *key, const void *elem)
8612 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8613 return strcmp (key, method_name);
8616 static gpointer
8617 find_method_icall (const IcallTypeDesc *imap, const char *name)
8619 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);
8620 if (!nameslot)
8621 return NULL;
8622 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8625 static int
8626 compare_class_imap (const void *key, const void *elem)
8628 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8629 return strcmp (key, class_name);
8632 static const IcallTypeDesc*
8633 find_class_icalls (const char *name)
8635 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);
8636 if (!nameslot)
8637 return NULL;
8638 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8641 #else /* HAVE_ARRAY_ELEM_INIT */
8643 static int
8644 compare_method_imap (const void *key, const void *elem)
8646 const char** method_name = (const char**)elem;
8647 return strcmp (key, *method_name);
8650 static gpointer
8651 find_method_icall (const IcallTypeDesc *imap, const char *name)
8653 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8654 if (!nameslot)
8655 return NULL;
8656 return (gpointer)icall_functions [(nameslot - icall_names)];
8659 static int
8660 compare_class_imap (const void *key, const void *elem)
8662 const char** class_name = (const char**)elem;
8663 return strcmp (key, *class_name);
8666 static const IcallTypeDesc*
8667 find_class_icalls (const char *name)
8669 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8670 if (!nameslot)
8671 return NULL;
8672 return &icall_type_descs [nameslot - icall_type_names];
8675 #endif /* HAVE_ARRAY_ELEM_INIT */
8677 #endif /* DISABLE_ICALL_TABLES */
8680 * we should probably export this as an helper (handle nested types).
8681 * Returns the number of chars written in buf.
8683 static int
8684 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8686 int nspacelen, cnamelen;
8687 nspacelen = strlen (klass->name_space);
8688 cnamelen = strlen (klass->name);
8689 if (nspacelen + cnamelen + 2 > bufsize)
8690 return 0;
8691 if (nspacelen) {
8692 memcpy (buf, klass->name_space, nspacelen);
8693 buf [nspacelen ++] = '.';
8695 memcpy (buf + nspacelen, klass->name, cnamelen);
8696 buf [nspacelen + cnamelen] = 0;
8697 return nspacelen + cnamelen;
8700 #ifdef DISABLE_ICALL_TABLES
8701 static void
8702 no_icall_table (void)
8704 g_assert_not_reached ();
8706 #endif
8708 gpointer
8709 mono_lookup_internal_call (MonoMethod *method)
8711 char *sigstart;
8712 char *tmpsig;
8713 char mname [2048];
8714 int typelen = 0, mlen, siglen;
8715 gpointer res;
8716 #ifndef DISABLE_ICALL_TABLES
8717 const IcallTypeDesc *imap = NULL;
8718 #endif
8720 g_assert (method != NULL);
8722 if (method->is_inflated)
8723 method = ((MonoMethodInflated *) method)->declaring;
8725 if (method->klass->nested_in) {
8726 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8727 if (!pos)
8728 return NULL;
8730 mname [pos++] = '/';
8731 mname [pos] = 0;
8733 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8734 if (!typelen)
8735 return NULL;
8737 typelen += pos;
8738 } else {
8739 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8740 if (!typelen)
8741 return NULL;
8744 #ifndef DISABLE_ICALL_TABLES
8745 imap = find_class_icalls (mname);
8746 #endif
8748 mname [typelen] = ':';
8749 mname [typelen + 1] = ':';
8751 mlen = strlen (method->name);
8752 memcpy (mname + typelen + 2, method->name, mlen);
8753 sigstart = mname + typelen + 2 + mlen;
8754 *sigstart = 0;
8756 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8757 siglen = strlen (tmpsig);
8758 if (typelen + mlen + siglen + 6 > sizeof (mname))
8759 return NULL;
8760 sigstart [0] = '(';
8761 memcpy (sigstart + 1, tmpsig, siglen);
8762 sigstart [siglen + 1] = ')';
8763 sigstart [siglen + 2] = 0;
8764 g_free (tmpsig);
8766 mono_icall_lock ();
8768 res = g_hash_table_lookup (icall_hash, mname);
8769 if (res) {
8770 mono_icall_unlock ();;
8771 return res;
8773 /* try without signature */
8774 *sigstart = 0;
8775 res = g_hash_table_lookup (icall_hash, mname);
8776 if (res) {
8777 mono_icall_unlock ();
8778 return res;
8781 #ifdef DISABLE_ICALL_TABLES
8782 mono_icall_unlock ();
8783 /* Fail only when the result is actually used */
8784 /* mono_marshal_get_native_wrapper () depends on this */
8785 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8786 return ves_icall_System_String_ctor_RedirectToCreateString;
8787 else
8788 return no_icall_table;
8789 #else
8790 /* it wasn't found in the static call tables */
8791 if (!imap) {
8792 mono_icall_unlock ();
8793 return NULL;
8795 res = find_method_icall (imap, sigstart - mlen);
8796 if (res) {
8797 mono_icall_unlock ();
8798 return res;
8800 /* try _with_ signature */
8801 *sigstart = '(';
8802 res = find_method_icall (imap, sigstart - mlen);
8803 if (res) {
8804 mono_icall_unlock ();
8805 return res;
8808 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8809 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8810 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8811 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8812 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");
8813 g_print ("If you see other errors or faults after this message they are probably related\n");
8814 g_print ("and you need to fix your mono install first.\n");
8816 mono_icall_unlock ();
8818 return NULL;
8819 #endif
8822 #ifdef ENABLE_ICALL_SYMBOL_MAP
8823 static int
8824 func_cmp (gconstpointer key, gconstpointer p)
8826 return (gsize)key - (gsize)*(gsize*)p;
8828 #endif
8831 * mono_lookup_icall_symbol:
8833 * Given the icall METHOD, returns its C symbol.
8835 const char*
8836 mono_lookup_icall_symbol (MonoMethod *m)
8838 #ifdef DISABLE_ICALL_TABLES
8839 g_assert_not_reached ();
8840 return NULL;
8841 #else
8842 #ifdef ENABLE_ICALL_SYMBOL_MAP
8843 gpointer func;
8844 int i;
8845 gpointer slot;
8846 static gconstpointer *functions_sorted;
8847 static const char**symbols_sorted;
8848 static gboolean inited;
8850 if (!inited) {
8851 gboolean changed;
8853 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8854 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8855 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8856 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8857 /* Bubble sort the two arrays */
8858 changed = TRUE;
8859 while (changed) {
8860 changed = FALSE;
8861 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8862 if (functions_sorted [i] > functions_sorted [i + 1]) {
8863 gconstpointer tmp;
8865 tmp = functions_sorted [i];
8866 functions_sorted [i] = functions_sorted [i + 1];
8867 functions_sorted [i + 1] = tmp;
8868 tmp = symbols_sorted [i];
8869 symbols_sorted [i] = symbols_sorted [i + 1];
8870 symbols_sorted [i + 1] = tmp;
8871 changed = TRUE;
8877 func = mono_lookup_internal_call (m);
8878 if (!func)
8879 return NULL;
8880 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8881 if (!slot)
8882 return NULL;
8883 g_assert (slot);
8884 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8885 #else
8886 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8887 g_assert_not_reached ();
8888 return 0;
8889 #endif
8890 #endif
8893 static MonoType*
8894 type_from_typename (char *type_name)
8896 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8898 if (!strcmp (type_name, "int"))
8899 klass = mono_defaults.int_class;
8900 else if (!strcmp (type_name, "ptr"))
8901 klass = mono_defaults.int_class;
8902 else if (!strcmp (type_name, "void"))
8903 klass = mono_defaults.void_class;
8904 else if (!strcmp (type_name, "int32"))
8905 klass = mono_defaults.int32_class;
8906 else if (!strcmp (type_name, "uint32"))
8907 klass = mono_defaults.uint32_class;
8908 else if (!strcmp (type_name, "int8"))
8909 klass = mono_defaults.sbyte_class;
8910 else if (!strcmp (type_name, "uint8"))
8911 klass = mono_defaults.byte_class;
8912 else if (!strcmp (type_name, "int16"))
8913 klass = mono_defaults.int16_class;
8914 else if (!strcmp (type_name, "uint16"))
8915 klass = mono_defaults.uint16_class;
8916 else if (!strcmp (type_name, "long"))
8917 klass = mono_defaults.int64_class;
8918 else if (!strcmp (type_name, "ulong"))
8919 klass = mono_defaults.uint64_class;
8920 else if (!strcmp (type_name, "float"))
8921 klass = mono_defaults.single_class;
8922 else if (!strcmp (type_name, "double"))
8923 klass = mono_defaults.double_class;
8924 else if (!strcmp (type_name, "object"))
8925 klass = mono_defaults.object_class;
8926 else if (!strcmp (type_name, "obj"))
8927 klass = mono_defaults.object_class;
8928 else if (!strcmp (type_name, "string"))
8929 klass = mono_defaults.string_class;
8930 else if (!strcmp (type_name, "bool"))
8931 klass = mono_defaults.boolean_class;
8932 else if (!strcmp (type_name, "boolean"))
8933 klass = mono_defaults.boolean_class;
8934 else {
8935 g_error ("%s", type_name);
8936 g_assert_not_reached ();
8938 return &klass->byval_arg;
8942 * LOCKING: Take the corlib image lock.
8944 MonoMethodSignature*
8945 mono_create_icall_signature (const char *sigstr)
8947 gchar **parts;
8948 int i, len;
8949 gchar **tmp;
8950 MonoMethodSignature *res, *res2;
8951 MonoImage *corlib = mono_defaults.corlib;
8953 mono_image_lock (corlib);
8954 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8955 mono_image_unlock (corlib);
8957 if (res)
8958 return res;
8960 parts = g_strsplit (sigstr, " ", 256);
8962 tmp = parts;
8963 len = 0;
8964 while (*tmp) {
8965 len ++;
8966 tmp ++;
8969 res = mono_metadata_signature_alloc (corlib, len - 1);
8970 res->pinvoke = 1;
8972 #ifdef HOST_WIN32
8974 * Under windows, the default pinvoke calling convention is STDCALL but
8975 * we need CDECL.
8977 res->call_convention = MONO_CALL_C;
8978 #endif
8980 res->ret = type_from_typename (parts [0]);
8981 for (i = 1; i < len; ++i) {
8982 res->params [i - 1] = type_from_typename (parts [i]);
8985 g_strfreev (parts);
8987 mono_image_lock (corlib);
8988 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8989 if (res2)
8990 res = res2; /*Value is allocated in the image pool*/
8991 else
8992 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8993 mono_image_unlock (corlib);
8995 return res;
8998 MonoJitICallInfo *
8999 mono_find_jit_icall_by_name (const char *name)
9001 MonoJitICallInfo *info;
9002 g_assert (jit_icall_hash_name);
9004 mono_icall_lock ();
9005 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9006 mono_icall_unlock ();
9007 return info;
9010 MonoJitICallInfo *
9011 mono_find_jit_icall_by_addr (gconstpointer addr)
9013 MonoJitICallInfo *info;
9014 g_assert (jit_icall_hash_addr);
9016 mono_icall_lock ();
9017 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9018 mono_icall_unlock ();
9020 return info;
9024 * mono_get_jit_icall_info:
9026 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9027 * caller should access it while holding the icall lock.
9029 GHashTable*
9030 mono_get_jit_icall_info (void)
9032 return jit_icall_hash_name;
9036 * mono_lookup_jit_icall_symbol:
9038 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9040 const char*
9041 mono_lookup_jit_icall_symbol (const char *name)
9043 MonoJitICallInfo *info;
9044 const char *res = NULL;
9046 mono_icall_lock ();
9047 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9048 if (info)
9049 res = info->c_symbol;
9050 mono_icall_unlock ();
9051 return res;
9054 void
9055 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9057 mono_icall_lock ();
9058 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9059 mono_icall_unlock ();
9063 * 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
9064 * icalls without wrappers in some cases.
9066 MonoJitICallInfo *
9067 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9069 MonoJitICallInfo *info;
9071 g_assert (func);
9072 g_assert (name);
9074 mono_icall_lock ();
9076 if (!jit_icall_hash_name) {
9077 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9078 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9081 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9082 g_warning ("jit icall already defined \"%s\"\n", name);
9083 g_assert_not_reached ();
9086 info = g_new0 (MonoJitICallInfo, 1);
9088 info->name = name;
9089 info->func = func;
9090 info->sig = sig;
9091 info->c_symbol = c_symbol;
9092 info->no_raise = no_raise;
9094 if (is_save) {
9095 info->wrapper = func;
9096 } else {
9097 info->wrapper = NULL;
9100 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9101 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9103 mono_icall_unlock ();
9104 return info;
9107 MonoJitICallInfo *
9108 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9110 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);