[reflection] Managed version of RuntimeType.GetFields_internal
[mono-project.git] / mono / metadata / icall.c
blobeb1ca5958dd0779dc6d1cfddb3859b335e80d206
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_for_class_failure (error, 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 gint32
1214 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1216 MONO_CHECK_ARG_NULL (obj, 0);
1218 MonoError error;
1219 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1220 mono_error_set_pending_exception (&error);
1221 return result;
1224 ICALL_EXPORT gint32
1225 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1226 MonoReflectionMethod *method,
1227 MonoArray *opt_param_types)
1229 MONO_CHECK_ARG_NULL (method, 0);
1231 MonoError error;
1232 gint32 result = mono_image_create_method_token (
1233 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1234 mono_error_set_pending_exception (&error);
1235 return result;
1238 ICALL_EXPORT void
1239 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1241 MonoError error;
1242 mono_image_create_pefile (mb, file, &error);
1243 mono_error_set_pending_exception (&error);
1246 ICALL_EXPORT void
1247 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1249 MonoError error;
1250 mono_image_build_metadata (mb, &error);
1251 mono_error_set_pending_exception (&error);
1254 ICALL_EXPORT void
1255 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1257 mono_image_register_token (mb->dynamic_image, token, obj);
1260 ICALL_EXPORT MonoObject*
1261 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1263 MonoObject *obj;
1265 mono_loader_lock ();
1266 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1267 mono_loader_unlock ();
1269 return obj;
1272 ICALL_EXPORT MonoReflectionModule*
1273 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1275 MonoError error;
1276 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1277 mono_error_set_pending_exception (&error);
1278 return result;
1282 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1283 * @tb: a TypeBuilder object
1285 * (icall)
1286 * Creates the generic class after all generic parameters have been added.
1288 ICALL_EXPORT void
1289 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1291 MonoError error;
1292 (void) mono_reflection_create_generic_class (tb, &error);
1293 mono_error_set_pending_exception (&error);
1296 #ifndef DISABLE_REFLECTION_EMIT
1297 ICALL_EXPORT MonoArray*
1298 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1300 MonoError error;
1301 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1302 mono_error_set_pending_exception (&error);
1303 return result;
1305 #endif
1307 static gboolean
1308 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1310 MonoMethod **dest = (MonoMethod **)data;
1312 /* skip unmanaged frames */
1313 if (!managed)
1314 return FALSE;
1316 if (!(*dest)) {
1317 if (!strcmp (m->klass->name_space, "System.Reflection"))
1318 return FALSE;
1319 *dest = m;
1320 return TRUE;
1322 return FALSE;
1325 static gboolean
1326 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1328 MonoMethod **dest = (MonoMethod **)data;
1330 /* skip unmanaged frames */
1331 if (!managed)
1332 return FALSE;
1334 if (m->wrapper_type != MONO_WRAPPER_NONE)
1335 return FALSE;
1337 if (m == *dest) {
1338 *dest = NULL;
1339 return FALSE;
1342 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1343 return FALSE;
1345 if (!(*dest)) {
1346 *dest = m;
1347 return TRUE;
1349 return FALSE;
1352 static gboolean
1353 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1355 MonoMethod **dest = (MonoMethod **)data;
1357 /* skip unmanaged frames */
1358 if (!managed)
1359 return FALSE;
1361 if (m->wrapper_type != MONO_WRAPPER_NONE)
1362 return FALSE;
1364 if (m == *dest) {
1365 *dest = NULL;
1366 return FALSE;
1369 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1370 || (!strcmp (m->klass->name_space, "System"))))
1371 return FALSE;
1373 if (!(*dest)) {
1374 *dest = m;
1375 return TRUE;
1377 return FALSE;
1380 static MonoReflectionType *
1381 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1383 MonoMethod *m, *dest;
1385 MonoType *type = NULL;
1386 MonoAssembly *assembly = NULL;
1387 gboolean type_resolve = FALSE;
1388 MonoImage *rootimage = NULL;
1390 mono_error_init (error);
1393 * We must compute the calling assembly as type loading must happen under a metadata context.
1394 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1395 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1397 m = mono_method_get_last_managed ();
1398 dest = m;
1399 if (m && m->klass->image != mono_defaults.corlib) {
1400 /* Happens with inlining */
1401 } else {
1402 /* Ugly hack: type_from_parsed_name is called from
1403 * System.Type.internal_from_name, which is called most
1404 * directly from System.Type.GetType(string,bool,bool) but
1405 * also indirectly from places such as
1406 * System.Type.GetType(string,func,func) (via
1407 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1408 * so we need to skip over all of those to find the true caller.
1410 * It would be nice if we had stack marks.
1412 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1413 if (!dest)
1414 dest = m;
1418 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1419 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1420 * to crash. This only seems to happen in some strange remoting
1421 * scenarios and I was unable to figure out what's happening there.
1422 * Dec 10, 2005 - Martin.
1425 if (dest) {
1426 assembly = dest->klass->image->assembly;
1427 type_resolve = TRUE;
1428 rootimage = assembly->image;
1429 } else {
1430 g_warning (G_STRLOC);
1433 if (info->assembly.name)
1434 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1436 if (assembly) {
1437 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1438 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1439 return_val_if_nok (error, NULL);
1442 // XXXX - aleksey -
1443 // Say we're looking for System.Generic.Dict<int, Local>
1444 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1445 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1446 // is messed up when we go to construct the Local as the type arg...
1448 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1449 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1450 if (!info->assembly.name && !type) {
1451 /* try mscorlib */
1452 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1453 return_val_if_nok (error, NULL);
1455 if (assembly && !type && type_resolve) {
1456 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1457 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1458 return_val_if_nok (error, NULL);
1461 if (!type)
1462 return NULL;
1464 return mono_type_get_object_checked (mono_domain_get (), type, error);
1467 ICALL_EXPORT MonoReflectionType*
1468 ves_icall_System_Type_internal_from_name (MonoString *name,
1469 MonoBoolean throwOnError,
1470 MonoBoolean ignoreCase)
1472 MonoError error;
1473 MonoTypeNameParse info;
1474 MonoReflectionType *type = NULL;
1475 gboolean parsedOk;
1477 char *str = mono_string_to_utf8_checked (name, &error);
1478 if (!is_ok (&error))
1479 goto leave;
1481 parsedOk = mono_reflection_parse_type (str, &info);
1483 /* mono_reflection_parse_type() mangles the string */
1484 if (!parsedOk) {
1485 mono_reflection_free_type_info (&info);
1486 if (throwOnError)
1487 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1488 goto leave;
1491 type = type_from_parsed_name (&info, ignoreCase, &error);
1493 mono_reflection_free_type_info (&info);
1495 if (!is_ok (&error))
1496 goto leave;
1498 if (type == NULL){
1499 if (throwOnError) {
1500 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1501 goto leave;
1505 leave:
1506 g_free (str);
1507 if (!is_ok (&error)) {
1508 if (throwOnError)
1509 mono_error_set_pending_exception (&error);
1510 else
1511 mono_error_cleanup (&error);
1512 return NULL;
1515 return type;
1519 ICALL_EXPORT MonoReflectionType*
1520 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1522 MonoError error;
1523 MonoReflectionType *ret;
1524 MonoDomain *domain = mono_domain_get ();
1526 ret = mono_type_get_object_checked (domain, handle, &error);
1527 mono_error_set_pending_exception (&error);
1529 return ret;
1532 ICALL_EXPORT MonoType*
1533 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1535 return mono_class_get_type (klass);
1538 ICALL_EXPORT void
1539 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array, MonoBoolean freeSeg)
1541 g_ptr_array_free (ptr_array, freeSeg);
1544 /* System.TypeCode */
1545 typedef enum {
1546 TYPECODE_EMPTY,
1547 TYPECODE_OBJECT,
1548 TYPECODE_DBNULL,
1549 TYPECODE_BOOLEAN,
1550 TYPECODE_CHAR,
1551 TYPECODE_SBYTE,
1552 TYPECODE_BYTE,
1553 TYPECODE_INT16,
1554 TYPECODE_UINT16,
1555 TYPECODE_INT32,
1556 TYPECODE_UINT32,
1557 TYPECODE_INT64,
1558 TYPECODE_UINT64,
1559 TYPECODE_SINGLE,
1560 TYPECODE_DOUBLE,
1561 TYPECODE_DECIMAL,
1562 TYPECODE_DATETIME,
1563 TYPECODE_STRING = 18
1564 } TypeCode;
1566 ICALL_EXPORT guint32
1567 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1569 int t = type->type->type;
1571 if (type->type->byref)
1572 return TYPECODE_OBJECT;
1574 handle_enum:
1575 switch (t) {
1576 case MONO_TYPE_VOID:
1577 return TYPECODE_OBJECT;
1578 case MONO_TYPE_BOOLEAN:
1579 return TYPECODE_BOOLEAN;
1580 case MONO_TYPE_U1:
1581 return TYPECODE_BYTE;
1582 case MONO_TYPE_I1:
1583 return TYPECODE_SBYTE;
1584 case MONO_TYPE_U2:
1585 return TYPECODE_UINT16;
1586 case MONO_TYPE_I2:
1587 return TYPECODE_INT16;
1588 case MONO_TYPE_CHAR:
1589 return TYPECODE_CHAR;
1590 case MONO_TYPE_PTR:
1591 case MONO_TYPE_U:
1592 case MONO_TYPE_I:
1593 return TYPECODE_OBJECT;
1594 case MONO_TYPE_U4:
1595 return TYPECODE_UINT32;
1596 case MONO_TYPE_I4:
1597 return TYPECODE_INT32;
1598 case MONO_TYPE_U8:
1599 return TYPECODE_UINT64;
1600 case MONO_TYPE_I8:
1601 return TYPECODE_INT64;
1602 case MONO_TYPE_R4:
1603 return TYPECODE_SINGLE;
1604 case MONO_TYPE_R8:
1605 return TYPECODE_DOUBLE;
1606 case MONO_TYPE_VALUETYPE: {
1607 MonoClass *klass = type->type->data.klass;
1609 if (klass->enumtype) {
1610 t = mono_class_enum_basetype (klass)->type;
1611 goto handle_enum;
1612 } else if (mono_is_corlib_image (klass->image)) {
1613 if (strcmp (klass->name_space, "System") == 0) {
1614 if (strcmp (klass->name, "Decimal") == 0)
1615 return TYPECODE_DECIMAL;
1616 else if (strcmp (klass->name, "DateTime") == 0)
1617 return TYPECODE_DATETIME;
1620 return TYPECODE_OBJECT;
1622 case MONO_TYPE_STRING:
1623 return TYPECODE_STRING;
1624 case MONO_TYPE_SZARRAY:
1625 case MONO_TYPE_ARRAY:
1626 case MONO_TYPE_OBJECT:
1627 case MONO_TYPE_VAR:
1628 case MONO_TYPE_MVAR:
1629 case MONO_TYPE_TYPEDBYREF:
1630 return TYPECODE_OBJECT;
1631 case MONO_TYPE_CLASS:
1633 MonoClass *klass = type->type->data.klass;
1634 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1635 if (strcmp (klass->name, "DBNull") == 0)
1636 return TYPECODE_DBNULL;
1639 return TYPECODE_OBJECT;
1640 case MONO_TYPE_GENERICINST:
1641 return TYPECODE_OBJECT;
1642 default:
1643 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1645 return 0;
1648 static gboolean
1649 mono_type_is_primitive (MonoType *type)
1651 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1652 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1655 static MonoType*
1656 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1658 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1659 return mono_class_enum_basetype (type->data.klass);
1660 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1661 return mono_class_enum_basetype (type->data.generic_class->container_class);
1662 return type;
1665 ICALL_EXPORT guint32
1666 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1668 MonoClass *klass;
1669 MonoClass *klassc;
1671 g_assert (type != NULL);
1673 klass = mono_class_from_mono_type (type->type);
1674 klassc = mono_class_from_mono_type (c->type);
1676 if (type->type->byref ^ c->type->byref)
1677 return FALSE;
1679 if (type->type->byref) {
1680 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1681 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1683 klass = mono_class_from_mono_type (t);
1684 klassc = mono_class_from_mono_type (ot);
1686 if (mono_type_is_primitive (t)) {
1687 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1688 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1689 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1690 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1691 return t->type == ot->type;
1692 } else {
1693 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1694 return FALSE;
1696 if (klass->valuetype)
1697 return klass == klassc;
1698 return klass->valuetype == klassc->valuetype;
1701 return mono_class_is_assignable_from (klass, klassc);
1704 ICALL_EXPORT guint32
1705 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1707 MonoError error;
1708 MonoClass *klass = mono_class_from_mono_type (type->type);
1709 mono_class_init_checked (klass, &error);
1710 if (!is_ok (&error)) {
1711 mono_error_set_pending_exception (&error);
1712 return FALSE;
1714 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1715 mono_error_set_pending_exception (&error);
1716 return result;
1719 ICALL_EXPORT guint32
1720 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1722 MonoClass *klass = mono_class_from_mono_type (type->type);
1723 return klass->flags;
1726 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1727 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1729 MonoError error;
1730 MonoClass *klass = field->field->parent;
1731 MonoMarshalType *info;
1732 MonoType *ftype;
1733 int i;
1735 if (klass->generic_container ||
1736 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1737 return NULL;
1739 ftype = mono_field_get_type (field->field);
1740 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1741 return NULL;
1743 info = mono_marshal_load_type_info (klass);
1745 for (i = 0; i < info->num_fields; ++i) {
1746 if (info->fields [i].field == field->field) {
1747 if (!info->fields [i].mspec)
1748 return NULL;
1749 else {
1750 MonoReflectionMarshalAsAttribute* obj;
1751 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1752 if (!mono_error_ok (&error))
1753 mono_error_set_pending_exception (&error);
1754 return obj;
1759 return NULL;
1762 ICALL_EXPORT MonoReflectionField*
1763 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1765 MonoError error;
1766 gboolean found = FALSE;
1767 MonoClass *klass;
1768 MonoClass *k;
1770 g_assert (handle);
1772 if (!type) {
1773 klass = handle->parent;
1774 } else {
1775 klass = mono_class_from_mono_type (type);
1777 /* Check that the field belongs to the class */
1778 for (k = klass; k; k = k->parent) {
1779 if (k == handle->parent) {
1780 found = TRUE;
1781 break;
1785 if (!found)
1786 /* The managed code will throw the exception */
1787 return NULL;
1790 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1791 mono_error_set_pending_exception (&error);
1792 return result;
1795 ICALL_EXPORT MonoArray*
1796 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1798 MonoError error;
1799 MonoType *type = mono_field_get_type_checked (field->field, &error);
1800 MonoArray *res;
1802 if (!mono_error_ok (&error)) {
1803 mono_error_set_pending_exception (&error);
1804 return NULL;
1807 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1808 mono_error_set_pending_exception (&error);
1809 return res;
1812 ICALL_EXPORT int
1813 vell_icall_get_method_attributes (MonoMethod *method)
1815 return method->flags;
1818 ICALL_EXPORT void
1819 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1821 MonoError error;
1822 MonoReflectionType *rt;
1823 MonoDomain *domain = mono_domain_get ();
1824 MonoMethodSignature* sig;
1826 sig = mono_method_signature_checked (method, &error);
1827 if (!mono_error_ok (&error)) {
1828 mono_error_set_pending_exception (&error);
1829 return;
1832 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1833 if (!mono_error_ok (&error)) {
1834 mono_error_set_pending_exception (&error);
1835 return;
1838 MONO_STRUCT_SETREF (info, parent, rt);
1840 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1841 if (!mono_error_ok (&error)) {
1842 mono_error_set_pending_exception (&error);
1843 return;
1846 MONO_STRUCT_SETREF (info, ret, rt);
1848 info->attrs = method->flags;
1849 info->implattrs = method->iflags;
1850 if (sig->call_convention == MONO_CALL_DEFAULT)
1851 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1852 else {
1853 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1854 info->callconv = 2;
1855 else
1856 info->callconv = 1;
1858 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1861 ICALL_EXPORT MonoArray*
1862 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1864 MonoError error;
1865 MonoDomain *domain = mono_domain_get ();
1867 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1868 mono_error_set_pending_exception (&error);
1869 return result;
1872 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1873 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1875 MonoError error;
1876 MonoDomain *domain = mono_domain_get ();
1877 MonoReflectionMarshalAsAttribute* res = NULL;
1878 MonoMarshalSpec **mspecs;
1879 int i;
1881 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1882 mono_method_get_marshal_info (method, mspecs);
1884 if (mspecs [0]) {
1885 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1886 if (!mono_error_ok (&error)) {
1887 mono_error_set_pending_exception (&error);
1888 return NULL;
1892 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1893 if (mspecs [i])
1894 mono_metadata_free_marshal_spec (mspecs [i]);
1895 g_free (mspecs);
1897 return res;
1900 ICALL_EXPORT gint32
1901 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1903 MonoClass *parent = field->field->parent;
1904 if (!parent->size_inited)
1905 mono_class_init (parent);
1906 mono_class_setup_fields_locking (parent);
1908 return field->field->offset - sizeof (MonoObject);
1911 ICALL_EXPORT MonoReflectionType*
1912 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1914 MonoError error;
1915 MonoReflectionType *ret;
1916 MonoClass *parent;
1918 parent = declaring? field->field->parent: field->klass;
1920 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1921 mono_error_set_pending_exception (&error);
1923 return ret;
1927 ICALL_EXPORT MonoObject *
1928 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1930 MonoError error;
1931 MonoClass *fklass = field->klass;
1932 MonoClassField *cf = field->field;
1933 MonoDomain *domain = mono_object_domain (field);
1935 if (fklass->image->assembly->ref_only) {
1936 mono_set_pending_exception (mono_get_exception_invalid_operation (
1937 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1938 return NULL;
1941 if (mono_security_core_clr_enabled () &&
1942 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1943 mono_error_set_pending_exception (&error);
1944 return NULL;
1947 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1948 mono_error_set_pending_exception (&error);
1949 return result;
1952 ICALL_EXPORT void
1953 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1955 MonoError error;
1956 MonoClassField *cf = field->field;
1957 MonoType *type;
1958 gchar *v;
1960 if (field->klass->image->assembly->ref_only) {
1961 mono_set_pending_exception (mono_get_exception_invalid_operation (
1962 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1963 return;
1966 if (mono_security_core_clr_enabled () &&
1967 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1968 mono_error_set_pending_exception (&error);
1969 return;
1972 type = mono_field_get_type_checked (cf, &error);
1973 if (!mono_error_ok (&error)) {
1974 mono_error_set_pending_exception (&error);
1975 return;
1978 v = (gchar *) value;
1979 if (!type->byref) {
1980 switch (type->type) {
1981 case MONO_TYPE_U1:
1982 case MONO_TYPE_I1:
1983 case MONO_TYPE_BOOLEAN:
1984 case MONO_TYPE_U2:
1985 case MONO_TYPE_I2:
1986 case MONO_TYPE_CHAR:
1987 case MONO_TYPE_U:
1988 case MONO_TYPE_I:
1989 case MONO_TYPE_U4:
1990 case MONO_TYPE_I4:
1991 case MONO_TYPE_R4:
1992 case MONO_TYPE_U8:
1993 case MONO_TYPE_I8:
1994 case MONO_TYPE_R8:
1995 case MONO_TYPE_VALUETYPE:
1996 case MONO_TYPE_PTR:
1997 if (v != NULL)
1998 v += sizeof (MonoObject);
1999 break;
2000 case MONO_TYPE_STRING:
2001 case MONO_TYPE_OBJECT:
2002 case MONO_TYPE_CLASS:
2003 case MONO_TYPE_ARRAY:
2004 case MONO_TYPE_SZARRAY:
2005 /* Do nothing */
2006 break;
2007 case MONO_TYPE_GENERICINST: {
2008 MonoGenericClass *gclass = type->data.generic_class;
2009 g_assert (!gclass->context.class_inst->is_open);
2011 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2012 MonoClass *nklass = mono_class_from_mono_type (type);
2013 MonoObject *nullable;
2016 * Convert the boxed vtype into a Nullable structure.
2017 * This is complicated by the fact that Nullables have
2018 * a variable structure.
2020 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2021 if (!mono_error_ok (&error)) {
2022 mono_error_set_pending_exception (&error);
2023 return;
2026 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2028 v = (gchar *)mono_object_unbox (nullable);
2030 else
2031 if (gclass->container_class->valuetype && (v != NULL))
2032 v += sizeof (MonoObject);
2033 break;
2035 default:
2036 g_error ("type 0x%x not handled in "
2037 "ves_icall_FieldInfo_SetValueInternal", type->type);
2038 return;
2042 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2043 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2044 if (!is_ok (&error)) {
2045 mono_error_set_pending_exception (&error);
2046 return;
2048 if (!vtable->initialized) {
2049 if (!mono_runtime_class_init_full (vtable, &error)) {
2050 mono_error_set_pending_exception (&error);
2051 return;
2054 mono_field_static_set_value (vtable, cf, v);
2055 } else {
2056 mono_field_set_value (obj, cf, v);
2060 ICALL_EXPORT void
2061 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2063 MonoClassField *f;
2065 g_assert (field);
2066 g_assert (obj);
2067 g_assert (value);
2069 f = field->field;
2070 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2071 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2072 return;
2075 if (MONO_TYPE_IS_REFERENCE (f->type))
2076 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2077 else
2078 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2081 ICALL_EXPORT MonoObject *
2082 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2084 MonoObject *o = NULL;
2085 MonoClassField *field = rfield->field;
2086 MonoClass *klass;
2087 MonoDomain *domain = mono_object_domain (rfield);
2088 gchar *v;
2089 MonoTypeEnum def_type;
2090 const char *def_value;
2091 MonoType *t;
2092 MonoError error;
2094 mono_class_init (field->parent);
2096 t = mono_field_get_type_checked (field, &error);
2097 if (!mono_error_ok (&error)) {
2098 mono_error_set_pending_exception (&error);
2099 return NULL;
2102 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2103 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2104 return NULL;
2107 if (image_is_dynamic (field->parent->image)) {
2108 MonoClass *klass = field->parent;
2109 int fidx = field - klass->fields;
2111 g_assert (fidx >= 0 && fidx < klass->field.count);
2112 g_assert (klass->ext);
2113 g_assert (klass->ext->field_def_values);
2114 def_type = klass->ext->field_def_values [fidx].def_type;
2115 def_value = klass->ext->field_def_values [fidx].data;
2116 if (def_type == MONO_TYPE_END) {
2117 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2118 return NULL;
2120 } else {
2121 def_value = mono_class_get_field_default_value (field, &def_type);
2122 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2123 if (!def_value) {
2124 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2125 return NULL;
2129 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2130 switch (def_type) {
2131 case MONO_TYPE_U1:
2132 case MONO_TYPE_I1:
2133 case MONO_TYPE_BOOLEAN:
2134 case MONO_TYPE_U2:
2135 case MONO_TYPE_I2:
2136 case MONO_TYPE_CHAR:
2137 case MONO_TYPE_U:
2138 case MONO_TYPE_I:
2139 case MONO_TYPE_U4:
2140 case MONO_TYPE_I4:
2141 case MONO_TYPE_R4:
2142 case MONO_TYPE_U8:
2143 case MONO_TYPE_I8:
2144 case MONO_TYPE_R8: {
2145 MonoType *t;
2147 /* boxed value type */
2148 t = g_new0 (MonoType, 1);
2149 t->type = def_type;
2150 klass = mono_class_from_mono_type (t);
2151 g_free (t);
2152 o = mono_object_new_checked (domain, klass, &error);
2153 if (!mono_error_ok (&error)) {
2154 mono_error_set_pending_exception (&error);
2155 return NULL;
2157 v = ((gchar *) o) + sizeof (MonoObject);
2158 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2159 if (mono_error_set_pending_exception (&error))
2160 return NULL;
2161 break;
2163 case MONO_TYPE_STRING:
2164 case MONO_TYPE_CLASS:
2165 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2166 if (mono_error_set_pending_exception (&error))
2167 return NULL;
2168 break;
2169 default:
2170 g_assert_not_reached ();
2173 return o;
2176 ICALL_EXPORT MonoReflectionType*
2177 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2179 MonoError error;
2180 MonoReflectionType *ret;
2181 MonoType *type;
2183 type = mono_field_get_type_checked (ref_field->field, &error);
2184 if (!mono_error_ok (&error)) {
2185 mono_error_set_pending_exception (&error);
2186 return NULL;
2189 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2190 if (!mono_error_ok (&error)) {
2191 mono_error_set_pending_exception (&error);
2192 return NULL;
2195 return ret;
2198 /* From MonoProperty.cs */
2199 typedef enum {
2200 PInfo_Attributes = 1,
2201 PInfo_GetMethod = 1 << 1,
2202 PInfo_SetMethod = 1 << 2,
2203 PInfo_ReflectedType = 1 << 3,
2204 PInfo_DeclaringType = 1 << 4,
2205 PInfo_Name = 1 << 5
2206 } PInfo;
2208 ICALL_EXPORT void
2209 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2211 MonoError error;
2212 MonoReflectionType *rt;
2213 MonoReflectionMethod *rm;
2214 MonoDomain *domain = mono_object_domain (property);
2215 const MonoProperty *pproperty = property->property;
2217 if ((req_info & PInfo_ReflectedType) != 0) {
2218 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2219 if (mono_error_set_pending_exception (&error))
2220 return;
2222 MONO_STRUCT_SETREF (info, parent, rt);
2224 if ((req_info & PInfo_DeclaringType) != 0) {
2225 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2226 if (mono_error_set_pending_exception (&error))
2227 return;
2229 MONO_STRUCT_SETREF (info, declaring_type, rt);
2232 if ((req_info & PInfo_Name) != 0)
2233 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2235 if ((req_info & PInfo_Attributes) != 0)
2236 info->attrs = pproperty->attrs;
2238 if ((req_info & PInfo_GetMethod) != 0) {
2239 if (pproperty->get &&
2240 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2241 pproperty->get->klass == property->klass)) {
2242 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2243 if (mono_error_set_pending_exception (&error))
2244 return;
2245 } else {
2246 rm = NULL;
2249 MONO_STRUCT_SETREF (info, get, rm);
2251 if ((req_info & PInfo_SetMethod) != 0) {
2252 if (pproperty->set &&
2253 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2254 pproperty->set->klass == property->klass)) {
2255 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2256 if (mono_error_set_pending_exception (&error))
2257 return;
2258 } else {
2259 rm = NULL;
2262 MONO_STRUCT_SETREF (info, set, rm);
2265 * There may be other methods defined for properties, though, it seems they are not exposed
2266 * in the reflection API
2270 ICALL_EXPORT void
2271 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2273 MonoError error;
2274 MonoReflectionType *rt;
2275 MonoReflectionMethod *rm;
2276 MonoDomain *domain = mono_object_domain (event);
2278 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2279 if (mono_error_set_pending_exception (&error))
2280 return;
2282 MONO_STRUCT_SETREF (info, reflected_type, rt);
2284 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2285 if (mono_error_set_pending_exception (&error))
2286 return;
2288 MONO_STRUCT_SETREF (info, declaring_type, rt);
2290 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2291 info->attrs = event->event->attrs;
2293 if (event->event->add) {
2294 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2295 if (mono_error_set_pending_exception (&error))
2296 return;
2297 } else {
2298 rm = NULL;
2301 MONO_STRUCT_SETREF (info, add_method, rm);
2303 if (event->event->remove) {
2304 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2305 if (mono_error_set_pending_exception (&error))
2306 return;
2307 } else {
2308 rm = NULL;
2311 MONO_STRUCT_SETREF (info, remove_method, rm);
2313 if (event->event->raise) {
2314 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2315 if (mono_error_set_pending_exception (&error))
2316 return;
2317 } else {
2318 rm = NULL;
2321 MONO_STRUCT_SETREF (info, raise_method, rm);
2323 #ifndef MONO_SMALL_CONFIG
2324 if (event->event->other) {
2325 int i, n = 0;
2326 while (event->event->other [n])
2327 n++;
2328 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2329 if (mono_error_set_pending_exception (&error))
2330 return;
2331 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2333 for (i = 0; i < n; i++) {
2334 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2335 if (mono_error_set_pending_exception (&error))
2336 return;
2337 mono_array_setref (info->other_methods, i, rm);
2340 #endif
2343 static void
2344 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2346 int i;
2347 MonoClass *ic;
2349 mono_class_setup_interfaces (klass, error);
2350 if (!mono_error_ok (error))
2351 return;
2353 for (i = 0; i < klass->interface_count; i++) {
2354 ic = klass->interfaces [i];
2355 g_hash_table_insert (ifaces, ic, ic);
2357 collect_interfaces (ic, ifaces, error);
2358 if (!mono_error_ok (error))
2359 return;
2363 typedef struct {
2364 MonoArray *iface_array;
2365 MonoGenericContext *context;
2366 MonoError *error;
2367 MonoDomain *domain;
2368 int next_idx;
2369 } FillIfaceArrayData;
2371 static void
2372 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2374 MonoReflectionType *rt;
2375 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2376 MonoClass *ic = (MonoClass *)key;
2377 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2379 if (!mono_error_ok (data->error))
2380 return;
2382 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2383 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2384 if (!mono_error_ok (data->error))
2385 return;
2388 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2389 if (!mono_error_ok (data->error))
2390 return;
2392 mono_array_setref (data->iface_array, data->next_idx++, rt);
2394 if (inflated)
2395 mono_metadata_free_type (inflated);
2398 static guint
2399 get_interfaces_hash (gconstpointer v1)
2401 MonoClass *k = (MonoClass*)v1;
2403 return k->type_token;
2406 ICALL_EXPORT MonoArray*
2407 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2409 MonoError error;
2410 MonoClass *klass = mono_class_from_mono_type (type->type);
2411 MonoClass *parent;
2412 FillIfaceArrayData data = { 0 };
2413 int len;
2415 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2417 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2418 data.context = mono_class_get_context (klass);
2419 klass = klass->generic_class->container_class;
2422 for (parent = klass; parent; parent = parent->parent) {
2423 mono_class_setup_interfaces (parent, &error);
2424 if (!mono_error_ok (&error))
2425 goto fail;
2426 collect_interfaces (parent, iface_hash, &error);
2427 if (!mono_error_ok (&error))
2428 goto fail;
2431 data.error = &error;
2432 data.domain = mono_object_domain (type);
2434 len = g_hash_table_size (iface_hash);
2435 if (len == 0) {
2436 g_hash_table_destroy (iface_hash);
2437 if (!data.domain->empty_types) {
2438 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2439 if (!is_ok (&error))
2440 goto fail;
2442 return data.domain->empty_types;
2445 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2446 if (!is_ok (&error))
2447 goto fail;
2448 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2449 if (!mono_error_ok (&error))
2450 goto fail;
2452 g_hash_table_destroy (iface_hash);
2453 return data.iface_array;
2455 fail:
2456 g_hash_table_destroy (iface_hash);
2457 mono_error_set_pending_exception (&error);
2458 return NULL;
2461 ICALL_EXPORT void
2462 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2464 gboolean variance_used;
2465 MonoClass *klass = mono_class_from_mono_type (type->type);
2466 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2467 MonoReflectionMethod *member;
2468 MonoMethod* method;
2469 gpointer iter;
2470 int i = 0, len, ioffset;
2471 MonoDomain *domain;
2472 MonoError error;
2474 mono_class_init_checked (klass, &error);
2475 if (mono_error_set_pending_exception (&error))
2476 return;
2477 mono_class_init_checked (iclass, &error);
2478 if (mono_error_set_pending_exception (&error))
2479 return;
2481 mono_class_setup_vtable (klass);
2483 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2484 if (ioffset == -1)
2485 return;
2487 len = mono_class_num_methods (iclass);
2488 domain = mono_object_domain (type);
2489 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2490 if (mono_error_set_pending_exception (&error))
2491 return;
2492 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2493 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2494 if (mono_error_set_pending_exception (&error))
2495 return;
2496 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2497 iter = NULL;
2498 while ((method = mono_class_get_methods (iclass, &iter))) {
2499 member = mono_method_get_object_checked (domain, method, iclass, &error);
2500 if (mono_error_set_pending_exception (&error))
2501 return;
2502 mono_array_setref (*methods, i, member);
2503 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2504 if (mono_error_set_pending_exception (&error))
2505 return;
2506 mono_array_setref (*targets, i, member);
2508 i ++;
2512 ICALL_EXPORT void
2513 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2515 MonoError error;
2516 MonoClass *klass = mono_class_from_mono_type (type->type);
2518 mono_class_init_checked (klass, &error);
2519 if (mono_error_set_pending_exception (&error))
2520 return;
2522 if (image_is_dynamic (klass->image)) {
2523 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2524 *packing = tb->packing_size;
2525 *size = tb->class_size;
2526 } else {
2527 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2531 ICALL_EXPORT MonoReflectionType*
2532 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2534 MonoError error;
2535 MonoReflectionType *ret;
2536 MonoClass *klass;
2538 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2539 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2540 mono_error_set_pending_exception (&error);
2541 return ret;
2544 klass = mono_class_from_mono_type (type->type);
2545 mono_class_init_checked (klass, &error);
2546 if (mono_error_set_pending_exception (&error))
2547 return NULL;
2550 // GetElementType should only return a type for:
2551 // Array Pointer PassedByRef
2552 if (type->type->byref)
2553 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2554 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2555 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2556 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2557 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2558 else
2559 return NULL;
2561 mono_error_set_pending_exception (&error);
2563 return ret;
2566 ICALL_EXPORT MonoReflectionType*
2567 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2569 MonoError error;
2570 MonoReflectionType *ret;
2572 if (type->type->byref)
2573 return NULL;
2575 MonoClass *klass = mono_class_from_mono_type (type->type);
2576 if (!klass->parent)
2577 return NULL;
2579 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2580 mono_error_set_pending_exception (&error);
2582 return ret;
2585 ICALL_EXPORT MonoBoolean
2586 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2588 return type->type->type == MONO_TYPE_PTR;
2591 ICALL_EXPORT MonoBoolean
2592 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2594 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)));
2597 ICALL_EXPORT MonoBoolean
2598 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2600 return type->type->byref;
2603 ICALL_EXPORT MonoBoolean
2604 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2606 MonoError error;
2607 MonoClass *klass = mono_class_from_mono_type (type->type);
2608 mono_class_init_checked (klass, &error);
2609 if (mono_error_set_pending_exception (&error))
2610 return FALSE;
2612 return mono_class_is_com_object (klass);
2615 ICALL_EXPORT guint32
2616 ves_icall_reflection_get_token (MonoObject* obj)
2618 MonoError error;
2619 guint32 result = mono_reflection_get_token_checked (obj, &error);
2620 mono_error_set_pending_exception (&error);
2621 return result;
2624 ICALL_EXPORT MonoReflectionModule*
2625 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2627 MonoError error;
2628 MonoReflectionModule *result = NULL;
2629 MonoClass *klass = mono_class_from_mono_type (type->type);
2630 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2631 mono_error_set_pending_exception (&error);
2632 return result;
2635 ICALL_EXPORT MonoReflectionAssembly*
2636 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2638 MonoError error;
2639 MonoDomain *domain = mono_domain_get ();
2640 MonoClass *klass = mono_class_from_mono_type (type->type);
2641 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2642 mono_error_set_pending_exception (&error);
2643 return result;
2646 ICALL_EXPORT MonoReflectionType*
2647 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2649 MonoError error;
2650 MonoReflectionType *ret;
2651 MonoDomain *domain = mono_domain_get ();
2652 MonoClass *klass;
2654 if (type->type->byref)
2655 return NULL;
2656 if (type->type->type == MONO_TYPE_VAR) {
2657 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2658 klass = param ? param->owner.klass : NULL;
2659 } else if (type->type->type == MONO_TYPE_MVAR) {
2660 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2661 klass = param ? param->owner.method->klass : NULL;
2662 } else {
2663 klass = mono_class_from_mono_type (type->type)->nested_in;
2666 if (!klass)
2667 return NULL;
2669 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2670 mono_error_set_pending_exception (&error);
2672 return ret;
2675 ICALL_EXPORT MonoString*
2676 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2678 MonoDomain *domain = mono_domain_get ();
2679 MonoClass *klass = mono_class_from_mono_type (type->type);
2681 if (type->type->byref) {
2682 char *n = g_strdup_printf ("%s&", klass->name);
2683 MonoString *res = mono_string_new (domain, n);
2685 g_free (n);
2687 return res;
2688 } else {
2689 return mono_string_new (domain, klass->name);
2693 ICALL_EXPORT MonoString*
2694 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2696 MonoDomain *domain = mono_domain_get ();
2697 MonoClass *klass = mono_class_from_mono_type (type->type);
2699 while (klass->nested_in)
2700 klass = klass->nested_in;
2702 if (klass->name_space [0] == '\0')
2703 return NULL;
2704 else
2705 return mono_string_new (domain, klass->name_space);
2708 ICALL_EXPORT gint32
2709 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2711 MonoClass *klass;
2713 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2714 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2715 return 0;
2718 klass = mono_class_from_mono_type (type->type);
2720 return klass->rank;
2723 static MonoArray*
2724 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2726 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2729 ICALL_EXPORT MonoArray*
2730 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2732 MonoError error;
2733 MonoReflectionType *rt;
2734 MonoArray *res;
2735 MonoClass *klass, *pklass;
2736 MonoDomain *domain = mono_object_domain (type);
2737 int i;
2739 klass = mono_class_from_mono_type (type->type);
2741 if (klass->generic_container) {
2742 MonoGenericContainer *container = klass->generic_container;
2743 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2744 if (mono_error_set_pending_exception (&error))
2745 return NULL;
2746 for (i = 0; i < container->type_argc; ++i) {
2747 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2749 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2750 if (mono_error_set_pending_exception (&error))
2751 return NULL;
2753 mono_array_setref (res, i, rt);
2755 } else if (klass->generic_class) {
2756 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2757 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2758 if (mono_error_set_pending_exception (&error))
2759 return NULL;
2760 for (i = 0; i < inst->type_argc; ++i) {
2761 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2762 if (mono_error_set_pending_exception (&error))
2763 return NULL;
2765 mono_array_setref (res, i, rt);
2767 } else {
2768 res = NULL;
2770 return res;
2773 ICALL_EXPORT gboolean
2774 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2776 MonoClass *klass;
2778 if (!IS_MONOTYPE (type))
2779 return FALSE;
2781 if (type->type->byref)
2782 return FALSE;
2784 klass = mono_class_from_mono_type (type->type);
2785 return klass->generic_container != NULL;
2788 ICALL_EXPORT MonoReflectionType*
2789 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2791 MonoError error;
2792 MonoReflectionType *ret;
2793 MonoClass *klass;
2795 if (type->type->byref)
2796 return NULL;
2798 klass = mono_class_from_mono_type (type->type);
2800 if (klass->generic_container) {
2801 return type; /* check this one */
2803 if (klass->generic_class) {
2804 MonoClass *generic_class = klass->generic_class->container_class;
2805 gpointer tb;
2807 tb = mono_class_get_ref_info (generic_class);
2809 if (generic_class->wastypebuilder && tb)
2810 return (MonoReflectionType *)tb;
2811 else {
2812 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2813 mono_error_set_pending_exception (&error);
2815 return ret;
2818 return NULL;
2821 ICALL_EXPORT MonoReflectionType*
2822 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2824 MonoError error;
2825 MonoReflectionType *ret;
2826 MonoClass *klass;
2827 MonoType *geninst, **types;
2828 int i, count;
2830 g_assert (IS_MONOTYPE (type));
2831 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2832 if (mono_error_set_pending_exception (&error))
2833 return NULL;
2835 count = mono_array_length (type_array);
2836 types = g_new0 (MonoType *, count);
2838 for (i = 0; i < count; i++) {
2839 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2840 types [i] = t->type;
2843 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2844 g_free (types);
2845 if (!geninst) {
2846 mono_error_set_pending_exception (&error);
2847 return NULL;
2850 klass = mono_class_from_mono_type (geninst);
2852 /*we might inflate to the GTD*/
2853 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2854 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2855 return NULL;
2858 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2859 mono_error_set_pending_exception (&error);
2861 return ret;
2864 ICALL_EXPORT gboolean
2865 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2867 MonoClass *klass;
2869 if (!IS_MONOTYPE (type))
2870 return FALSE;
2872 if (type->type->byref)
2873 return FALSE;
2875 klass = mono_class_from_mono_type (type->type);
2876 return klass->generic_class != NULL || klass->generic_container != NULL;
2879 ICALL_EXPORT gint32
2880 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2882 if (!IS_MONOTYPE (type))
2883 return -1;
2885 if (is_generic_parameter (type->type))
2886 return mono_type_get_generic_param_num (type->type);
2887 return -1;
2890 ICALL_EXPORT MonoGenericParamInfo *
2891 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2893 return mono_generic_param_info (type->type->data.generic_param);
2896 ICALL_EXPORT MonoBoolean
2897 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2899 return is_generic_parameter (type->type);
2902 ICALL_EXPORT MonoBoolean
2903 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2905 return is_generic_parameter (tb->type.type);
2908 ICALL_EXPORT void
2909 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2910 MonoReflectionType *t)
2912 enumtype->type = t->type;
2915 ICALL_EXPORT MonoReflectionMethod*
2916 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2917 MonoReflectionMethod* generic)
2919 MonoDomain *domain;
2920 MonoClass *klass;
2921 MonoMethod *method;
2922 gpointer iter;
2923 MonoError error;
2924 MonoReflectionMethod *ret = NULL;
2926 domain = ((MonoObject *)type)->vtable->domain;
2928 klass = mono_class_from_mono_type (type->type);
2929 mono_class_init_checked (klass, &error);
2930 if (mono_error_set_pending_exception (&error))
2931 return NULL;
2933 iter = NULL;
2934 while ((method = mono_class_get_methods (klass, &iter))) {
2935 if (method->token == generic->method->token) {
2936 ret = mono_method_get_object_checked (domain, method, klass, &error);
2937 if (mono_error_set_pending_exception (&error))
2938 return NULL;
2942 return ret;
2945 ICALL_EXPORT MonoReflectionMethod *
2946 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2948 MonoMethod *method;
2949 MonoType *type = ref_type->type;
2950 MonoError error;
2951 MonoReflectionMethod *ret = NULL;
2953 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2954 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2955 return NULL;
2957 if (type->type == MONO_TYPE_VAR)
2958 return NULL;
2960 method = mono_type_get_generic_param_owner (type)->owner.method;
2961 g_assert (method);
2963 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2964 if (!mono_error_ok (&error))
2965 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2966 return ret;
2969 ICALL_EXPORT MonoBoolean
2970 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2972 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2973 return FALSE;
2976 ICALL_EXPORT MonoBoolean
2977 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2979 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2980 return FALSE;
2983 ICALL_EXPORT void
2984 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2986 MonoDomain *domain = mono_domain_get ();
2987 MonoImage *image = method->method->klass->image;
2988 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2989 MonoTableInfo *tables = image->tables;
2990 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2991 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2992 guint32 im_cols [MONO_IMPLMAP_SIZE];
2993 guint32 scope_token;
2994 const char *import = NULL;
2995 const char *scope = NULL;
2997 if (image_is_dynamic (image)) {
2998 MonoReflectionMethodAux *method_aux =
2999 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3000 if (method_aux) {
3001 import = method_aux->dllentry;
3002 scope = method_aux->dll;
3005 if (!import || !scope) {
3006 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3007 return;
3010 else {
3011 if (piinfo->implmap_idx) {
3012 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3014 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3015 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3016 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3017 scope = mono_metadata_string_heap (image, scope_token);
3021 *flags = piinfo->piflags;
3022 *entry_point = mono_string_new (domain, import);
3023 *dll_name = mono_string_new (domain, scope);
3026 ICALL_EXPORT MonoReflectionMethod *
3027 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3029 MonoMethodInflated *imethod;
3030 MonoMethod *result;
3031 MonoReflectionMethod *ret = NULL;
3032 MonoError error;
3034 if (method->method->is_generic)
3035 return method;
3037 if (!method->method->is_inflated)
3038 return NULL;
3040 imethod = (MonoMethodInflated *) method->method;
3042 result = imethod->declaring;
3043 /* Not a generic method. */
3044 if (!result->is_generic)
3045 return NULL;
3047 if (image_is_dynamic (method->method->klass->image)) {
3048 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3049 MonoReflectionMethod *res;
3052 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3053 * the dynamic case as well ?
3055 mono_image_lock ((MonoImage*)image);
3056 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3057 mono_image_unlock ((MonoImage*)image);
3059 if (res)
3060 return res;
3063 if (imethod->context.class_inst) {
3064 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3065 /*Generic methods gets the context of the GTD.*/
3066 if (mono_class_get_context (klass)) {
3067 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3068 if (!mono_error_ok (&error))
3069 goto leave;
3073 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3074 leave:
3075 if (!mono_error_ok (&error))
3076 mono_error_set_pending_exception (&error);
3077 return ret;
3080 ICALL_EXPORT gboolean
3081 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3083 return mono_method_signature (method->method)->generic_param_count != 0;
3086 ICALL_EXPORT gboolean
3087 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3089 return method->method->is_generic;
3092 ICALL_EXPORT MonoArray*
3093 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3095 MonoError error;
3096 MonoReflectionType *rt;
3097 MonoArray *res;
3098 MonoDomain *domain;
3099 int count, i;
3101 domain = mono_object_domain (method);
3103 if (method->method->is_inflated) {
3104 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3106 if (inst) {
3107 count = inst->type_argc;
3108 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3109 if (mono_error_set_pending_exception (&error))
3110 return NULL;
3112 for (i = 0; i < count; i++) {
3113 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3114 if (mono_error_set_pending_exception (&error))
3115 return NULL;
3117 mono_array_setref (res, i, rt);
3120 return res;
3124 count = mono_method_signature (method->method)->generic_param_count;
3125 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3126 if (mono_error_set_pending_exception (&error))
3127 return NULL;
3129 for (i = 0; i < count; i++) {
3130 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3131 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3132 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3134 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3135 if (mono_error_set_pending_exception (&error))
3136 return NULL;
3138 mono_array_setref (res, i, rt);
3141 return res;
3144 ICALL_EXPORT MonoObject *
3145 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3147 MonoError error;
3149 * Invoke from reflection is supposed to always be a virtual call (the API
3150 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3151 * greater flexibility.
3153 MonoMethod *m = method->method;
3154 MonoMethodSignature *sig = mono_method_signature (m);
3155 MonoImage *image;
3156 int pcount;
3157 void *obj = this_arg;
3159 *exc = NULL;
3161 if (mono_security_core_clr_enabled () &&
3162 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3163 mono_error_set_pending_exception (&error);
3164 return NULL;
3167 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3168 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3169 mono_error_cleanup (&error); /* FIXME does this make sense? */
3170 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3171 return NULL;
3174 if (this_arg) {
3175 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3176 if (!is_ok (&error)) {
3177 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3178 return NULL;
3180 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3181 char *target_name = mono_type_get_full_name (m->klass);
3182 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3183 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3184 g_free (msg);
3185 g_free (target_name);
3186 g_free (this_name);
3187 return NULL;
3189 m = mono_object_get_virtual_method (this_arg, m);
3190 /* must pass the pointer to the value for valuetype methods */
3191 if (m->klass->valuetype)
3192 obj = mono_object_unbox (this_arg);
3193 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3194 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3195 return NULL;
3199 if (sig->ret->byref) {
3200 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"));
3201 return NULL;
3204 pcount = params? mono_array_length (params): 0;
3205 if (pcount != sig->param_count) {
3206 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3207 return NULL;
3210 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3211 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."));
3212 return NULL;
3215 image = m->klass->image;
3216 if (image->assembly->ref_only) {
3217 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."));
3218 return NULL;
3221 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3222 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3223 return NULL;
3226 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3227 MonoArray *arr;
3228 int i;
3229 uintptr_t *lengths;
3230 intptr_t *lower_bounds;
3231 pcount = mono_array_length (params);
3232 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3233 /* Note: the synthetized array .ctors have int32 as argument type */
3234 for (i = 0; i < pcount; ++i)
3235 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3237 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3238 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3239 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3240 if (!mono_error_ok (&error)) {
3241 mono_error_set_pending_exception (&error);
3242 return NULL;
3245 for (i = 0; i < mono_array_length (arr); ++i) {
3246 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3247 if (!mono_error_ok (&error)) {
3248 mono_error_set_pending_exception (&error);
3249 return NULL;
3251 mono_array_setref_fast (arr, i, subarray);
3253 return (MonoObject*)arr;
3256 if (m->klass->rank == pcount) {
3257 /* Only lengths provided. */
3258 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3259 if (!mono_error_ok (&error)) {
3260 mono_error_set_pending_exception (&error);
3261 return NULL;
3264 return (MonoObject*)arr;
3265 } else {
3266 g_assert (pcount == (m->klass->rank * 2));
3267 /* The arguments are lower-bound-length pairs */
3268 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3270 for (i = 0; i < pcount / 2; ++i) {
3271 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3272 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3275 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3276 if (!mono_error_ok (&error)) {
3277 mono_error_set_pending_exception (&error);
3278 return NULL;
3281 return (MonoObject*)arr;
3284 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3285 mono_error_set_pending_exception (&error);
3286 return result;
3289 #ifndef DISABLE_REMOTING
3290 ICALL_EXPORT MonoObject *
3291 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3293 MonoError error;
3294 MonoDomain *domain = mono_object_domain (method);
3295 MonoMethod *m = method->method;
3296 MonoMethodSignature *sig = mono_method_signature (m);
3297 MonoArray *out_args;
3298 MonoObject *result;
3299 int i, j, outarg_count = 0;
3301 if (m->klass == mono_defaults.object_class) {
3302 if (!strcmp (m->name, "FieldGetter")) {
3303 MonoClass *k = this_arg->vtable->klass;
3304 MonoString *name;
3305 char *str;
3307 /* If this is a proxy, then it must be a CBO */
3308 if (k == mono_defaults.transparent_proxy_class) {
3309 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3310 this_arg = tp->rp->unwrapped_server;
3311 g_assert (this_arg);
3312 k = this_arg->vtable->klass;
3315 name = mono_array_get (params, MonoString *, 1);
3316 str = mono_string_to_utf8_checked (name, &error);
3317 if (mono_error_set_pending_exception (&error))
3318 return NULL;
3320 do {
3321 MonoClassField* field = mono_class_get_field_from_name (k, str);
3322 if (field) {
3323 g_free (str);
3324 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3325 if (field_klass->valuetype) {
3326 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3327 if (mono_error_set_pending_exception (&error))
3328 return NULL;
3329 } else
3330 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3332 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3333 if (mono_error_set_pending_exception (&error))
3334 return NULL;
3335 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3336 mono_array_setref (out_args, 0, result);
3337 return NULL;
3339 k = k->parent;
3340 } while (k);
3342 g_free (str);
3343 g_assert_not_reached ();
3345 } else if (!strcmp (m->name, "FieldSetter")) {
3346 MonoClass *k = this_arg->vtable->klass;
3347 MonoString *name;
3348 guint32 size;
3349 gint32 align;
3350 char *str;
3352 /* If this is a proxy, then it must be a CBO */
3353 if (k == mono_defaults.transparent_proxy_class) {
3354 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3355 this_arg = tp->rp->unwrapped_server;
3356 g_assert (this_arg);
3357 k = this_arg->vtable->klass;
3360 name = mono_array_get (params, MonoString *, 1);
3361 str = mono_string_to_utf8_checked (name, &error);
3362 if (mono_error_set_pending_exception (&error))
3363 return NULL;
3365 do {
3366 MonoClassField* field = mono_class_get_field_from_name (k, str);
3367 if (field) {
3368 g_free (str);
3369 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3370 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3372 if (field_klass->valuetype) {
3373 size = mono_type_size (field->type, &align);
3374 g_assert (size == mono_class_value_size (field_klass, NULL));
3375 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3376 } else {
3377 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3380 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3381 if (mono_error_set_pending_exception (&error))
3382 return NULL;
3383 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3385 return NULL;
3388 k = k->parent;
3389 } while (k);
3391 g_free (str);
3392 g_assert_not_reached ();
3397 for (i = 0; i < mono_array_length (params); i++) {
3398 if (sig->params [i]->byref)
3399 outarg_count++;
3402 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3403 if (mono_error_set_pending_exception (&error))
3404 return NULL;
3406 /* handle constructors only for objects already allocated */
3407 if (!strcmp (method->method->name, ".ctor"))
3408 g_assert (this_arg);
3410 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3411 g_assert (!method->method->klass->valuetype);
3412 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3413 if (mono_error_set_pending_exception (&error))
3414 return NULL;
3416 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3417 if (sig->params [i]->byref) {
3418 gpointer arg;
3419 arg = mono_array_get (params, gpointer, i);
3420 mono_array_setref (out_args, j, arg);
3421 j++;
3425 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3427 return result;
3429 #endif
3431 static guint64
3432 read_enum_value (const char *mem, int type)
3434 switch (type) {
3435 case MONO_TYPE_BOOLEAN:
3436 case MONO_TYPE_U1:
3437 return *(guint8*)mem;
3438 case MONO_TYPE_I1:
3439 return *(gint8*)mem;
3440 case MONO_TYPE_CHAR:
3441 case MONO_TYPE_U2:
3442 return read16 (mem);
3443 case MONO_TYPE_I2:
3444 return (gint16) read16 (mem);
3445 case MONO_TYPE_U4:
3446 return read32 (mem);
3447 case MONO_TYPE_I4:
3448 return (gint32) read32 (mem);
3449 case MONO_TYPE_U8:
3450 case MONO_TYPE_I8:
3451 return read64 (mem);
3452 default:
3453 g_assert_not_reached ();
3455 return 0;
3458 static void
3459 write_enum_value (char *mem, int type, guint64 value)
3461 switch (type) {
3462 case MONO_TYPE_U1:
3463 case MONO_TYPE_I1: {
3464 guint8 *p = (guint8*)mem;
3465 *p = value;
3466 break;
3468 case MONO_TYPE_U2:
3469 case MONO_TYPE_I2:
3470 case MONO_TYPE_CHAR: {
3471 guint16 *p = (guint16 *)mem;
3472 *p = value;
3473 break;
3475 case MONO_TYPE_U4:
3476 case MONO_TYPE_I4: {
3477 guint32 *p = (guint32 *)mem;
3478 *p = value;
3479 break;
3481 case MONO_TYPE_U8:
3482 case MONO_TYPE_I8: {
3483 guint64 *p = (guint64 *)mem;
3484 *p = value;
3485 break;
3487 default:
3488 g_assert_not_reached ();
3490 return;
3493 ICALL_EXPORT MonoObject *
3494 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3496 MonoError error;
3497 MonoDomain *domain;
3498 MonoClass *enumc;
3499 MonoObject *res;
3500 MonoType *etype;
3502 domain = mono_object_domain (enumType);
3503 enumc = mono_class_from_mono_type (enumType->type);
3505 mono_class_init_checked (enumc, &error);
3506 if (mono_error_set_pending_exception (&error))
3507 return NULL;
3509 etype = mono_class_enum_basetype (enumc);
3511 res = mono_object_new_checked (domain, enumc, &error);
3512 if (mono_error_set_pending_exception (&error))
3513 return NULL;
3514 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3516 return res;
3519 ICALL_EXPORT MonoBoolean
3520 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3522 int size = mono_class_value_size (a->vtable->klass, NULL);
3523 guint64 a_val = 0, b_val = 0;
3525 memcpy (&a_val, mono_object_unbox (a), size);
3526 memcpy (&b_val, mono_object_unbox (b), size);
3528 return (a_val & b_val) == b_val;
3531 ICALL_EXPORT MonoObject *
3532 ves_icall_System_Enum_get_value (MonoObject *eobj)
3534 MonoError error;
3535 MonoObject *res;
3536 MonoClass *enumc;
3537 gpointer dst;
3538 gpointer src;
3539 int size;
3541 if (!eobj)
3542 return NULL;
3544 g_assert (eobj->vtable->klass->enumtype);
3546 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3547 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3548 if (mono_error_set_pending_exception (&error))
3549 return NULL;
3550 dst = (char *)res + sizeof (MonoObject);
3551 src = (char *)eobj + sizeof (MonoObject);
3552 size = mono_class_value_size (enumc, NULL);
3554 memcpy (dst, src, size);
3556 return res;
3559 ICALL_EXPORT MonoReflectionType *
3560 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3562 MonoError error;
3563 MonoReflectionType *ret;
3564 MonoType *etype;
3565 MonoClass *klass;
3567 klass = mono_class_from_mono_type (type->type);
3568 mono_class_init_checked (klass, &error);
3569 if (mono_error_set_pending_exception (&error))
3570 return NULL;
3572 etype = mono_class_enum_basetype (klass);
3573 if (!etype) {
3574 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3575 return NULL;
3578 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3579 mono_error_set_pending_exception (&error);
3581 return ret;
3584 ICALL_EXPORT int
3585 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3587 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3588 gpointer odata = (char *)other + sizeof (MonoObject);
3589 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3590 g_assert (basetype);
3592 if (other == NULL)
3593 return 1;
3595 if (eobj->vtable->klass != other->vtable->klass)
3596 return 2;
3598 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3599 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3600 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3601 if (me == other) \
3602 return 0; \
3603 return me > other ? 1 : -1; \
3604 } while (0)
3606 switch (basetype->type) {
3607 case MONO_TYPE_U1:
3608 COMPARE_ENUM_VALUES (guint8);
3609 case MONO_TYPE_I1:
3610 COMPARE_ENUM_VALUES (gint8);
3611 case MONO_TYPE_CHAR:
3612 case MONO_TYPE_U2:
3613 COMPARE_ENUM_VALUES (guint16);
3614 case MONO_TYPE_I2:
3615 COMPARE_ENUM_VALUES (gint16);
3616 case MONO_TYPE_U4:
3617 COMPARE_ENUM_VALUES (guint32);
3618 case MONO_TYPE_I4:
3619 COMPARE_ENUM_VALUES (gint32);
3620 case MONO_TYPE_U8:
3621 COMPARE_ENUM_VALUES (guint64);
3622 case MONO_TYPE_I8:
3623 COMPARE_ENUM_VALUES (gint64);
3624 default:
3625 break;
3627 #undef COMPARE_ENUM_VALUES
3628 /* indicates that the enum was of an unsupported unerlying type */
3629 return 3;
3632 ICALL_EXPORT int
3633 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3635 gpointer data = (char *)eobj + sizeof (MonoObject);
3636 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3637 g_assert (basetype);
3639 switch (basetype->type) {
3640 case MONO_TYPE_I1: {
3641 gint8 value = *((gint8*)data);
3642 return ((int)value ^ (int)value << 8);
3644 case MONO_TYPE_U1:
3645 return *((guint8*)data);
3646 case MONO_TYPE_CHAR:
3647 case MONO_TYPE_U2:
3648 return *((guint16*)data);
3650 case MONO_TYPE_I2: {
3651 gint16 value = *((gint16*)data);
3652 return ((int)(guint16)value | (((int)value) << 16));
3654 case MONO_TYPE_U4:
3655 return *((guint32*)data);
3656 case MONO_TYPE_I4:
3657 return *((gint32*)data);
3658 case MONO_TYPE_U8:
3659 case MONO_TYPE_I8: {
3660 gint64 value = *((gint64*)data);
3661 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3663 default:
3664 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3666 return 0;
3669 ICALL_EXPORT MonoBoolean
3670 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3672 MonoError error;
3673 MonoDomain *domain = mono_object_domain (type);
3674 MonoClass *enumc = mono_class_from_mono_type (type->type);
3675 guint j = 0, nvalues;
3676 gpointer iter;
3677 MonoClassField *field;
3678 int base_type;
3679 guint64 field_value, previous_value = 0;
3680 gboolean sorted = TRUE;
3682 mono_class_init_checked (enumc, &error);
3683 if (mono_error_set_pending_exception (&error))
3684 return FALSE;
3687 if (!enumc->enumtype) {
3688 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3689 return TRUE;
3692 base_type = mono_class_enum_basetype (enumc)->type;
3694 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3695 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3696 if (mono_error_set_pending_exception (&error))
3697 return FALSE;
3698 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3699 if (mono_error_set_pending_exception (&error))
3700 return FALSE;
3702 iter = NULL;
3703 while ((field = mono_class_get_fields (enumc, &iter))) {
3704 const char *p;
3705 MonoTypeEnum def_type;
3707 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3708 continue;
3709 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3710 continue;
3711 if (mono_field_is_deleted (field))
3712 continue;
3713 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3715 p = mono_class_get_field_default_value (field, &def_type);
3716 /* len = */ mono_metadata_decode_blob_size (p, &p);
3718 field_value = read_enum_value (p, base_type);
3719 mono_array_set (*values, guint64, j, field_value);
3721 if (previous_value > field_value)
3722 sorted = FALSE;
3724 previous_value = field_value;
3725 ++j;
3728 return sorted;
3731 enum {
3732 BFLAGS_IgnoreCase = 1,
3733 BFLAGS_DeclaredOnly = 2,
3734 BFLAGS_Instance = 4,
3735 BFLAGS_Static = 8,
3736 BFLAGS_Public = 0x10,
3737 BFLAGS_NonPublic = 0x20,
3738 BFLAGS_FlattenHierarchy = 0x40,
3739 BFLAGS_InvokeMethod = 0x100,
3740 BFLAGS_CreateInstance = 0x200,
3741 BFLAGS_GetField = 0x400,
3742 BFLAGS_SetField = 0x800,
3743 BFLAGS_GetProperty = 0x1000,
3744 BFLAGS_SetProperty = 0x2000,
3745 BFLAGS_ExactBinding = 0x10000,
3746 BFLAGS_SuppressChangeType = 0x20000,
3747 BFLAGS_OptionalParamBinding = 0x40000
3750 ICALL_EXPORT GPtrArray*
3751 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, MonoString *name, guint32 bflags)
3753 MonoError error;
3754 MonoDomain *domain;
3755 MonoClass *startklass, *klass;
3756 int match;
3757 gpointer iter;
3758 char *utf8_name = NULL;
3759 int (*compare_func) (const char *s1, const char *s2) = NULL;
3760 MonoClassField *field;
3762 domain = ((MonoObject *)type)->vtable->domain;
3763 if (type->type->byref) {
3764 return g_ptr_array_new ();
3767 klass = startklass = mono_class_from_mono_type (type->type);
3769 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3771 handle_parent:
3772 if (mono_class_has_failure (klass)) {
3773 mono_error_init (&error);
3774 mono_error_set_for_class_failure (&error, klass);
3775 goto fail;
3778 iter = NULL;
3779 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3780 guint32 flags = mono_field_get_flags (field);
3781 match = 0;
3782 if (mono_field_is_deleted_with_flags (field, flags))
3783 continue;
3784 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3785 if (bflags & BFLAGS_Public)
3786 match++;
3787 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3788 if (bflags & BFLAGS_NonPublic) {
3789 match++;
3792 if (!match)
3793 continue;
3794 match = 0;
3795 if (flags & FIELD_ATTRIBUTE_STATIC) {
3796 if (bflags & BFLAGS_Static)
3797 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3798 match++;
3799 } else {
3800 if (bflags & BFLAGS_Instance)
3801 match++;
3804 if (!match)
3805 continue;
3807 if (name != NULL) {
3808 if (utf8_name == NULL) {
3809 utf8_name = mono_string_to_utf8_checked (name, &error);
3810 if (!is_ok (&error))
3811 goto fail;
3812 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3815 if (compare_func (mono_field_get_name (field), utf8_name))
3816 continue;
3819 g_ptr_array_add (ptr_array, field);
3821 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3822 goto handle_parent;
3824 if (utf8_name != NULL)
3825 g_free (utf8_name);
3826 return ptr_array;
3828 fail:
3829 g_ptr_array_free (ptr_array, FALSE);
3830 mono_error_set_pending_exception (&error);
3831 return NULL;
3834 static gboolean
3835 method_nonpublic (MonoMethod* method, gboolean start_klass)
3837 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3838 case METHOD_ATTRIBUTE_ASSEM:
3839 return (start_klass || mono_defaults.generic_ilist_class);
3840 case METHOD_ATTRIBUTE_PRIVATE:
3841 return start_klass;
3842 case METHOD_ATTRIBUTE_PUBLIC:
3843 return FALSE;
3844 default:
3845 return TRUE;
3849 GPtrArray*
3850 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3852 GPtrArray *array;
3853 MonoClass *startklass;
3854 MonoMethod *method;
3855 gpointer iter;
3856 int match, nslots;
3857 /*FIXME, use MonoBitSet*/
3858 guint32 method_slots_default [8];
3859 guint32 *method_slots = NULL;
3860 int (*compare_func) (const char *s1, const char *s2) = NULL;
3862 array = g_ptr_array_new ();
3863 startklass = klass;
3864 *ex = NULL;
3866 if (name != NULL)
3867 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3869 /* An optimization for calls made from Delegate:CreateDelegate () */
3870 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3871 method = mono_get_delegate_invoke (klass);
3872 g_assert (method);
3874 g_ptr_array_add (array, method);
3875 return array;
3878 mono_class_setup_methods (klass);
3879 mono_class_setup_vtable (klass);
3880 if (mono_class_has_failure (klass))
3881 goto loader_error;
3883 if (is_generic_parameter (&klass->byval_arg))
3884 nslots = mono_class_get_vtable_size (klass->parent);
3885 else
3886 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3887 if (nslots >= sizeof (method_slots_default) * 8) {
3888 method_slots = g_new0 (guint32, nslots / 32 + 1);
3889 } else {
3890 method_slots = method_slots_default;
3891 memset (method_slots, 0, sizeof (method_slots_default));
3893 handle_parent:
3894 mono_class_setup_methods (klass);
3895 mono_class_setup_vtable (klass);
3896 if (mono_class_has_failure (klass))
3897 goto loader_error;
3899 iter = NULL;
3900 while ((method = mono_class_get_methods (klass, &iter))) {
3901 match = 0;
3902 if (method->slot != -1) {
3903 g_assert (method->slot < nslots);
3904 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3905 continue;
3906 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3907 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3910 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3911 continue;
3912 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3913 if (bflags & BFLAGS_Public)
3914 match++;
3915 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3916 match++;
3918 if (!match)
3919 continue;
3920 match = 0;
3921 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3922 if (bflags & BFLAGS_Static)
3923 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3924 match++;
3925 } else {
3926 if (bflags & BFLAGS_Instance)
3927 match++;
3930 if (!match)
3931 continue;
3933 if (name != NULL) {
3934 if (compare_func (name, method->name))
3935 continue;
3938 match = 0;
3939 g_ptr_array_add (array, method);
3941 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3942 goto handle_parent;
3943 if (method_slots != method_slots_default)
3944 g_free (method_slots);
3946 return array;
3948 loader_error:
3949 if (method_slots != method_slots_default)
3950 g_free (method_slots);
3951 g_ptr_array_free (array, TRUE);
3953 if (mono_class_has_failure (klass)) {
3954 *ex = mono_class_get_exception_for_failure (klass);
3955 } else {
3956 *ex = mono_get_exception_execution_engine ("Unknown error");
3958 return NULL;
3961 ICALL_EXPORT MonoArray*
3962 ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3964 static MonoClass *MethodInfo_array;
3965 MonoError error;
3966 MonoDomain *domain;
3967 MonoArray *res;
3968 MonoVTable *array_vtable;
3969 MonoException *ex = NULL;
3970 const char *mname = NULL;
3971 GPtrArray *method_array;
3972 MonoClass *klass, *refklass;
3973 int i;
3975 mono_error_init (&error);
3977 if (!MethodInfo_array) {
3978 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3979 mono_memory_barrier ();
3980 MethodInfo_array = klass;
3983 klass = mono_class_from_mono_type (type->type);
3984 refklass = mono_class_from_mono_type (reftype->type);
3985 domain = ((MonoObject *)type)->vtable->domain;
3986 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3987 if (!is_ok (&error)) {
3988 mono_error_set_pending_exception (&error);
3989 return NULL;
3991 if (type->type->byref) {
3992 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3993 mono_error_set_pending_exception (&error);
3995 return res;
3998 if (name) {
3999 mname = mono_string_to_utf8_checked (name, &error);
4000 if (mono_error_set_pending_exception (&error))
4001 return NULL;
4004 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4005 g_free ((char*)mname);
4006 if (ex) {
4007 mono_set_pending_exception (ex);
4008 return NULL;
4011 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4012 if (!mono_error_ok (&error)) {
4013 mono_error_set_pending_exception (&error);
4014 return NULL;
4017 for (i = 0; i < method_array->len; ++i) {
4018 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4019 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4020 if (!mono_error_ok (&error))
4021 goto failure;
4022 mono_array_setref (res, i, rm);
4025 failure:
4026 g_ptr_array_free (method_array, TRUE);
4027 if (!mono_error_ok (&error))
4028 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4029 return res;
4032 ICALL_EXPORT MonoArray*
4033 ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4035 MonoDomain *domain;
4036 MonoClass *startklass, *klass, *refklass;
4037 MonoArray *res = NULL;
4038 MonoMethod *method;
4039 MonoObject *member;
4040 int i, match;
4041 gpointer iter = NULL;
4042 MonoPtrArray tmp_array;
4043 MonoError error;
4045 domain = ((MonoObject *)type)->vtable->domain;
4046 if (type->type->byref) {
4047 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4048 mono_error_set_pending_exception (&error);
4049 return res;
4052 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4055 klass = startklass = mono_class_from_mono_type (type->type);
4056 refklass = mono_class_from_mono_type (reftype->type);
4058 mono_class_setup_methods (klass);
4059 if (mono_class_has_failure (klass)) {
4060 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4061 goto leave;
4064 iter = NULL;
4065 while ((method = mono_class_get_methods (klass, &iter))) {
4066 match = 0;
4067 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4068 continue;
4069 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4070 if (bflags & BFLAGS_Public)
4071 match++;
4072 } else {
4073 if (bflags & BFLAGS_NonPublic)
4074 match++;
4076 if (!match)
4077 continue;
4078 match = 0;
4079 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4080 if (bflags & BFLAGS_Static)
4081 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4082 match++;
4083 } else {
4084 if (bflags & BFLAGS_Instance)
4085 match++;
4088 if (!match)
4089 continue;
4090 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4091 if (mono_error_set_pending_exception (&error))
4092 goto leave;
4094 mono_ptr_array_append (tmp_array, member);
4097 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4098 if (mono_error_set_pending_exception (&error))
4099 goto leave;
4101 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4102 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4104 leave:
4105 mono_ptr_array_destroy (tmp_array);
4107 return res;
4110 static guint
4111 property_hash (gconstpointer data)
4113 MonoProperty *prop = (MonoProperty*)data;
4115 return g_str_hash (prop->name);
4118 static gboolean
4119 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4121 if (method1->slot != -1 && method1->slot == method2->slot)
4122 return TRUE;
4124 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4125 if (method1->is_inflated)
4126 method1 = ((MonoMethodInflated*) method1)->declaring;
4127 if (method2->is_inflated)
4128 method2 = ((MonoMethodInflated*) method2)->declaring;
4131 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4134 static gboolean
4135 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4137 // Properties are hide-by-name-and-signature
4138 if (!g_str_equal (prop1->name, prop2->name))
4139 return FALSE;
4141 /* If we see a property in a generic method, we want to
4142 compare the generic signatures, not the inflated signatures
4143 because we might conflate two properties that were
4144 distinct:
4146 class Foo<T,U> {
4147 public T this[T t] { getter { return t; } } // method 1
4148 public U this[U u] { getter { return u; } } // method 2
4151 If we see int Foo<int,int>::Item[int] we need to know if
4152 the indexer came from method 1 or from method 2, and we
4153 shouldn't conflate them. (Bugzilla 36283)
4155 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4156 return FALSE;
4158 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4159 return FALSE;
4161 return TRUE;
4164 static gboolean
4165 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4167 if (!accessor)
4168 return FALSE;
4170 return method_nonpublic (accessor, start_klass);
4173 ICALL_EXPORT MonoArray*
4174 ves_icall_RuntimeType_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4176 MonoError error;
4177 MonoDomain *domain;
4178 MonoClass *startklass, *klass;
4179 MonoArray *res;
4180 MonoMethod *method;
4181 MonoProperty *prop;
4182 int i, match;
4183 guint32 flags;
4184 gchar *propname = NULL;
4185 int (*compare_func) (const char *s1, const char *s2) = NULL;
4186 gpointer iter;
4187 GHashTable *properties = NULL;
4188 MonoPtrArray tmp_array;
4190 mono_error_init (&error);
4192 domain = ((MonoObject *)type)->vtable->domain;
4193 if (type->type->byref) {
4194 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4195 mono_error_set_pending_exception (&error);
4196 return res;
4199 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4201 klass = startklass = mono_class_from_mono_type (type->type);
4203 if (name != NULL) {
4204 propname = mono_string_to_utf8_checked (name, &error);
4205 if (mono_error_set_pending_exception (&error))
4206 return NULL;
4207 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4210 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4211 handle_parent:
4212 mono_class_setup_methods (klass);
4213 mono_class_setup_vtable (klass);
4214 if (mono_class_has_failure (klass))
4215 goto loader_error;
4217 iter = NULL;
4218 while ((prop = mono_class_get_properties (klass, &iter))) {
4219 match = 0;
4220 method = prop->get;
4221 if (!method)
4222 method = prop->set;
4223 if (method)
4224 flags = method->flags;
4225 else
4226 flags = 0;
4227 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4228 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4229 if (bflags & BFLAGS_Public)
4230 match++;
4231 } else if (bflags & BFLAGS_NonPublic) {
4232 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4233 property_accessor_nonpublic(prop->set, startklass == klass)) {
4234 match++;
4237 if (!match)
4238 continue;
4239 match = 0;
4240 if (flags & METHOD_ATTRIBUTE_STATIC) {
4241 if (bflags & BFLAGS_Static)
4242 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4243 match++;
4244 } else {
4245 if (bflags & BFLAGS_Instance)
4246 match++;
4249 if (!match)
4250 continue;
4251 match = 0;
4253 if (name != NULL) {
4254 if (compare_func (propname, prop->name))
4255 continue;
4258 if (g_hash_table_lookup (properties, prop))
4259 continue;
4261 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4262 if (!pr)
4263 goto failure;
4264 mono_ptr_array_append (tmp_array, pr);
4266 g_hash_table_insert (properties, prop, prop);
4268 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4269 goto handle_parent;
4271 g_hash_table_destroy (properties);
4272 g_free (propname);
4274 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4275 if (!is_ok (&error))
4276 goto failure;
4277 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4278 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4280 mono_ptr_array_destroy (tmp_array);
4282 return res;
4286 loader_error:
4287 if (mono_class_has_failure (klass))
4288 mono_error_set_for_class_failure (&error, klass);
4290 failure:
4291 if (properties)
4292 g_hash_table_destroy (properties);
4293 if (name)
4294 g_free (propname);
4295 mono_ptr_array_destroy (tmp_array);
4297 mono_error_set_pending_exception (&error);
4299 return NULL;
4302 static guint
4303 event_hash (gconstpointer data)
4305 MonoEvent *event = (MonoEvent*)data;
4307 return g_str_hash (event->name);
4310 static gboolean
4311 event_equal (MonoEvent *event1, MonoEvent *event2)
4313 // Events are hide-by-name
4314 return g_str_equal (event1->name, event2->name);
4317 ICALL_EXPORT MonoArray*
4318 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4320 MonoError error;
4321 MonoDomain *domain;
4322 MonoClass *startklass, *klass;
4323 MonoArray *res;
4324 MonoMethod *method;
4325 MonoEvent *event;
4326 int i, match;
4327 gpointer iter;
4328 char *utf8_name = NULL;
4329 int (*compare_func) (const char *s1, const char *s2) = NULL;
4330 GHashTable *events = NULL;
4331 MonoPtrArray tmp_array;
4333 mono_error_init (&error);
4335 domain = mono_object_domain (type);
4336 if (type->type->byref) {
4337 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4338 mono_error_set_pending_exception (&error);
4339 return res;
4342 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4344 klass = startklass = mono_class_from_mono_type (type->type);
4346 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4347 handle_parent:
4348 mono_class_setup_methods (klass);
4349 mono_class_setup_vtable (klass);
4350 if (mono_class_has_failure (klass))
4351 goto loader_error;
4353 iter = NULL;
4354 while ((event = mono_class_get_events (klass, &iter))) {
4355 match = 0;
4356 method = event->add;
4357 if (!method)
4358 method = event->remove;
4359 if (!method)
4360 method = event->raise;
4361 if (method) {
4362 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4363 if (bflags & BFLAGS_Public)
4364 match++;
4365 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4366 if (bflags & BFLAGS_NonPublic)
4367 match++;
4370 else
4371 if (bflags & BFLAGS_NonPublic)
4372 match ++;
4373 if (!match)
4374 continue;
4375 match = 0;
4376 if (method) {
4377 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4378 if (bflags & BFLAGS_Static)
4379 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4380 match++;
4381 } else {
4382 if (bflags & BFLAGS_Instance)
4383 match++;
4386 else
4387 if (bflags & BFLAGS_Instance)
4388 match ++;
4389 if (!match)
4390 continue;
4392 if (name != NULL) {
4393 if (utf8_name == NULL) {
4394 utf8_name = mono_string_to_utf8_checked (name, &error);
4395 if (!is_ok (&error))
4396 goto failure;
4397 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4400 if (compare_func (event->name, utf8_name))
4401 continue;
4404 if (g_hash_table_lookup (events, event))
4405 continue;
4407 MonoReflectionEvent *ev_obj;
4408 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4409 if (!ev_obj)
4410 goto failure;
4411 mono_ptr_array_append (tmp_array, ev_obj);
4413 g_hash_table_insert (events, event, event);
4415 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4416 goto handle_parent;
4418 g_hash_table_destroy (events);
4420 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4421 if (!is_ok (&error))
4422 goto failure;
4424 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4425 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4427 mono_ptr_array_destroy (tmp_array);
4429 if (utf8_name != NULL)
4430 g_free (utf8_name);
4432 return res;
4434 loader_error:
4435 if (mono_class_has_failure (klass))
4436 mono_error_set_for_class_failure (&error, klass);
4438 failure:
4440 if (events != NULL)
4441 g_hash_table_destroy (events);
4442 if (utf8_name != NULL)
4443 g_free (utf8_name);
4445 mono_ptr_array_destroy (tmp_array);
4447 mono_error_set_pending_exception (&error);
4448 return NULL;
4451 ICALL_EXPORT MonoArray*
4452 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4454 MonoError error;
4455 MonoReflectionType *rt;
4456 MonoDomain *domain;
4457 MonoClass *klass;
4458 MonoArray *res = NULL;
4459 int i, match;
4460 MonoClass *nested;
4461 gpointer iter;
4462 char *str = NULL;
4463 MonoPtrArray tmp_array;
4465 mono_error_init (&error);
4467 domain = ((MonoObject *)type)->vtable->domain;
4468 if (type->type->byref) {
4469 MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
4470 mono_error_set_pending_exception (&error);
4471 return result;
4473 klass = mono_class_from_mono_type (type->type);
4476 * If a nested type is generic, return its generic type definition.
4477 * Note that this means that the return value is essentially the set
4478 * of nested types of the generic type definition of @klass.
4480 * A note in MSDN claims that a generic type definition can have
4481 * nested types that aren't generic. In any case, the container of that
4482 * nested type would be the generic type definition.
4484 if (klass->generic_class)
4485 klass = klass->generic_class->container_class;
4487 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4488 iter = NULL;
4489 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4490 match = 0;
4491 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4492 if (bflags & BFLAGS_Public)
4493 match++;
4494 } else {
4495 if (bflags & BFLAGS_NonPublic)
4496 match++;
4498 if (!match)
4499 continue;
4501 if (name != NULL) {
4502 if (str == NULL) {
4503 str = mono_string_to_utf8_checked (name, &error);
4504 if (!is_ok (&error))
4505 goto leave;
4506 mono_identifier_unescape_type_name_chars (str);
4509 if (strcmp (nested->name, str))
4510 continue;
4513 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4514 if (!is_ok (&error))
4515 goto leave;
4517 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4520 res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
4521 if (!is_ok (&error))
4522 goto leave;
4524 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4525 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4527 leave:
4528 mono_ptr_array_destroy (tmp_array);
4530 g_free (str);
4532 mono_error_set_pending_exception (&error);
4533 return res;
4536 ICALL_EXPORT MonoReflectionType*
4537 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4539 MonoError error;
4540 MonoReflectionType *ret;
4541 gchar *str;
4542 MonoType *type = NULL;
4543 MonoTypeNameParse info;
4544 gboolean type_resolve;
4546 /* On MS.NET, this does not fire a TypeResolve event */
4547 type_resolve = TRUE;
4548 str = mono_string_to_utf8_checked (name, &error);
4549 if (mono_error_set_pending_exception (&error))
4550 return NULL;
4551 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4552 if (!mono_reflection_parse_type (str, &info)) {
4553 g_free (str);
4554 mono_reflection_free_type_info (&info);
4555 if (throwOnError) {
4556 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4557 return NULL;
4559 /*g_print ("failed parse\n");*/
4560 return NULL;
4563 if (info.assembly.name) {
4564 g_free (str);
4565 mono_reflection_free_type_info (&info);
4566 if (throwOnError) {
4567 /* 1.0 and 2.0 throw different exceptions */
4568 if (mono_defaults.generic_ilist_class)
4569 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4570 else
4571 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4572 return NULL;
4574 return NULL;
4577 if (module != NULL) {
4578 if (module->image) {
4579 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4580 if (!is_ok (&error)) {
4581 g_free (str);
4582 mono_reflection_free_type_info (&info);
4583 mono_error_set_pending_exception (&error);
4584 return NULL;
4586 } else
4587 type = NULL;
4589 else
4590 if (assembly_is_dynamic (assembly->assembly)) {
4591 /* Enumerate all modules */
4592 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4593 int i;
4595 type = NULL;
4596 if (abuilder->modules) {
4597 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4598 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4599 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4600 if (!is_ok (&error)) {
4601 g_free (str);
4602 mono_reflection_free_type_info (&info);
4603 mono_error_set_pending_exception (&error);
4604 return NULL;
4606 if (type)
4607 break;
4611 if (!type && abuilder->loaded_modules) {
4612 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4613 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4614 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4615 if (!is_ok (&error)) {
4616 g_free (str);
4617 mono_reflection_free_type_info (&info);
4618 mono_error_set_pending_exception (&error);
4619 return NULL;
4621 if (type)
4622 break;
4626 else {
4627 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4628 if (!is_ok (&error)) {
4629 g_free (str);
4630 mono_reflection_free_type_info (&info);
4631 mono_error_set_pending_exception (&error);
4632 return NULL;
4635 g_free (str);
4636 mono_reflection_free_type_info (&info);
4637 if (!type) {
4638 MonoException *e = NULL;
4640 if (throwOnError)
4641 e = mono_get_exception_type_load (name, NULL);
4643 if (e != NULL)
4644 mono_set_pending_exception (e);
4645 return NULL;
4648 if (type->type == MONO_TYPE_CLASS) {
4649 MonoClass *klass = mono_type_get_class (type);
4651 /* need to report exceptions ? */
4652 if (throwOnError && mono_class_has_failure (klass)) {
4653 /* report SecurityException (or others) that occured when loading the assembly */
4654 MonoException *exc = mono_class_get_exception_for_failure (klass);
4655 mono_set_pending_exception (exc);
4656 return NULL;
4660 /* g_print ("got it\n"); */
4661 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4662 mono_error_set_pending_exception (&error);
4664 return ret;
4667 static gboolean
4668 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4670 gchar *content;
4671 gchar *shadow_ini_file;
4672 gsize len;
4674 /* Check for shadow-copied assembly */
4675 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4676 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4677 content = NULL;
4678 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4679 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4680 if (content) {
4681 g_free (content);
4682 content = NULL;
4685 g_free (shadow_ini_file);
4686 if (content != NULL) {
4687 if (*filename)
4688 g_free (*filename);
4689 *filename = content;
4690 return TRUE;
4693 return FALSE;
4696 ICALL_EXPORT MonoString *
4697 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4699 MonoDomain *domain = mono_object_domain (assembly);
4700 MonoAssembly *mass = assembly->assembly;
4701 MonoString *res = NULL;
4702 gchar *uri;
4703 gchar *absolute;
4704 gchar *dirname;
4706 if (g_path_is_absolute (mass->image->name)) {
4707 absolute = g_strdup (mass->image->name);
4708 dirname = g_path_get_dirname (absolute);
4709 } else {
4710 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4711 dirname = g_strdup (mass->basedir);
4714 replace_shadow_path (domain, dirname, &absolute);
4715 g_free (dirname);
4716 #if HOST_WIN32
4718 gint i;
4719 for (i = strlen (absolute) - 1; i >= 0; i--)
4720 if (absolute [i] == '\\')
4721 absolute [i] = '/';
4723 #endif
4724 if (escaped) {
4725 uri = g_filename_to_uri (absolute, NULL, NULL);
4726 } else {
4727 const char *prepend = "file://";
4728 #if HOST_WIN32
4729 if (*absolute == '/' && *(absolute + 1) == '/') {
4730 prepend = "file:";
4731 } else {
4732 prepend = "file:///";
4734 #endif
4735 uri = g_strconcat (prepend, absolute, NULL);
4738 if (uri) {
4739 res = mono_string_new (domain, uri);
4740 g_free (uri);
4742 g_free (absolute);
4743 return res;
4746 ICALL_EXPORT MonoBoolean
4747 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4749 MonoAssembly *mass = assembly->assembly;
4751 return mass->in_gac;
4754 ICALL_EXPORT MonoReflectionAssembly*
4755 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4757 MonoError error;
4758 gchar *name;
4759 MonoAssembly *res;
4760 MonoImageOpenStatus status;
4761 MonoReflectionAssembly* result = NULL;
4763 name = mono_string_to_utf8_checked (mname, &error);
4764 if (mono_error_set_pending_exception (&error))
4765 return NULL;
4766 res = mono_assembly_load_with_partial_name (name, &status);
4768 g_free (name);
4770 if (res == NULL)
4771 return NULL;
4772 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4773 if (!result)
4774 mono_error_set_pending_exception (&error);
4775 return result;
4778 ICALL_EXPORT MonoString *
4779 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4781 MonoDomain *domain = mono_object_domain (assembly);
4782 MonoString *res;
4784 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4786 return res;
4789 ICALL_EXPORT MonoBoolean
4790 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4792 return assembly->assembly->ref_only;
4795 ICALL_EXPORT MonoString *
4796 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4798 MonoDomain *domain = mono_object_domain (assembly);
4800 return mono_string_new (domain, assembly->assembly->image->version);
4803 ICALL_EXPORT MonoReflectionMethod*
4804 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4806 MonoError error;
4807 MonoReflectionMethod *res = NULL;
4808 MonoMethod *method;
4810 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4812 if (!token)
4813 return NULL;
4814 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4815 if (!mono_error_ok (&error))
4816 goto leave;
4818 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4820 leave:
4821 if (!mono_error_ok (&error))
4822 mono_error_set_pending_exception (&error);
4823 return res;
4826 ICALL_EXPORT MonoReflectionModule*
4827 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4829 MonoError error;
4830 MonoReflectionModule *result = NULL;
4831 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4832 if (!mono_error_ok (&error))
4833 mono_error_set_pending_exception (&error);
4834 return result;
4837 ICALL_EXPORT MonoArray*
4838 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4840 MonoError error;
4841 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4842 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4843 if (mono_error_set_pending_exception (&error))
4844 return NULL;
4845 int i;
4846 const char *val;
4848 for (i = 0; i < table->rows; ++i) {
4849 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4850 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4852 return result;
4855 ICALL_EXPORT MonoString*
4856 ves_icall_System_Reflection_Assembly_GetAotId ()
4858 int i;
4859 guint8 aotid_sum = 0;
4860 MonoDomain* domain = mono_domain_get ();
4862 if (!domain->entry_assembly || !domain->entry_assembly->image)
4863 return NULL;
4865 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4867 for (i = 0; i < 16; ++i)
4868 aotid_sum |= (*aotid)[i];
4870 if (aotid_sum == 0)
4871 return NULL;
4873 return mono_string_new (domain, mono_guid_to_string((guint8*) aotid));
4876 static MonoObject*
4877 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4879 static MonoMethod *create_version = NULL;
4880 MonoObject *result;
4881 gpointer args [4];
4883 mono_error_init (error);
4886 if (!create_version) {
4887 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4888 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4889 g_assert (create_version);
4890 mono_method_desc_free (desc);
4893 args [0] = &major;
4894 args [1] = &minor;
4895 args [2] = &build;
4896 args [3] = &revision;
4897 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4898 return_val_if_nok (error, NULL);
4900 mono_runtime_invoke_checked (create_version, result, args, error);
4901 return_val_if_nok (error, NULL);
4903 return result;
4906 ICALL_EXPORT MonoArray*
4907 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4909 MonoError error;
4910 MonoArray *result;
4911 MonoDomain *domain = mono_object_domain (assembly);
4912 int i, count = 0;
4913 static MonoMethod *create_culture = NULL;
4914 MonoImage *image = assembly->assembly->image;
4915 MonoTableInfo *t;
4916 MonoObject *o;
4918 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4919 count = t->rows;
4921 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4922 if (mono_error_set_pending_exception (&error))
4923 return NULL;
4926 if (count > 0 && !create_culture) {
4927 MonoMethodDesc *desc = mono_method_desc_new (
4928 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4929 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4930 g_assert (create_culture);
4931 mono_method_desc_free (desc);
4934 for (i = 0; i < count; i++) {
4935 MonoObject *version;
4936 MonoReflectionAssemblyName *aname;
4937 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4939 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4941 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4942 domain, mono_class_get_assembly_name_class (), &error);
4943 if (mono_error_set_pending_exception (&error))
4944 return NULL;
4946 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4948 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4949 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4950 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4951 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4952 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4953 aname->versioncompat = 1; /* SameMachine (default) */
4954 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4956 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4957 if (mono_error_set_pending_exception (&error))
4958 return NULL;
4960 MONO_OBJECT_SETREF (aname, version, version);
4962 if (create_culture) {
4963 gpointer args [2];
4964 MonoBoolean assembly_ref = 1;
4965 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4966 args [1] = &assembly_ref;
4968 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4969 if (mono_error_set_pending_exception (&error))
4970 return NULL;
4972 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4975 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4976 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4977 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4979 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4980 /* public key token isn't copied - the class library will
4981 automatically generate it from the public key if required */
4982 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4983 if (mono_error_set_pending_exception (&error))
4984 return NULL;
4986 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4987 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4988 } else {
4989 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4990 if (mono_error_set_pending_exception (&error))
4991 return NULL;
4993 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4994 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4996 } else {
4997 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4998 if (mono_error_set_pending_exception (&error))
4999 return NULL;
5001 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5004 /* note: this function doesn't return the codebase on purpose (i.e. it can
5005 be used under partial trust as path information isn't present). */
5007 mono_array_setref (result, i, aname);
5009 return result;
5012 /* move this in some file in mono/util/ */
5013 static char *
5014 g_concat_dir_and_file (const char *dir, const char *file)
5016 g_return_val_if_fail (dir != NULL, NULL);
5017 g_return_val_if_fail (file != NULL, NULL);
5020 * If the directory name doesn't have a / on the end, we need
5021 * to add one so we get a proper path to the file
5023 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5024 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5025 else
5026 return g_strconcat (dir, file, NULL);
5029 ICALL_EXPORT void *
5030 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5032 MonoError error;
5033 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5034 guint32 i;
5035 guint32 cols [MONO_MANIFEST_SIZE];
5036 guint32 impl, file_idx;
5037 const char *val;
5038 MonoImage *module;
5040 char *n = mono_string_to_utf8_checked (name, &error);
5041 if (mono_error_set_pending_exception (&error))
5042 return NULL;
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_checked (name, &error);
5091 if (mono_error_set_pending_exception (&error))
5092 return FALSE;
5093 for (i = 0; i < table->rows; ++i) {
5094 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5095 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5096 if (strcmp (val, n) == 0)
5097 break;
5099 g_free (n);
5100 if (i == table->rows)
5101 return FALSE;
5103 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5104 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5106 else {
5107 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5108 case MONO_IMPLEMENTATION_FILE:
5109 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5110 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5111 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5112 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5113 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5114 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5115 info->location = 0;
5116 else
5117 info->location = RESOURCE_LOCATION_EMBEDDED;
5118 break;
5120 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5121 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5122 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5123 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5124 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5125 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5126 g_free (msg);
5127 mono_set_pending_exception (ex);
5128 return FALSE;
5130 MonoReflectionAssembly *assm_obj;
5131 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5132 if (!assm_obj) {
5133 mono_error_set_pending_exception (&error);
5134 return FALSE;
5136 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5138 /* Obtain info recursively */
5139 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5140 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5141 break;
5143 case MONO_IMPLEMENTATION_EXP_TYPE:
5144 g_assert_not_reached ();
5145 break;
5149 return TRUE;
5152 ICALL_EXPORT MonoObject*
5153 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5155 MonoError error;
5156 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5157 MonoArray *result = NULL;
5158 int i, count;
5159 const char *val;
5160 char *n;
5162 /* check hash if needed */
5163 if (name) {
5164 n = mono_string_to_utf8_checked (name, &error);
5165 if (mono_error_set_pending_exception (&error))
5166 return NULL;
5168 for (i = 0; i < table->rows; ++i) {
5169 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5170 if (strcmp (val, n) == 0) {
5171 MonoString *fn;
5172 g_free (n);
5173 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5174 fn = mono_string_new (mono_object_domain (assembly), n);
5175 g_free (n);
5176 return (MonoObject*)fn;
5179 g_free (n);
5180 return NULL;
5183 count = 0;
5184 for (i = 0; i < table->rows; ++i) {
5185 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5186 count ++;
5189 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5190 if (mono_error_set_pending_exception (&error))
5191 return NULL;
5194 count = 0;
5195 for (i = 0; i < table->rows; ++i) {
5196 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5197 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5198 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5199 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5200 g_free (n);
5201 count ++;
5204 return (MonoObject*)result;
5207 ICALL_EXPORT MonoArray*
5208 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5210 MonoError error;
5211 MonoDomain *domain = mono_domain_get();
5212 MonoArray *res;
5213 MonoClass *klass;
5214 int i, j, file_count = 0;
5215 MonoImage **modules;
5216 guint32 module_count, real_module_count;
5217 MonoTableInfo *table;
5218 guint32 cols [MONO_FILE_SIZE];
5219 MonoImage *image = assembly->assembly->image;
5221 g_assert (image != NULL);
5222 g_assert (!assembly_is_dynamic (assembly->assembly));
5224 table = &image->tables [MONO_TABLE_FILE];
5225 file_count = table->rows;
5227 modules = image->modules;
5228 module_count = image->module_count;
5230 real_module_count = 0;
5231 for (i = 0; i < module_count; ++i)
5232 if (modules [i])
5233 real_module_count ++;
5235 klass = mono_class_get_module_class ();
5236 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5237 if (mono_error_set_pending_exception (&error))
5238 return NULL;
5240 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5241 if (mono_error_set_pending_exception (&error))
5242 return NULL;
5244 mono_array_setref (res, 0, image_obj);
5245 j = 1;
5246 for (i = 0; i < module_count; ++i)
5247 if (modules [i]) {
5248 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5249 if (mono_error_set_pending_exception (&error))
5250 return NULL;
5251 mono_array_setref (res, j, rm);
5252 ++j;
5255 for (i = 0; i < file_count; ++i, ++j) {
5256 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5257 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5258 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5259 if (mono_error_set_pending_exception (&error))
5260 return NULL;
5261 mono_array_setref (res, j, rm);
5263 else {
5264 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5265 if (!m) {
5266 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5267 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5268 return NULL;
5270 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5271 if (mono_error_set_pending_exception (&error))
5272 return NULL;
5273 mono_array_setref (res, j, rm);
5277 return res;
5280 ICALL_EXPORT MonoReflectionMethod*
5281 ves_icall_GetCurrentMethod (void)
5283 MonoReflectionMethod *res = NULL;
5284 MonoError error;
5286 MonoMethod *m = mono_method_get_last_managed ();
5288 if (!m) {
5289 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5290 return NULL;
5293 while (m->is_inflated)
5294 m = ((MonoMethodInflated*)m)->declaring;
5296 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5297 mono_error_set_pending_exception (&error);
5298 return res;
5302 static MonoMethod*
5303 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5305 int offset = -1, i;
5306 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5307 MonoError error;
5308 MonoMethod *result;
5309 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5310 //method is inflated, we should inflate it on the other class
5311 MonoGenericContext ctx;
5312 ctx.method_inst = inflated->context.method_inst;
5313 ctx.class_inst = inflated->context.class_inst;
5314 if (klass->generic_class)
5315 ctx.class_inst = klass->generic_class->context.class_inst;
5316 else if (klass->generic_container)
5317 ctx.class_inst = klass->generic_container->context.class_inst;
5318 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5319 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5320 return result;
5323 mono_class_setup_methods (method->klass);
5324 if (mono_class_has_failure (method->klass))
5325 return NULL;
5326 for (i = 0; i < method->klass->method.count; ++i) {
5327 if (method->klass->methods [i] == method) {
5328 offset = i;
5329 break;
5332 mono_class_setup_methods (klass);
5333 if (mono_class_has_failure (klass))
5334 return NULL;
5335 g_assert (offset >= 0 && offset < klass->method.count);
5336 return klass->methods [offset];
5339 ICALL_EXPORT MonoReflectionMethod*
5340 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5342 MonoReflectionMethod *res = NULL;
5343 MonoError error;
5344 MonoClass *klass;
5345 if (type) {
5346 klass = mono_class_from_mono_type (type);
5347 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5348 return NULL;
5349 if (method->klass != klass) {
5350 method = mono_method_get_equivalent_method (method, klass);
5351 if (!method)
5352 return NULL;
5354 } else
5355 klass = method->klass;
5356 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5357 mono_error_set_pending_exception (&error);
5358 return res;
5361 ICALL_EXPORT MonoReflectionMethodBody*
5362 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5364 MonoError error;
5365 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5366 mono_error_set_pending_exception (&error);
5367 return result;
5370 ICALL_EXPORT MonoReflectionAssembly*
5371 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5373 MonoError error;
5374 MonoReflectionAssembly *result;
5375 MonoMethod *dest = NULL;
5377 mono_stack_walk_no_il (get_executing, &dest);
5378 g_assert (dest);
5379 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5380 if (!result)
5381 mono_error_set_pending_exception (&error);
5382 return result;
5386 ICALL_EXPORT MonoReflectionAssembly*
5387 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5389 MonoError error;
5390 MonoReflectionAssembly *result;
5391 MonoDomain* domain = mono_domain_get ();
5393 if (!domain->entry_assembly)
5394 return NULL;
5396 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5397 if (!result)
5398 mono_error_set_pending_exception (&error);
5399 return result;
5402 ICALL_EXPORT MonoReflectionAssembly*
5403 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5405 MonoError error;
5406 MonoMethod *m;
5407 MonoMethod *dest;
5408 MonoReflectionAssembly *result;
5410 dest = NULL;
5411 mono_stack_walk_no_il (get_executing, &dest);
5412 m = dest;
5413 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5414 if (!dest)
5415 dest = m;
5416 if (!m) {
5417 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5418 return NULL;
5420 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5421 if (!result)
5422 mono_error_set_pending_exception (&error);
5423 return result;
5426 ICALL_EXPORT MonoString *
5427 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5428 gboolean assembly_qualified)
5430 MonoDomain *domain = mono_object_domain (object);
5431 MonoTypeNameFormat format;
5432 MonoString *res;
5433 gchar *name;
5435 if (full_name)
5436 format = assembly_qualified ?
5437 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5438 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5439 else
5440 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5442 name = mono_type_get_name_full (object->type, format);
5443 if (!name)
5444 return NULL;
5446 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5447 g_free (name);
5448 return NULL;
5451 res = mono_string_new (domain, name);
5452 g_free (name);
5454 return res;
5457 ICALL_EXPORT int
5458 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5460 MonoError error;
5461 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5463 mono_class_init_checked (klass, &error);
5464 mono_error_set_pending_exception (&error);
5465 return mono_security_core_clr_class_level (klass);
5468 ICALL_EXPORT int
5469 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5471 MonoClassField *field = rfield->field;
5472 return mono_security_core_clr_field_level (field, TRUE);
5475 ICALL_EXPORT int
5476 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5478 MonoMethod *method = rfield->method;
5479 return mono_security_core_clr_method_level (method, TRUE);
5482 static void
5483 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)
5485 static MonoMethod *create_culture = NULL;
5486 MonoObject *obj;
5487 gpointer args [2];
5488 guint32 pkey_len;
5489 const char *pkey_ptr;
5490 gchar *codebase;
5491 MonoBoolean assembly_ref = 0;
5493 mono_error_init (error);
5495 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5496 aname->major = name->major;
5497 aname->minor = name->minor;
5498 aname->build = name->build;
5499 aname->flags = name->flags;
5500 aname->revision = name->revision;
5501 aname->hashalg = name->hash_alg;
5502 aname->versioncompat = 1; /* SameMachine (default) */
5503 aname->processor_architecture = name->arch;
5505 if (by_default_version) {
5506 MonoObject *version;
5508 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5509 return_if_nok (error);
5511 MONO_OBJECT_SETREF (aname, version, version);
5514 codebase = NULL;
5515 if (absolute != NULL && *absolute != '\0') {
5516 const gchar *prepend = "file://";
5517 gchar *result;
5519 codebase = g_strdup (absolute);
5521 #if HOST_WIN32
5523 gint i;
5524 for (i = strlen (codebase) - 1; i >= 0; i--)
5525 if (codebase [i] == '\\')
5526 codebase [i] = '/';
5528 if (*codebase == '/' && *(codebase + 1) == '/') {
5529 prepend = "file:";
5530 } else {
5531 prepend = "file:///";
5534 #endif
5535 result = g_strconcat (prepend, codebase, NULL);
5536 g_free (codebase);
5537 codebase = result;
5540 if (codebase) {
5541 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5542 g_free (codebase);
5545 if (!create_culture) {
5546 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5547 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5548 g_assert (create_culture);
5549 mono_method_desc_free (desc);
5552 if (name->culture) {
5553 args [0] = mono_string_new (domain, name->culture);
5554 args [1] = &assembly_ref;
5556 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5557 return_if_nok (error);
5559 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5562 if (name->public_key) {
5563 pkey_ptr = (char*)name->public_key;
5564 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5566 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5567 return_if_nok (error);
5568 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5569 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5570 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5571 } else if (default_publickey) {
5572 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5573 return_if_nok (error);
5574 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5575 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5578 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5579 if (name->public_key_token [0]) {
5580 int i, j;
5581 char *p;
5583 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5584 return_if_nok (error);
5586 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5587 p = mono_array_addr (keyToken, char, 0);
5589 for (i = 0, j = 0; i < 8; i++) {
5590 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5591 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5592 p++;
5594 } else if (default_token) {
5595 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5596 return_if_nok (error);
5597 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5601 ICALL_EXPORT MonoString *
5602 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5604 MonoDomain *domain = mono_object_domain (assembly);
5605 MonoAssembly *mass = assembly->assembly;
5606 MonoString *res;
5607 gchar *name;
5609 name = mono_stringify_assembly_name (&mass->aname);
5610 res = mono_string_new (domain, name);
5611 g_free (name);
5613 return res;
5616 ICALL_EXPORT void
5617 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5619 MonoError error;
5620 gchar *absolute, *dirname;
5621 MonoAssembly *mass = assembly->assembly;
5623 /* XXX this is duplicated code to compute the codebase URI, unify it */
5624 if (g_path_is_absolute (mass->image->name)) {
5625 absolute = g_strdup (mass->image->name);
5626 dirname = g_path_get_dirname (absolute);
5627 } else {
5628 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5629 dirname = g_strdup (mass->basedir);
5632 replace_shadow_path (mono_object_domain (assembly), dirname, &absolute);
5633 g_free (dirname);
5635 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5636 mono_error_set_pending_exception (&error);
5638 g_free (absolute);
5641 ICALL_EXPORT void
5642 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5644 MonoError error;
5645 char *filename;
5646 MonoImageOpenStatus status = MONO_IMAGE_OK;
5647 gboolean res;
5648 MonoImage *image;
5649 MonoAssemblyName name;
5650 char *dirname;
5652 filename = mono_string_to_utf8_checked (fname, &error);
5653 if (mono_error_set_pending_exception (&error))
5654 return;
5656 dirname = g_path_get_dirname (filename);
5657 replace_shadow_path (mono_domain_get (), dirname, &filename);
5658 g_free (dirname);
5660 image = mono_image_open (filename, &status);
5662 if (!image){
5663 MonoException *exc;
5665 g_free (filename);
5666 if (status == MONO_IMAGE_IMAGE_INVALID)
5667 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5668 else
5669 exc = mono_get_exception_file_not_found2 (NULL, fname);
5670 mono_set_pending_exception (exc);
5671 return;
5674 res = mono_assembly_fill_assembly_name (image, &name);
5675 if (!res) {
5676 mono_image_close (image);
5677 g_free (filename);
5678 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5679 return;
5682 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5683 mono_error_set_pending_exception (&error);
5685 mono_image_close (image);
5686 g_free (filename);
5689 ICALL_EXPORT MonoBoolean
5690 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5691 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5693 MonoBoolean result = FALSE;
5694 MonoDeclSecurityEntry entry;
5696 /* SecurityAction.RequestMinimum */
5697 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5698 *minimum = entry.blob;
5699 *minLength = entry.size;
5700 result = TRUE;
5702 /* SecurityAction.RequestOptional */
5703 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5704 *optional = entry.blob;
5705 *optLength = entry.size;
5706 result = TRUE;
5708 /* SecurityAction.RequestRefuse */
5709 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5710 *refused = entry.blob;
5711 *refLength = entry.size;
5712 result = TRUE;
5715 return result;
5718 static gboolean
5719 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5721 guint32 attrs, visibility;
5722 do {
5723 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5724 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5725 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5726 return FALSE;
5728 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5730 return TRUE;
5733 static MonoArray*
5734 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5736 MonoReflectionType *rt;
5737 MonoArray *res;
5738 MonoClass *klass;
5739 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5740 int i, count;
5742 mono_error_init (error);
5744 /* we start the count from 1 because we skip the special type <Module> */
5745 if (exportedOnly) {
5746 count = 0;
5747 for (i = 1; i < tdef->rows; ++i) {
5748 if (mono_module_type_is_visible (tdef, image, i + 1))
5749 count++;
5751 } else {
5752 count = tdef->rows - 1;
5754 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5755 return_val_if_nok (error, NULL);
5756 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5757 return_val_if_nok (error, NULL);
5758 count = 0;
5759 for (i = 1; i < tdef->rows; ++i) {
5760 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5761 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5763 if (klass) {
5764 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5765 return_val_if_nok (error, NULL);
5767 mono_array_setref (res, count, rt);
5768 } else {
5769 MonoException *ex = mono_error_convert_to_exception (error);
5770 mono_array_setref (*exceptions, count, ex);
5772 count++;
5776 return res;
5779 ICALL_EXPORT MonoArray*
5780 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5782 MonoError error;
5783 MonoArray *res = NULL;
5784 MonoArray *exceptions = NULL;
5785 MonoImage *image = NULL;
5786 MonoTableInfo *table = NULL;
5787 MonoDomain *domain;
5788 GList *list = NULL;
5789 int i, len, ex_count;
5791 domain = mono_object_domain (assembly);
5793 g_assert (!assembly_is_dynamic (assembly->assembly));
5794 image = assembly->assembly->image;
5795 table = &image->tables [MONO_TABLE_FILE];
5796 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5797 if (mono_error_set_pending_exception (&error))
5798 return NULL;
5800 /* Append data from all modules in the assembly */
5801 for (i = 0; i < table->rows; ++i) {
5802 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5803 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5804 if (loaded_image) {
5805 MonoArray *ex2;
5806 MonoArray *res2;
5808 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5809 if (mono_error_set_pending_exception (&error))
5810 return NULL;
5813 /* Append the new types to the end of the array */
5814 if (mono_array_length (res2) > 0) {
5815 guint32 len1, len2;
5816 MonoArray *res3, *ex3;
5818 len1 = mono_array_length (res);
5819 len2 = mono_array_length (res2);
5821 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5822 if (mono_error_set_pending_exception (&error))
5823 return NULL;
5824 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5825 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5826 res = res3;
5828 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5829 if (mono_error_set_pending_exception (&error))
5830 return NULL;
5831 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5832 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5833 exceptions = ex3;
5839 /* the ReflectionTypeLoadException must have all the types (Types property),
5840 * NULL replacing types which throws an exception. The LoaderException must
5841 * contain all exceptions for NULL items.
5844 len = mono_array_length (res);
5846 ex_count = 0;
5847 for (i = 0; i < len; i++) {
5848 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5849 MonoClass *klass;
5851 if (t) {
5852 klass = mono_type_get_class (t->type);
5853 if ((klass != NULL) && mono_class_has_failure (klass)) {
5854 /* keep the class in the list */
5855 list = g_list_append (list, klass);
5856 /* and replace Type with NULL */
5857 mono_array_setref (res, i, NULL);
5859 } else {
5860 ex_count ++;
5864 if (list || ex_count) {
5865 GList *tmp = NULL;
5866 MonoException *exc = NULL;
5867 MonoArray *exl = NULL;
5868 int j, length = g_list_length (list) + ex_count;
5870 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5871 if (mono_error_set_pending_exception (&error)) {
5872 g_list_free (list);
5873 return NULL;
5875 /* Types for which mono_class_get_checked () succeeded */
5876 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5877 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5878 mono_array_setref (exl, i, exc);
5880 /* Types for which it don't */
5881 for (j = 0; j < mono_array_length (exceptions); ++j) {
5882 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5883 if (exc) {
5884 g_assert (i < length);
5885 mono_array_setref (exl, i, exc);
5886 i ++;
5889 g_list_free (list);
5890 list = NULL;
5892 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5893 if (!is_ok (&error)) {
5894 mono_error_set_pending_exception (&error);
5895 return NULL;
5897 mono_set_pending_exception (exc);
5898 return NULL;
5901 return res;
5904 ICALL_EXPORT gboolean
5905 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5907 MonoError error;
5908 MonoAssemblyName aname;
5909 MonoDomain *domain = mono_object_domain (name);
5910 char *val;
5911 gboolean is_version_defined;
5912 gboolean is_token_defined;
5914 aname.public_key = NULL;
5915 val = mono_string_to_utf8_checked (assname, &error);
5916 if (mono_error_set_pending_exception (&error))
5917 return FALSE;
5919 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5920 g_free ((guint8*) aname.public_key);
5921 g_free (val);
5922 return FALSE;
5925 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5926 mono_error_set_pending_exception (&error);
5928 mono_assembly_name_free (&aname);
5929 g_free ((guint8*) aname.public_key);
5930 g_free (val);
5932 return TRUE;
5935 ICALL_EXPORT MonoReflectionType*
5936 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5938 MonoError error;
5939 MonoReflectionType *ret;
5940 MonoDomain *domain = mono_object_domain (module);
5941 MonoClass *klass;
5943 g_assert (module->image);
5945 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5946 /* These images do not have a global type */
5947 return NULL;
5949 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5950 if (!mono_error_ok (&error)) {
5951 mono_error_set_pending_exception (&error);
5952 return NULL;
5955 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5956 if (!mono_error_ok (&error)) {
5957 mono_error_set_pending_exception (&error);
5958 return NULL;
5961 return ret;
5964 ICALL_EXPORT void
5965 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5967 /*if (module->image)
5968 mono_image_close (module->image);*/
5971 ICALL_EXPORT MonoString*
5972 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5974 MonoDomain *domain = mono_object_domain (module);
5976 g_assert (module->image);
5977 return mono_string_new (domain, module->image->guid);
5980 ICALL_EXPORT gpointer
5981 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5983 #ifdef HOST_WIN32
5984 if (module->image && module->image->is_module_handle)
5985 return module->image->raw_data;
5986 #endif
5988 return (gpointer) (-1);
5991 ICALL_EXPORT void
5992 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5994 if (image_is_dynamic (image)) {
5995 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5996 *pe_kind = dyn->pe_kind;
5997 *machine = dyn->machine;
5999 else {
6000 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
6001 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
6005 ICALL_EXPORT gint32
6006 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
6008 return (image->md_version_major << 16) | (image->md_version_minor);
6011 ICALL_EXPORT MonoArray*
6012 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
6014 MonoError error;
6015 MonoArray *exceptions;
6016 int i;
6018 if (!module->image) {
6019 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
6020 mono_error_set_pending_exception (&error);
6021 return arr;
6022 } else {
6023 MonoArray *res;
6025 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6026 if (mono_error_set_pending_exception (&error))
6027 return NULL;
6029 for (i = 0; i < mono_array_length (exceptions); ++i) {
6030 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6031 if (ex) {
6032 mono_set_pending_exception (ex);
6033 return NULL;
6036 return res;
6040 static gboolean
6041 mono_memberref_is_method (MonoImage *image, guint32 token)
6043 if (!image_is_dynamic (image)) {
6044 guint32 cols [MONO_MEMBERREF_SIZE];
6045 const char *sig;
6046 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6047 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6048 mono_metadata_decode_blob_size (sig, &sig);
6049 return (*sig != 0x6);
6050 } else {
6051 MonoError error;
6052 MonoClass *handle_class;
6054 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6055 mono_error_cleanup (&error); /* just probing, ignore error */
6056 return FALSE;
6059 return mono_defaults.methodhandle_class == handle_class;
6063 static void
6064 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6066 if (type_args)
6067 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6068 mono_array_addr (type_args, MonoType*, 0));
6069 else
6070 context->class_inst = NULL;
6071 if (method_args)
6072 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6073 mono_array_addr (method_args, MonoType*, 0));
6074 else
6075 context->method_inst = NULL;
6078 ICALL_EXPORT MonoType*
6079 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6081 MonoClass *klass;
6082 int table = mono_metadata_token_table (token);
6083 int index = mono_metadata_token_index (token);
6084 MonoGenericContext context;
6085 MonoError error;
6087 *resolve_error = ResolveTokenError_Other;
6089 /* Validate token */
6090 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6091 (table != MONO_TABLE_TYPESPEC)) {
6092 *resolve_error = ResolveTokenError_BadTable;
6093 return NULL;
6096 if (image_is_dynamic (image)) {
6097 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6098 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6099 mono_error_cleanup (&error);
6100 return klass ? &klass->byval_arg : NULL;
6103 init_generic_context_from_args (&context, type_args, method_args);
6104 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6105 mono_error_cleanup (&error);
6106 return klass ? &klass->byval_arg : NULL;
6109 if ((index <= 0) || (index > image->tables [table].rows)) {
6110 *resolve_error = ResolveTokenError_OutOfRange;
6111 return NULL;
6114 init_generic_context_from_args (&context, type_args, method_args);
6115 klass = mono_class_get_checked (image, token, &error);
6116 if (klass)
6117 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6118 if (!mono_error_ok (&error)) {
6119 mono_error_set_pending_exception (&error);
6120 return NULL;
6123 if (klass)
6124 return &klass->byval_arg;
6125 else
6126 return NULL;
6129 ICALL_EXPORT MonoMethod*
6130 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6132 MonoError error;
6133 int table = mono_metadata_token_table (token);
6134 int index = mono_metadata_token_index (token);
6135 MonoGenericContext context;
6136 MonoMethod *method;
6138 *resolve_error = ResolveTokenError_Other;
6140 /* Validate token */
6141 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6142 (table != MONO_TABLE_MEMBERREF)) {
6143 *resolve_error = ResolveTokenError_BadTable;
6144 return NULL;
6147 if (image_is_dynamic (image)) {
6148 if (table == MONO_TABLE_METHOD) {
6149 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6150 mono_error_cleanup (&error);
6151 return method;
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 = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6161 mono_error_cleanup (&error);
6162 return method;
6165 if ((index <= 0) || (index > image->tables [table].rows)) {
6166 *resolve_error = ResolveTokenError_OutOfRange;
6167 return NULL;
6169 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6170 *resolve_error = ResolveTokenError_BadTable;
6171 return NULL;
6174 init_generic_context_from_args (&context, type_args, method_args);
6175 method = mono_get_method_checked (image, token, NULL, &context, &error);
6176 mono_error_set_pending_exception (&error);
6178 return method;
6181 ICALL_EXPORT MonoString*
6182 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6184 MonoError error;
6185 int index = mono_metadata_token_index (token);
6187 *resolve_error = ResolveTokenError_Other;
6189 /* Validate token */
6190 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6191 *resolve_error = ResolveTokenError_BadTable;
6192 return NULL;
6195 if (image_is_dynamic (image)) {
6196 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6197 mono_error_cleanup (&error);
6198 return result;
6201 if ((index <= 0) || (index >= image->heap_us.size)) {
6202 *resolve_error = ResolveTokenError_OutOfRange;
6203 return NULL;
6206 /* FIXME: What to do if the index points into the middle of a string ? */
6208 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6209 mono_error_set_pending_exception (&error);
6210 return result;
6213 ICALL_EXPORT MonoClassField*
6214 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6216 MonoError error;
6217 MonoClass *klass;
6218 int table = mono_metadata_token_table (token);
6219 int index = mono_metadata_token_index (token);
6220 MonoGenericContext context;
6221 MonoClassField *field;
6223 *resolve_error = ResolveTokenError_Other;
6225 /* Validate token */
6226 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6227 *resolve_error = ResolveTokenError_BadTable;
6228 return NULL;
6231 if (image_is_dynamic (image)) {
6232 if (table == MONO_TABLE_FIELD) {
6233 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6234 mono_error_cleanup (&error);
6235 return field;
6238 if (mono_memberref_is_method (image, token)) {
6239 *resolve_error = ResolveTokenError_BadTable;
6240 return NULL;
6243 init_generic_context_from_args (&context, type_args, method_args);
6244 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6245 mono_error_cleanup (&error);
6246 return field;
6249 if ((index <= 0) || (index > image->tables [table].rows)) {
6250 *resolve_error = ResolveTokenError_OutOfRange;
6251 return NULL;
6253 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6254 *resolve_error = ResolveTokenError_BadTable;
6255 return NULL;
6258 init_generic_context_from_args (&context, type_args, method_args);
6259 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6260 mono_error_set_pending_exception (&error);
6262 return field;
6266 ICALL_EXPORT MonoObject*
6267 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6269 MonoError merror;
6270 MonoObject *ret;
6271 int table = mono_metadata_token_table (token);
6273 *error = ResolveTokenError_Other;
6275 switch (table) {
6276 case MONO_TABLE_TYPEDEF:
6277 case MONO_TABLE_TYPEREF:
6278 case MONO_TABLE_TYPESPEC: {
6279 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6280 if (t) {
6281 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6282 mono_error_set_pending_exception (&merror);
6284 return ret;
6286 else
6287 return NULL;
6289 case MONO_TABLE_METHOD:
6290 case MONO_TABLE_METHODSPEC: {
6291 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6292 if (m) {
6293 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6294 mono_error_set_pending_exception (&merror);
6296 return ret;
6297 } else
6298 return NULL;
6300 case MONO_TABLE_FIELD: {
6301 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6302 if (f) {
6303 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6304 mono_error_set_pending_exception (&merror);
6305 return ret;
6307 else
6308 return NULL;
6310 case MONO_TABLE_MEMBERREF:
6311 if (mono_memberref_is_method (image, token)) {
6312 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6313 if (m) {
6314 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6315 mono_error_set_pending_exception (&merror);
6317 return ret;
6318 } else
6319 return NULL;
6321 else {
6322 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6323 if (f) {
6324 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6325 mono_error_set_pending_exception (&merror);
6326 return ret;
6328 else
6329 return NULL;
6331 break;
6333 default:
6334 *error = ResolveTokenError_BadTable;
6337 return NULL;
6340 ICALL_EXPORT MonoArray*
6341 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6343 MonoError error;
6344 int table = mono_metadata_token_table (token);
6345 int idx = mono_metadata_token_index (token);
6346 MonoTableInfo *tables = image->tables;
6347 guint32 sig, len;
6348 const char *ptr;
6349 MonoArray *res;
6351 *resolve_error = ResolveTokenError_OutOfRange;
6353 /* FIXME: Support other tables ? */
6354 if (table != MONO_TABLE_STANDALONESIG)
6355 return NULL;
6357 if (image_is_dynamic (image))
6358 return NULL;
6360 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6361 return NULL;
6363 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6365 ptr = mono_metadata_blob_heap (image, sig);
6366 len = mono_metadata_decode_blob_size (ptr, &ptr);
6368 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6369 if (mono_error_set_pending_exception (&error))
6370 return NULL;
6371 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6372 return res;
6375 ICALL_EXPORT MonoReflectionType*
6376 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6378 MonoError error;
6379 MonoReflectionType *ret;
6380 MonoClass *klass;
6381 int isbyref = 0, rank;
6382 char *p;
6383 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6384 if (mono_error_set_pending_exception (&error))
6385 return NULL;
6387 klass = mono_class_from_mono_type (tb->type.type);
6388 p = str;
6389 /* logic taken from mono_reflection_parse_type(): keep in sync */
6390 while (*p) {
6391 switch (*p) {
6392 case '&':
6393 if (isbyref) { /* only one level allowed by the spec */
6394 g_free (str);
6395 return NULL;
6397 isbyref = 1;
6398 p++;
6400 g_free (str);
6402 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6403 mono_error_set_pending_exception (&error);
6405 return ret;
6406 case '*':
6407 klass = mono_ptr_class_get (&klass->byval_arg);
6408 mono_class_init (klass);
6409 p++;
6410 break;
6411 case '[':
6412 rank = 1;
6413 p++;
6414 while (*p) {
6415 if (*p == ']')
6416 break;
6417 if (*p == ',')
6418 rank++;
6419 else if (*p != '*') { /* '*' means unknown lower bound */
6420 g_free (str);
6421 return NULL;
6423 ++p;
6425 if (*p != ']') {
6426 g_free (str);
6427 return NULL;
6429 p++;
6430 klass = mono_array_class_get (klass, rank);
6431 mono_class_init (klass);
6432 break;
6433 default:
6434 break;
6438 g_free (str);
6440 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6441 mono_error_set_pending_exception (&error);
6443 return ret;
6446 ICALL_EXPORT MonoBoolean
6447 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6449 MonoType *type;
6450 MonoBoolean res;
6452 type = t->type;
6453 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6455 return res;
6458 static void
6459 check_for_invalid_type (MonoClass *klass, MonoError *error)
6461 char *name;
6462 MonoString *str;
6464 mono_error_init (error);
6466 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6467 return;
6469 name = mono_type_get_full_name (klass);
6470 str = mono_string_new (mono_domain_get (), name);
6471 g_free (name);
6472 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6475 ICALL_EXPORT MonoReflectionType *
6476 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6478 MonoError error;
6479 MonoReflectionType *ret;
6480 MonoClass *klass, *aklass;
6482 klass = mono_class_from_mono_type (type->type);
6483 check_for_invalid_type (klass, &error);
6484 mono_error_set_pending_exception (&error);
6486 if (rank == 0) //single dimentional array
6487 aklass = mono_array_class_get (klass, 1);
6488 else
6489 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6491 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6492 mono_error_set_pending_exception (&error);
6494 return ret;
6497 ICALL_EXPORT MonoReflectionType *
6498 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6500 MonoError error;
6501 MonoReflectionType *ret;
6502 MonoClass *klass;
6504 klass = mono_class_from_mono_type (type->type);
6505 mono_class_init_checked (klass, &error);
6506 if (mono_error_set_pending_exception (&error))
6507 return NULL;
6509 check_for_invalid_type (klass, &error);
6510 if (mono_error_set_pending_exception (&error))
6511 return NULL;
6513 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6514 mono_error_set_pending_exception (&error);
6516 return ret;
6519 ICALL_EXPORT MonoReflectionType *
6520 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6522 MonoError error;
6523 MonoReflectionType *ret;
6524 MonoClass *klass, *pklass;
6526 klass = mono_class_from_mono_type (type->type);
6527 mono_class_init_checked (klass, &error);
6528 if (mono_error_set_pending_exception (&error))
6529 return NULL;
6530 check_for_invalid_type (klass, &error);
6531 if (mono_error_set_pending_exception (&error))
6532 return NULL;
6534 pklass = mono_ptr_class_get (type->type);
6536 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6537 mono_error_set_pending_exception (&error);
6539 return ret;
6542 ICALL_EXPORT MonoObject *
6543 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6544 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6546 MonoError error;
6547 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6548 MonoObject *delegate;
6549 gpointer func;
6550 MonoMethod *method = info->method;
6552 mono_class_init_checked (delegate_class, &error);
6553 if (mono_error_set_pending_exception (&error))
6554 return NULL;
6556 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6557 /* FIXME improve this exception message */
6558 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6559 __func__,
6560 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6561 mono_error_set_pending_exception (&error);
6562 return NULL;
6565 if (mono_security_core_clr_enabled ()) {
6566 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6567 if (throwOnBindFailure)
6568 mono_error_set_pending_exception (&error);
6569 else
6570 mono_error_cleanup (&error);
6571 return NULL;
6575 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6576 if (mono_error_set_pending_exception (&error))
6577 return NULL;
6579 if (method_is_dynamic (method)) {
6580 /* Creating a trampoline would leak memory */
6581 func = mono_compile_method_checked (method, &error);
6582 if (mono_error_set_pending_exception (&error))
6583 return NULL;
6584 } else {
6585 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6586 method = mono_object_get_virtual_method (target, method);
6587 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6588 if (mono_error_set_pending_exception (&error))
6589 return NULL;
6590 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6593 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6594 if (mono_error_set_pending_exception (&error))
6595 return NULL;
6596 return delegate;
6599 ICALL_EXPORT MonoMulticastDelegate *
6600 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6602 MonoError error;
6603 MonoMulticastDelegate *ret;
6605 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6607 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6608 if (mono_error_set_pending_exception (&error))
6609 return NULL;
6611 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6613 return ret;
6616 ICALL_EXPORT MonoReflectionMethod*
6617 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6619 MonoReflectionMethod *ret = NULL;
6620 MonoError error;
6621 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6622 mono_error_set_pending_exception (&error);
6623 return ret;
6626 /* System.Buffer */
6628 static inline gint32
6629 mono_array_get_byte_length (MonoArray *array)
6631 MonoClass *klass;
6632 int length;
6633 int i;
6635 klass = array->obj.vtable->klass;
6637 if (array->bounds == NULL)
6638 length = array->max_length;
6639 else {
6640 length = 1;
6641 for (i = 0; i < klass->rank; ++ i)
6642 length *= array->bounds [i].length;
6645 switch (klass->element_class->byval_arg.type) {
6646 case MONO_TYPE_I1:
6647 case MONO_TYPE_U1:
6648 case MONO_TYPE_BOOLEAN:
6649 return length;
6650 case MONO_TYPE_I2:
6651 case MONO_TYPE_U2:
6652 case MONO_TYPE_CHAR:
6653 return length << 1;
6654 case MONO_TYPE_I4:
6655 case MONO_TYPE_U4:
6656 case MONO_TYPE_R4:
6657 return length << 2;
6658 case MONO_TYPE_I:
6659 case MONO_TYPE_U:
6660 return length * sizeof (gpointer);
6661 case MONO_TYPE_I8:
6662 case MONO_TYPE_U8:
6663 case MONO_TYPE_R8:
6664 return length << 3;
6665 default:
6666 return -1;
6670 ICALL_EXPORT gint32
6671 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6673 return mono_array_get_byte_length (array);
6676 ICALL_EXPORT gint8
6677 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6679 return mono_array_get (array, gint8, idx);
6682 ICALL_EXPORT void
6683 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6685 mono_array_set (array, gint8, idx, value);
6688 ICALL_EXPORT MonoBoolean
6689 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6691 guint8 *src_buf, *dest_buf;
6693 if (count < 0) {
6694 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6695 return FALSE;
6698 g_assert (count >= 0);
6700 /* This is called directly from the class libraries without going through the managed wrapper */
6701 MONO_CHECK_ARG_NULL (src, FALSE);
6702 MONO_CHECK_ARG_NULL (dest, FALSE);
6704 /* watch out for integer overflow */
6705 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6706 return FALSE;
6708 src_buf = (guint8 *)src->vector + src_offset;
6709 dest_buf = (guint8 *)dest->vector + dest_offset;
6711 if (src != dest)
6712 memcpy (dest_buf, src_buf, count);
6713 else
6714 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6716 return TRUE;
6719 #ifndef DISABLE_REMOTING
6720 ICALL_EXPORT MonoObject *
6721 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6723 MonoError error;
6724 MonoDomain *domain = mono_object_domain (this_obj);
6725 MonoObject *res;
6726 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6727 MonoTransparentProxy *tp;
6728 MonoType *type;
6729 MonoClass *klass;
6731 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6732 if (mono_error_set_pending_exception (&error))
6733 return NULL;
6735 tp = (MonoTransparentProxy*) res;
6737 MONO_OBJECT_SETREF (tp, rp, rp);
6738 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6739 klass = mono_class_from_mono_type (type);
6741 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6742 mono_class_setup_vtable (klass);
6743 if (mono_class_has_failure (klass)) {
6744 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6745 return NULL;
6748 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6749 if (mono_error_set_pending_exception (&error))
6750 return NULL;
6751 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6752 if (mono_error_set_pending_exception (&error))
6753 return NULL;
6755 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6756 if (mono_error_set_pending_exception (&error))
6757 return NULL;
6758 return res;
6761 ICALL_EXPORT MonoReflectionType *
6762 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6764 MonoError error;
6765 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6766 mono_error_set_pending_exception (&error);
6768 return ret;
6770 #endif
6772 /* System.Environment */
6774 MonoString*
6775 ves_icall_System_Environment_get_UserName (void)
6777 /* using glib is more portable */
6778 return mono_string_new (mono_domain_get (), g_get_user_name ());
6782 ICALL_EXPORT MonoString *
6783 ves_icall_System_Environment_get_MachineName (void)
6785 #if defined (HOST_WIN32)
6786 gunichar2 *buf;
6787 guint32 len;
6788 MonoString *result;
6790 len = MAX_COMPUTERNAME_LENGTH + 1;
6791 buf = g_new (gunichar2, len);
6793 result = NULL;
6794 if (GetComputerName (buf, (PDWORD) &len)) {
6795 MonoError error;
6796 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6797 mono_error_set_pending_exception (&error);
6800 g_free (buf);
6801 return result;
6802 #elif !defined(DISABLE_SOCKETS)
6803 MonoString *result;
6804 char *buf;
6805 int n;
6806 #if defined _SC_HOST_NAME_MAX
6807 n = sysconf (_SC_HOST_NAME_MAX);
6808 if (n == -1)
6809 #endif
6810 n = 512;
6811 buf = g_malloc (n+1);
6813 if (gethostname (buf, n) == 0){
6814 buf [n] = 0;
6815 result = mono_string_new (mono_domain_get (), buf);
6816 } else
6817 result = NULL;
6818 g_free (buf);
6820 return result;
6821 #else
6822 return mono_string_new (mono_domain_get (), "mono");
6823 #endif
6826 ICALL_EXPORT int
6827 ves_icall_System_Environment_get_Platform (void)
6829 #if defined (TARGET_WIN32)
6830 /* Win32NT */
6831 return 2;
6832 #elif defined(__MACH__)
6833 /* OSX */
6835 // Notice that the value is hidden from user code, and only exposed
6836 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6837 // define and making assumptions based on Unix/128/4 values before there
6838 // was a MacOS define. Lots of code would assume that not-Unix meant
6839 // Windows, but in this case, it would be OSX.
6841 return 6;
6842 #else
6843 /* Unix */
6844 return 4;
6845 #endif
6848 ICALL_EXPORT MonoString *
6849 ves_icall_System_Environment_get_NewLine (void)
6851 #if defined (HOST_WIN32)
6852 return mono_string_new (mono_domain_get (), "\r\n");
6853 #else
6854 return mono_string_new (mono_domain_get (), "\n");
6855 #endif
6858 ICALL_EXPORT MonoBoolean
6859 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6861 #if SIZEOF_VOID_P == 8
6862 return TRUE;
6863 #else
6864 #ifdef HOST_WIN32
6865 gboolean isWow64Process = FALSE;
6866 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6867 return (MonoBoolean)isWow64Process;
6869 #elif defined(HAVE_SYS_UTSNAME_H)
6870 struct utsname name;
6872 if (uname (&name) >= 0) {
6873 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6875 #endif
6876 return FALSE;
6877 #endif
6880 ICALL_EXPORT MonoString *
6881 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6883 MonoError error;
6884 const gchar *value;
6885 gchar *utf8_name;
6887 if (name == NULL)
6888 return NULL;
6890 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6891 if (mono_error_set_pending_exception (&error))
6892 return NULL;
6893 value = g_getenv (utf8_name);
6895 g_free (utf8_name);
6897 if (value == 0)
6898 return NULL;
6900 return mono_string_new (mono_domain_get (), value);
6904 * There is no standard way to get at environ.
6906 #ifndef _MSC_VER
6907 #ifndef __MINGW32_VERSION
6908 #if defined(__APPLE__)
6909 #if defined (TARGET_OSX)
6910 /* Apple defines this in crt_externs.h but doesn't provide that header for
6911 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6912 * in fact exist on all implementations (so far)
6914 gchar ***_NSGetEnviron(void);
6915 #define environ (*_NSGetEnviron())
6916 #else
6917 static char *mono_environ[1] = { NULL };
6918 #define environ mono_environ
6919 #endif /* defined (TARGET_OSX) */
6920 #else
6921 extern
6922 char **environ;
6923 #endif
6924 #endif
6925 #endif
6927 ICALL_EXPORT MonoArray *
6928 ves_icall_System_Environment_GetCoomandLineArgs (void)
6930 MonoError error;
6931 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6932 mono_error_set_pending_exception (&error);
6933 return result;
6936 ICALL_EXPORT MonoArray *
6937 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6939 #ifdef HOST_WIN32
6940 MonoError error;
6941 MonoArray *names;
6942 MonoDomain *domain;
6943 MonoString *str;
6944 WCHAR* env_strings;
6945 WCHAR* env_string;
6946 WCHAR* equal_str;
6947 int n = 0;
6949 env_strings = GetEnvironmentStrings();
6951 if (env_strings) {
6952 env_string = env_strings;
6953 while (*env_string != '\0') {
6954 /* weird case that MS seems to skip */
6955 if (*env_string != '=')
6956 n++;
6957 while (*env_string != '\0')
6958 env_string++;
6959 env_string++;
6963 domain = mono_domain_get ();
6964 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6965 if (mono_error_set_pending_exception (&error))
6966 return NULL;
6968 if (env_strings) {
6969 n = 0;
6970 env_string = env_strings;
6971 while (*env_string != '\0') {
6972 /* weird case that MS seems to skip */
6973 if (*env_string != '=') {
6974 equal_str = wcschr(env_string, '=');
6975 g_assert(equal_str);
6976 MonoError error;
6977 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6978 if (mono_error_set_pending_exception (&error))
6979 return NULL;
6981 mono_array_setref (names, n, str);
6982 n++;
6984 while (*env_string != '\0')
6985 env_string++;
6986 env_string++;
6989 FreeEnvironmentStrings (env_strings);
6992 return names;
6994 #else
6995 MonoError error;
6996 MonoArray *names;
6997 MonoDomain *domain;
6998 MonoString *str;
6999 gchar **e, **parts;
7000 int n;
7002 n = 0;
7003 for (e = environ; *e != 0; ++ e)
7004 ++ n;
7006 domain = mono_domain_get ();
7007 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
7008 if (mono_error_set_pending_exception (&error))
7009 return NULL;
7011 n = 0;
7012 for (e = environ; *e != 0; ++ e) {
7013 parts = g_strsplit (*e, "=", 2);
7014 if (*parts != 0) {
7015 str = mono_string_new (domain, *parts);
7016 mono_array_setref (names, n, str);
7019 g_strfreev (parts);
7021 ++ n;
7024 return names;
7025 #endif
7028 ICALL_EXPORT void
7029 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7031 #ifdef HOST_WIN32
7032 gunichar2 *utf16_name, *utf16_value;
7033 #else
7034 gchar *utf8_name, *utf8_value;
7035 MonoError error;
7036 #endif
7038 #ifdef HOST_WIN32
7039 utf16_name = mono_string_to_utf16 (name);
7040 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7041 SetEnvironmentVariable (utf16_name, NULL);
7042 g_free (utf16_name);
7043 return;
7046 utf16_value = mono_string_to_utf16 (value);
7048 SetEnvironmentVariable (utf16_name, utf16_value);
7050 g_free (utf16_name);
7051 g_free (utf16_value);
7052 #else
7053 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
7054 if (mono_error_set_pending_exception (&error))
7055 return;
7057 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7058 g_unsetenv (utf8_name);
7059 g_free (utf8_name);
7060 return;
7063 utf8_value = mono_string_to_utf8_checked (value, &error);
7064 if (!mono_error_ok (&error)) {
7065 g_free (utf8_name);
7066 mono_error_set_pending_exception (&error);
7067 return;
7069 g_setenv (utf8_name, utf8_value, TRUE);
7071 g_free (utf8_name);
7072 g_free (utf8_value);
7073 #endif
7076 ICALL_EXPORT void
7077 ves_icall_System_Environment_Exit (int result)
7079 mono_environment_exitcode_set (result);
7081 /* FIXME: There are some cleanup hangs that should be worked out, but
7082 * if the program is going to exit, everything will be cleaned up when
7083 * NaCl exits anyway.
7085 #ifndef __native_client__
7086 if (!mono_runtime_try_shutdown ())
7087 mono_thread_exit ();
7089 /* Suspend all managed threads since the runtime is going away */
7090 mono_thread_suspend_all_other_threads ();
7092 mono_runtime_quit ();
7093 #endif
7095 /* we may need to do some cleanup here... */
7096 exit (result);
7099 ICALL_EXPORT MonoString*
7100 ves_icall_System_Environment_GetGacPath (void)
7102 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7105 ICALL_EXPORT MonoString*
7106 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7108 #if defined (HOST_WIN32)
7109 #ifndef CSIDL_FLAG_CREATE
7110 #define CSIDL_FLAG_CREATE 0x8000
7111 #endif
7113 WCHAR path [MAX_PATH];
7114 /* Create directory if no existing */
7115 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7116 int len = 0;
7117 while (path [len])
7118 ++ len;
7119 MonoError error;
7120 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7121 mono_error_set_pending_exception (&error);
7122 return res;
7124 #else
7125 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7126 #endif
7127 return mono_string_new (mono_domain_get (), "");
7130 ICALL_EXPORT MonoArray *
7131 ves_icall_System_Environment_GetLogicalDrives (void)
7133 MonoError error;
7134 gunichar2 buf [256], *ptr, *dname;
7135 gunichar2 *u16;
7136 guint initial_size = 127, size = 128;
7137 gint ndrives;
7138 MonoArray *result;
7139 MonoString *drivestr;
7140 MonoDomain *domain = mono_domain_get ();
7141 gint len;
7143 buf [0] = '\0';
7144 ptr = buf;
7146 while (size > initial_size) {
7147 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7148 if (size > initial_size) {
7149 if (ptr != buf)
7150 g_free (ptr);
7151 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7152 initial_size = size;
7153 size++;
7157 /* Count strings */
7158 dname = ptr;
7159 ndrives = 0;
7160 do {
7161 while (*dname++);
7162 ndrives++;
7163 } while (*dname);
7165 dname = ptr;
7166 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7167 if (mono_error_set_pending_exception (&error))
7168 goto leave;
7170 ndrives = 0;
7171 do {
7172 len = 0;
7173 u16 = dname;
7174 while (*u16) { u16++; len ++; }
7175 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7176 if (mono_error_set_pending_exception (&error))
7177 goto leave;
7179 mono_array_setref (result, ndrives++, drivestr);
7180 while (*dname++);
7181 } while (*dname);
7183 leave:
7184 if (ptr != buf)
7185 g_free (ptr);
7187 return result;
7190 ICALL_EXPORT MonoString *
7191 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7193 MonoError error;
7194 gunichar2 volume_name [MAX_PATH + 1];
7196 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7197 return NULL;
7198 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7199 mono_error_set_pending_exception (&error);
7200 return result;
7203 ICALL_EXPORT MonoString *
7204 ves_icall_System_Environment_InternalGetHome (void)
7206 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7209 static const char *encodings [] = {
7210 (char *) 1,
7211 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7212 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7213 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7214 (char *) 2,
7215 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7216 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7217 "x_unicode_2_0_utf_7",
7218 (char *) 3,
7219 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7220 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7221 (char *) 4,
7222 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7223 "iso_10646_ucs2",
7224 (char *) 5,
7225 "unicodefffe", "utf_16be",
7226 (char *) 6,
7227 "iso_8859_1",
7228 (char *) 0
7232 * Returns the internal codepage, if the value of "int_code_page" is
7233 * 1 at entry, and we can not compute a suitable code page number,
7234 * returns the code page as a string
7236 ICALL_EXPORT MonoString*
7237 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7239 const char *cset;
7240 const char *p;
7241 char *c;
7242 char *codepage = NULL;
7243 int code;
7244 int want_name = *int_code_page;
7245 int i;
7247 *int_code_page = -1;
7249 g_get_charset (&cset);
7250 c = codepage = strdup (cset);
7251 for (c = codepage; *c; c++){
7252 if (isascii (*c) && isalpha (*c))
7253 *c = tolower (*c);
7254 if (*c == '-')
7255 *c = '_';
7257 /* g_print ("charset: %s\n", cset); */
7259 /* handle some common aliases */
7260 p = encodings [0];
7261 code = 0;
7262 for (i = 0; p != 0; ){
7263 if ((gsize) p < 7){
7264 code = (gssize) p;
7265 p = encodings [++i];
7266 continue;
7268 if (strcmp (p, codepage) == 0){
7269 *int_code_page = code;
7270 break;
7272 p = encodings [++i];
7275 if (strstr (codepage, "utf_8") != NULL)
7276 *int_code_page |= 0x10000000;
7277 free (codepage);
7279 if (want_name && *int_code_page == -1)
7280 return mono_string_new (mono_domain_get (), cset);
7281 else
7282 return NULL;
7285 ICALL_EXPORT MonoBoolean
7286 ves_icall_System_Environment_get_HasShutdownStarted (void)
7288 if (mono_runtime_is_shutting_down ())
7289 return TRUE;
7291 if (mono_domain_is_unloading (mono_domain_get ()))
7292 return TRUE;
7294 return FALSE;
7297 ICALL_EXPORT void
7298 ves_icall_System_Environment_BroadcastSettingChange (void)
7300 #ifdef HOST_WIN32
7301 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7302 #endif
7305 ICALL_EXPORT
7306 gint32
7307 ves_icall_System_Environment_get_TickCount (void)
7309 /* this will overflow after ~24 days */
7310 return (gint32) (mono_msec_boottime () & 0xffffffff);
7313 ICALL_EXPORT gint32
7314 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7316 return 9;
7319 #ifndef DISABLE_REMOTING
7320 ICALL_EXPORT MonoBoolean
7321 ves_icall_IsTransparentProxy (MonoObject *proxy)
7323 if (!proxy)
7324 return 0;
7326 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7327 return 1;
7329 return 0;
7332 ICALL_EXPORT MonoReflectionMethod *
7333 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7334 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7336 MonoReflectionMethod *ret = NULL;
7337 MonoError error;
7339 MonoClass *klass;
7340 MonoMethod *method;
7341 MonoMethod **vtable;
7342 MonoMethod *res = NULL;
7344 MONO_CHECK_ARG_NULL (rtype, NULL);
7345 MONO_CHECK_ARG_NULL (rmethod, NULL);
7347 method = rmethod->method;
7348 klass = mono_class_from_mono_type (rtype->type);
7349 mono_class_init_checked (klass, &error);
7350 if (mono_error_set_pending_exception (&error))
7351 return NULL;
7353 if (MONO_CLASS_IS_INTERFACE (klass))
7354 return NULL;
7356 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7357 return NULL;
7359 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7360 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7361 return rmethod;
7362 else
7363 return NULL;
7366 mono_class_setup_vtable (klass);
7367 vtable = klass->vtable;
7369 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7370 gboolean variance_used = FALSE;
7371 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7372 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7373 if (offs >= 0)
7374 res = vtable [offs + method->slot];
7375 } else {
7376 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7377 return NULL;
7379 if (method->slot != -1)
7380 res = vtable [method->slot];
7383 if (!res)
7384 return NULL;
7386 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7387 mono_error_set_pending_exception (&error);
7388 return ret;
7391 ICALL_EXPORT void
7392 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7394 MonoError error;
7395 MonoClass *klass;
7396 MonoVTable* vtable;
7398 klass = mono_class_from_mono_type (type->type);
7399 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7400 if (!is_ok (&error)) {
7401 mono_error_set_pending_exception (&error);
7402 return;
7405 mono_vtable_set_is_remote (vtable, enable);
7408 #else /* DISABLE_REMOTING */
7410 ICALL_EXPORT void
7411 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7413 g_assert_not_reached ();
7416 #endif
7418 ICALL_EXPORT MonoObject *
7419 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7421 MonoError error;
7422 MonoClass *klass;
7423 MonoDomain *domain;
7424 MonoObject *ret;
7426 domain = mono_object_domain (type);
7427 klass = mono_class_from_mono_type (type->type);
7428 mono_class_init_checked (klass, &error);
7429 if (mono_error_set_pending_exception (&error))
7430 return NULL;
7432 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7433 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7434 return NULL;
7437 if (klass->rank >= 1) {
7438 g_assert (klass->rank == 1);
7439 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7440 mono_error_set_pending_exception (&error);
7441 return ret;
7442 } else {
7443 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7444 if (!is_ok (&error)) {
7445 mono_error_set_pending_exception (&error);
7446 return NULL;
7448 /* Bypass remoting object creation check */
7449 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7450 mono_error_set_pending_exception (&error);
7452 return ret;
7456 ICALL_EXPORT MonoString *
7457 ves_icall_System_IO_get_temp_path (void)
7459 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7462 #ifndef PLATFORM_NO_DRIVEINFO
7463 ICALL_EXPORT MonoBoolean
7464 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7465 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7466 gint32 *error)
7468 gboolean result;
7469 ULARGE_INTEGER wapi_free_bytes_avail;
7470 ULARGE_INTEGER wapi_total_number_of_bytes;
7471 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7473 *error = ERROR_SUCCESS;
7474 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7475 &wapi_total_number_of_free_bytes);
7477 if (result) {
7478 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7479 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7480 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7481 } else {
7482 *free_bytes_avail = 0;
7483 *total_number_of_bytes = 0;
7484 *total_number_of_free_bytes = 0;
7485 *error = GetLastError ();
7488 return result;
7491 ICALL_EXPORT guint32
7492 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7494 return GetDriveType (mono_string_chars (root_path_name));
7496 #endif
7498 ICALL_EXPORT gpointer
7499 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7501 MonoError error;
7502 gpointer result = mono_compile_method_checked (method, &error);
7503 mono_error_set_pending_exception (&error);
7504 return result;
7507 ICALL_EXPORT MonoString *
7508 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7510 MonoString *mcpath;
7511 gchar *path;
7513 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7515 #if defined (HOST_WIN32)
7516 /* Avoid mixing '/' and '\\' */
7518 gint i;
7519 for (i = strlen (path) - 1; i >= 0; i--)
7520 if (path [i] == '/')
7521 path [i] = '\\';
7523 #endif
7524 mcpath = mono_string_new (mono_domain_get (), path);
7525 g_free (path);
7527 return mcpath;
7530 /* this is an icall */
7531 static MonoString *
7532 get_bundled_app_config (void)
7534 MonoError error;
7535 const gchar *app_config;
7536 MonoDomain *domain;
7537 MonoString *file;
7538 gchar *config_file_name, *config_file_path;
7539 gsize len, config_file_path_length, config_ext_length;
7540 gchar *module;
7542 domain = mono_domain_get ();
7543 file = domain->setup->configuration_file;
7544 if (!file || file->length == 0)
7545 return NULL;
7547 // Retrieve config file and remove the extension
7548 config_file_name = mono_string_to_utf8_checked (file, &error);
7549 if (mono_error_set_pending_exception (&error))
7550 return NULL;
7551 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7552 if (!config_file_path)
7553 config_file_path = config_file_name;
7555 config_file_path_length = strlen (config_file_path);
7556 config_ext_length = strlen (".config");
7557 if (config_file_path_length <= config_ext_length)
7558 return NULL;
7560 len = config_file_path_length - config_ext_length;
7561 module = (gchar *)g_malloc0 (len + 1);
7562 memcpy (module, config_file_path, len);
7563 // Get the config file from the module name
7564 app_config = mono_config_string_for_assembly_file (module);
7565 // Clean-up
7566 g_free (module);
7567 if (config_file_name != config_file_path)
7568 g_free (config_file_name);
7569 g_free (config_file_path);
7571 if (!app_config)
7572 return NULL;
7574 return mono_string_new (mono_domain_get (), app_config);
7577 static MonoString *
7578 get_bundled_machine_config (void)
7580 const gchar *machine_config;
7582 machine_config = mono_get_machine_config ();
7584 if (!machine_config)
7585 return NULL;
7587 return mono_string_new (mono_domain_get (), machine_config);
7590 ICALL_EXPORT MonoString *
7591 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7593 MonoString *ipath;
7594 gchar *path;
7596 path = g_path_get_dirname (mono_get_config_dir ());
7598 #if defined (HOST_WIN32)
7599 /* Avoid mixing '/' and '\\' */
7601 gint i;
7602 for (i = strlen (path) - 1; i >= 0; i--)
7603 if (path [i] == '/')
7604 path [i] = '\\';
7606 #endif
7607 ipath = mono_string_new (mono_domain_get (), path);
7608 g_free (path);
7610 return ipath;
7613 ICALL_EXPORT gboolean
7614 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7616 MonoPEResourceDataEntry *entry;
7617 MonoImage *image;
7619 if (!assembly || !result || !size)
7620 return FALSE;
7622 *result = NULL;
7623 *size = 0;
7624 image = assembly->assembly->image;
7625 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7626 if (!entry)
7627 return FALSE;
7629 *result = mono_image_rva_map (image, entry->rde_data_offset);
7630 if (!(*result)) {
7631 g_free (entry);
7632 return FALSE;
7634 *size = entry->rde_size;
7635 g_free (entry);
7636 return TRUE;
7639 ICALL_EXPORT MonoBoolean
7640 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7642 return mono_is_debugger_attached ();
7645 ICALL_EXPORT MonoBoolean
7646 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7648 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7649 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7650 else
7651 return FALSE;
7654 ICALL_EXPORT void
7655 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7657 if (mono_get_runtime_callbacks ()->debug_log)
7658 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7661 ICALL_EXPORT void
7662 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7664 #if defined (HOST_WIN32)
7665 OutputDebugString (mono_string_chars (message));
7666 #else
7667 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7668 #endif
7671 /* Only used for value types */
7672 ICALL_EXPORT MonoObject *
7673 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7675 MonoError error;
7676 MonoObject *result;
7677 MonoClass *klass;
7678 MonoDomain *domain;
7680 domain = mono_object_domain (type);
7681 klass = mono_class_from_mono_type (type->type);
7682 mono_class_init_checked (klass, &error);
7683 if (mono_error_set_pending_exception (&error))
7684 return NULL;
7686 if (mono_class_is_nullable (klass))
7687 /* No arguments -> null */
7688 return NULL;
7690 result = mono_object_new_checked (domain, klass, &error);
7691 mono_error_set_pending_exception (&error);
7692 return result;
7695 ICALL_EXPORT MonoReflectionMethod *
7696 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7698 MonoReflectionMethod *ret = NULL;
7699 MonoError error;
7701 MonoClass *klass, *parent;
7702 MonoGenericContext *generic_inst = NULL;
7703 MonoMethod *method = m->method;
7704 MonoMethod *result = NULL;
7705 int slot;
7707 if (method->klass == NULL)
7708 return m;
7710 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7711 MONO_CLASS_IS_INTERFACE (method->klass) ||
7712 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7713 return m;
7715 slot = mono_method_get_vtable_slot (method);
7716 if (slot == -1)
7717 return m;
7719 klass = method->klass;
7720 if (klass->generic_class) {
7721 generic_inst = mono_class_get_context (klass);
7722 klass = klass->generic_class->container_class;
7725 if (definition) {
7726 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7727 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7728 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7729 or klass is the generic container class and generic_inst is the instantiation.
7731 when we go to the parent, if the parent is an open constructed type, we need to
7732 replace the type parameters by the definitions from the generic_inst, and then take it
7733 apart again into the klass and the generic_inst.
7735 For cases like this:
7736 class C<T> : B<T, int> {
7737 public override void Foo () { ... }
7739 class B<U,V> : A<HashMap<U,V>> {
7740 public override void Foo () { ... }
7742 class A<X> {
7743 public virtual void Foo () { ... }
7746 if at each iteration the parent isn't open, we can skip inflating it. if at some
7747 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7748 NULL;
7750 MonoGenericContext *parent_inst = NULL;
7751 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7752 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7753 if (!mono_error_ok (&error)) {
7754 mono_error_set_pending_exception (&error);
7755 return NULL;
7758 if (parent->generic_class) {
7759 parent_inst = mono_class_get_context (parent);
7760 parent = parent->generic_class->container_class;
7763 mono_class_setup_vtable (parent);
7764 if (parent->vtable_size <= slot)
7765 break;
7766 klass = parent;
7767 generic_inst = parent_inst;
7769 } else {
7770 klass = klass->parent;
7771 if (!klass)
7772 return m;
7773 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7774 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7775 if (!mono_error_ok (&error)) {
7776 mono_error_set_pending_exception (&error);
7777 return NULL;
7780 generic_inst = NULL;
7782 if (klass->generic_class) {
7783 generic_inst = mono_class_get_context (klass);
7784 klass = klass->generic_class->container_class;
7789 if (generic_inst) {
7790 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7791 if (!mono_error_ok (&error)) {
7792 mono_error_set_pending_exception (&error);
7793 return NULL;
7797 if (klass == method->klass)
7798 return m;
7800 /*This is possible if definition == FALSE.
7801 * Do it here to be really sure we don't read invalid memory.
7803 if (slot >= klass->vtable_size)
7804 return m;
7806 mono_class_setup_vtable (klass);
7808 result = klass->vtable [slot];
7809 if (result == NULL) {
7810 /* It is an abstract method */
7811 gpointer iter = NULL;
7812 while ((result = mono_class_get_methods (klass, &iter)))
7813 if (result->slot == slot)
7814 break;
7817 if (result == NULL)
7818 return m;
7820 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7821 mono_error_set_pending_exception (&error);
7822 return ret;
7825 ICALL_EXPORT MonoString*
7826 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7828 MonoMethod *method = m->method;
7830 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7831 return m->name;
7834 ICALL_EXPORT void
7835 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7837 iter->sig = *(MonoMethodSignature**)argsp;
7839 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7840 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7842 iter->next_arg = 0;
7843 /* FIXME: it's not documented what start is exactly... */
7844 if (start) {
7845 iter->args = start;
7846 } else {
7847 iter->args = argsp + sizeof (gpointer);
7849 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7851 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7854 ICALL_EXPORT MonoTypedRef
7855 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7857 guint32 i, arg_size;
7858 gint32 align;
7859 MonoTypedRef res;
7861 i = iter->sig->sentinelpos + iter->next_arg;
7863 g_assert (i < iter->sig->param_count);
7865 res.type = iter->sig->params [i];
7866 res.klass = mono_class_from_mono_type (res.type);
7867 arg_size = mono_type_stack_size (res.type, &align);
7868 #if defined(__arm__) || defined(__mips__)
7869 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7870 #endif
7871 res.value = iter->args;
7872 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7873 /* Values are stored as 8 byte register sized objects, but 'value'
7874 * is dereferenced as a pointer in other routines.
7876 res.value = (char*)res.value + 4;
7877 #endif
7878 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7879 if (arg_size <= sizeof (gpointer)) {
7880 int dummy;
7881 int padding = arg_size - mono_type_size (res.type, &dummy);
7882 res.value = (guint8*)res.value + padding;
7884 #endif
7885 iter->args = (char*)iter->args + arg_size;
7886 iter->next_arg++;
7888 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7890 return res;
7893 ICALL_EXPORT MonoTypedRef
7894 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7896 guint32 i, arg_size;
7897 gint32 align;
7898 MonoTypedRef res;
7900 i = iter->sig->sentinelpos + iter->next_arg;
7902 g_assert (i < iter->sig->param_count);
7904 while (i < iter->sig->param_count) {
7905 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7906 continue;
7907 res.type = iter->sig->params [i];
7908 res.klass = mono_class_from_mono_type (res.type);
7909 /* FIXME: endianess issue... */
7910 arg_size = mono_type_stack_size (res.type, &align);
7911 #if defined(__arm__) || defined(__mips__)
7912 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7913 #endif
7914 res.value = iter->args;
7915 iter->args = (char*)iter->args + arg_size;
7916 iter->next_arg++;
7917 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7918 return res;
7920 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7922 res.type = NULL;
7923 res.value = NULL;
7924 res.klass = NULL;
7925 return res;
7928 ICALL_EXPORT MonoType*
7929 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7931 gint i;
7933 i = iter->sig->sentinelpos + iter->next_arg;
7935 g_assert (i < iter->sig->param_count);
7937 return iter->sig->params [i];
7940 ICALL_EXPORT MonoObject*
7941 mono_TypedReference_ToObject (MonoTypedRef* tref)
7943 MonoError error;
7944 MonoObject *result = NULL;
7945 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7946 MonoObject** objp = (MonoObject **)tref->value;
7947 return *objp;
7950 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7951 mono_error_set_pending_exception (&error);
7952 return result;
7955 ICALL_EXPORT MonoTypedRef
7956 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7958 MonoTypedRef res;
7959 MonoReflectionField *f;
7960 MonoClass *klass;
7961 MonoType *ftype = NULL;
7962 guint8 *p = NULL;
7963 int i;
7965 memset (&res, 0, sizeof (res));
7967 g_assert (fields);
7968 g_assert (mono_array_length (fields) > 0);
7970 klass = target->vtable->klass;
7972 for (i = 0; i < mono_array_length (fields); ++i) {
7973 f = mono_array_get (fields, MonoReflectionField*, i);
7974 if (f == NULL) {
7975 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7976 return res;
7978 if (f->field->parent != klass) {
7979 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7980 return res;
7982 if (i == 0)
7983 p = (guint8*)target + f->field->offset;
7984 else
7985 p += f->field->offset - sizeof (MonoObject);
7986 klass = mono_class_from_mono_type (f->field->type);
7987 ftype = f->field->type;
7990 res.type = ftype;
7991 res.klass = mono_class_from_mono_type (ftype);
7992 res.value = p;
7994 return res;
7997 static void
7998 prelink_method (MonoMethod *method, MonoError *error)
8000 const char *exc_class, *exc_arg;
8002 mono_error_init (error);
8003 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8004 return;
8005 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
8006 if (exc_class) {
8007 mono_error_set_exception_instance (error,
8008 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
8009 return;
8011 /* create the wrapper, too? */
8014 ICALL_EXPORT void
8015 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8017 MonoError error;
8019 prelink_method (method->method, &error);
8020 mono_error_set_pending_exception (&error);
8023 ICALL_EXPORT void
8024 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8026 MonoError error;
8027 MonoClass *klass = mono_class_from_mono_type (type->type);
8028 MonoMethod* m;
8029 gpointer iter = NULL;
8031 mono_class_init_checked (klass, &error);
8032 if (mono_error_set_pending_exception (&error))
8033 return;
8035 while ((m = mono_class_get_methods (klass, &iter))) {
8036 prelink_method (m, &error);
8037 if (mono_error_set_pending_exception (&error))
8038 return;
8042 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8043 ICALL_EXPORT void
8044 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8045 gint32 const **exponents,
8046 gunichar2 const **digitLowerTable,
8047 gunichar2 const **digitUpperTable,
8048 gint64 const **tenPowersList,
8049 gint32 const **decHexDigits)
8051 *mantissas = Formatter_MantissaBitsTable;
8052 *exponents = Formatter_TensExponentTable;
8053 *digitLowerTable = Formatter_DigitLowerTable;
8054 *digitUpperTable = Formatter_DigitUpperTable;
8055 *tenPowersList = Formatter_TenPowersList;
8056 *decHexDigits = Formatter_DecHexDigits;
8060 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8061 * and avoid useless allocations.
8063 static MonoArray*
8064 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8066 MonoReflectionType *rt;
8067 MonoArray *res;
8068 int i, count = 0;
8070 mono_error_init (error);
8071 for (i = 0; i < type->num_mods; ++i) {
8072 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8073 count++;
8075 if (!count)
8076 return NULL;
8077 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8078 return_val_if_nok (error, NULL);
8079 count = 0;
8080 for (i = 0; i < type->num_mods; ++i) {
8081 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8082 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8083 return_val_if_nok (error, NULL);
8085 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8086 return_val_if_nok (error, NULL);
8088 mono_array_setref (res, count, rt);
8089 count++;
8092 return res;
8095 ICALL_EXPORT MonoArray*
8096 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8098 MonoError error;
8099 MonoType *type = param->ClassImpl->type;
8100 MonoClass *member_class = mono_object_class (param->MemberImpl);
8101 MonoMethod *method = NULL;
8102 MonoImage *image;
8103 int pos;
8104 MonoMethodSignature *sig;
8105 MonoArray *res;
8107 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8108 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8109 method = rmethod->method;
8110 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8111 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8112 if (!(method = prop->property->get))
8113 method = prop->property->set;
8114 g_assert (method);
8115 } else {
8116 char *type_name = mono_type_get_full_name (member_class);
8117 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8118 MonoException *ex = mono_get_exception_not_supported (msg);
8119 g_free (type_name);
8120 g_free (msg);
8121 mono_set_pending_exception (ex);
8122 return NULL;
8125 image = method->klass->image;
8126 pos = param->PositionImpl;
8127 sig = mono_method_signature (method);
8128 if (pos == -1)
8129 type = sig->ret;
8130 else
8131 type = sig->params [pos];
8133 res = type_array_from_modifiers (image, type, optional, &error);
8134 mono_error_set_pending_exception (&error);
8135 return res;
8138 static MonoType*
8139 get_property_type (MonoProperty *prop)
8141 MonoMethodSignature *sig;
8142 if (prop->get) {
8143 sig = mono_method_signature (prop->get);
8144 return sig->ret;
8145 } else if (prop->set) {
8146 sig = mono_method_signature (prop->set);
8147 return sig->params [sig->param_count - 1];
8149 return NULL;
8152 ICALL_EXPORT MonoArray*
8153 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8155 MonoError error;
8156 MonoType *type = get_property_type (property->property);
8157 MonoImage *image = property->klass->image;
8158 MonoArray *res;
8160 if (!type)
8161 return NULL;
8162 res = type_array_from_modifiers (image, type, optional, &error);
8163 mono_error_set_pending_exception (&error);
8164 return res;
8168 *Construct a MonoType suited to be used to decode a constant blob object.
8170 * @type is the target type which will be constructed
8171 * @blob_type is the blob type, for example, that comes from the constant table
8172 * @real_type is the expected constructed type.
8174 static void
8175 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8177 type->type = blob_type;
8178 type->data.klass = NULL;
8179 if (blob_type == MONO_TYPE_CLASS)
8180 type->data.klass = mono_defaults.object_class;
8181 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8182 /* For enums, we need to use the base type */
8183 type->type = MONO_TYPE_VALUETYPE;
8184 type->data.klass = mono_class_from_mono_type (real_type);
8185 } else
8186 type->data.klass = mono_class_from_mono_type (real_type);
8189 ICALL_EXPORT MonoObject*
8190 property_info_get_default_value (MonoReflectionProperty *property)
8192 MonoError error;
8193 MonoType blob_type;
8194 MonoProperty *prop = property->property;
8195 MonoType *type = get_property_type (prop);
8196 MonoDomain *domain = mono_object_domain (property);
8197 MonoTypeEnum def_type;
8198 const char *def_value;
8199 MonoObject *o;
8201 mono_class_init (prop->parent);
8203 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8204 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8205 return NULL;
8208 def_value = mono_class_get_property_default_value (prop, &def_type);
8210 mono_type_from_blob_type (&blob_type, def_type, type);
8211 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8213 mono_error_set_pending_exception (&error);
8214 return o;
8217 ICALL_EXPORT MonoBoolean
8218 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8220 MonoError error;
8221 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8222 MonoCustomAttrInfo *cinfo;
8223 gboolean found;
8225 mono_class_init_checked (attr_class, &error);
8226 if (mono_error_set_pending_exception (&error))
8227 return FALSE;
8229 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8230 if (!is_ok (&error)) {
8231 mono_error_set_pending_exception (&error);
8232 return FALSE;
8234 if (!cinfo)
8235 return FALSE;
8236 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8237 if (!cinfo->cached)
8238 mono_custom_attrs_free (cinfo);
8239 return found;
8242 ICALL_EXPORT MonoArray*
8243 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8245 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8246 MonoArray *res;
8247 MonoError error;
8249 if (attr_class) {
8250 mono_class_init_checked (attr_class, &error);
8251 if (mono_error_set_pending_exception (&error))
8252 return NULL;
8255 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8256 if (!mono_error_ok (&error)) {
8257 mono_error_set_pending_exception (&error);
8258 return NULL;
8261 return res;
8264 ICALL_EXPORT MonoArray*
8265 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8267 MonoError error;
8268 MonoArray *result;
8269 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8270 mono_error_set_pending_exception (&error);
8271 return result;
8275 ICALL_EXPORT MonoString*
8276 ves_icall_Mono_Runtime_GetDisplayName (void)
8278 char *info;
8279 MonoString *display_name;
8281 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8282 display_name = mono_string_new (mono_domain_get (), info);
8283 g_free (info);
8284 return display_name;
8287 ICALL_EXPORT MonoString*
8288 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8290 MonoError error;
8291 MonoString *message;
8292 guint32 ret;
8293 gunichar2 buf[256];
8295 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8296 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8297 buf, 255, NULL);
8298 if (ret == 0) {
8299 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8300 } else {
8301 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8302 if (mono_error_set_pending_exception (&error))
8303 return NULL;
8306 return message;
8309 ICALL_EXPORT gpointer
8310 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8312 return GetCurrentProcess ();
8315 ICALL_EXPORT MonoBoolean
8316 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8318 return GetExitCodeProcess (handle, (guint32*) exitcode);
8321 ICALL_EXPORT MonoBoolean
8322 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8324 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8325 return CloseHandle (handle);
8326 #else
8327 return CloseProcess (handle);
8328 #endif
8331 ICALL_EXPORT MonoBoolean
8332 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8334 return TerminateProcess (handle, exitcode);
8337 ICALL_EXPORT gint32
8338 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8340 return WaitForInputIdle (handle, milliseconds);
8343 ICALL_EXPORT MonoBoolean
8344 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8346 return GetProcessWorkingSetSize (handle, min, max);
8349 ICALL_EXPORT MonoBoolean
8350 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8352 return SetProcessWorkingSetSize (handle, min, max);
8355 ICALL_EXPORT MonoBoolean
8356 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8358 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8361 ICALL_EXPORT gint32
8362 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8364 return mono_process_current_pid ();
8367 ICALL_EXPORT gint32
8368 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8370 return GetPriorityClass (handle);
8373 ICALL_EXPORT MonoBoolean
8374 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8376 return SetPriorityClass (handle, priorityClass);
8379 #ifndef DISABLE_ICALL_TABLES
8381 #define ICALL_TYPE(id,name,first)
8382 #define ICALL(id,name,func) Icall_ ## id,
8384 enum {
8385 #include "metadata/icall-def.h"
8386 Icall_last
8389 #undef ICALL_TYPE
8390 #undef ICALL
8391 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8392 #define ICALL(id,name,func)
8393 enum {
8394 #include "metadata/icall-def.h"
8395 Icall_type_num
8398 #undef ICALL_TYPE
8399 #undef ICALL
8400 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8401 #define ICALL(id,name,func)
8402 typedef struct {
8403 guint16 first_icall;
8404 } IcallTypeDesc;
8406 static const IcallTypeDesc
8407 icall_type_descs [] = {
8408 #include "metadata/icall-def.h"
8409 {Icall_last}
8412 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8414 #undef ICALL_TYPE
8415 #define ICALL_TYPE(id,name,first)
8416 #undef ICALL
8418 #ifdef HAVE_ARRAY_ELEM_INIT
8419 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8420 #define MSGSTRFIELD1(line) str##line
8422 static const struct msgstrtn_t {
8423 #define ICALL(id,name,func)
8424 #undef ICALL_TYPE
8425 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8426 #include "metadata/icall-def.h"
8427 #undef ICALL_TYPE
8428 } icall_type_names_str = {
8429 #define ICALL_TYPE(id,name,first) (name),
8430 #include "metadata/icall-def.h"
8431 #undef ICALL_TYPE
8433 static const guint16 icall_type_names_idx [] = {
8434 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8435 #include "metadata/icall-def.h"
8436 #undef ICALL_TYPE
8438 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8440 static const struct msgstr_t {
8441 #undef ICALL
8442 #define ICALL_TYPE(id,name,first)
8443 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8444 #include "metadata/icall-def.h"
8445 #undef ICALL
8446 } icall_names_str = {
8447 #define ICALL(id,name,func) (name),
8448 #include "metadata/icall-def.h"
8449 #undef ICALL
8451 static const guint16 icall_names_idx [] = {
8452 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8453 #include "metadata/icall-def.h"
8454 #undef ICALL
8456 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8458 #else
8460 #undef ICALL_TYPE
8461 #undef ICALL
8462 #define ICALL_TYPE(id,name,first) name,
8463 #define ICALL(id,name,func)
8464 static const char* const
8465 icall_type_names [] = {
8466 #include "metadata/icall-def.h"
8467 NULL
8470 #define icall_type_name_get(id) (icall_type_names [(id)])
8472 #undef ICALL_TYPE
8473 #undef ICALL
8474 #define ICALL_TYPE(id,name,first)
8475 #define ICALL(id,name,func) name,
8476 static const char* const
8477 icall_names [] = {
8478 #include "metadata/icall-def.h"
8479 NULL
8481 #define icall_name_get(id) icall_names [(id)]
8483 #endif /* !HAVE_ARRAY_ELEM_INIT */
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_functions [] = {
8491 #include "metadata/icall-def.h"
8492 NULL
8495 #ifdef ENABLE_ICALL_SYMBOL_MAP
8496 #undef ICALL_TYPE
8497 #undef ICALL
8498 #define ICALL_TYPE(id,name,first)
8499 #define ICALL(id,name,func) #func,
8500 static const gconstpointer
8501 icall_symbols [] = {
8502 #include "metadata/icall-def.h"
8503 NULL
8505 #endif
8507 #endif /* DISABLE_ICALL_TABLES */
8509 static mono_mutex_t icall_mutex;
8510 static GHashTable *icall_hash = NULL;
8511 static GHashTable *jit_icall_hash_name = NULL;
8512 static GHashTable *jit_icall_hash_addr = NULL;
8514 void
8515 mono_icall_init (void)
8517 #ifndef DISABLE_ICALL_TABLES
8518 int i = 0;
8520 /* check that tables are sorted: disable in release */
8521 if (TRUE) {
8522 int j;
8523 const char *prev_class = NULL;
8524 const char *prev_method;
8526 for (i = 0; i < Icall_type_num; ++i) {
8527 const IcallTypeDesc *desc;
8528 int num_icalls;
8529 prev_method = NULL;
8530 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8531 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8532 prev_class = icall_type_name_get (i);
8533 desc = &icall_type_descs [i];
8534 num_icalls = icall_desc_num_icalls (desc);
8535 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8536 for (j = 0; j < num_icalls; ++j) {
8537 const char *methodn = icall_name_get (desc->first_icall + j);
8538 if (prev_method && strcmp (prev_method, methodn) >= 0)
8539 g_print ("method %s should come before method %s\n", methodn, prev_method);
8540 prev_method = methodn;
8544 #endif
8546 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8547 mono_os_mutex_init (&icall_mutex);
8550 static void
8551 mono_icall_lock (void)
8553 mono_locks_os_acquire (&icall_mutex, IcallLock);
8556 static void
8557 mono_icall_unlock (void)
8559 mono_locks_os_release (&icall_mutex, IcallLock);
8562 void
8563 mono_icall_cleanup (void)
8565 g_hash_table_destroy (icall_hash);
8566 g_hash_table_destroy (jit_icall_hash_name);
8567 g_hash_table_destroy (jit_icall_hash_addr);
8568 mono_os_mutex_destroy (&icall_mutex);
8572 * mono_add_internal_call:
8573 * @name: method specification to surface to the managed world
8574 * @method: pointer to a C method to invoke when the method is called
8576 * This method surfaces the C function pointed by @method as a method
8577 * that has been surfaced in managed code with the method specified in
8578 * @name as an internal call.
8580 * Internal calls are surfaced to all app domains loaded and they are
8581 * accessibly by a type with the specified name.
8583 * You must provide a fully qualified type name, that is namespaces
8584 * and type name, followed by a colon and the method name, with an
8585 * optional signature to bind.
8587 * For example, the following are all valid declarations:
8589 * "MyApp.Services.ScriptService:Accelerate"
8590 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8592 * You use method parameters in cases where there might be more than
8593 * one surface method to managed code. That way you can register different
8594 * internal calls for different method overloads.
8596 * The internal calls are invoked with no marshalling. This means that .NET
8597 * types like System.String are exposed as `MonoString *` parameters. This is
8598 * different than the way that strings are surfaced in P/Invoke.
8600 * For more information on how the parameters are marshalled, see the
8601 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8602 * page.
8604 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8605 * reference for more information on the format of method descriptions.
8607 void
8608 mono_add_internal_call (const char *name, gconstpointer method)
8610 mono_icall_lock ();
8612 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8614 mono_icall_unlock ();
8617 #ifndef DISABLE_ICALL_TABLES
8619 #ifdef HAVE_ARRAY_ELEM_INIT
8620 static int
8621 compare_method_imap (const void *key, const void *elem)
8623 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8624 return strcmp (key, method_name);
8627 static gpointer
8628 find_method_icall (const IcallTypeDesc *imap, const char *name)
8630 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);
8631 if (!nameslot)
8632 return NULL;
8633 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8636 static int
8637 compare_class_imap (const void *key, const void *elem)
8639 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8640 return strcmp (key, class_name);
8643 static const IcallTypeDesc*
8644 find_class_icalls (const char *name)
8646 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);
8647 if (!nameslot)
8648 return NULL;
8649 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8652 #else /* HAVE_ARRAY_ELEM_INIT */
8654 static int
8655 compare_method_imap (const void *key, const void *elem)
8657 const char** method_name = (const char**)elem;
8658 return strcmp (key, *method_name);
8661 static gpointer
8662 find_method_icall (const IcallTypeDesc *imap, const char *name)
8664 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8665 if (!nameslot)
8666 return NULL;
8667 return (gpointer)icall_functions [(nameslot - icall_names)];
8670 static int
8671 compare_class_imap (const void *key, const void *elem)
8673 const char** class_name = (const char**)elem;
8674 return strcmp (key, *class_name);
8677 static const IcallTypeDesc*
8678 find_class_icalls (const char *name)
8680 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8681 if (!nameslot)
8682 return NULL;
8683 return &icall_type_descs [nameslot - icall_type_names];
8686 #endif /* HAVE_ARRAY_ELEM_INIT */
8688 #endif /* DISABLE_ICALL_TABLES */
8691 * we should probably export this as an helper (handle nested types).
8692 * Returns the number of chars written in buf.
8694 static int
8695 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8697 int nspacelen, cnamelen;
8698 nspacelen = strlen (klass->name_space);
8699 cnamelen = strlen (klass->name);
8700 if (nspacelen + cnamelen + 2 > bufsize)
8701 return 0;
8702 if (nspacelen) {
8703 memcpy (buf, klass->name_space, nspacelen);
8704 buf [nspacelen ++] = '.';
8706 memcpy (buf + nspacelen, klass->name, cnamelen);
8707 buf [nspacelen + cnamelen] = 0;
8708 return nspacelen + cnamelen;
8711 #ifdef DISABLE_ICALL_TABLES
8712 static void
8713 no_icall_table (void)
8715 g_assert_not_reached ();
8717 #endif
8719 gpointer
8720 mono_lookup_internal_call (MonoMethod *method)
8722 char *sigstart;
8723 char *tmpsig;
8724 char mname [2048];
8725 int typelen = 0, mlen, siglen;
8726 gpointer res;
8727 #ifndef DISABLE_ICALL_TABLES
8728 const IcallTypeDesc *imap = NULL;
8729 #endif
8731 g_assert (method != NULL);
8733 if (method->is_inflated)
8734 method = ((MonoMethodInflated *) method)->declaring;
8736 if (method->klass->nested_in) {
8737 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8738 if (!pos)
8739 return NULL;
8741 mname [pos++] = '/';
8742 mname [pos] = 0;
8744 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8745 if (!typelen)
8746 return NULL;
8748 typelen += pos;
8749 } else {
8750 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8751 if (!typelen)
8752 return NULL;
8755 #ifndef DISABLE_ICALL_TABLES
8756 imap = find_class_icalls (mname);
8757 #endif
8759 mname [typelen] = ':';
8760 mname [typelen + 1] = ':';
8762 mlen = strlen (method->name);
8763 memcpy (mname + typelen + 2, method->name, mlen);
8764 sigstart = mname + typelen + 2 + mlen;
8765 *sigstart = 0;
8767 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8768 siglen = strlen (tmpsig);
8769 if (typelen + mlen + siglen + 6 > sizeof (mname))
8770 return NULL;
8771 sigstart [0] = '(';
8772 memcpy (sigstart + 1, tmpsig, siglen);
8773 sigstart [siglen + 1] = ')';
8774 sigstart [siglen + 2] = 0;
8775 g_free (tmpsig);
8777 mono_icall_lock ();
8779 res = g_hash_table_lookup (icall_hash, mname);
8780 if (res) {
8781 mono_icall_unlock ();;
8782 return res;
8784 /* try without signature */
8785 *sigstart = 0;
8786 res = g_hash_table_lookup (icall_hash, mname);
8787 if (res) {
8788 mono_icall_unlock ();
8789 return res;
8792 #ifdef DISABLE_ICALL_TABLES
8793 mono_icall_unlock ();
8794 /* Fail only when the result is actually used */
8795 /* mono_marshal_get_native_wrapper () depends on this */
8796 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8797 return ves_icall_System_String_ctor_RedirectToCreateString;
8798 else
8799 return no_icall_table;
8800 #else
8801 /* it wasn't found in the static call tables */
8802 if (!imap) {
8803 mono_icall_unlock ();
8804 return NULL;
8806 res = find_method_icall (imap, sigstart - mlen);
8807 if (res) {
8808 mono_icall_unlock ();
8809 return res;
8811 /* try _with_ signature */
8812 *sigstart = '(';
8813 res = find_method_icall (imap, sigstart - mlen);
8814 if (res) {
8815 mono_icall_unlock ();
8816 return res;
8819 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8820 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8821 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8822 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8823 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");
8824 g_print ("If you see other errors or faults after this message they are probably related\n");
8825 g_print ("and you need to fix your mono install first.\n");
8827 mono_icall_unlock ();
8829 return NULL;
8830 #endif
8833 #ifdef ENABLE_ICALL_SYMBOL_MAP
8834 static int
8835 func_cmp (gconstpointer key, gconstpointer p)
8837 return (gsize)key - (gsize)*(gsize*)p;
8839 #endif
8842 * mono_lookup_icall_symbol:
8844 * Given the icall METHOD, returns its C symbol.
8846 const char*
8847 mono_lookup_icall_symbol (MonoMethod *m)
8849 #ifdef DISABLE_ICALL_TABLES
8850 g_assert_not_reached ();
8851 return NULL;
8852 #else
8853 #ifdef ENABLE_ICALL_SYMBOL_MAP
8854 gpointer func;
8855 int i;
8856 gpointer slot;
8857 static gconstpointer *functions_sorted;
8858 static const char**symbols_sorted;
8859 static gboolean inited;
8861 if (!inited) {
8862 gboolean changed;
8864 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8865 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8866 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8867 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8868 /* Bubble sort the two arrays */
8869 changed = TRUE;
8870 while (changed) {
8871 changed = FALSE;
8872 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8873 if (functions_sorted [i] > functions_sorted [i + 1]) {
8874 gconstpointer tmp;
8876 tmp = functions_sorted [i];
8877 functions_sorted [i] = functions_sorted [i + 1];
8878 functions_sorted [i + 1] = tmp;
8879 tmp = symbols_sorted [i];
8880 symbols_sorted [i] = symbols_sorted [i + 1];
8881 symbols_sorted [i + 1] = tmp;
8882 changed = TRUE;
8888 func = mono_lookup_internal_call (m);
8889 if (!func)
8890 return NULL;
8891 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8892 if (!slot)
8893 return NULL;
8894 g_assert (slot);
8895 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8896 #else
8897 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8898 g_assert_not_reached ();
8899 return 0;
8900 #endif
8901 #endif
8904 static MonoType*
8905 type_from_typename (char *type_name)
8907 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8909 if (!strcmp (type_name, "int"))
8910 klass = mono_defaults.int_class;
8911 else if (!strcmp (type_name, "ptr"))
8912 klass = mono_defaults.int_class;
8913 else if (!strcmp (type_name, "void"))
8914 klass = mono_defaults.void_class;
8915 else if (!strcmp (type_name, "int32"))
8916 klass = mono_defaults.int32_class;
8917 else if (!strcmp (type_name, "uint32"))
8918 klass = mono_defaults.uint32_class;
8919 else if (!strcmp (type_name, "int8"))
8920 klass = mono_defaults.sbyte_class;
8921 else if (!strcmp (type_name, "uint8"))
8922 klass = mono_defaults.byte_class;
8923 else if (!strcmp (type_name, "int16"))
8924 klass = mono_defaults.int16_class;
8925 else if (!strcmp (type_name, "uint16"))
8926 klass = mono_defaults.uint16_class;
8927 else if (!strcmp (type_name, "long"))
8928 klass = mono_defaults.int64_class;
8929 else if (!strcmp (type_name, "ulong"))
8930 klass = mono_defaults.uint64_class;
8931 else if (!strcmp (type_name, "float"))
8932 klass = mono_defaults.single_class;
8933 else if (!strcmp (type_name, "double"))
8934 klass = mono_defaults.double_class;
8935 else if (!strcmp (type_name, "object"))
8936 klass = mono_defaults.object_class;
8937 else if (!strcmp (type_name, "obj"))
8938 klass = mono_defaults.object_class;
8939 else if (!strcmp (type_name, "string"))
8940 klass = mono_defaults.string_class;
8941 else if (!strcmp (type_name, "bool"))
8942 klass = mono_defaults.boolean_class;
8943 else if (!strcmp (type_name, "boolean"))
8944 klass = mono_defaults.boolean_class;
8945 else {
8946 g_error ("%s", type_name);
8947 g_assert_not_reached ();
8949 return &klass->byval_arg;
8953 * LOCKING: Take the corlib image lock.
8955 MonoMethodSignature*
8956 mono_create_icall_signature (const char *sigstr)
8958 gchar **parts;
8959 int i, len;
8960 gchar **tmp;
8961 MonoMethodSignature *res, *res2;
8962 MonoImage *corlib = mono_defaults.corlib;
8964 mono_image_lock (corlib);
8965 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8966 mono_image_unlock (corlib);
8968 if (res)
8969 return res;
8971 parts = g_strsplit (sigstr, " ", 256);
8973 tmp = parts;
8974 len = 0;
8975 while (*tmp) {
8976 len ++;
8977 tmp ++;
8980 res = mono_metadata_signature_alloc (corlib, len - 1);
8981 res->pinvoke = 1;
8983 #ifdef HOST_WIN32
8985 * Under windows, the default pinvoke calling convention is STDCALL but
8986 * we need CDECL.
8988 res->call_convention = MONO_CALL_C;
8989 #endif
8991 res->ret = type_from_typename (parts [0]);
8992 for (i = 1; i < len; ++i) {
8993 res->params [i - 1] = type_from_typename (parts [i]);
8996 g_strfreev (parts);
8998 mono_image_lock (corlib);
8999 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
9000 if (res2)
9001 res = res2; /*Value is allocated in the image pool*/
9002 else
9003 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
9004 mono_image_unlock (corlib);
9006 return res;
9009 MonoJitICallInfo *
9010 mono_find_jit_icall_by_name (const char *name)
9012 MonoJitICallInfo *info;
9013 g_assert (jit_icall_hash_name);
9015 mono_icall_lock ();
9016 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9017 mono_icall_unlock ();
9018 return info;
9021 MonoJitICallInfo *
9022 mono_find_jit_icall_by_addr (gconstpointer addr)
9024 MonoJitICallInfo *info;
9025 g_assert (jit_icall_hash_addr);
9027 mono_icall_lock ();
9028 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9029 mono_icall_unlock ();
9031 return info;
9035 * mono_get_jit_icall_info:
9037 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9038 * caller should access it while holding the icall lock.
9040 GHashTable*
9041 mono_get_jit_icall_info (void)
9043 return jit_icall_hash_name;
9047 * mono_lookup_jit_icall_symbol:
9049 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9051 const char*
9052 mono_lookup_jit_icall_symbol (const char *name)
9054 MonoJitICallInfo *info;
9055 const char *res = NULL;
9057 mono_icall_lock ();
9058 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9059 if (info)
9060 res = info->c_symbol;
9061 mono_icall_unlock ();
9062 return res;
9065 void
9066 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9068 mono_icall_lock ();
9069 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9070 mono_icall_unlock ();
9074 * 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
9075 * icalls without wrappers in some cases.
9077 MonoJitICallInfo *
9078 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9080 MonoJitICallInfo *info;
9082 g_assert (func);
9083 g_assert (name);
9085 mono_icall_lock ();
9087 if (!jit_icall_hash_name) {
9088 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9089 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9092 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9093 g_warning ("jit icall already defined \"%s\"\n", name);
9094 g_assert_not_reached ();
9097 info = g_new0 (MonoJitICallInfo, 1);
9099 info->name = name;
9100 info->func = func;
9101 info->sig = sig;
9102 info->c_symbol = c_symbol;
9103 info->no_raise = no_raise;
9105 if (is_save) {
9106 info->wrapper = func;
9107 } else {
9108 info->wrapper = NULL;
9111 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9112 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9114 mono_icall_unlock ();
9115 return info;
9118 MonoJitICallInfo *
9119 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9121 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);