[corlib] GetAotId now returns null, if unavailable
[mono-project.git] / mono / metadata / icall.c
blob73d2491a35beca078d7b476b7ea50658067b04a8
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 /* System.TypeCode */
1539 typedef enum {
1540 TYPECODE_EMPTY,
1541 TYPECODE_OBJECT,
1542 TYPECODE_DBNULL,
1543 TYPECODE_BOOLEAN,
1544 TYPECODE_CHAR,
1545 TYPECODE_SBYTE,
1546 TYPECODE_BYTE,
1547 TYPECODE_INT16,
1548 TYPECODE_UINT16,
1549 TYPECODE_INT32,
1550 TYPECODE_UINT32,
1551 TYPECODE_INT64,
1552 TYPECODE_UINT64,
1553 TYPECODE_SINGLE,
1554 TYPECODE_DOUBLE,
1555 TYPECODE_DECIMAL,
1556 TYPECODE_DATETIME,
1557 TYPECODE_STRING = 18
1558 } TypeCode;
1560 ICALL_EXPORT guint32
1561 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1563 int t = type->type->type;
1565 if (type->type->byref)
1566 return TYPECODE_OBJECT;
1568 handle_enum:
1569 switch (t) {
1570 case MONO_TYPE_VOID:
1571 return TYPECODE_OBJECT;
1572 case MONO_TYPE_BOOLEAN:
1573 return TYPECODE_BOOLEAN;
1574 case MONO_TYPE_U1:
1575 return TYPECODE_BYTE;
1576 case MONO_TYPE_I1:
1577 return TYPECODE_SBYTE;
1578 case MONO_TYPE_U2:
1579 return TYPECODE_UINT16;
1580 case MONO_TYPE_I2:
1581 return TYPECODE_INT16;
1582 case MONO_TYPE_CHAR:
1583 return TYPECODE_CHAR;
1584 case MONO_TYPE_PTR:
1585 case MONO_TYPE_U:
1586 case MONO_TYPE_I:
1587 return TYPECODE_OBJECT;
1588 case MONO_TYPE_U4:
1589 return TYPECODE_UINT32;
1590 case MONO_TYPE_I4:
1591 return TYPECODE_INT32;
1592 case MONO_TYPE_U8:
1593 return TYPECODE_UINT64;
1594 case MONO_TYPE_I8:
1595 return TYPECODE_INT64;
1596 case MONO_TYPE_R4:
1597 return TYPECODE_SINGLE;
1598 case MONO_TYPE_R8:
1599 return TYPECODE_DOUBLE;
1600 case MONO_TYPE_VALUETYPE: {
1601 MonoClass *klass = type->type->data.klass;
1603 if (klass->enumtype) {
1604 t = mono_class_enum_basetype (klass)->type;
1605 goto handle_enum;
1606 } else if (mono_is_corlib_image (klass->image)) {
1607 if (strcmp (klass->name_space, "System") == 0) {
1608 if (strcmp (klass->name, "Decimal") == 0)
1609 return TYPECODE_DECIMAL;
1610 else if (strcmp (klass->name, "DateTime") == 0)
1611 return TYPECODE_DATETIME;
1614 return TYPECODE_OBJECT;
1616 case MONO_TYPE_STRING:
1617 return TYPECODE_STRING;
1618 case MONO_TYPE_SZARRAY:
1619 case MONO_TYPE_ARRAY:
1620 case MONO_TYPE_OBJECT:
1621 case MONO_TYPE_VAR:
1622 case MONO_TYPE_MVAR:
1623 case MONO_TYPE_TYPEDBYREF:
1624 return TYPECODE_OBJECT;
1625 case MONO_TYPE_CLASS:
1627 MonoClass *klass = type->type->data.klass;
1628 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1629 if (strcmp (klass->name, "DBNull") == 0)
1630 return TYPECODE_DBNULL;
1633 return TYPECODE_OBJECT;
1634 case MONO_TYPE_GENERICINST:
1635 return TYPECODE_OBJECT;
1636 default:
1637 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1639 return 0;
1642 static gboolean
1643 mono_type_is_primitive (MonoType *type)
1645 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1646 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1649 static MonoType*
1650 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1652 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1653 return mono_class_enum_basetype (type->data.klass);
1654 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1655 return mono_class_enum_basetype (type->data.generic_class->container_class);
1656 return type;
1659 ICALL_EXPORT guint32
1660 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1662 MonoClass *klass;
1663 MonoClass *klassc;
1665 g_assert (type != NULL);
1667 klass = mono_class_from_mono_type (type->type);
1668 klassc = mono_class_from_mono_type (c->type);
1670 if (type->type->byref ^ c->type->byref)
1671 return FALSE;
1673 if (type->type->byref) {
1674 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1675 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1677 klass = mono_class_from_mono_type (t);
1678 klassc = mono_class_from_mono_type (ot);
1680 if (mono_type_is_primitive (t)) {
1681 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1682 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1683 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1684 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1685 return t->type == ot->type;
1686 } else {
1687 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1688 return FALSE;
1690 if (klass->valuetype)
1691 return klass == klassc;
1692 return klass->valuetype == klassc->valuetype;
1695 return mono_class_is_assignable_from (klass, klassc);
1698 ICALL_EXPORT guint32
1699 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1701 MonoError error;
1702 MonoClass *klass = mono_class_from_mono_type (type->type);
1703 mono_class_init_checked (klass, &error);
1704 if (!is_ok (&error)) {
1705 mono_error_set_pending_exception (&error);
1706 return FALSE;
1708 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1709 mono_error_set_pending_exception (&error);
1710 return result;
1713 ICALL_EXPORT guint32
1714 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1716 MonoClass *klass = mono_class_from_mono_type (type->type);
1717 return klass->flags;
1720 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1721 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1723 MonoError error;
1724 MonoClass *klass = field->field->parent;
1725 MonoMarshalType *info;
1726 MonoType *ftype;
1727 int i;
1729 if (klass->generic_container ||
1730 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1731 return NULL;
1733 ftype = mono_field_get_type (field->field);
1734 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1735 return NULL;
1737 info = mono_marshal_load_type_info (klass);
1739 for (i = 0; i < info->num_fields; ++i) {
1740 if (info->fields [i].field == field->field) {
1741 if (!info->fields [i].mspec)
1742 return NULL;
1743 else {
1744 MonoReflectionMarshalAsAttribute* obj;
1745 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1746 if (!mono_error_ok (&error))
1747 mono_error_set_pending_exception (&error);
1748 return obj;
1753 return NULL;
1756 ICALL_EXPORT MonoReflectionField*
1757 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1759 MonoError error;
1760 gboolean found = FALSE;
1761 MonoClass *klass;
1762 MonoClass *k;
1764 g_assert (handle);
1766 if (!type) {
1767 klass = handle->parent;
1768 } else {
1769 klass = mono_class_from_mono_type (type);
1771 /* Check that the field belongs to the class */
1772 for (k = klass; k; k = k->parent) {
1773 if (k == handle->parent) {
1774 found = TRUE;
1775 break;
1779 if (!found)
1780 /* The managed code will throw the exception */
1781 return NULL;
1784 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1785 mono_error_set_pending_exception (&error);
1786 return result;
1789 ICALL_EXPORT MonoArray*
1790 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1792 MonoError error;
1793 MonoType *type = mono_field_get_type_checked (field->field, &error);
1794 MonoArray *res;
1796 if (!mono_error_ok (&error)) {
1797 mono_error_set_pending_exception (&error);
1798 return NULL;
1801 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1802 mono_error_set_pending_exception (&error);
1803 return res;
1806 ICALL_EXPORT int
1807 vell_icall_get_method_attributes (MonoMethod *method)
1809 return method->flags;
1812 ICALL_EXPORT void
1813 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1815 MonoError error;
1816 MonoReflectionType *rt;
1817 MonoDomain *domain = mono_domain_get ();
1818 MonoMethodSignature* sig;
1820 sig = mono_method_signature_checked (method, &error);
1821 if (!mono_error_ok (&error)) {
1822 mono_error_set_pending_exception (&error);
1823 return;
1826 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1827 if (!mono_error_ok (&error)) {
1828 mono_error_set_pending_exception (&error);
1829 return;
1832 MONO_STRUCT_SETREF (info, parent, rt);
1834 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1835 if (!mono_error_ok (&error)) {
1836 mono_error_set_pending_exception (&error);
1837 return;
1840 MONO_STRUCT_SETREF (info, ret, rt);
1842 info->attrs = method->flags;
1843 info->implattrs = method->iflags;
1844 if (sig->call_convention == MONO_CALL_DEFAULT)
1845 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1846 else {
1847 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1848 info->callconv = 2;
1849 else
1850 info->callconv = 1;
1852 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1855 ICALL_EXPORT MonoArray*
1856 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1858 MonoError error;
1859 MonoDomain *domain = mono_domain_get ();
1861 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1862 mono_error_set_pending_exception (&error);
1863 return result;
1866 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1867 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1869 MonoError error;
1870 MonoDomain *domain = mono_domain_get ();
1871 MonoReflectionMarshalAsAttribute* res = NULL;
1872 MonoMarshalSpec **mspecs;
1873 int i;
1875 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1876 mono_method_get_marshal_info (method, mspecs);
1878 if (mspecs [0]) {
1879 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1880 if (!mono_error_ok (&error)) {
1881 mono_error_set_pending_exception (&error);
1882 return NULL;
1886 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1887 if (mspecs [i])
1888 mono_metadata_free_marshal_spec (mspecs [i]);
1889 g_free (mspecs);
1891 return res;
1894 ICALL_EXPORT gint32
1895 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1897 MonoClass *parent = field->field->parent;
1898 if (!parent->size_inited)
1899 mono_class_init (parent);
1900 mono_class_setup_fields_locking (parent);
1902 return field->field->offset - sizeof (MonoObject);
1905 ICALL_EXPORT MonoReflectionType*
1906 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1908 MonoError error;
1909 MonoReflectionType *ret;
1910 MonoClass *parent;
1912 parent = declaring? field->field->parent: field->klass;
1914 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1915 mono_error_set_pending_exception (&error);
1917 return ret;
1921 ICALL_EXPORT MonoObject *
1922 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1924 MonoError error;
1925 MonoClass *fklass = field->klass;
1926 MonoClassField *cf = field->field;
1927 MonoDomain *domain = mono_object_domain (field);
1929 if (fklass->image->assembly->ref_only) {
1930 mono_set_pending_exception (mono_get_exception_invalid_operation (
1931 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1932 return NULL;
1935 if (mono_security_core_clr_enabled () &&
1936 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1937 mono_error_set_pending_exception (&error);
1938 return NULL;
1941 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1942 mono_error_set_pending_exception (&error);
1943 return result;
1946 ICALL_EXPORT void
1947 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1949 MonoError error;
1950 MonoClassField *cf = field->field;
1951 MonoType *type;
1952 gchar *v;
1954 if (field->klass->image->assembly->ref_only) {
1955 mono_set_pending_exception (mono_get_exception_invalid_operation (
1956 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1957 return;
1960 if (mono_security_core_clr_enabled () &&
1961 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1962 mono_error_set_pending_exception (&error);
1963 return;
1966 type = mono_field_get_type_checked (cf, &error);
1967 if (!mono_error_ok (&error)) {
1968 mono_error_set_pending_exception (&error);
1969 return;
1972 v = (gchar *) value;
1973 if (!type->byref) {
1974 switch (type->type) {
1975 case MONO_TYPE_U1:
1976 case MONO_TYPE_I1:
1977 case MONO_TYPE_BOOLEAN:
1978 case MONO_TYPE_U2:
1979 case MONO_TYPE_I2:
1980 case MONO_TYPE_CHAR:
1981 case MONO_TYPE_U:
1982 case MONO_TYPE_I:
1983 case MONO_TYPE_U4:
1984 case MONO_TYPE_I4:
1985 case MONO_TYPE_R4:
1986 case MONO_TYPE_U8:
1987 case MONO_TYPE_I8:
1988 case MONO_TYPE_R8:
1989 case MONO_TYPE_VALUETYPE:
1990 case MONO_TYPE_PTR:
1991 if (v != NULL)
1992 v += sizeof (MonoObject);
1993 break;
1994 case MONO_TYPE_STRING:
1995 case MONO_TYPE_OBJECT:
1996 case MONO_TYPE_CLASS:
1997 case MONO_TYPE_ARRAY:
1998 case MONO_TYPE_SZARRAY:
1999 /* Do nothing */
2000 break;
2001 case MONO_TYPE_GENERICINST: {
2002 MonoGenericClass *gclass = type->data.generic_class;
2003 g_assert (!gclass->context.class_inst->is_open);
2005 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2006 MonoClass *nklass = mono_class_from_mono_type (type);
2007 MonoObject *nullable;
2010 * Convert the boxed vtype into a Nullable structure.
2011 * This is complicated by the fact that Nullables have
2012 * a variable structure.
2014 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2015 if (!mono_error_ok (&error)) {
2016 mono_error_set_pending_exception (&error);
2017 return;
2020 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2022 v = (gchar *)mono_object_unbox (nullable);
2024 else
2025 if (gclass->container_class->valuetype && (v != NULL))
2026 v += sizeof (MonoObject);
2027 break;
2029 default:
2030 g_error ("type 0x%x not handled in "
2031 "ves_icall_FieldInfo_SetValueInternal", type->type);
2032 return;
2036 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2037 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2038 if (!is_ok (&error)) {
2039 mono_error_set_pending_exception (&error);
2040 return;
2042 if (!vtable->initialized) {
2043 if (!mono_runtime_class_init_full (vtable, &error)) {
2044 mono_error_set_pending_exception (&error);
2045 return;
2048 mono_field_static_set_value (vtable, cf, v);
2049 } else {
2050 mono_field_set_value (obj, cf, v);
2054 ICALL_EXPORT void
2055 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2057 MonoClassField *f;
2059 g_assert (field);
2060 g_assert (obj);
2061 g_assert (value);
2063 f = field->field;
2064 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2065 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2066 return;
2069 if (MONO_TYPE_IS_REFERENCE (f->type))
2070 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2071 else
2072 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2075 ICALL_EXPORT MonoObject *
2076 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2078 MonoObject *o = NULL;
2079 MonoClassField *field = rfield->field;
2080 MonoClass *klass;
2081 MonoDomain *domain = mono_object_domain (rfield);
2082 gchar *v;
2083 MonoTypeEnum def_type;
2084 const char *def_value;
2085 MonoType *t;
2086 MonoError error;
2088 mono_class_init (field->parent);
2090 t = mono_field_get_type_checked (field, &error);
2091 if (!mono_error_ok (&error)) {
2092 mono_error_set_pending_exception (&error);
2093 return NULL;
2096 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2097 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2098 return NULL;
2101 if (image_is_dynamic (field->parent->image)) {
2102 MonoClass *klass = field->parent;
2103 int fidx = field - klass->fields;
2105 g_assert (fidx >= 0 && fidx < klass->field.count);
2106 g_assert (klass->ext);
2107 g_assert (klass->ext->field_def_values);
2108 def_type = klass->ext->field_def_values [fidx].def_type;
2109 def_value = klass->ext->field_def_values [fidx].data;
2110 if (def_type == MONO_TYPE_END) {
2111 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2112 return NULL;
2114 } else {
2115 def_value = mono_class_get_field_default_value (field, &def_type);
2116 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2117 if (!def_value) {
2118 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2119 return NULL;
2123 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2124 switch (def_type) {
2125 case MONO_TYPE_U1:
2126 case MONO_TYPE_I1:
2127 case MONO_TYPE_BOOLEAN:
2128 case MONO_TYPE_U2:
2129 case MONO_TYPE_I2:
2130 case MONO_TYPE_CHAR:
2131 case MONO_TYPE_U:
2132 case MONO_TYPE_I:
2133 case MONO_TYPE_U4:
2134 case MONO_TYPE_I4:
2135 case MONO_TYPE_R4:
2136 case MONO_TYPE_U8:
2137 case MONO_TYPE_I8:
2138 case MONO_TYPE_R8: {
2139 MonoType *t;
2141 /* boxed value type */
2142 t = g_new0 (MonoType, 1);
2143 t->type = def_type;
2144 klass = mono_class_from_mono_type (t);
2145 g_free (t);
2146 o = mono_object_new_checked (domain, klass, &error);
2147 if (!mono_error_ok (&error)) {
2148 mono_error_set_pending_exception (&error);
2149 return NULL;
2151 v = ((gchar *) o) + sizeof (MonoObject);
2152 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2153 if (mono_error_set_pending_exception (&error))
2154 return NULL;
2155 break;
2157 case MONO_TYPE_STRING:
2158 case MONO_TYPE_CLASS:
2159 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2160 if (mono_error_set_pending_exception (&error))
2161 return NULL;
2162 break;
2163 default:
2164 g_assert_not_reached ();
2167 return o;
2170 ICALL_EXPORT MonoReflectionType*
2171 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2173 MonoError error;
2174 MonoReflectionType *ret;
2175 MonoType *type;
2177 type = mono_field_get_type_checked (ref_field->field, &error);
2178 if (!mono_error_ok (&error)) {
2179 mono_error_set_pending_exception (&error);
2180 return NULL;
2183 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2184 if (!mono_error_ok (&error)) {
2185 mono_error_set_pending_exception (&error);
2186 return NULL;
2189 return ret;
2192 /* From MonoProperty.cs */
2193 typedef enum {
2194 PInfo_Attributes = 1,
2195 PInfo_GetMethod = 1 << 1,
2196 PInfo_SetMethod = 1 << 2,
2197 PInfo_ReflectedType = 1 << 3,
2198 PInfo_DeclaringType = 1 << 4,
2199 PInfo_Name = 1 << 5
2200 } PInfo;
2202 ICALL_EXPORT void
2203 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2205 MonoError error;
2206 MonoReflectionType *rt;
2207 MonoReflectionMethod *rm;
2208 MonoDomain *domain = mono_object_domain (property);
2209 const MonoProperty *pproperty = property->property;
2211 if ((req_info & PInfo_ReflectedType) != 0) {
2212 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2213 if (mono_error_set_pending_exception (&error))
2214 return;
2216 MONO_STRUCT_SETREF (info, parent, rt);
2218 if ((req_info & PInfo_DeclaringType) != 0) {
2219 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2220 if (mono_error_set_pending_exception (&error))
2221 return;
2223 MONO_STRUCT_SETREF (info, declaring_type, rt);
2226 if ((req_info & PInfo_Name) != 0)
2227 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2229 if ((req_info & PInfo_Attributes) != 0)
2230 info->attrs = pproperty->attrs;
2232 if ((req_info & PInfo_GetMethod) != 0) {
2233 if (pproperty->get &&
2234 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2235 pproperty->get->klass == property->klass)) {
2236 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2237 if (mono_error_set_pending_exception (&error))
2238 return;
2239 } else {
2240 rm = NULL;
2243 MONO_STRUCT_SETREF (info, get, rm);
2245 if ((req_info & PInfo_SetMethod) != 0) {
2246 if (pproperty->set &&
2247 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2248 pproperty->set->klass == property->klass)) {
2249 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2250 if (mono_error_set_pending_exception (&error))
2251 return;
2252 } else {
2253 rm = NULL;
2256 MONO_STRUCT_SETREF (info, set, rm);
2259 * There may be other methods defined for properties, though, it seems they are not exposed
2260 * in the reflection API
2264 ICALL_EXPORT void
2265 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2267 MonoError error;
2268 MonoReflectionType *rt;
2269 MonoReflectionMethod *rm;
2270 MonoDomain *domain = mono_object_domain (event);
2272 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2273 if (mono_error_set_pending_exception (&error))
2274 return;
2276 MONO_STRUCT_SETREF (info, reflected_type, rt);
2278 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2279 if (mono_error_set_pending_exception (&error))
2280 return;
2282 MONO_STRUCT_SETREF (info, declaring_type, rt);
2284 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2285 info->attrs = event->event->attrs;
2287 if (event->event->add) {
2288 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2289 if (mono_error_set_pending_exception (&error))
2290 return;
2291 } else {
2292 rm = NULL;
2295 MONO_STRUCT_SETREF (info, add_method, rm);
2297 if (event->event->remove) {
2298 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2299 if (mono_error_set_pending_exception (&error))
2300 return;
2301 } else {
2302 rm = NULL;
2305 MONO_STRUCT_SETREF (info, remove_method, rm);
2307 if (event->event->raise) {
2308 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2309 if (mono_error_set_pending_exception (&error))
2310 return;
2311 } else {
2312 rm = NULL;
2315 MONO_STRUCT_SETREF (info, raise_method, rm);
2317 #ifndef MONO_SMALL_CONFIG
2318 if (event->event->other) {
2319 int i, n = 0;
2320 while (event->event->other [n])
2321 n++;
2322 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2323 if (mono_error_set_pending_exception (&error))
2324 return;
2325 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2327 for (i = 0; i < n; i++) {
2328 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2329 if (mono_error_set_pending_exception (&error))
2330 return;
2331 mono_array_setref (info->other_methods, i, rm);
2334 #endif
2337 static void
2338 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2340 int i;
2341 MonoClass *ic;
2343 mono_class_setup_interfaces (klass, error);
2344 if (!mono_error_ok (error))
2345 return;
2347 for (i = 0; i < klass->interface_count; i++) {
2348 ic = klass->interfaces [i];
2349 g_hash_table_insert (ifaces, ic, ic);
2351 collect_interfaces (ic, ifaces, error);
2352 if (!mono_error_ok (error))
2353 return;
2357 typedef struct {
2358 MonoArray *iface_array;
2359 MonoGenericContext *context;
2360 MonoError *error;
2361 MonoDomain *domain;
2362 int next_idx;
2363 } FillIfaceArrayData;
2365 static void
2366 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2368 MonoReflectionType *rt;
2369 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2370 MonoClass *ic = (MonoClass *)key;
2371 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2373 if (!mono_error_ok (data->error))
2374 return;
2376 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2377 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2378 if (!mono_error_ok (data->error))
2379 return;
2382 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2383 if (!mono_error_ok (data->error))
2384 return;
2386 mono_array_setref (data->iface_array, data->next_idx++, rt);
2388 if (inflated)
2389 mono_metadata_free_type (inflated);
2392 static guint
2393 get_interfaces_hash (gconstpointer v1)
2395 MonoClass *k = (MonoClass*)v1;
2397 return k->type_token;
2400 ICALL_EXPORT MonoArray*
2401 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2403 MonoError error;
2404 MonoClass *klass = mono_class_from_mono_type (type->type);
2405 MonoClass *parent;
2406 FillIfaceArrayData data = { 0 };
2407 int len;
2409 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2411 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2412 data.context = mono_class_get_context (klass);
2413 klass = klass->generic_class->container_class;
2416 for (parent = klass; parent; parent = parent->parent) {
2417 mono_class_setup_interfaces (parent, &error);
2418 if (!mono_error_ok (&error))
2419 goto fail;
2420 collect_interfaces (parent, iface_hash, &error);
2421 if (!mono_error_ok (&error))
2422 goto fail;
2425 data.error = &error;
2426 data.domain = mono_object_domain (type);
2428 len = g_hash_table_size (iface_hash);
2429 if (len == 0) {
2430 g_hash_table_destroy (iface_hash);
2431 if (!data.domain->empty_types) {
2432 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2433 if (!is_ok (&error))
2434 goto fail;
2436 return data.domain->empty_types;
2439 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2440 if (!is_ok (&error))
2441 goto fail;
2442 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2443 if (!mono_error_ok (&error))
2444 goto fail;
2446 g_hash_table_destroy (iface_hash);
2447 return data.iface_array;
2449 fail:
2450 g_hash_table_destroy (iface_hash);
2451 mono_error_set_pending_exception (&error);
2452 return NULL;
2455 ICALL_EXPORT void
2456 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2458 gboolean variance_used;
2459 MonoClass *klass = mono_class_from_mono_type (type->type);
2460 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2461 MonoReflectionMethod *member;
2462 MonoMethod* method;
2463 gpointer iter;
2464 int i = 0, len, ioffset;
2465 MonoDomain *domain;
2466 MonoError error;
2468 mono_class_init_checked (klass, &error);
2469 if (mono_error_set_pending_exception (&error))
2470 return;
2471 mono_class_init_checked (iclass, &error);
2472 if (mono_error_set_pending_exception (&error))
2473 return;
2475 mono_class_setup_vtable (klass);
2477 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2478 if (ioffset == -1)
2479 return;
2481 len = mono_class_num_methods (iclass);
2482 domain = mono_object_domain (type);
2483 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2484 if (mono_error_set_pending_exception (&error))
2485 return;
2486 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2487 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2488 if (mono_error_set_pending_exception (&error))
2489 return;
2490 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2491 iter = NULL;
2492 while ((method = mono_class_get_methods (iclass, &iter))) {
2493 member = mono_method_get_object_checked (domain, method, iclass, &error);
2494 if (mono_error_set_pending_exception (&error))
2495 return;
2496 mono_array_setref (*methods, i, member);
2497 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2498 if (mono_error_set_pending_exception (&error))
2499 return;
2500 mono_array_setref (*targets, i, member);
2502 i ++;
2506 ICALL_EXPORT void
2507 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2509 MonoError error;
2510 MonoClass *klass = mono_class_from_mono_type (type->type);
2512 mono_class_init_checked (klass, &error);
2513 if (mono_error_set_pending_exception (&error))
2514 return;
2516 if (image_is_dynamic (klass->image)) {
2517 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2518 *packing = tb->packing_size;
2519 *size = tb->class_size;
2520 } else {
2521 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2525 ICALL_EXPORT MonoReflectionType*
2526 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2528 MonoError error;
2529 MonoReflectionType *ret;
2530 MonoClass *klass;
2532 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2533 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2534 mono_error_set_pending_exception (&error);
2535 return ret;
2538 klass = mono_class_from_mono_type (type->type);
2539 mono_class_init_checked (klass, &error);
2540 if (mono_error_set_pending_exception (&error))
2541 return NULL;
2544 // GetElementType should only return a type for:
2545 // Array Pointer PassedByRef
2546 if (type->type->byref)
2547 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2548 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2549 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2550 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2551 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2552 else
2553 return NULL;
2555 mono_error_set_pending_exception (&error);
2557 return ret;
2560 ICALL_EXPORT MonoReflectionType*
2561 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2563 MonoError error;
2564 MonoReflectionType *ret;
2566 if (type->type->byref)
2567 return NULL;
2569 MonoClass *klass = mono_class_from_mono_type (type->type);
2570 if (!klass->parent)
2571 return NULL;
2573 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2574 mono_error_set_pending_exception (&error);
2576 return ret;
2579 ICALL_EXPORT MonoBoolean
2580 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2582 return type->type->type == MONO_TYPE_PTR;
2585 ICALL_EXPORT MonoBoolean
2586 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2588 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)));
2591 ICALL_EXPORT MonoBoolean
2592 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2594 return type->type->byref;
2597 ICALL_EXPORT MonoBoolean
2598 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2600 MonoError error;
2601 MonoClass *klass = mono_class_from_mono_type (type->type);
2602 mono_class_init_checked (klass, &error);
2603 if (mono_error_set_pending_exception (&error))
2604 return FALSE;
2606 return mono_class_is_com_object (klass);
2609 ICALL_EXPORT guint32
2610 ves_icall_reflection_get_token (MonoObject* obj)
2612 MonoError error;
2613 guint32 result = mono_reflection_get_token_checked (obj, &error);
2614 mono_error_set_pending_exception (&error);
2615 return result;
2618 ICALL_EXPORT MonoReflectionModule*
2619 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2621 MonoError error;
2622 MonoReflectionModule *result = NULL;
2623 MonoClass *klass = mono_class_from_mono_type (type->type);
2624 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2625 mono_error_set_pending_exception (&error);
2626 return result;
2629 ICALL_EXPORT MonoReflectionAssembly*
2630 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2632 MonoError error;
2633 MonoDomain *domain = mono_domain_get ();
2634 MonoClass *klass = mono_class_from_mono_type (type->type);
2635 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2636 mono_error_set_pending_exception (&error);
2637 return result;
2640 ICALL_EXPORT MonoReflectionType*
2641 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2643 MonoError error;
2644 MonoReflectionType *ret;
2645 MonoDomain *domain = mono_domain_get ();
2646 MonoClass *klass;
2648 if (type->type->byref)
2649 return NULL;
2650 if (type->type->type == MONO_TYPE_VAR) {
2651 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2652 klass = param ? param->owner.klass : NULL;
2653 } else if (type->type->type == MONO_TYPE_MVAR) {
2654 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2655 klass = param ? param->owner.method->klass : NULL;
2656 } else {
2657 klass = mono_class_from_mono_type (type->type)->nested_in;
2660 if (!klass)
2661 return NULL;
2663 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2664 mono_error_set_pending_exception (&error);
2666 return ret;
2669 ICALL_EXPORT MonoString*
2670 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2672 MonoDomain *domain = mono_domain_get ();
2673 MonoClass *klass = mono_class_from_mono_type (type->type);
2675 if (type->type->byref) {
2676 char *n = g_strdup_printf ("%s&", klass->name);
2677 MonoString *res = mono_string_new (domain, n);
2679 g_free (n);
2681 return res;
2682 } else {
2683 return mono_string_new (domain, klass->name);
2687 ICALL_EXPORT MonoString*
2688 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2690 MonoDomain *domain = mono_domain_get ();
2691 MonoClass *klass = mono_class_from_mono_type (type->type);
2693 while (klass->nested_in)
2694 klass = klass->nested_in;
2696 if (klass->name_space [0] == '\0')
2697 return NULL;
2698 else
2699 return mono_string_new (domain, klass->name_space);
2702 ICALL_EXPORT gint32
2703 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2705 MonoClass *klass;
2707 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2708 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2709 return 0;
2712 klass = mono_class_from_mono_type (type->type);
2714 return klass->rank;
2717 static MonoArray*
2718 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2720 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2723 ICALL_EXPORT MonoArray*
2724 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2726 MonoError error;
2727 MonoReflectionType *rt;
2728 MonoArray *res;
2729 MonoClass *klass, *pklass;
2730 MonoDomain *domain = mono_object_domain (type);
2731 int i;
2733 klass = mono_class_from_mono_type (type->type);
2735 if (klass->generic_container) {
2736 MonoGenericContainer *container = klass->generic_container;
2737 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2738 if (mono_error_set_pending_exception (&error))
2739 return NULL;
2740 for (i = 0; i < container->type_argc; ++i) {
2741 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2743 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2744 if (mono_error_set_pending_exception (&error))
2745 return NULL;
2747 mono_array_setref (res, i, rt);
2749 } else if (klass->generic_class) {
2750 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2751 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2752 if (mono_error_set_pending_exception (&error))
2753 return NULL;
2754 for (i = 0; i < inst->type_argc; ++i) {
2755 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2756 if (mono_error_set_pending_exception (&error))
2757 return NULL;
2759 mono_array_setref (res, i, rt);
2761 } else {
2762 res = NULL;
2764 return res;
2767 ICALL_EXPORT gboolean
2768 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2770 MonoClass *klass;
2772 if (!IS_MONOTYPE (type))
2773 return FALSE;
2775 if (type->type->byref)
2776 return FALSE;
2778 klass = mono_class_from_mono_type (type->type);
2779 return klass->generic_container != NULL;
2782 ICALL_EXPORT MonoReflectionType*
2783 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2785 MonoError error;
2786 MonoReflectionType *ret;
2787 MonoClass *klass;
2789 if (type->type->byref)
2790 return NULL;
2792 klass = mono_class_from_mono_type (type->type);
2794 if (klass->generic_container) {
2795 return type; /* check this one */
2797 if (klass->generic_class) {
2798 MonoClass *generic_class = klass->generic_class->container_class;
2799 gpointer tb;
2801 tb = mono_class_get_ref_info (generic_class);
2803 if (generic_class->wastypebuilder && tb)
2804 return (MonoReflectionType *)tb;
2805 else {
2806 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2807 mono_error_set_pending_exception (&error);
2809 return ret;
2812 return NULL;
2815 ICALL_EXPORT MonoReflectionType*
2816 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2818 MonoError error;
2819 MonoReflectionType *ret;
2820 MonoClass *klass;
2821 MonoType *geninst, **types;
2822 int i, count;
2824 g_assert (IS_MONOTYPE (type));
2825 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2826 if (mono_error_set_pending_exception (&error))
2827 return NULL;
2829 count = mono_array_length (type_array);
2830 types = g_new0 (MonoType *, count);
2832 for (i = 0; i < count; i++) {
2833 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2834 types [i] = t->type;
2837 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2838 g_free (types);
2839 if (!geninst) {
2840 mono_error_set_pending_exception (&error);
2841 return NULL;
2844 klass = mono_class_from_mono_type (geninst);
2846 /*we might inflate to the GTD*/
2847 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2848 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2849 return NULL;
2852 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2853 mono_error_set_pending_exception (&error);
2855 return ret;
2858 ICALL_EXPORT gboolean
2859 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2861 MonoClass *klass;
2863 if (!IS_MONOTYPE (type))
2864 return FALSE;
2866 if (type->type->byref)
2867 return FALSE;
2869 klass = mono_class_from_mono_type (type->type);
2870 return klass->generic_class != NULL || klass->generic_container != NULL;
2873 ICALL_EXPORT gint32
2874 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2876 if (!IS_MONOTYPE (type))
2877 return -1;
2879 if (is_generic_parameter (type->type))
2880 return mono_type_get_generic_param_num (type->type);
2881 return -1;
2884 ICALL_EXPORT GenericParameterAttributes
2885 ves_icall_RuntimeType_GetGenericParameterAttributes (MonoReflectionType *type)
2887 g_assert (IS_MONOTYPE (type));
2888 g_assert (is_generic_parameter (type->type));
2889 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2892 ICALL_EXPORT MonoArray *
2893 ves_icall_RuntimeType_GetGenericParameterConstraints (MonoReflectionType *type)
2895 MonoError error;
2896 MonoReflectionType *rt;
2897 MonoGenericParamInfo *param_info;
2898 MonoDomain *domain;
2899 MonoClass **ptr;
2900 MonoArray *res;
2901 int i, count;
2903 g_assert (IS_MONOTYPE (type));
2905 domain = mono_object_domain (type);
2906 param_info = mono_generic_param_info (type->type->data.generic_param);
2907 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2910 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, &error);
2911 if (mono_error_set_pending_exception (&error))
2912 return NULL;
2913 for (i = 0; i < count; i++) {
2914 rt = mono_type_get_object_checked (domain, &param_info->constraints [i]->byval_arg, &error);
2915 if (mono_error_set_pending_exception (&error))
2916 return NULL;
2918 mono_array_setref (res, i, rt);
2922 return res;
2925 ICALL_EXPORT MonoBoolean
2926 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2928 return is_generic_parameter (type->type);
2931 ICALL_EXPORT MonoBoolean
2932 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2934 return is_generic_parameter (tb->type.type);
2937 ICALL_EXPORT void
2938 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2939 MonoReflectionType *t)
2941 enumtype->type = t->type;
2944 ICALL_EXPORT MonoReflectionMethod*
2945 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2946 MonoReflectionMethod* generic)
2948 MonoDomain *domain;
2949 MonoClass *klass;
2950 MonoMethod *method;
2951 gpointer iter;
2952 MonoError error;
2953 MonoReflectionMethod *ret = NULL;
2955 domain = ((MonoObject *)type)->vtable->domain;
2957 klass = mono_class_from_mono_type (type->type);
2958 mono_class_init_checked (klass, &error);
2959 if (mono_error_set_pending_exception (&error))
2960 return NULL;
2962 iter = NULL;
2963 while ((method = mono_class_get_methods (klass, &iter))) {
2964 if (method->token == generic->method->token) {
2965 ret = mono_method_get_object_checked (domain, method, klass, &error);
2966 if (mono_error_set_pending_exception (&error))
2967 return NULL;
2971 return ret;
2974 ICALL_EXPORT MonoReflectionMethod *
2975 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2977 MonoMethod *method;
2978 MonoType *type = ref_type->type;
2979 MonoError error;
2980 MonoReflectionMethod *ret = NULL;
2982 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2983 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2984 return NULL;
2986 if (type->type == MONO_TYPE_VAR)
2987 return NULL;
2989 method = mono_type_get_generic_param_owner (type)->owner.method;
2990 g_assert (method);
2992 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2993 if (!mono_error_ok (&error))
2994 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2995 return ret;
2998 ICALL_EXPORT MonoBoolean
2999 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3001 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3002 return FALSE;
3005 ICALL_EXPORT MonoBoolean
3006 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3008 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3009 return FALSE;
3012 ICALL_EXPORT void
3013 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3015 MonoDomain *domain = mono_domain_get ();
3016 MonoImage *image = method->method->klass->image;
3017 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3018 MonoTableInfo *tables = image->tables;
3019 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3020 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3021 guint32 im_cols [MONO_IMPLMAP_SIZE];
3022 guint32 scope_token;
3023 const char *import = NULL;
3024 const char *scope = NULL;
3026 if (image_is_dynamic (image)) {
3027 MonoReflectionMethodAux *method_aux =
3028 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3029 if (method_aux) {
3030 import = method_aux->dllentry;
3031 scope = method_aux->dll;
3034 if (!import || !scope) {
3035 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3036 return;
3039 else {
3040 if (piinfo->implmap_idx) {
3041 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3043 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3044 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3045 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3046 scope = mono_metadata_string_heap (image, scope_token);
3050 *flags = piinfo->piflags;
3051 *entry_point = mono_string_new (domain, import);
3052 *dll_name = mono_string_new (domain, scope);
3055 ICALL_EXPORT MonoReflectionMethod *
3056 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3058 MonoMethodInflated *imethod;
3059 MonoMethod *result;
3060 MonoReflectionMethod *ret = NULL;
3061 MonoError error;
3063 if (method->method->is_generic)
3064 return method;
3066 if (!method->method->is_inflated)
3067 return NULL;
3069 imethod = (MonoMethodInflated *) method->method;
3071 result = imethod->declaring;
3072 /* Not a generic method. */
3073 if (!result->is_generic)
3074 return NULL;
3076 if (image_is_dynamic (method->method->klass->image)) {
3077 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3078 MonoReflectionMethod *res;
3081 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3082 * the dynamic case as well ?
3084 mono_image_lock ((MonoImage*)image);
3085 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3086 mono_image_unlock ((MonoImage*)image);
3088 if (res)
3089 return res;
3092 if (imethod->context.class_inst) {
3093 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3094 /*Generic methods gets the context of the GTD.*/
3095 if (mono_class_get_context (klass)) {
3096 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3097 if (!mono_error_ok (&error))
3098 goto leave;
3102 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3103 leave:
3104 if (!mono_error_ok (&error))
3105 mono_error_set_pending_exception (&error);
3106 return ret;
3109 ICALL_EXPORT gboolean
3110 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3112 return mono_method_signature (method->method)->generic_param_count != 0;
3115 ICALL_EXPORT gboolean
3116 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3118 return method->method->is_generic;
3121 ICALL_EXPORT MonoArray*
3122 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3124 MonoError error;
3125 MonoReflectionType *rt;
3126 MonoArray *res;
3127 MonoDomain *domain;
3128 int count, i;
3130 domain = mono_object_domain (method);
3132 if (method->method->is_inflated) {
3133 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3135 if (inst) {
3136 count = inst->type_argc;
3137 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3138 if (mono_error_set_pending_exception (&error))
3139 return NULL;
3141 for (i = 0; i < count; i++) {
3142 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3143 if (mono_error_set_pending_exception (&error))
3144 return NULL;
3146 mono_array_setref (res, i, rt);
3149 return res;
3153 count = mono_method_signature (method->method)->generic_param_count;
3154 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3155 if (mono_error_set_pending_exception (&error))
3156 return NULL;
3158 for (i = 0; i < count; i++) {
3159 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3160 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3161 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3163 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3164 if (mono_error_set_pending_exception (&error))
3165 return NULL;
3167 mono_array_setref (res, i, rt);
3170 return res;
3173 ICALL_EXPORT MonoObject *
3174 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3176 MonoError error;
3178 * Invoke from reflection is supposed to always be a virtual call (the API
3179 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3180 * greater flexibility.
3182 MonoMethod *m = method->method;
3183 MonoMethodSignature *sig = mono_method_signature (m);
3184 MonoImage *image;
3185 int pcount;
3186 void *obj = this_arg;
3188 *exc = NULL;
3190 if (mono_security_core_clr_enabled () &&
3191 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3192 mono_error_set_pending_exception (&error);
3193 return NULL;
3196 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3197 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3198 mono_error_cleanup (&error); /* FIXME does this make sense? */
3199 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3200 return NULL;
3203 if (this_arg) {
3204 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3205 if (!is_ok (&error)) {
3206 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3207 return NULL;
3209 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3210 char *target_name = mono_type_get_full_name (m->klass);
3211 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3212 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3213 g_free (msg);
3214 g_free (target_name);
3215 g_free (this_name);
3216 return NULL;
3218 m = mono_object_get_virtual_method (this_arg, m);
3219 /* must pass the pointer to the value for valuetype methods */
3220 if (m->klass->valuetype)
3221 obj = mono_object_unbox (this_arg);
3222 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3223 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3224 return NULL;
3228 if (sig->ret->byref) {
3229 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"));
3230 return NULL;
3233 pcount = params? mono_array_length (params): 0;
3234 if (pcount != sig->param_count) {
3235 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3236 return NULL;
3239 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3240 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."));
3241 return NULL;
3244 image = m->klass->image;
3245 if (image->assembly->ref_only) {
3246 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."));
3247 return NULL;
3250 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3251 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3252 return NULL;
3255 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3256 MonoArray *arr;
3257 int i;
3258 uintptr_t *lengths;
3259 intptr_t *lower_bounds;
3260 pcount = mono_array_length (params);
3261 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3262 /* Note: the synthetized array .ctors have int32 as argument type */
3263 for (i = 0; i < pcount; ++i)
3264 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3266 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3267 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3268 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3269 if (!mono_error_ok (&error)) {
3270 mono_error_set_pending_exception (&error);
3271 return NULL;
3274 for (i = 0; i < mono_array_length (arr); ++i) {
3275 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3276 if (!mono_error_ok (&error)) {
3277 mono_error_set_pending_exception (&error);
3278 return NULL;
3280 mono_array_setref_fast (arr, i, subarray);
3282 return (MonoObject*)arr;
3285 if (m->klass->rank == pcount) {
3286 /* Only lengths provided. */
3287 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3288 if (!mono_error_ok (&error)) {
3289 mono_error_set_pending_exception (&error);
3290 return NULL;
3293 return (MonoObject*)arr;
3294 } else {
3295 g_assert (pcount == (m->klass->rank * 2));
3296 /* The arguments are lower-bound-length pairs */
3297 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3299 for (i = 0; i < pcount / 2; ++i) {
3300 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3301 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3304 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3305 if (!mono_error_ok (&error)) {
3306 mono_error_set_pending_exception (&error);
3307 return NULL;
3310 return (MonoObject*)arr;
3313 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3314 mono_error_set_pending_exception (&error);
3315 return result;
3318 #ifndef DISABLE_REMOTING
3319 ICALL_EXPORT MonoObject *
3320 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3322 MonoError error;
3323 MonoDomain *domain = mono_object_domain (method);
3324 MonoMethod *m = method->method;
3325 MonoMethodSignature *sig = mono_method_signature (m);
3326 MonoArray *out_args;
3327 MonoObject *result;
3328 int i, j, outarg_count = 0;
3330 if (m->klass == mono_defaults.object_class) {
3331 if (!strcmp (m->name, "FieldGetter")) {
3332 MonoClass *k = this_arg->vtable->klass;
3333 MonoString *name;
3334 char *str;
3336 /* If this is a proxy, then it must be a CBO */
3337 if (k == mono_defaults.transparent_proxy_class) {
3338 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3339 this_arg = tp->rp->unwrapped_server;
3340 g_assert (this_arg);
3341 k = this_arg->vtable->klass;
3344 name = mono_array_get (params, MonoString *, 1);
3345 str = mono_string_to_utf8_checked (name, &error);
3346 if (mono_error_set_pending_exception (&error))
3347 return NULL;
3349 do {
3350 MonoClassField* field = mono_class_get_field_from_name (k, str);
3351 if (field) {
3352 g_free (str);
3353 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3354 if (field_klass->valuetype) {
3355 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3356 if (mono_error_set_pending_exception (&error))
3357 return NULL;
3358 } else
3359 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3361 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3362 if (mono_error_set_pending_exception (&error))
3363 return NULL;
3364 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3365 mono_array_setref (out_args, 0, result);
3366 return NULL;
3368 k = k->parent;
3369 } while (k);
3371 g_free (str);
3372 g_assert_not_reached ();
3374 } else if (!strcmp (m->name, "FieldSetter")) {
3375 MonoClass *k = this_arg->vtable->klass;
3376 MonoString *name;
3377 guint32 size;
3378 gint32 align;
3379 char *str;
3381 /* If this is a proxy, then it must be a CBO */
3382 if (k == mono_defaults.transparent_proxy_class) {
3383 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3384 this_arg = tp->rp->unwrapped_server;
3385 g_assert (this_arg);
3386 k = this_arg->vtable->klass;
3389 name = mono_array_get (params, MonoString *, 1);
3390 str = mono_string_to_utf8_checked (name, &error);
3391 if (mono_error_set_pending_exception (&error))
3392 return NULL;
3394 do {
3395 MonoClassField* field = mono_class_get_field_from_name (k, str);
3396 if (field) {
3397 g_free (str);
3398 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3399 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3401 if (field_klass->valuetype) {
3402 size = mono_type_size (field->type, &align);
3403 g_assert (size == mono_class_value_size (field_klass, NULL));
3404 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3405 } else {
3406 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3409 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3410 if (mono_error_set_pending_exception (&error))
3411 return NULL;
3412 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3414 return NULL;
3417 k = k->parent;
3418 } while (k);
3420 g_free (str);
3421 g_assert_not_reached ();
3426 for (i = 0; i < mono_array_length (params); i++) {
3427 if (sig->params [i]->byref)
3428 outarg_count++;
3431 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3432 if (mono_error_set_pending_exception (&error))
3433 return NULL;
3435 /* handle constructors only for objects already allocated */
3436 if (!strcmp (method->method->name, ".ctor"))
3437 g_assert (this_arg);
3439 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3440 g_assert (!method->method->klass->valuetype);
3441 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3442 if (mono_error_set_pending_exception (&error))
3443 return NULL;
3445 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3446 if (sig->params [i]->byref) {
3447 gpointer arg;
3448 arg = mono_array_get (params, gpointer, i);
3449 mono_array_setref (out_args, j, arg);
3450 j++;
3454 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3456 return result;
3458 #endif
3460 static guint64
3461 read_enum_value (const char *mem, int type)
3463 switch (type) {
3464 case MONO_TYPE_BOOLEAN:
3465 case MONO_TYPE_U1:
3466 return *(guint8*)mem;
3467 case MONO_TYPE_I1:
3468 return *(gint8*)mem;
3469 case MONO_TYPE_CHAR:
3470 case MONO_TYPE_U2:
3471 return read16 (mem);
3472 case MONO_TYPE_I2:
3473 return (gint16) read16 (mem);
3474 case MONO_TYPE_U4:
3475 return read32 (mem);
3476 case MONO_TYPE_I4:
3477 return (gint32) read32 (mem);
3478 case MONO_TYPE_U8:
3479 case MONO_TYPE_I8:
3480 return read64 (mem);
3481 default:
3482 g_assert_not_reached ();
3484 return 0;
3487 static void
3488 write_enum_value (char *mem, int type, guint64 value)
3490 switch (type) {
3491 case MONO_TYPE_U1:
3492 case MONO_TYPE_I1: {
3493 guint8 *p = (guint8*)mem;
3494 *p = value;
3495 break;
3497 case MONO_TYPE_U2:
3498 case MONO_TYPE_I2:
3499 case MONO_TYPE_CHAR: {
3500 guint16 *p = (guint16 *)mem;
3501 *p = value;
3502 break;
3504 case MONO_TYPE_U4:
3505 case MONO_TYPE_I4: {
3506 guint32 *p = (guint32 *)mem;
3507 *p = value;
3508 break;
3510 case MONO_TYPE_U8:
3511 case MONO_TYPE_I8: {
3512 guint64 *p = (guint64 *)mem;
3513 *p = value;
3514 break;
3516 default:
3517 g_assert_not_reached ();
3519 return;
3522 ICALL_EXPORT MonoObject *
3523 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3525 MonoError error;
3526 MonoDomain *domain;
3527 MonoClass *enumc;
3528 MonoObject *res;
3529 MonoType *etype;
3531 domain = mono_object_domain (enumType);
3532 enumc = mono_class_from_mono_type (enumType->type);
3534 mono_class_init_checked (enumc, &error);
3535 if (mono_error_set_pending_exception (&error))
3536 return NULL;
3538 etype = mono_class_enum_basetype (enumc);
3540 res = mono_object_new_checked (domain, enumc, &error);
3541 if (mono_error_set_pending_exception (&error))
3542 return NULL;
3543 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3545 return res;
3548 ICALL_EXPORT MonoBoolean
3549 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3551 int size = mono_class_value_size (a->vtable->klass, NULL);
3552 guint64 a_val = 0, b_val = 0;
3554 memcpy (&a_val, mono_object_unbox (a), size);
3555 memcpy (&b_val, mono_object_unbox (b), size);
3557 return (a_val & b_val) == b_val;
3560 ICALL_EXPORT MonoObject *
3561 ves_icall_System_Enum_get_value (MonoObject *eobj)
3563 MonoError error;
3564 MonoObject *res;
3565 MonoClass *enumc;
3566 gpointer dst;
3567 gpointer src;
3568 int size;
3570 if (!eobj)
3571 return NULL;
3573 g_assert (eobj->vtable->klass->enumtype);
3575 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3576 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3577 if (mono_error_set_pending_exception (&error))
3578 return NULL;
3579 dst = (char *)res + sizeof (MonoObject);
3580 src = (char *)eobj + sizeof (MonoObject);
3581 size = mono_class_value_size (enumc, NULL);
3583 memcpy (dst, src, size);
3585 return res;
3588 ICALL_EXPORT MonoReflectionType *
3589 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3591 MonoError error;
3592 MonoReflectionType *ret;
3593 MonoType *etype;
3594 MonoClass *klass;
3596 klass = mono_class_from_mono_type (type->type);
3597 mono_class_init_checked (klass, &error);
3598 if (mono_error_set_pending_exception (&error))
3599 return NULL;
3601 etype = mono_class_enum_basetype (klass);
3602 if (!etype) {
3603 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3604 return NULL;
3607 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3608 mono_error_set_pending_exception (&error);
3610 return ret;
3613 ICALL_EXPORT int
3614 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3616 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3617 gpointer odata = (char *)other + sizeof (MonoObject);
3618 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3619 g_assert (basetype);
3621 if (other == NULL)
3622 return 1;
3624 if (eobj->vtable->klass != other->vtable->klass)
3625 return 2;
3627 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3628 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3629 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3630 if (me == other) \
3631 return 0; \
3632 return me > other ? 1 : -1; \
3633 } while (0)
3635 switch (basetype->type) {
3636 case MONO_TYPE_U1:
3637 COMPARE_ENUM_VALUES (guint8);
3638 case MONO_TYPE_I1:
3639 COMPARE_ENUM_VALUES (gint8);
3640 case MONO_TYPE_CHAR:
3641 case MONO_TYPE_U2:
3642 COMPARE_ENUM_VALUES (guint16);
3643 case MONO_TYPE_I2:
3644 COMPARE_ENUM_VALUES (gint16);
3645 case MONO_TYPE_U4:
3646 COMPARE_ENUM_VALUES (guint32);
3647 case MONO_TYPE_I4:
3648 COMPARE_ENUM_VALUES (gint32);
3649 case MONO_TYPE_U8:
3650 COMPARE_ENUM_VALUES (guint64);
3651 case MONO_TYPE_I8:
3652 COMPARE_ENUM_VALUES (gint64);
3653 default:
3654 break;
3656 #undef COMPARE_ENUM_VALUES
3657 /* indicates that the enum was of an unsupported unerlying type */
3658 return 3;
3661 ICALL_EXPORT int
3662 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3664 gpointer data = (char *)eobj + sizeof (MonoObject);
3665 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3666 g_assert (basetype);
3668 switch (basetype->type) {
3669 case MONO_TYPE_I1: {
3670 gint8 value = *((gint8*)data);
3671 return ((int)value ^ (int)value << 8);
3673 case MONO_TYPE_U1:
3674 return *((guint8*)data);
3675 case MONO_TYPE_CHAR:
3676 case MONO_TYPE_U2:
3677 return *((guint16*)data);
3679 case MONO_TYPE_I2: {
3680 gint16 value = *((gint16*)data);
3681 return ((int)(guint16)value | (((int)value) << 16));
3683 case MONO_TYPE_U4:
3684 return *((guint32*)data);
3685 case MONO_TYPE_I4:
3686 return *((gint32*)data);
3687 case MONO_TYPE_U8:
3688 case MONO_TYPE_I8: {
3689 gint64 value = *((gint64*)data);
3690 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3692 default:
3693 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3695 return 0;
3698 ICALL_EXPORT MonoBoolean
3699 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3701 MonoError error;
3702 MonoDomain *domain = mono_object_domain (type);
3703 MonoClass *enumc = mono_class_from_mono_type (type->type);
3704 guint j = 0, nvalues;
3705 gpointer iter;
3706 MonoClassField *field;
3707 int base_type;
3708 guint64 field_value, previous_value = 0;
3709 gboolean sorted = TRUE;
3711 mono_class_init_checked (enumc, &error);
3712 if (mono_error_set_pending_exception (&error))
3713 return FALSE;
3716 if (!enumc->enumtype) {
3717 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3718 return TRUE;
3721 base_type = mono_class_enum_basetype (enumc)->type;
3723 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3724 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3725 if (mono_error_set_pending_exception (&error))
3726 return FALSE;
3727 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3728 if (mono_error_set_pending_exception (&error))
3729 return FALSE;
3731 iter = NULL;
3732 while ((field = mono_class_get_fields (enumc, &iter))) {
3733 const char *p;
3734 MonoTypeEnum def_type;
3736 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3737 continue;
3738 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3739 continue;
3740 if (mono_field_is_deleted (field))
3741 continue;
3742 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3744 p = mono_class_get_field_default_value (field, &def_type);
3745 /* len = */ mono_metadata_decode_blob_size (p, &p);
3747 field_value = read_enum_value (p, base_type);
3748 mono_array_set (*values, guint64, j, field_value);
3750 if (previous_value > field_value)
3751 sorted = FALSE;
3753 previous_value = field_value;
3754 ++j;
3757 return sorted;
3760 enum {
3761 BFLAGS_IgnoreCase = 1,
3762 BFLAGS_DeclaredOnly = 2,
3763 BFLAGS_Instance = 4,
3764 BFLAGS_Static = 8,
3765 BFLAGS_Public = 0x10,
3766 BFLAGS_NonPublic = 0x20,
3767 BFLAGS_FlattenHierarchy = 0x40,
3768 BFLAGS_InvokeMethod = 0x100,
3769 BFLAGS_CreateInstance = 0x200,
3770 BFLAGS_GetField = 0x400,
3771 BFLAGS_SetField = 0x800,
3772 BFLAGS_GetProperty = 0x1000,
3773 BFLAGS_SetProperty = 0x2000,
3774 BFLAGS_ExactBinding = 0x10000,
3775 BFLAGS_SuppressChangeType = 0x20000,
3776 BFLAGS_OptionalParamBinding = 0x40000
3779 ICALL_EXPORT MonoArray*
3780 ves_icall_RuntimeType_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3782 MonoError error;
3783 MonoDomain *domain;
3784 MonoClass *startklass, *klass, *refklass;
3785 MonoArray *res;
3786 MonoObject *member;
3787 int i, match;
3788 gpointer iter;
3789 char *utf8_name = NULL;
3790 int (*compare_func) (const char *s1, const char *s2) = NULL;
3791 MonoClassField *field;
3792 MonoPtrArray tmp_array;
3794 domain = ((MonoObject *)type)->vtable->domain;
3795 if (type->type->byref) {
3796 MonoArray *result = mono_array_new_checked (domain, mono_defaults.field_info_class, 0, &error);
3797 mono_error_set_pending_exception (&error);
3798 return result;
3801 klass = startklass = mono_class_from_mono_type (type->type);
3802 refklass = mono_class_from_mono_type (reftype->type);
3804 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3806 handle_parent:
3807 if (mono_class_has_failure (klass)) {
3808 mono_ptr_array_destroy (tmp_array);
3809 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3810 return NULL;
3813 iter = NULL;
3814 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3815 guint32 flags = mono_field_get_flags (field);
3816 match = 0;
3817 if (mono_field_is_deleted_with_flags (field, flags))
3818 continue;
3819 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3820 if (bflags & BFLAGS_Public)
3821 match++;
3822 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3823 if (bflags & BFLAGS_NonPublic) {
3824 match++;
3827 if (!match)
3828 continue;
3829 match = 0;
3830 if (flags & FIELD_ATTRIBUTE_STATIC) {
3831 if (bflags & BFLAGS_Static)
3832 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3833 match++;
3834 } else {
3835 if (bflags & BFLAGS_Instance)
3836 match++;
3839 if (!match)
3840 continue;
3842 if (name != NULL) {
3843 if (utf8_name == NULL) {
3844 utf8_name = mono_string_to_utf8_checked (name, &error);
3845 if (!is_ok (&error))
3846 goto fail;
3847 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3850 if (compare_func (mono_field_get_name (field), utf8_name))
3851 continue;
3854 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3855 if (!mono_error_ok (&error))
3856 goto fail;
3857 mono_ptr_array_append (tmp_array, member);
3859 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3860 goto handle_parent;
3862 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array), &error);
3863 if (!is_ok (&error))
3864 goto fail;
3866 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3867 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3869 mono_ptr_array_destroy (tmp_array);
3871 if (utf8_name != NULL)
3872 g_free (utf8_name);
3874 return res;
3875 fail:
3876 mono_ptr_array_destroy (tmp_array);
3877 mono_error_set_pending_exception (&error);
3878 return NULL;
3881 static gboolean
3882 method_nonpublic (MonoMethod* method, gboolean start_klass)
3884 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3885 case METHOD_ATTRIBUTE_ASSEM:
3886 return (start_klass || mono_defaults.generic_ilist_class);
3887 case METHOD_ATTRIBUTE_PRIVATE:
3888 return start_klass;
3889 case METHOD_ATTRIBUTE_PUBLIC:
3890 return FALSE;
3891 default:
3892 return TRUE;
3896 GPtrArray*
3897 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3899 GPtrArray *array;
3900 MonoClass *startklass;
3901 MonoMethod *method;
3902 gpointer iter;
3903 int match, nslots;
3904 /*FIXME, use MonoBitSet*/
3905 guint32 method_slots_default [8];
3906 guint32 *method_slots = NULL;
3907 int (*compare_func) (const char *s1, const char *s2) = NULL;
3909 array = g_ptr_array_new ();
3910 startklass = klass;
3911 *ex = NULL;
3913 if (name != NULL)
3914 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3916 /* An optimization for calls made from Delegate:CreateDelegate () */
3917 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3918 method = mono_get_delegate_invoke (klass);
3919 g_assert (method);
3921 g_ptr_array_add (array, method);
3922 return array;
3925 mono_class_setup_methods (klass);
3926 mono_class_setup_vtable (klass);
3927 if (mono_class_has_failure (klass))
3928 goto loader_error;
3930 if (is_generic_parameter (&klass->byval_arg))
3931 nslots = mono_class_get_vtable_size (klass->parent);
3932 else
3933 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3934 if (nslots >= sizeof (method_slots_default) * 8) {
3935 method_slots = g_new0 (guint32, nslots / 32 + 1);
3936 } else {
3937 method_slots = method_slots_default;
3938 memset (method_slots, 0, sizeof (method_slots_default));
3940 handle_parent:
3941 mono_class_setup_methods (klass);
3942 mono_class_setup_vtable (klass);
3943 if (mono_class_has_failure (klass))
3944 goto loader_error;
3946 iter = NULL;
3947 while ((method = mono_class_get_methods (klass, &iter))) {
3948 match = 0;
3949 if (method->slot != -1) {
3950 g_assert (method->slot < nslots);
3951 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3952 continue;
3953 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3954 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3957 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3958 continue;
3959 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3960 if (bflags & BFLAGS_Public)
3961 match++;
3962 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3963 match++;
3965 if (!match)
3966 continue;
3967 match = 0;
3968 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3969 if (bflags & BFLAGS_Static)
3970 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3971 match++;
3972 } else {
3973 if (bflags & BFLAGS_Instance)
3974 match++;
3977 if (!match)
3978 continue;
3980 if (name != NULL) {
3981 if (compare_func (name, method->name))
3982 continue;
3985 match = 0;
3986 g_ptr_array_add (array, method);
3988 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3989 goto handle_parent;
3990 if (method_slots != method_slots_default)
3991 g_free (method_slots);
3993 return array;
3995 loader_error:
3996 if (method_slots != method_slots_default)
3997 g_free (method_slots);
3998 g_ptr_array_free (array, TRUE);
4000 if (mono_class_has_failure (klass)) {
4001 *ex = mono_class_get_exception_for_failure (klass);
4002 } else {
4003 *ex = mono_get_exception_execution_engine ("Unknown error");
4005 return NULL;
4008 ICALL_EXPORT MonoArray*
4009 ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4011 static MonoClass *MethodInfo_array;
4012 MonoError error;
4013 MonoDomain *domain;
4014 MonoArray *res;
4015 MonoVTable *array_vtable;
4016 MonoException *ex = NULL;
4017 const char *mname = NULL;
4018 GPtrArray *method_array;
4019 MonoClass *klass, *refklass;
4020 int i;
4022 mono_error_init (&error);
4024 if (!MethodInfo_array) {
4025 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
4026 mono_memory_barrier ();
4027 MethodInfo_array = klass;
4030 klass = mono_class_from_mono_type (type->type);
4031 refklass = mono_class_from_mono_type (reftype->type);
4032 domain = ((MonoObject *)type)->vtable->domain;
4033 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
4034 if (!is_ok (&error)) {
4035 mono_error_set_pending_exception (&error);
4036 return NULL;
4038 if (type->type->byref) {
4039 res = mono_array_new_specific_checked (array_vtable, 0, &error);
4040 mono_error_set_pending_exception (&error);
4042 return res;
4045 if (name) {
4046 mname = mono_string_to_utf8_checked (name, &error);
4047 if (mono_error_set_pending_exception (&error))
4048 return NULL;
4051 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
4052 g_free ((char*)mname);
4053 if (ex) {
4054 mono_set_pending_exception (ex);
4055 return NULL;
4058 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
4059 if (!mono_error_ok (&error)) {
4060 mono_error_set_pending_exception (&error);
4061 return NULL;
4064 for (i = 0; i < method_array->len; ++i) {
4065 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
4066 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
4067 if (!mono_error_ok (&error))
4068 goto failure;
4069 mono_array_setref (res, i, rm);
4072 failure:
4073 g_ptr_array_free (method_array, TRUE);
4074 if (!mono_error_ok (&error))
4075 mono_set_pending_exception (mono_error_convert_to_exception (&error));
4076 return res;
4079 ICALL_EXPORT MonoArray*
4080 ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4082 MonoDomain *domain;
4083 MonoClass *startklass, *klass, *refklass;
4084 MonoArray *res = NULL;
4085 MonoMethod *method;
4086 MonoObject *member;
4087 int i, match;
4088 gpointer iter = NULL;
4089 MonoPtrArray tmp_array;
4090 MonoError error;
4092 domain = ((MonoObject *)type)->vtable->domain;
4093 if (type->type->byref) {
4094 res = mono_array_new_cached (domain, mono_defaults.method_info_class, 0, &error);
4095 mono_error_set_pending_exception (&error);
4096 return res;
4099 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
4102 klass = startklass = mono_class_from_mono_type (type->type);
4103 refklass = mono_class_from_mono_type (reftype->type);
4105 mono_class_setup_methods (klass);
4106 if (mono_class_has_failure (klass)) {
4107 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
4108 goto leave;
4111 iter = NULL;
4112 while ((method = mono_class_get_methods (klass, &iter))) {
4113 match = 0;
4114 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4115 continue;
4116 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4117 if (bflags & BFLAGS_Public)
4118 match++;
4119 } else {
4120 if (bflags & BFLAGS_NonPublic)
4121 match++;
4123 if (!match)
4124 continue;
4125 match = 0;
4126 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4127 if (bflags & BFLAGS_Static)
4128 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4129 match++;
4130 } else {
4131 if (bflags & BFLAGS_Instance)
4132 match++;
4135 if (!match)
4136 continue;
4137 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
4138 if (mono_error_set_pending_exception (&error))
4139 goto leave;
4141 mono_ptr_array_append (tmp_array, member);
4144 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array), &error);
4145 if (mono_error_set_pending_exception (&error))
4146 goto leave;
4148 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4149 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4151 leave:
4152 mono_ptr_array_destroy (tmp_array);
4154 return res;
4157 static guint
4158 property_hash (gconstpointer data)
4160 MonoProperty *prop = (MonoProperty*)data;
4162 return g_str_hash (prop->name);
4165 static gboolean
4166 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4168 if (method1->slot != -1 && method1->slot == method2->slot)
4169 return TRUE;
4171 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4172 if (method1->is_inflated)
4173 method1 = ((MonoMethodInflated*) method1)->declaring;
4174 if (method2->is_inflated)
4175 method2 = ((MonoMethodInflated*) method2)->declaring;
4178 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4181 static gboolean
4182 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4184 // Properties are hide-by-name-and-signature
4185 if (!g_str_equal (prop1->name, prop2->name))
4186 return FALSE;
4188 /* If we see a property in a generic method, we want to
4189 compare the generic signatures, not the inflated signatures
4190 because we might conflate two properties that were
4191 distinct:
4193 class Foo<T,U> {
4194 public T this[T t] { getter { return t; } } // method 1
4195 public U this[U u] { getter { return u; } } // method 2
4198 If we see int Foo<int,int>::Item[int] we need to know if
4199 the indexer came from method 1 or from method 2, and we
4200 shouldn't conflate them. (Bugzilla 36283)
4202 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4203 return FALSE;
4205 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4206 return FALSE;
4208 return TRUE;
4211 static gboolean
4212 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4214 if (!accessor)
4215 return FALSE;
4217 return method_nonpublic (accessor, start_klass);
4220 ICALL_EXPORT MonoArray*
4221 ves_icall_RuntimeType_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4223 MonoError error;
4224 MonoDomain *domain;
4225 MonoClass *startklass, *klass;
4226 MonoArray *res;
4227 MonoMethod *method;
4228 MonoProperty *prop;
4229 int i, match;
4230 guint32 flags;
4231 gchar *propname = NULL;
4232 int (*compare_func) (const char *s1, const char *s2) = NULL;
4233 gpointer iter;
4234 GHashTable *properties = NULL;
4235 MonoPtrArray tmp_array;
4237 mono_error_init (&error);
4239 domain = ((MonoObject *)type)->vtable->domain;
4240 if (type->type->byref) {
4241 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), 0, &error);
4242 mono_error_set_pending_exception (&error);
4243 return res;
4246 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4248 klass = startklass = mono_class_from_mono_type (type->type);
4250 if (name != NULL) {
4251 propname = mono_string_to_utf8_checked (name, &error);
4252 if (mono_error_set_pending_exception (&error))
4253 return NULL;
4254 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4257 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4258 handle_parent:
4259 mono_class_setup_methods (klass);
4260 mono_class_setup_vtable (klass);
4261 if (mono_class_has_failure (klass))
4262 goto loader_error;
4264 iter = NULL;
4265 while ((prop = mono_class_get_properties (klass, &iter))) {
4266 match = 0;
4267 method = prop->get;
4268 if (!method)
4269 method = prop->set;
4270 if (method)
4271 flags = method->flags;
4272 else
4273 flags = 0;
4274 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4275 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4276 if (bflags & BFLAGS_Public)
4277 match++;
4278 } else if (bflags & BFLAGS_NonPublic) {
4279 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4280 property_accessor_nonpublic(prop->set, startklass == klass)) {
4281 match++;
4284 if (!match)
4285 continue;
4286 match = 0;
4287 if (flags & METHOD_ATTRIBUTE_STATIC) {
4288 if (bflags & BFLAGS_Static)
4289 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4290 match++;
4291 } else {
4292 if (bflags & BFLAGS_Instance)
4293 match++;
4296 if (!match)
4297 continue;
4298 match = 0;
4300 if (name != NULL) {
4301 if (compare_func (propname, prop->name))
4302 continue;
4305 if (g_hash_table_lookup (properties, prop))
4306 continue;
4308 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4309 if (!pr)
4310 goto failure;
4311 mono_ptr_array_append (tmp_array, pr);
4313 g_hash_table_insert (properties, prop, prop);
4315 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4316 goto handle_parent;
4318 g_hash_table_destroy (properties);
4319 g_free (propname);
4321 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array), &error);
4322 if (!is_ok (&error))
4323 goto failure;
4324 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4325 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4327 mono_ptr_array_destroy (tmp_array);
4329 return res;
4333 loader_error:
4334 if (mono_class_has_failure (klass))
4335 mono_error_set_for_class_failure (&error, klass);
4337 failure:
4338 if (properties)
4339 g_hash_table_destroy (properties);
4340 if (name)
4341 g_free (propname);
4342 mono_ptr_array_destroy (tmp_array);
4344 mono_error_set_pending_exception (&error);
4346 return NULL;
4349 static guint
4350 event_hash (gconstpointer data)
4352 MonoEvent *event = (MonoEvent*)data;
4354 return g_str_hash (event->name);
4357 static gboolean
4358 event_equal (MonoEvent *event1, MonoEvent *event2)
4360 // Events are hide-by-name
4361 return g_str_equal (event1->name, event2->name);
4364 ICALL_EXPORT MonoArray*
4365 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4367 MonoError error;
4368 MonoDomain *domain;
4369 MonoClass *startklass, *klass;
4370 MonoArray *res;
4371 MonoMethod *method;
4372 MonoEvent *event;
4373 int i, match;
4374 gpointer iter;
4375 char *utf8_name = NULL;
4376 int (*compare_func) (const char *s1, const char *s2) = NULL;
4377 GHashTable *events = NULL;
4378 MonoPtrArray tmp_array;
4380 mono_error_init (&error);
4382 domain = mono_object_domain (type);
4383 if (type->type->byref) {
4384 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), 0, &error);
4385 mono_error_set_pending_exception (&error);
4386 return res;
4389 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4391 klass = startklass = mono_class_from_mono_type (type->type);
4393 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4394 handle_parent:
4395 mono_class_setup_methods (klass);
4396 mono_class_setup_vtable (klass);
4397 if (mono_class_has_failure (klass))
4398 goto loader_error;
4400 iter = NULL;
4401 while ((event = mono_class_get_events (klass, &iter))) {
4402 match = 0;
4403 method = event->add;
4404 if (!method)
4405 method = event->remove;
4406 if (!method)
4407 method = event->raise;
4408 if (method) {
4409 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4410 if (bflags & BFLAGS_Public)
4411 match++;
4412 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4413 if (bflags & BFLAGS_NonPublic)
4414 match++;
4417 else
4418 if (bflags & BFLAGS_NonPublic)
4419 match ++;
4420 if (!match)
4421 continue;
4422 match = 0;
4423 if (method) {
4424 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4425 if (bflags & BFLAGS_Static)
4426 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4427 match++;
4428 } else {
4429 if (bflags & BFLAGS_Instance)
4430 match++;
4433 else
4434 if (bflags & BFLAGS_Instance)
4435 match ++;
4436 if (!match)
4437 continue;
4439 if (name != NULL) {
4440 if (utf8_name == NULL) {
4441 utf8_name = mono_string_to_utf8_checked (name, &error);
4442 if (!is_ok (&error))
4443 goto failure;
4444 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4447 if (compare_func (event->name, utf8_name))
4448 continue;
4451 if (g_hash_table_lookup (events, event))
4452 continue;
4454 MonoReflectionEvent *ev_obj;
4455 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4456 if (!ev_obj)
4457 goto failure;
4458 mono_ptr_array_append (tmp_array, ev_obj);
4460 g_hash_table_insert (events, event, event);
4462 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4463 goto handle_parent;
4465 g_hash_table_destroy (events);
4467 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array), &error);
4468 if (!is_ok (&error))
4469 goto failure;
4471 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4472 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4474 mono_ptr_array_destroy (tmp_array);
4476 if (utf8_name != NULL)
4477 g_free (utf8_name);
4479 return res;
4481 loader_error:
4482 if (mono_class_has_failure (klass))
4483 mono_error_set_for_class_failure (&error, klass);
4485 failure:
4487 if (events != NULL)
4488 g_hash_table_destroy (events);
4489 if (utf8_name != NULL)
4490 g_free (utf8_name);
4492 mono_ptr_array_destroy (tmp_array);
4494 mono_error_set_pending_exception (&error);
4495 return NULL;
4498 ICALL_EXPORT MonoArray*
4499 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4501 MonoError error;
4502 MonoReflectionType *rt;
4503 MonoDomain *domain;
4504 MonoClass *klass;
4505 MonoArray *res = NULL;
4506 int i, match;
4507 MonoClass *nested;
4508 gpointer iter;
4509 char *str = NULL;
4510 MonoPtrArray tmp_array;
4512 mono_error_init (&error);
4514 domain = ((MonoObject *)type)->vtable->domain;
4515 if (type->type->byref) {
4516 MonoArray *result = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, &error);
4517 mono_error_set_pending_exception (&error);
4518 return result;
4520 klass = mono_class_from_mono_type (type->type);
4523 * If a nested type is generic, return its generic type definition.
4524 * Note that this means that the return value is essentially the set
4525 * of nested types of the generic type definition of @klass.
4527 * A note in MSDN claims that a generic type definition can have
4528 * nested types that aren't generic. In any case, the container of that
4529 * nested type would be the generic type definition.
4531 if (klass->generic_class)
4532 klass = klass->generic_class->container_class;
4534 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4535 iter = NULL;
4536 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4537 match = 0;
4538 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4539 if (bflags & BFLAGS_Public)
4540 match++;
4541 } else {
4542 if (bflags & BFLAGS_NonPublic)
4543 match++;
4545 if (!match)
4546 continue;
4548 if (name != NULL) {
4549 if (str == NULL) {
4550 str = mono_string_to_utf8_checked (name, &error);
4551 if (!is_ok (&error))
4552 goto leave;
4553 mono_identifier_unescape_type_name_chars (str);
4556 if (strcmp (nested->name, str))
4557 continue;
4560 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4561 if (!is_ok (&error))
4562 goto leave;
4564 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4567 res = mono_array_new_cached (domain, mono_defaults.runtimetype_class, mono_ptr_array_size (tmp_array), &error);
4568 if (!is_ok (&error))
4569 goto leave;
4571 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4572 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4574 leave:
4575 mono_ptr_array_destroy (tmp_array);
4577 g_free (str);
4579 mono_error_set_pending_exception (&error);
4580 return res;
4583 ICALL_EXPORT MonoReflectionType*
4584 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4586 MonoError error;
4587 MonoReflectionType *ret;
4588 gchar *str;
4589 MonoType *type = NULL;
4590 MonoTypeNameParse info;
4591 gboolean type_resolve;
4593 /* On MS.NET, this does not fire a TypeResolve event */
4594 type_resolve = TRUE;
4595 str = mono_string_to_utf8_checked (name, &error);
4596 if (mono_error_set_pending_exception (&error))
4597 return NULL;
4598 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4599 if (!mono_reflection_parse_type (str, &info)) {
4600 g_free (str);
4601 mono_reflection_free_type_info (&info);
4602 if (throwOnError) {
4603 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4604 return NULL;
4606 /*g_print ("failed parse\n");*/
4607 return NULL;
4610 if (info.assembly.name) {
4611 g_free (str);
4612 mono_reflection_free_type_info (&info);
4613 if (throwOnError) {
4614 /* 1.0 and 2.0 throw different exceptions */
4615 if (mono_defaults.generic_ilist_class)
4616 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4617 else
4618 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4619 return NULL;
4621 return NULL;
4624 if (module != NULL) {
4625 if (module->image) {
4626 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4627 if (!is_ok (&error)) {
4628 g_free (str);
4629 mono_reflection_free_type_info (&info);
4630 mono_error_set_pending_exception (&error);
4631 return NULL;
4633 } else
4634 type = NULL;
4636 else
4637 if (assembly_is_dynamic (assembly->assembly)) {
4638 /* Enumerate all modules */
4639 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4640 int i;
4642 type = NULL;
4643 if (abuilder->modules) {
4644 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4645 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4646 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4647 if (!is_ok (&error)) {
4648 g_free (str);
4649 mono_reflection_free_type_info (&info);
4650 mono_error_set_pending_exception (&error);
4651 return NULL;
4653 if (type)
4654 break;
4658 if (!type && abuilder->loaded_modules) {
4659 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4660 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4661 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4662 if (!is_ok (&error)) {
4663 g_free (str);
4664 mono_reflection_free_type_info (&info);
4665 mono_error_set_pending_exception (&error);
4666 return NULL;
4668 if (type)
4669 break;
4673 else {
4674 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4675 if (!is_ok (&error)) {
4676 g_free (str);
4677 mono_reflection_free_type_info (&info);
4678 mono_error_set_pending_exception (&error);
4679 return NULL;
4682 g_free (str);
4683 mono_reflection_free_type_info (&info);
4684 if (!type) {
4685 MonoException *e = NULL;
4687 if (throwOnError)
4688 e = mono_get_exception_type_load (name, NULL);
4690 if (e != NULL)
4691 mono_set_pending_exception (e);
4692 return NULL;
4695 if (type->type == MONO_TYPE_CLASS) {
4696 MonoClass *klass = mono_type_get_class (type);
4698 /* need to report exceptions ? */
4699 if (throwOnError && mono_class_has_failure (klass)) {
4700 /* report SecurityException (or others) that occured when loading the assembly */
4701 MonoException *exc = mono_class_get_exception_for_failure (klass);
4702 mono_set_pending_exception (exc);
4703 return NULL;
4707 /* g_print ("got it\n"); */
4708 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4709 mono_error_set_pending_exception (&error);
4711 return ret;
4714 static gboolean
4715 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4717 gchar *content;
4718 gchar *shadow_ini_file;
4719 gsize len;
4721 /* Check for shadow-copied assembly */
4722 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4723 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4724 content = NULL;
4725 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4726 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4727 if (content) {
4728 g_free (content);
4729 content = NULL;
4732 g_free (shadow_ini_file);
4733 if (content != NULL) {
4734 if (*filename)
4735 g_free (*filename);
4736 *filename = content;
4737 return TRUE;
4740 return FALSE;
4743 ICALL_EXPORT MonoString *
4744 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4746 MonoDomain *domain = mono_object_domain (assembly);
4747 MonoAssembly *mass = assembly->assembly;
4748 MonoString *res = NULL;
4749 gchar *uri;
4750 gchar *absolute;
4751 gchar *dirname;
4753 if (g_path_is_absolute (mass->image->name)) {
4754 absolute = g_strdup (mass->image->name);
4755 dirname = g_path_get_dirname (absolute);
4756 } else {
4757 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4758 dirname = g_strdup (mass->basedir);
4761 replace_shadow_path (domain, dirname, &absolute);
4762 g_free (dirname);
4763 #if HOST_WIN32
4765 gint i;
4766 for (i = strlen (absolute) - 1; i >= 0; i--)
4767 if (absolute [i] == '\\')
4768 absolute [i] = '/';
4770 #endif
4771 if (escaped) {
4772 uri = g_filename_to_uri (absolute, NULL, NULL);
4773 } else {
4774 const char *prepend = "file://";
4775 #if HOST_WIN32
4776 if (*absolute == '/' && *(absolute + 1) == '/') {
4777 prepend = "file:";
4778 } else {
4779 prepend = "file:///";
4781 #endif
4782 uri = g_strconcat (prepend, absolute, NULL);
4785 if (uri) {
4786 res = mono_string_new (domain, uri);
4787 g_free (uri);
4789 g_free (absolute);
4790 return res;
4793 ICALL_EXPORT MonoBoolean
4794 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4796 MonoAssembly *mass = assembly->assembly;
4798 return mass->in_gac;
4801 ICALL_EXPORT MonoReflectionAssembly*
4802 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4804 MonoError error;
4805 gchar *name;
4806 MonoAssembly *res;
4807 MonoImageOpenStatus status;
4808 MonoReflectionAssembly* result = NULL;
4810 name = mono_string_to_utf8_checked (mname, &error);
4811 if (mono_error_set_pending_exception (&error))
4812 return NULL;
4813 res = mono_assembly_load_with_partial_name (name, &status);
4815 g_free (name);
4817 if (res == NULL)
4818 return NULL;
4819 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4820 if (!result)
4821 mono_error_set_pending_exception (&error);
4822 return result;
4825 ICALL_EXPORT MonoString *
4826 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4828 MonoDomain *domain = mono_object_domain (assembly);
4829 MonoString *res;
4831 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4833 return res;
4836 ICALL_EXPORT MonoBoolean
4837 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4839 return assembly->assembly->ref_only;
4842 ICALL_EXPORT MonoString *
4843 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4845 MonoDomain *domain = mono_object_domain (assembly);
4847 return mono_string_new (domain, assembly->assembly->image->version);
4850 ICALL_EXPORT MonoReflectionMethod*
4851 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4853 MonoError error;
4854 MonoReflectionMethod *res = NULL;
4855 MonoMethod *method;
4857 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4859 if (!token)
4860 return NULL;
4861 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4862 if (!mono_error_ok (&error))
4863 goto leave;
4865 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4867 leave:
4868 if (!mono_error_ok (&error))
4869 mono_error_set_pending_exception (&error);
4870 return res;
4873 ICALL_EXPORT MonoReflectionModule*
4874 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4876 MonoError error;
4877 MonoReflectionModule *result = NULL;
4878 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4879 if (!mono_error_ok (&error))
4880 mono_error_set_pending_exception (&error);
4881 return result;
4884 ICALL_EXPORT MonoArray*
4885 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4887 MonoError error;
4888 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4889 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4890 if (mono_error_set_pending_exception (&error))
4891 return NULL;
4892 int i;
4893 const char *val;
4895 for (i = 0; i < table->rows; ++i) {
4896 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4897 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4899 return result;
4902 ICALL_EXPORT MonoString*
4903 ves_icall_System_Reflection_Assembly_GetAotId ()
4905 int i;
4906 guint8 aotid_sum = 0;
4907 MonoDomain* domain = mono_domain_get ();
4909 if (!domain->entry_assembly || !domain->entry_assembly->image)
4910 return NULL;
4912 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4914 for (i = 0; i < 16; ++i)
4915 aotid_sum |= (*aotid)[i];
4917 if (aotid_sum == 0)
4918 return NULL;
4920 return mono_string_new (domain, mono_guid_to_string((guint8*) aotid));
4923 static MonoObject*
4924 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4926 static MonoMethod *create_version = NULL;
4927 MonoObject *result;
4928 gpointer args [4];
4930 mono_error_init (error);
4933 if (!create_version) {
4934 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4935 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4936 g_assert (create_version);
4937 mono_method_desc_free (desc);
4940 args [0] = &major;
4941 args [1] = &minor;
4942 args [2] = &build;
4943 args [3] = &revision;
4944 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4945 return_val_if_nok (error, NULL);
4947 mono_runtime_invoke_checked (create_version, result, args, error);
4948 return_val_if_nok (error, NULL);
4950 return result;
4953 ICALL_EXPORT MonoArray*
4954 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4956 MonoError error;
4957 MonoArray *result;
4958 MonoDomain *domain = mono_object_domain (assembly);
4959 int i, count = 0;
4960 static MonoMethod *create_culture = NULL;
4961 MonoImage *image = assembly->assembly->image;
4962 MonoTableInfo *t;
4963 MonoObject *o;
4965 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4966 count = t->rows;
4968 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4969 if (mono_error_set_pending_exception (&error))
4970 return NULL;
4973 if (count > 0 && !create_culture) {
4974 MonoMethodDesc *desc = mono_method_desc_new (
4975 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4976 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4977 g_assert (create_culture);
4978 mono_method_desc_free (desc);
4981 for (i = 0; i < count; i++) {
4982 MonoObject *version;
4983 MonoReflectionAssemblyName *aname;
4984 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4986 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4988 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4989 domain, mono_class_get_assembly_name_class (), &error);
4990 if (mono_error_set_pending_exception (&error))
4991 return NULL;
4993 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4995 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4996 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4997 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4998 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4999 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
5000 aname->versioncompat = 1; /* SameMachine (default) */
5001 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
5003 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
5004 if (mono_error_set_pending_exception (&error))
5005 return NULL;
5007 MONO_OBJECT_SETREF (aname, version, version);
5009 if (create_culture) {
5010 gpointer args [2];
5011 MonoBoolean assembly_ref = 1;
5012 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
5013 args [1] = &assembly_ref;
5015 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
5016 if (mono_error_set_pending_exception (&error))
5017 return NULL;
5019 MONO_OBJECT_SETREF (aname, cultureInfo, o);
5022 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
5023 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
5024 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5026 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
5027 /* public key token isn't copied - the class library will
5028 automatically generate it from the public key if required */
5029 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5030 if (mono_error_set_pending_exception (&error))
5031 return NULL;
5033 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5034 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
5035 } else {
5036 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
5037 if (mono_error_set_pending_exception (&error))
5038 return NULL;
5040 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5041 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
5043 } else {
5044 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
5045 if (mono_error_set_pending_exception (&error))
5046 return NULL;
5048 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5051 /* note: this function doesn't return the codebase on purpose (i.e. it can
5052 be used under partial trust as path information isn't present). */
5054 mono_array_setref (result, i, aname);
5056 return result;
5059 /* move this in some file in mono/util/ */
5060 static char *
5061 g_concat_dir_and_file (const char *dir, const char *file)
5063 g_return_val_if_fail (dir != NULL, NULL);
5064 g_return_val_if_fail (file != NULL, NULL);
5067 * If the directory name doesn't have a / on the end, we need
5068 * to add one so we get a proper path to the file
5070 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
5071 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
5072 else
5073 return g_strconcat (dir, file, NULL);
5076 ICALL_EXPORT void *
5077 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
5079 MonoError error;
5080 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5081 guint32 i;
5082 guint32 cols [MONO_MANIFEST_SIZE];
5083 guint32 impl, file_idx;
5084 const char *val;
5085 MonoImage *module;
5087 char *n = mono_string_to_utf8_checked (name, &error);
5088 if (mono_error_set_pending_exception (&error))
5089 return NULL;
5091 for (i = 0; i < table->rows; ++i) {
5092 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5093 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5094 if (strcmp (val, n) == 0)
5095 break;
5097 g_free (n);
5098 if (i == table->rows)
5099 return NULL;
5100 /* FIXME */
5101 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
5102 if (impl) {
5104 * this code should only be called after obtaining the
5105 * ResourceInfo and handling the other cases.
5107 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
5108 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
5110 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
5111 if (!module)
5112 return NULL;
5114 else
5115 module = assembly->assembly->image;
5118 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
5119 if (mono_error_set_pending_exception (&error))
5120 return NULL;
5121 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
5123 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
5126 ICALL_EXPORT gboolean
5127 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
5129 MonoError error;
5130 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
5131 int i;
5132 guint32 cols [MONO_MANIFEST_SIZE];
5133 guint32 file_cols [MONO_FILE_SIZE];
5134 const char *val;
5135 char *n;
5137 n = mono_string_to_utf8_checked (name, &error);
5138 if (mono_error_set_pending_exception (&error))
5139 return FALSE;
5140 for (i = 0; i < table->rows; ++i) {
5141 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
5142 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
5143 if (strcmp (val, n) == 0)
5144 break;
5146 g_free (n);
5147 if (i == table->rows)
5148 return FALSE;
5150 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
5151 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
5153 else {
5154 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5155 case MONO_IMPLEMENTATION_FILE:
5156 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5157 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5158 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5159 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
5160 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
5161 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5162 info->location = 0;
5163 else
5164 info->location = RESOURCE_LOCATION_EMBEDDED;
5165 break;
5167 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5168 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5169 mono_assembly_load_reference (assembly->assembly->image, i - 1);
5170 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
5171 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
5172 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5173 g_free (msg);
5174 mono_set_pending_exception (ex);
5175 return FALSE;
5177 MonoReflectionAssembly *assm_obj;
5178 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5179 if (!assm_obj) {
5180 mono_error_set_pending_exception (&error);
5181 return FALSE;
5183 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5185 /* Obtain info recursively */
5186 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5187 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5188 break;
5190 case MONO_IMPLEMENTATION_EXP_TYPE:
5191 g_assert_not_reached ();
5192 break;
5196 return TRUE;
5199 ICALL_EXPORT MonoObject*
5200 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5202 MonoError error;
5203 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5204 MonoArray *result = NULL;
5205 int i, count;
5206 const char *val;
5207 char *n;
5209 /* check hash if needed */
5210 if (name) {
5211 n = mono_string_to_utf8_checked (name, &error);
5212 if (mono_error_set_pending_exception (&error))
5213 return NULL;
5215 for (i = 0; i < table->rows; ++i) {
5216 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5217 if (strcmp (val, n) == 0) {
5218 MonoString *fn;
5219 g_free (n);
5220 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5221 fn = mono_string_new (mono_object_domain (assembly), n);
5222 g_free (n);
5223 return (MonoObject*)fn;
5226 g_free (n);
5227 return NULL;
5230 count = 0;
5231 for (i = 0; i < table->rows; ++i) {
5232 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5233 count ++;
5236 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5237 if (mono_error_set_pending_exception (&error))
5238 return NULL;
5241 count = 0;
5242 for (i = 0; i < table->rows; ++i) {
5243 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5244 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5245 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5246 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5247 g_free (n);
5248 count ++;
5251 return (MonoObject*)result;
5254 ICALL_EXPORT MonoArray*
5255 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5257 MonoError error;
5258 MonoDomain *domain = mono_domain_get();
5259 MonoArray *res;
5260 MonoClass *klass;
5261 int i, j, file_count = 0;
5262 MonoImage **modules;
5263 guint32 module_count, real_module_count;
5264 MonoTableInfo *table;
5265 guint32 cols [MONO_FILE_SIZE];
5266 MonoImage *image = assembly->assembly->image;
5268 g_assert (image != NULL);
5269 g_assert (!assembly_is_dynamic (assembly->assembly));
5271 table = &image->tables [MONO_TABLE_FILE];
5272 file_count = table->rows;
5274 modules = image->modules;
5275 module_count = image->module_count;
5277 real_module_count = 0;
5278 for (i = 0; i < module_count; ++i)
5279 if (modules [i])
5280 real_module_count ++;
5282 klass = mono_class_get_module_class ();
5283 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5284 if (mono_error_set_pending_exception (&error))
5285 return NULL;
5287 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5288 if (mono_error_set_pending_exception (&error))
5289 return NULL;
5291 mono_array_setref (res, 0, image_obj);
5292 j = 1;
5293 for (i = 0; i < module_count; ++i)
5294 if (modules [i]) {
5295 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5296 if (mono_error_set_pending_exception (&error))
5297 return NULL;
5298 mono_array_setref (res, j, rm);
5299 ++j;
5302 for (i = 0; i < file_count; ++i, ++j) {
5303 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5304 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5305 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5306 if (mono_error_set_pending_exception (&error))
5307 return NULL;
5308 mono_array_setref (res, j, rm);
5310 else {
5311 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5312 if (!m) {
5313 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5314 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5315 return NULL;
5317 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5318 if (mono_error_set_pending_exception (&error))
5319 return NULL;
5320 mono_array_setref (res, j, rm);
5324 return res;
5327 ICALL_EXPORT MonoReflectionMethod*
5328 ves_icall_GetCurrentMethod (void)
5330 MonoReflectionMethod *res = NULL;
5331 MonoError error;
5333 MonoMethod *m = mono_method_get_last_managed ();
5335 if (!m) {
5336 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5337 return NULL;
5340 while (m->is_inflated)
5341 m = ((MonoMethodInflated*)m)->declaring;
5343 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5344 mono_error_set_pending_exception (&error);
5345 return res;
5349 static MonoMethod*
5350 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5352 int offset = -1, i;
5353 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5354 MonoError error;
5355 MonoMethod *result;
5356 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5357 //method is inflated, we should inflate it on the other class
5358 MonoGenericContext ctx;
5359 ctx.method_inst = inflated->context.method_inst;
5360 ctx.class_inst = inflated->context.class_inst;
5361 if (klass->generic_class)
5362 ctx.class_inst = klass->generic_class->context.class_inst;
5363 else if (klass->generic_container)
5364 ctx.class_inst = klass->generic_container->context.class_inst;
5365 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5366 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5367 return result;
5370 mono_class_setup_methods (method->klass);
5371 if (mono_class_has_failure (method->klass))
5372 return NULL;
5373 for (i = 0; i < method->klass->method.count; ++i) {
5374 if (method->klass->methods [i] == method) {
5375 offset = i;
5376 break;
5379 mono_class_setup_methods (klass);
5380 if (mono_class_has_failure (klass))
5381 return NULL;
5382 g_assert (offset >= 0 && offset < klass->method.count);
5383 return klass->methods [offset];
5386 ICALL_EXPORT MonoReflectionMethod*
5387 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5389 MonoReflectionMethod *res = NULL;
5390 MonoError error;
5391 MonoClass *klass;
5392 if (type) {
5393 klass = mono_class_from_mono_type (type);
5394 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5395 return NULL;
5396 if (method->klass != klass) {
5397 method = mono_method_get_equivalent_method (method, klass);
5398 if (!method)
5399 return NULL;
5401 } else
5402 klass = method->klass;
5403 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5404 mono_error_set_pending_exception (&error);
5405 return res;
5408 ICALL_EXPORT MonoReflectionMethodBody*
5409 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5411 MonoError error;
5412 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5413 mono_error_set_pending_exception (&error);
5414 return result;
5417 ICALL_EXPORT MonoReflectionAssembly*
5418 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5420 MonoError error;
5421 MonoReflectionAssembly *result;
5422 MonoMethod *dest = NULL;
5424 mono_stack_walk_no_il (get_executing, &dest);
5425 g_assert (dest);
5426 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5427 if (!result)
5428 mono_error_set_pending_exception (&error);
5429 return result;
5433 ICALL_EXPORT MonoReflectionAssembly*
5434 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5436 MonoError error;
5437 MonoReflectionAssembly *result;
5438 MonoDomain* domain = mono_domain_get ();
5440 if (!domain->entry_assembly)
5441 return NULL;
5443 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5444 if (!result)
5445 mono_error_set_pending_exception (&error);
5446 return result;
5449 ICALL_EXPORT MonoReflectionAssembly*
5450 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5452 MonoError error;
5453 MonoMethod *m;
5454 MonoMethod *dest;
5455 MonoReflectionAssembly *result;
5457 dest = NULL;
5458 mono_stack_walk_no_il (get_executing, &dest);
5459 m = dest;
5460 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5461 if (!dest)
5462 dest = m;
5463 if (!m) {
5464 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5465 return NULL;
5467 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5468 if (!result)
5469 mono_error_set_pending_exception (&error);
5470 return result;
5473 ICALL_EXPORT MonoString *
5474 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5475 gboolean assembly_qualified)
5477 MonoDomain *domain = mono_object_domain (object);
5478 MonoTypeNameFormat format;
5479 MonoString *res;
5480 gchar *name;
5482 if (full_name)
5483 format = assembly_qualified ?
5484 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5485 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5486 else
5487 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5489 name = mono_type_get_name_full (object->type, format);
5490 if (!name)
5491 return NULL;
5493 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5494 g_free (name);
5495 return NULL;
5498 res = mono_string_new (domain, name);
5499 g_free (name);
5501 return res;
5504 ICALL_EXPORT int
5505 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5507 MonoError error;
5508 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5510 mono_class_init_checked (klass, &error);
5511 mono_error_set_pending_exception (&error);
5512 return mono_security_core_clr_class_level (klass);
5515 ICALL_EXPORT int
5516 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5518 MonoClassField *field = rfield->field;
5519 return mono_security_core_clr_field_level (field, TRUE);
5522 ICALL_EXPORT int
5523 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5525 MonoMethod *method = rfield->method;
5526 return mono_security_core_clr_method_level (method, TRUE);
5529 static void
5530 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)
5532 static MonoMethod *create_culture = NULL;
5533 MonoObject *obj;
5534 gpointer args [2];
5535 guint32 pkey_len;
5536 const char *pkey_ptr;
5537 gchar *codebase;
5538 MonoBoolean assembly_ref = 0;
5540 mono_error_init (error);
5542 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5543 aname->major = name->major;
5544 aname->minor = name->minor;
5545 aname->build = name->build;
5546 aname->flags = name->flags;
5547 aname->revision = name->revision;
5548 aname->hashalg = name->hash_alg;
5549 aname->versioncompat = 1; /* SameMachine (default) */
5550 aname->processor_architecture = name->arch;
5552 if (by_default_version) {
5553 MonoObject *version;
5555 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5556 return_if_nok (error);
5558 MONO_OBJECT_SETREF (aname, version, version);
5561 codebase = NULL;
5562 if (absolute != NULL && *absolute != '\0') {
5563 const gchar *prepend = "file://";
5564 gchar *result;
5566 codebase = g_strdup (absolute);
5568 #if HOST_WIN32
5570 gint i;
5571 for (i = strlen (codebase) - 1; i >= 0; i--)
5572 if (codebase [i] == '\\')
5573 codebase [i] = '/';
5575 if (*codebase == '/' && *(codebase + 1) == '/') {
5576 prepend = "file:";
5577 } else {
5578 prepend = "file:///";
5581 #endif
5582 result = g_strconcat (prepend, codebase, NULL);
5583 g_free (codebase);
5584 codebase = result;
5587 if (codebase) {
5588 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5589 g_free (codebase);
5592 if (!create_culture) {
5593 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5594 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5595 g_assert (create_culture);
5596 mono_method_desc_free (desc);
5599 if (name->culture) {
5600 args [0] = mono_string_new (domain, name->culture);
5601 args [1] = &assembly_ref;
5603 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5604 return_if_nok (error);
5606 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5609 if (name->public_key) {
5610 pkey_ptr = (char*)name->public_key;
5611 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5613 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5614 return_if_nok (error);
5615 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5616 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5617 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5618 } else if (default_publickey) {
5619 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5620 return_if_nok (error);
5621 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5622 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5625 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5626 if (name->public_key_token [0]) {
5627 int i, j;
5628 char *p;
5630 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5631 return_if_nok (error);
5633 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5634 p = mono_array_addr (keyToken, char, 0);
5636 for (i = 0, j = 0; i < 8; i++) {
5637 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5638 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5639 p++;
5641 } else if (default_token) {
5642 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5643 return_if_nok (error);
5644 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5648 ICALL_EXPORT MonoString *
5649 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5651 MonoDomain *domain = mono_object_domain (assembly);
5652 MonoAssembly *mass = assembly->assembly;
5653 MonoString *res;
5654 gchar *name;
5656 name = mono_stringify_assembly_name (&mass->aname);
5657 res = mono_string_new (domain, name);
5658 g_free (name);
5660 return res;
5663 ICALL_EXPORT void
5664 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5666 MonoError error;
5667 gchar *absolute, *dirname;
5668 MonoAssembly *mass = assembly->assembly;
5670 /* XXX this is duplicated code to compute the codebase URI, unify it */
5671 if (g_path_is_absolute (mass->image->name)) {
5672 absolute = g_strdup (mass->image->name);
5673 dirname = g_path_get_dirname (absolute);
5674 } else {
5675 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5676 dirname = g_strdup (mass->basedir);
5679 replace_shadow_path (mono_object_domain (assembly), dirname, &absolute);
5680 g_free (dirname);
5682 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5683 mono_error_set_pending_exception (&error);
5685 g_free (absolute);
5688 ICALL_EXPORT void
5689 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5691 MonoError error;
5692 char *filename;
5693 MonoImageOpenStatus status = MONO_IMAGE_OK;
5694 gboolean res;
5695 MonoImage *image;
5696 MonoAssemblyName name;
5697 char *dirname;
5699 filename = mono_string_to_utf8_checked (fname, &error);
5700 if (mono_error_set_pending_exception (&error))
5701 return;
5703 dirname = g_path_get_dirname (filename);
5704 replace_shadow_path (mono_domain_get (), dirname, &filename);
5705 g_free (dirname);
5707 image = mono_image_open (filename, &status);
5709 if (!image){
5710 MonoException *exc;
5712 g_free (filename);
5713 if (status == MONO_IMAGE_IMAGE_INVALID)
5714 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5715 else
5716 exc = mono_get_exception_file_not_found2 (NULL, fname);
5717 mono_set_pending_exception (exc);
5718 return;
5721 res = mono_assembly_fill_assembly_name (image, &name);
5722 if (!res) {
5723 mono_image_close (image);
5724 g_free (filename);
5725 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5726 return;
5729 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5730 mono_error_set_pending_exception (&error);
5732 mono_image_close (image);
5733 g_free (filename);
5736 ICALL_EXPORT MonoBoolean
5737 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5738 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5740 MonoBoolean result = FALSE;
5741 MonoDeclSecurityEntry entry;
5743 /* SecurityAction.RequestMinimum */
5744 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5745 *minimum = entry.blob;
5746 *minLength = entry.size;
5747 result = TRUE;
5749 /* SecurityAction.RequestOptional */
5750 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5751 *optional = entry.blob;
5752 *optLength = entry.size;
5753 result = TRUE;
5755 /* SecurityAction.RequestRefuse */
5756 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5757 *refused = entry.blob;
5758 *refLength = entry.size;
5759 result = TRUE;
5762 return result;
5765 static gboolean
5766 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5768 guint32 attrs, visibility;
5769 do {
5770 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5771 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5772 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5773 return FALSE;
5775 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5777 return TRUE;
5780 static MonoArray*
5781 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5783 MonoReflectionType *rt;
5784 MonoArray *res;
5785 MonoClass *klass;
5786 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5787 int i, count;
5789 mono_error_init (error);
5791 /* we start the count from 1 because we skip the special type <Module> */
5792 if (exportedOnly) {
5793 count = 0;
5794 for (i = 1; i < tdef->rows; ++i) {
5795 if (mono_module_type_is_visible (tdef, image, i + 1))
5796 count++;
5798 } else {
5799 count = tdef->rows - 1;
5801 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5802 return_val_if_nok (error, NULL);
5803 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5804 return_val_if_nok (error, NULL);
5805 count = 0;
5806 for (i = 1; i < tdef->rows; ++i) {
5807 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5808 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5810 if (klass) {
5811 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5812 return_val_if_nok (error, NULL);
5814 mono_array_setref (res, count, rt);
5815 } else {
5816 MonoException *ex = mono_error_convert_to_exception (error);
5817 mono_array_setref (*exceptions, count, ex);
5819 count++;
5823 return res;
5826 ICALL_EXPORT MonoArray*
5827 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5829 MonoError error;
5830 MonoArray *res = NULL;
5831 MonoArray *exceptions = NULL;
5832 MonoImage *image = NULL;
5833 MonoTableInfo *table = NULL;
5834 MonoDomain *domain;
5835 GList *list = NULL;
5836 int i, len, ex_count;
5838 domain = mono_object_domain (assembly);
5840 g_assert (!assembly_is_dynamic (assembly->assembly));
5841 image = assembly->assembly->image;
5842 table = &image->tables [MONO_TABLE_FILE];
5843 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5844 if (mono_error_set_pending_exception (&error))
5845 return NULL;
5847 /* Append data from all modules in the assembly */
5848 for (i = 0; i < table->rows; ++i) {
5849 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5850 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5851 if (loaded_image) {
5852 MonoArray *ex2;
5853 MonoArray *res2;
5855 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5856 if (mono_error_set_pending_exception (&error))
5857 return NULL;
5860 /* Append the new types to the end of the array */
5861 if (mono_array_length (res2) > 0) {
5862 guint32 len1, len2;
5863 MonoArray *res3, *ex3;
5865 len1 = mono_array_length (res);
5866 len2 = mono_array_length (res2);
5868 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5869 if (mono_error_set_pending_exception (&error))
5870 return NULL;
5871 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5872 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5873 res = res3;
5875 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5876 if (mono_error_set_pending_exception (&error))
5877 return NULL;
5878 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5879 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5880 exceptions = ex3;
5886 /* the ReflectionTypeLoadException must have all the types (Types property),
5887 * NULL replacing types which throws an exception. The LoaderException must
5888 * contain all exceptions for NULL items.
5891 len = mono_array_length (res);
5893 ex_count = 0;
5894 for (i = 0; i < len; i++) {
5895 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5896 MonoClass *klass;
5898 if (t) {
5899 klass = mono_type_get_class (t->type);
5900 if ((klass != NULL) && mono_class_has_failure (klass)) {
5901 /* keep the class in the list */
5902 list = g_list_append (list, klass);
5903 /* and replace Type with NULL */
5904 mono_array_setref (res, i, NULL);
5906 } else {
5907 ex_count ++;
5911 if (list || ex_count) {
5912 GList *tmp = NULL;
5913 MonoException *exc = NULL;
5914 MonoArray *exl = NULL;
5915 int j, length = g_list_length (list) + ex_count;
5917 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5918 if (mono_error_set_pending_exception (&error)) {
5919 g_list_free (list);
5920 return NULL;
5922 /* Types for which mono_class_get_checked () succeeded */
5923 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5924 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5925 mono_array_setref (exl, i, exc);
5927 /* Types for which it don't */
5928 for (j = 0; j < mono_array_length (exceptions); ++j) {
5929 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5930 if (exc) {
5931 g_assert (i < length);
5932 mono_array_setref (exl, i, exc);
5933 i ++;
5936 g_list_free (list);
5937 list = NULL;
5939 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5940 if (!is_ok (&error)) {
5941 mono_error_set_pending_exception (&error);
5942 return NULL;
5944 mono_set_pending_exception (exc);
5945 return NULL;
5948 return res;
5951 ICALL_EXPORT gboolean
5952 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5954 MonoError error;
5955 MonoAssemblyName aname;
5956 MonoDomain *domain = mono_object_domain (name);
5957 char *val;
5958 gboolean is_version_defined;
5959 gboolean is_token_defined;
5961 aname.public_key = NULL;
5962 val = mono_string_to_utf8_checked (assname, &error);
5963 if (mono_error_set_pending_exception (&error))
5964 return FALSE;
5966 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5967 g_free ((guint8*) aname.public_key);
5968 g_free (val);
5969 return FALSE;
5972 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5973 mono_error_set_pending_exception (&error);
5975 mono_assembly_name_free (&aname);
5976 g_free ((guint8*) aname.public_key);
5977 g_free (val);
5979 return TRUE;
5982 ICALL_EXPORT MonoReflectionType*
5983 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5985 MonoError error;
5986 MonoReflectionType *ret;
5987 MonoDomain *domain = mono_object_domain (module);
5988 MonoClass *klass;
5990 g_assert (module->image);
5992 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5993 /* These images do not have a global type */
5994 return NULL;
5996 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5997 if (!mono_error_ok (&error)) {
5998 mono_error_set_pending_exception (&error);
5999 return NULL;
6002 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
6003 if (!mono_error_ok (&error)) {
6004 mono_error_set_pending_exception (&error);
6005 return NULL;
6008 return ret;
6011 ICALL_EXPORT void
6012 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
6014 /*if (module->image)
6015 mono_image_close (module->image);*/
6018 ICALL_EXPORT MonoString*
6019 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
6021 MonoDomain *domain = mono_object_domain (module);
6023 g_assert (module->image);
6024 return mono_string_new (domain, module->image->guid);
6027 ICALL_EXPORT gpointer
6028 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
6030 #ifdef HOST_WIN32
6031 if (module->image && module->image->is_module_handle)
6032 return module->image->raw_data;
6033 #endif
6035 return (gpointer) (-1);
6038 ICALL_EXPORT void
6039 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
6041 if (image_is_dynamic (image)) {
6042 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
6043 *pe_kind = dyn->pe_kind;
6044 *machine = dyn->machine;
6046 else {
6047 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
6048 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
6052 ICALL_EXPORT gint32
6053 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
6055 return (image->md_version_major << 16) | (image->md_version_minor);
6058 ICALL_EXPORT MonoArray*
6059 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
6061 MonoError error;
6062 MonoArray *exceptions;
6063 int i;
6065 if (!module->image) {
6066 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
6067 mono_error_set_pending_exception (&error);
6068 return arr;
6069 } else {
6070 MonoArray *res;
6072 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
6073 if (mono_error_set_pending_exception (&error))
6074 return NULL;
6076 for (i = 0; i < mono_array_length (exceptions); ++i) {
6077 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
6078 if (ex) {
6079 mono_set_pending_exception (ex);
6080 return NULL;
6083 return res;
6087 static gboolean
6088 mono_memberref_is_method (MonoImage *image, guint32 token)
6090 if (!image_is_dynamic (image)) {
6091 guint32 cols [MONO_MEMBERREF_SIZE];
6092 const char *sig;
6093 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
6094 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6095 mono_metadata_decode_blob_size (sig, &sig);
6096 return (*sig != 0x6);
6097 } else {
6098 MonoError error;
6099 MonoClass *handle_class;
6101 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
6102 mono_error_cleanup (&error); /* just probing, ignore error */
6103 return FALSE;
6106 return mono_defaults.methodhandle_class == handle_class;
6110 static void
6111 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
6113 if (type_args)
6114 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
6115 mono_array_addr (type_args, MonoType*, 0));
6116 else
6117 context->class_inst = NULL;
6118 if (method_args)
6119 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
6120 mono_array_addr (method_args, MonoType*, 0));
6121 else
6122 context->method_inst = NULL;
6125 ICALL_EXPORT MonoType*
6126 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6128 MonoClass *klass;
6129 int table = mono_metadata_token_table (token);
6130 int index = mono_metadata_token_index (token);
6131 MonoGenericContext context;
6132 MonoError error;
6134 *resolve_error = ResolveTokenError_Other;
6136 /* Validate token */
6137 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6138 (table != MONO_TABLE_TYPESPEC)) {
6139 *resolve_error = ResolveTokenError_BadTable;
6140 return NULL;
6143 if (image_is_dynamic (image)) {
6144 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6145 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6146 mono_error_cleanup (&error);
6147 return klass ? &klass->byval_arg : NULL;
6150 init_generic_context_from_args (&context, type_args, method_args);
6151 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6152 mono_error_cleanup (&error);
6153 return klass ? &klass->byval_arg : NULL;
6156 if ((index <= 0) || (index > image->tables [table].rows)) {
6157 *resolve_error = ResolveTokenError_OutOfRange;
6158 return NULL;
6161 init_generic_context_from_args (&context, type_args, method_args);
6162 klass = mono_class_get_checked (image, token, &error);
6163 if (klass)
6164 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
6165 if (!mono_error_ok (&error)) {
6166 mono_error_set_pending_exception (&error);
6167 return NULL;
6170 if (klass)
6171 return &klass->byval_arg;
6172 else
6173 return NULL;
6176 ICALL_EXPORT MonoMethod*
6177 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6179 MonoError error;
6180 int table = mono_metadata_token_table (token);
6181 int index = mono_metadata_token_index (token);
6182 MonoGenericContext context;
6183 MonoMethod *method;
6185 *resolve_error = ResolveTokenError_Other;
6187 /* Validate token */
6188 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6189 (table != MONO_TABLE_MEMBERREF)) {
6190 *resolve_error = ResolveTokenError_BadTable;
6191 return NULL;
6194 if (image_is_dynamic (image)) {
6195 if (table == MONO_TABLE_METHOD) {
6196 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6197 mono_error_cleanup (&error);
6198 return method;
6201 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6202 *resolve_error = ResolveTokenError_BadTable;
6203 return NULL;
6206 init_generic_context_from_args (&context, type_args, method_args);
6207 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6208 mono_error_cleanup (&error);
6209 return method;
6212 if ((index <= 0) || (index > image->tables [table].rows)) {
6213 *resolve_error = ResolveTokenError_OutOfRange;
6214 return NULL;
6216 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6217 *resolve_error = ResolveTokenError_BadTable;
6218 return NULL;
6221 init_generic_context_from_args (&context, type_args, method_args);
6222 method = mono_get_method_checked (image, token, NULL, &context, &error);
6223 mono_error_set_pending_exception (&error);
6225 return method;
6228 ICALL_EXPORT MonoString*
6229 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6231 MonoError error;
6232 int index = mono_metadata_token_index (token);
6234 *resolve_error = ResolveTokenError_Other;
6236 /* Validate token */
6237 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6238 *resolve_error = ResolveTokenError_BadTable;
6239 return NULL;
6242 if (image_is_dynamic (image)) {
6243 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6244 mono_error_cleanup (&error);
6245 return result;
6248 if ((index <= 0) || (index >= image->heap_us.size)) {
6249 *resolve_error = ResolveTokenError_OutOfRange;
6250 return NULL;
6253 /* FIXME: What to do if the index points into the middle of a string ? */
6255 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6256 mono_error_set_pending_exception (&error);
6257 return result;
6260 ICALL_EXPORT MonoClassField*
6261 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6263 MonoError error;
6264 MonoClass *klass;
6265 int table = mono_metadata_token_table (token);
6266 int index = mono_metadata_token_index (token);
6267 MonoGenericContext context;
6268 MonoClassField *field;
6270 *resolve_error = ResolveTokenError_Other;
6272 /* Validate token */
6273 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6274 *resolve_error = ResolveTokenError_BadTable;
6275 return NULL;
6278 if (image_is_dynamic (image)) {
6279 if (table == MONO_TABLE_FIELD) {
6280 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6281 mono_error_cleanup (&error);
6282 return field;
6285 if (mono_memberref_is_method (image, token)) {
6286 *resolve_error = ResolveTokenError_BadTable;
6287 return NULL;
6290 init_generic_context_from_args (&context, type_args, method_args);
6291 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6292 mono_error_cleanup (&error);
6293 return field;
6296 if ((index <= 0) || (index > image->tables [table].rows)) {
6297 *resolve_error = ResolveTokenError_OutOfRange;
6298 return NULL;
6300 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6301 *resolve_error = ResolveTokenError_BadTable;
6302 return NULL;
6305 init_generic_context_from_args (&context, type_args, method_args);
6306 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6307 mono_error_set_pending_exception (&error);
6309 return field;
6313 ICALL_EXPORT MonoObject*
6314 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6316 MonoError merror;
6317 MonoObject *ret;
6318 int table = mono_metadata_token_table (token);
6320 *error = ResolveTokenError_Other;
6322 switch (table) {
6323 case MONO_TABLE_TYPEDEF:
6324 case MONO_TABLE_TYPEREF:
6325 case MONO_TABLE_TYPESPEC: {
6326 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6327 if (t) {
6328 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6329 mono_error_set_pending_exception (&merror);
6331 return ret;
6333 else
6334 return NULL;
6336 case MONO_TABLE_METHOD:
6337 case MONO_TABLE_METHODSPEC: {
6338 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6339 if (m) {
6340 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6341 mono_error_set_pending_exception (&merror);
6343 return ret;
6344 } else
6345 return NULL;
6347 case MONO_TABLE_FIELD: {
6348 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6349 if (f) {
6350 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6351 mono_error_set_pending_exception (&merror);
6352 return ret;
6354 else
6355 return NULL;
6357 case MONO_TABLE_MEMBERREF:
6358 if (mono_memberref_is_method (image, token)) {
6359 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6360 if (m) {
6361 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6362 mono_error_set_pending_exception (&merror);
6364 return ret;
6365 } else
6366 return NULL;
6368 else {
6369 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6370 if (f) {
6371 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6372 mono_error_set_pending_exception (&merror);
6373 return ret;
6375 else
6376 return NULL;
6378 break;
6380 default:
6381 *error = ResolveTokenError_BadTable;
6384 return NULL;
6387 ICALL_EXPORT MonoArray*
6388 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6390 MonoError error;
6391 int table = mono_metadata_token_table (token);
6392 int idx = mono_metadata_token_index (token);
6393 MonoTableInfo *tables = image->tables;
6394 guint32 sig, len;
6395 const char *ptr;
6396 MonoArray *res;
6398 *resolve_error = ResolveTokenError_OutOfRange;
6400 /* FIXME: Support other tables ? */
6401 if (table != MONO_TABLE_STANDALONESIG)
6402 return NULL;
6404 if (image_is_dynamic (image))
6405 return NULL;
6407 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6408 return NULL;
6410 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6412 ptr = mono_metadata_blob_heap (image, sig);
6413 len = mono_metadata_decode_blob_size (ptr, &ptr);
6415 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6416 if (mono_error_set_pending_exception (&error))
6417 return NULL;
6418 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6419 return res;
6422 ICALL_EXPORT MonoReflectionType*
6423 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6425 MonoError error;
6426 MonoReflectionType *ret;
6427 MonoClass *klass;
6428 int isbyref = 0, rank;
6429 char *p;
6430 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6431 if (mono_error_set_pending_exception (&error))
6432 return NULL;
6434 klass = mono_class_from_mono_type (tb->type.type);
6435 p = str;
6436 /* logic taken from mono_reflection_parse_type(): keep in sync */
6437 while (*p) {
6438 switch (*p) {
6439 case '&':
6440 if (isbyref) { /* only one level allowed by the spec */
6441 g_free (str);
6442 return NULL;
6444 isbyref = 1;
6445 p++;
6447 g_free (str);
6449 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6450 mono_error_set_pending_exception (&error);
6452 return ret;
6453 case '*':
6454 klass = mono_ptr_class_get (&klass->byval_arg);
6455 mono_class_init (klass);
6456 p++;
6457 break;
6458 case '[':
6459 rank = 1;
6460 p++;
6461 while (*p) {
6462 if (*p == ']')
6463 break;
6464 if (*p == ',')
6465 rank++;
6466 else if (*p != '*') { /* '*' means unknown lower bound */
6467 g_free (str);
6468 return NULL;
6470 ++p;
6472 if (*p != ']') {
6473 g_free (str);
6474 return NULL;
6476 p++;
6477 klass = mono_array_class_get (klass, rank);
6478 mono_class_init (klass);
6479 break;
6480 default:
6481 break;
6485 g_free (str);
6487 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6488 mono_error_set_pending_exception (&error);
6490 return ret;
6493 ICALL_EXPORT MonoBoolean
6494 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6496 MonoType *type;
6497 MonoBoolean res;
6499 type = t->type;
6500 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6502 return res;
6505 static void
6506 check_for_invalid_type (MonoClass *klass, MonoError *error)
6508 char *name;
6509 MonoString *str;
6511 mono_error_init (error);
6513 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6514 return;
6516 name = mono_type_get_full_name (klass);
6517 str = mono_string_new (mono_domain_get (), name);
6518 g_free (name);
6519 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6522 ICALL_EXPORT MonoReflectionType *
6523 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6525 MonoError error;
6526 MonoReflectionType *ret;
6527 MonoClass *klass, *aklass;
6529 klass = mono_class_from_mono_type (type->type);
6530 check_for_invalid_type (klass, &error);
6531 mono_error_set_pending_exception (&error);
6533 if (rank == 0) //single dimentional array
6534 aklass = mono_array_class_get (klass, 1);
6535 else
6536 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6538 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6539 mono_error_set_pending_exception (&error);
6541 return ret;
6544 ICALL_EXPORT MonoReflectionType *
6545 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6547 MonoError error;
6548 MonoReflectionType *ret;
6549 MonoClass *klass;
6551 klass = mono_class_from_mono_type (type->type);
6552 mono_class_init_checked (klass, &error);
6553 if (mono_error_set_pending_exception (&error))
6554 return NULL;
6556 check_for_invalid_type (klass, &error);
6557 if (mono_error_set_pending_exception (&error))
6558 return NULL;
6560 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6561 mono_error_set_pending_exception (&error);
6563 return ret;
6566 ICALL_EXPORT MonoReflectionType *
6567 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6569 MonoError error;
6570 MonoReflectionType *ret;
6571 MonoClass *klass, *pklass;
6573 klass = mono_class_from_mono_type (type->type);
6574 mono_class_init_checked (klass, &error);
6575 if (mono_error_set_pending_exception (&error))
6576 return NULL;
6577 check_for_invalid_type (klass, &error);
6578 if (mono_error_set_pending_exception (&error))
6579 return NULL;
6581 pklass = mono_ptr_class_get (type->type);
6583 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6584 mono_error_set_pending_exception (&error);
6586 return ret;
6589 ICALL_EXPORT MonoObject *
6590 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6591 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6593 MonoError error;
6594 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6595 MonoObject *delegate;
6596 gpointer func;
6597 MonoMethod *method = info->method;
6599 mono_class_init_checked (delegate_class, &error);
6600 if (mono_error_set_pending_exception (&error))
6601 return NULL;
6603 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6604 /* FIXME improve this exception message */
6605 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6606 __func__,
6607 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6608 mono_error_set_pending_exception (&error);
6609 return NULL;
6612 if (mono_security_core_clr_enabled ()) {
6613 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6614 if (throwOnBindFailure)
6615 mono_error_set_pending_exception (&error);
6616 else
6617 mono_error_cleanup (&error);
6618 return NULL;
6622 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6623 if (mono_error_set_pending_exception (&error))
6624 return NULL;
6626 if (method_is_dynamic (method)) {
6627 /* Creating a trampoline would leak memory */
6628 func = mono_compile_method_checked (method, &error);
6629 if (mono_error_set_pending_exception (&error))
6630 return NULL;
6631 } else {
6632 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6633 method = mono_object_get_virtual_method (target, method);
6634 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6635 if (mono_error_set_pending_exception (&error))
6636 return NULL;
6637 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6640 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6641 if (mono_error_set_pending_exception (&error))
6642 return NULL;
6643 return delegate;
6646 ICALL_EXPORT MonoMulticastDelegate *
6647 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6649 MonoError error;
6650 MonoMulticastDelegate *ret;
6652 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6654 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6655 if (mono_error_set_pending_exception (&error))
6656 return NULL;
6658 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6660 return ret;
6663 ICALL_EXPORT MonoReflectionMethod*
6664 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6666 MonoReflectionMethod *ret = NULL;
6667 MonoError error;
6668 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6669 mono_error_set_pending_exception (&error);
6670 return ret;
6673 /* System.Buffer */
6675 static inline gint32
6676 mono_array_get_byte_length (MonoArray *array)
6678 MonoClass *klass;
6679 int length;
6680 int i;
6682 klass = array->obj.vtable->klass;
6684 if (array->bounds == NULL)
6685 length = array->max_length;
6686 else {
6687 length = 1;
6688 for (i = 0; i < klass->rank; ++ i)
6689 length *= array->bounds [i].length;
6692 switch (klass->element_class->byval_arg.type) {
6693 case MONO_TYPE_I1:
6694 case MONO_TYPE_U1:
6695 case MONO_TYPE_BOOLEAN:
6696 return length;
6697 case MONO_TYPE_I2:
6698 case MONO_TYPE_U2:
6699 case MONO_TYPE_CHAR:
6700 return length << 1;
6701 case MONO_TYPE_I4:
6702 case MONO_TYPE_U4:
6703 case MONO_TYPE_R4:
6704 return length << 2;
6705 case MONO_TYPE_I:
6706 case MONO_TYPE_U:
6707 return length * sizeof (gpointer);
6708 case MONO_TYPE_I8:
6709 case MONO_TYPE_U8:
6710 case MONO_TYPE_R8:
6711 return length << 3;
6712 default:
6713 return -1;
6717 ICALL_EXPORT gint32
6718 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6720 return mono_array_get_byte_length (array);
6723 ICALL_EXPORT gint8
6724 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6726 return mono_array_get (array, gint8, idx);
6729 ICALL_EXPORT void
6730 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6732 mono_array_set (array, gint8, idx, value);
6735 ICALL_EXPORT MonoBoolean
6736 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6738 guint8 *src_buf, *dest_buf;
6740 if (count < 0) {
6741 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6742 return FALSE;
6745 g_assert (count >= 0);
6747 /* This is called directly from the class libraries without going through the managed wrapper */
6748 MONO_CHECK_ARG_NULL (src, FALSE);
6749 MONO_CHECK_ARG_NULL (dest, FALSE);
6751 /* watch out for integer overflow */
6752 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6753 return FALSE;
6755 src_buf = (guint8 *)src->vector + src_offset;
6756 dest_buf = (guint8 *)dest->vector + dest_offset;
6758 if (src != dest)
6759 memcpy (dest_buf, src_buf, count);
6760 else
6761 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6763 return TRUE;
6766 #ifndef DISABLE_REMOTING
6767 ICALL_EXPORT MonoObject *
6768 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6770 MonoError error;
6771 MonoDomain *domain = mono_object_domain (this_obj);
6772 MonoObject *res;
6773 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6774 MonoTransparentProxy *tp;
6775 MonoType *type;
6776 MonoClass *klass;
6778 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6779 if (mono_error_set_pending_exception (&error))
6780 return NULL;
6782 tp = (MonoTransparentProxy*) res;
6784 MONO_OBJECT_SETREF (tp, rp, rp);
6785 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6786 klass = mono_class_from_mono_type (type);
6788 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6789 mono_class_setup_vtable (klass);
6790 if (mono_class_has_failure (klass)) {
6791 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6792 return NULL;
6795 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6796 if (mono_error_set_pending_exception (&error))
6797 return NULL;
6798 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6799 if (mono_error_set_pending_exception (&error))
6800 return NULL;
6802 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6803 if (mono_error_set_pending_exception (&error))
6804 return NULL;
6805 return res;
6808 ICALL_EXPORT MonoReflectionType *
6809 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6811 MonoError error;
6812 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6813 mono_error_set_pending_exception (&error);
6815 return ret;
6817 #endif
6819 /* System.Environment */
6821 MonoString*
6822 ves_icall_System_Environment_get_UserName (void)
6824 /* using glib is more portable */
6825 return mono_string_new (mono_domain_get (), g_get_user_name ());
6829 ICALL_EXPORT MonoString *
6830 ves_icall_System_Environment_get_MachineName (void)
6832 #if defined (HOST_WIN32)
6833 gunichar2 *buf;
6834 guint32 len;
6835 MonoString *result;
6837 len = MAX_COMPUTERNAME_LENGTH + 1;
6838 buf = g_new (gunichar2, len);
6840 result = NULL;
6841 if (GetComputerName (buf, (PDWORD) &len)) {
6842 MonoError error;
6843 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6844 mono_error_set_pending_exception (&error);
6847 g_free (buf);
6848 return result;
6849 #elif !defined(DISABLE_SOCKETS)
6850 MonoString *result;
6851 char *buf;
6852 int n;
6853 #if defined _SC_HOST_NAME_MAX
6854 n = sysconf (_SC_HOST_NAME_MAX);
6855 if (n == -1)
6856 #endif
6857 n = 512;
6858 buf = g_malloc (n+1);
6860 if (gethostname (buf, n) == 0){
6861 buf [n] = 0;
6862 result = mono_string_new (mono_domain_get (), buf);
6863 } else
6864 result = NULL;
6865 g_free (buf);
6867 return result;
6868 #else
6869 return mono_string_new (mono_domain_get (), "mono");
6870 #endif
6873 ICALL_EXPORT int
6874 ves_icall_System_Environment_get_Platform (void)
6876 #if defined (TARGET_WIN32)
6877 /* Win32NT */
6878 return 2;
6879 #elif defined(__MACH__)
6880 /* OSX */
6882 // Notice that the value is hidden from user code, and only exposed
6883 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6884 // define and making assumptions based on Unix/128/4 values before there
6885 // was a MacOS define. Lots of code would assume that not-Unix meant
6886 // Windows, but in this case, it would be OSX.
6888 return 6;
6889 #else
6890 /* Unix */
6891 return 4;
6892 #endif
6895 ICALL_EXPORT MonoString *
6896 ves_icall_System_Environment_get_NewLine (void)
6898 #if defined (HOST_WIN32)
6899 return mono_string_new (mono_domain_get (), "\r\n");
6900 #else
6901 return mono_string_new (mono_domain_get (), "\n");
6902 #endif
6905 ICALL_EXPORT MonoBoolean
6906 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6908 #if SIZEOF_VOID_P == 8
6909 return TRUE;
6910 #else
6911 #ifdef HOST_WIN32
6912 gboolean isWow64Process = FALSE;
6913 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6914 return (MonoBoolean)isWow64Process;
6916 #elif defined(HAVE_SYS_UTSNAME_H)
6917 struct utsname name;
6919 if (uname (&name) >= 0) {
6920 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6922 #endif
6923 return FALSE;
6924 #endif
6927 ICALL_EXPORT MonoString *
6928 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6930 MonoError error;
6931 const gchar *value;
6932 gchar *utf8_name;
6934 if (name == NULL)
6935 return NULL;
6937 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6938 if (mono_error_set_pending_exception (&error))
6939 return NULL;
6940 value = g_getenv (utf8_name);
6942 g_free (utf8_name);
6944 if (value == 0)
6945 return NULL;
6947 return mono_string_new (mono_domain_get (), value);
6951 * There is no standard way to get at environ.
6953 #ifndef _MSC_VER
6954 #ifndef __MINGW32_VERSION
6955 #if defined(__APPLE__)
6956 #if defined (TARGET_OSX)
6957 /* Apple defines this in crt_externs.h but doesn't provide that header for
6958 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6959 * in fact exist on all implementations (so far)
6961 gchar ***_NSGetEnviron(void);
6962 #define environ (*_NSGetEnviron())
6963 #else
6964 static char *mono_environ[1] = { NULL };
6965 #define environ mono_environ
6966 #endif /* defined (TARGET_OSX) */
6967 #else
6968 extern
6969 char **environ;
6970 #endif
6971 #endif
6972 #endif
6974 ICALL_EXPORT MonoArray *
6975 ves_icall_System_Environment_GetCoomandLineArgs (void)
6977 MonoError error;
6978 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6979 mono_error_set_pending_exception (&error);
6980 return result;
6983 ICALL_EXPORT MonoArray *
6984 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6986 #ifdef HOST_WIN32
6987 MonoError error;
6988 MonoArray *names;
6989 MonoDomain *domain;
6990 MonoString *str;
6991 WCHAR* env_strings;
6992 WCHAR* env_string;
6993 WCHAR* equal_str;
6994 int n = 0;
6996 env_strings = GetEnvironmentStrings();
6998 if (env_strings) {
6999 env_string = env_strings;
7000 while (*env_string != '\0') {
7001 /* weird case that MS seems to skip */
7002 if (*env_string != '=')
7003 n++;
7004 while (*env_string != '\0')
7005 env_string++;
7006 env_string++;
7010 domain = mono_domain_get ();
7011 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
7012 if (mono_error_set_pending_exception (&error))
7013 return NULL;
7015 if (env_strings) {
7016 n = 0;
7017 env_string = env_strings;
7018 while (*env_string != '\0') {
7019 /* weird case that MS seems to skip */
7020 if (*env_string != '=') {
7021 equal_str = wcschr(env_string, '=');
7022 g_assert(equal_str);
7023 MonoError error;
7024 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
7025 if (mono_error_set_pending_exception (&error))
7026 return NULL;
7028 mono_array_setref (names, n, str);
7029 n++;
7031 while (*env_string != '\0')
7032 env_string++;
7033 env_string++;
7036 FreeEnvironmentStrings (env_strings);
7039 return names;
7041 #else
7042 MonoError error;
7043 MonoArray *names;
7044 MonoDomain *domain;
7045 MonoString *str;
7046 gchar **e, **parts;
7047 int n;
7049 n = 0;
7050 for (e = environ; *e != 0; ++ e)
7051 ++ n;
7053 domain = mono_domain_get ();
7054 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
7055 if (mono_error_set_pending_exception (&error))
7056 return NULL;
7058 n = 0;
7059 for (e = environ; *e != 0; ++ e) {
7060 parts = g_strsplit (*e, "=", 2);
7061 if (*parts != 0) {
7062 str = mono_string_new (domain, *parts);
7063 mono_array_setref (names, n, str);
7066 g_strfreev (parts);
7068 ++ n;
7071 return names;
7072 #endif
7075 ICALL_EXPORT void
7076 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
7078 #ifdef HOST_WIN32
7079 gunichar2 *utf16_name, *utf16_value;
7080 #else
7081 gchar *utf8_name, *utf8_value;
7082 MonoError error;
7083 #endif
7085 #ifdef HOST_WIN32
7086 utf16_name = mono_string_to_utf16 (name);
7087 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7088 SetEnvironmentVariable (utf16_name, NULL);
7089 g_free (utf16_name);
7090 return;
7093 utf16_value = mono_string_to_utf16 (value);
7095 SetEnvironmentVariable (utf16_name, utf16_value);
7097 g_free (utf16_name);
7098 g_free (utf16_value);
7099 #else
7100 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
7101 if (mono_error_set_pending_exception (&error))
7102 return;
7104 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
7105 g_unsetenv (utf8_name);
7106 g_free (utf8_name);
7107 return;
7110 utf8_value = mono_string_to_utf8_checked (value, &error);
7111 if (!mono_error_ok (&error)) {
7112 g_free (utf8_name);
7113 mono_error_set_pending_exception (&error);
7114 return;
7116 g_setenv (utf8_name, utf8_value, TRUE);
7118 g_free (utf8_name);
7119 g_free (utf8_value);
7120 #endif
7123 ICALL_EXPORT void
7124 ves_icall_System_Environment_Exit (int result)
7126 mono_environment_exitcode_set (result);
7128 /* FIXME: There are some cleanup hangs that should be worked out, but
7129 * if the program is going to exit, everything will be cleaned up when
7130 * NaCl exits anyway.
7132 #ifndef __native_client__
7133 if (!mono_runtime_try_shutdown ())
7134 mono_thread_exit ();
7136 /* Suspend all managed threads since the runtime is going away */
7137 mono_thread_suspend_all_other_threads ();
7139 mono_runtime_quit ();
7140 #endif
7142 /* we may need to do some cleanup here... */
7143 exit (result);
7146 ICALL_EXPORT MonoString*
7147 ves_icall_System_Environment_GetGacPath (void)
7149 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7152 ICALL_EXPORT MonoString*
7153 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
7155 #if defined (HOST_WIN32)
7156 #ifndef CSIDL_FLAG_CREATE
7157 #define CSIDL_FLAG_CREATE 0x8000
7158 #endif
7160 WCHAR path [MAX_PATH];
7161 /* Create directory if no existing */
7162 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
7163 int len = 0;
7164 while (path [len])
7165 ++ len;
7166 MonoError error;
7167 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
7168 mono_error_set_pending_exception (&error);
7169 return res;
7171 #else
7172 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7173 #endif
7174 return mono_string_new (mono_domain_get (), "");
7177 ICALL_EXPORT MonoArray *
7178 ves_icall_System_Environment_GetLogicalDrives (void)
7180 MonoError error;
7181 gunichar2 buf [256], *ptr, *dname;
7182 gunichar2 *u16;
7183 guint initial_size = 127, size = 128;
7184 gint ndrives;
7185 MonoArray *result;
7186 MonoString *drivestr;
7187 MonoDomain *domain = mono_domain_get ();
7188 gint len;
7190 buf [0] = '\0';
7191 ptr = buf;
7193 while (size > initial_size) {
7194 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
7195 if (size > initial_size) {
7196 if (ptr != buf)
7197 g_free (ptr);
7198 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7199 initial_size = size;
7200 size++;
7204 /* Count strings */
7205 dname = ptr;
7206 ndrives = 0;
7207 do {
7208 while (*dname++);
7209 ndrives++;
7210 } while (*dname);
7212 dname = ptr;
7213 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7214 if (mono_error_set_pending_exception (&error))
7215 goto leave;
7217 ndrives = 0;
7218 do {
7219 len = 0;
7220 u16 = dname;
7221 while (*u16) { u16++; len ++; }
7222 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7223 if (mono_error_set_pending_exception (&error))
7224 goto leave;
7226 mono_array_setref (result, ndrives++, drivestr);
7227 while (*dname++);
7228 } while (*dname);
7230 leave:
7231 if (ptr != buf)
7232 g_free (ptr);
7234 return result;
7237 ICALL_EXPORT MonoString *
7238 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7240 MonoError error;
7241 gunichar2 volume_name [MAX_PATH + 1];
7243 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7244 return NULL;
7245 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7246 mono_error_set_pending_exception (&error);
7247 return result;
7250 ICALL_EXPORT MonoString *
7251 ves_icall_System_Environment_InternalGetHome (void)
7253 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7256 static const char *encodings [] = {
7257 (char *) 1,
7258 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7259 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7260 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7261 (char *) 2,
7262 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7263 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7264 "x_unicode_2_0_utf_7",
7265 (char *) 3,
7266 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7267 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7268 (char *) 4,
7269 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7270 "iso_10646_ucs2",
7271 (char *) 5,
7272 "unicodefffe", "utf_16be",
7273 (char *) 6,
7274 "iso_8859_1",
7275 (char *) 0
7279 * Returns the internal codepage, if the value of "int_code_page" is
7280 * 1 at entry, and we can not compute a suitable code page number,
7281 * returns the code page as a string
7283 ICALL_EXPORT MonoString*
7284 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7286 const char *cset;
7287 const char *p;
7288 char *c;
7289 char *codepage = NULL;
7290 int code;
7291 int want_name = *int_code_page;
7292 int i;
7294 *int_code_page = -1;
7296 g_get_charset (&cset);
7297 c = codepage = strdup (cset);
7298 for (c = codepage; *c; c++){
7299 if (isascii (*c) && isalpha (*c))
7300 *c = tolower (*c);
7301 if (*c == '-')
7302 *c = '_';
7304 /* g_print ("charset: %s\n", cset); */
7306 /* handle some common aliases */
7307 p = encodings [0];
7308 code = 0;
7309 for (i = 0; p != 0; ){
7310 if ((gsize) p < 7){
7311 code = (gssize) p;
7312 p = encodings [++i];
7313 continue;
7315 if (strcmp (p, codepage) == 0){
7316 *int_code_page = code;
7317 break;
7319 p = encodings [++i];
7322 if (strstr (codepage, "utf_8") != NULL)
7323 *int_code_page |= 0x10000000;
7324 free (codepage);
7326 if (want_name && *int_code_page == -1)
7327 return mono_string_new (mono_domain_get (), cset);
7328 else
7329 return NULL;
7332 ICALL_EXPORT MonoBoolean
7333 ves_icall_System_Environment_get_HasShutdownStarted (void)
7335 if (mono_runtime_is_shutting_down ())
7336 return TRUE;
7338 if (mono_domain_is_unloading (mono_domain_get ()))
7339 return TRUE;
7341 return FALSE;
7344 ICALL_EXPORT void
7345 ves_icall_System_Environment_BroadcastSettingChange (void)
7347 #ifdef HOST_WIN32
7348 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7349 #endif
7352 ICALL_EXPORT
7353 gint32
7354 ves_icall_System_Environment_get_TickCount (void)
7356 /* this will overflow after ~24 days */
7357 return (gint32) (mono_msec_boottime () & 0xffffffff);
7360 ICALL_EXPORT gint32
7361 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7363 return 9;
7366 #ifndef DISABLE_REMOTING
7367 ICALL_EXPORT MonoBoolean
7368 ves_icall_IsTransparentProxy (MonoObject *proxy)
7370 if (!proxy)
7371 return 0;
7373 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7374 return 1;
7376 return 0;
7379 ICALL_EXPORT MonoReflectionMethod *
7380 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7381 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7383 MonoReflectionMethod *ret = NULL;
7384 MonoError error;
7386 MonoClass *klass;
7387 MonoMethod *method;
7388 MonoMethod **vtable;
7389 MonoMethod *res = NULL;
7391 MONO_CHECK_ARG_NULL (rtype, NULL);
7392 MONO_CHECK_ARG_NULL (rmethod, NULL);
7394 method = rmethod->method;
7395 klass = mono_class_from_mono_type (rtype->type);
7396 mono_class_init_checked (klass, &error);
7397 if (mono_error_set_pending_exception (&error))
7398 return NULL;
7400 if (MONO_CLASS_IS_INTERFACE (klass))
7401 return NULL;
7403 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7404 return NULL;
7406 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7407 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7408 return rmethod;
7409 else
7410 return NULL;
7413 mono_class_setup_vtable (klass);
7414 vtable = klass->vtable;
7416 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7417 gboolean variance_used = FALSE;
7418 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7419 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7420 if (offs >= 0)
7421 res = vtable [offs + method->slot];
7422 } else {
7423 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7424 return NULL;
7426 if (method->slot != -1)
7427 res = vtable [method->slot];
7430 if (!res)
7431 return NULL;
7433 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7434 mono_error_set_pending_exception (&error);
7435 return ret;
7438 ICALL_EXPORT void
7439 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7441 MonoError error;
7442 MonoClass *klass;
7443 MonoVTable* vtable;
7445 klass = mono_class_from_mono_type (type->type);
7446 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7447 if (!is_ok (&error)) {
7448 mono_error_set_pending_exception (&error);
7449 return;
7452 mono_vtable_set_is_remote (vtable, enable);
7455 #else /* DISABLE_REMOTING */
7457 ICALL_EXPORT void
7458 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7460 g_assert_not_reached ();
7463 #endif
7465 ICALL_EXPORT MonoObject *
7466 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7468 MonoError error;
7469 MonoClass *klass;
7470 MonoDomain *domain;
7471 MonoObject *ret;
7473 domain = mono_object_domain (type);
7474 klass = mono_class_from_mono_type (type->type);
7475 mono_class_init_checked (klass, &error);
7476 if (mono_error_set_pending_exception (&error))
7477 return NULL;
7479 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7480 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7481 return NULL;
7484 if (klass->rank >= 1) {
7485 g_assert (klass->rank == 1);
7486 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7487 mono_error_set_pending_exception (&error);
7488 return ret;
7489 } else {
7490 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7491 if (!is_ok (&error)) {
7492 mono_error_set_pending_exception (&error);
7493 return NULL;
7495 /* Bypass remoting object creation check */
7496 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7497 mono_error_set_pending_exception (&error);
7499 return ret;
7503 ICALL_EXPORT MonoString *
7504 ves_icall_System_IO_get_temp_path (void)
7506 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7509 #ifndef PLATFORM_NO_DRIVEINFO
7510 ICALL_EXPORT MonoBoolean
7511 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7512 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7513 gint32 *error)
7515 gboolean result;
7516 ULARGE_INTEGER wapi_free_bytes_avail;
7517 ULARGE_INTEGER wapi_total_number_of_bytes;
7518 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7520 *error = ERROR_SUCCESS;
7521 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7522 &wapi_total_number_of_free_bytes);
7524 if (result) {
7525 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7526 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7527 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7528 } else {
7529 *free_bytes_avail = 0;
7530 *total_number_of_bytes = 0;
7531 *total_number_of_free_bytes = 0;
7532 *error = GetLastError ();
7535 return result;
7538 ICALL_EXPORT guint32
7539 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7541 return GetDriveType (mono_string_chars (root_path_name));
7543 #endif
7545 ICALL_EXPORT gpointer
7546 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7548 MonoError error;
7549 gpointer result = mono_compile_method_checked (method, &error);
7550 mono_error_set_pending_exception (&error);
7551 return result;
7554 ICALL_EXPORT MonoString *
7555 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7557 MonoString *mcpath;
7558 gchar *path;
7560 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7562 #if defined (HOST_WIN32)
7563 /* Avoid mixing '/' and '\\' */
7565 gint i;
7566 for (i = strlen (path) - 1; i >= 0; i--)
7567 if (path [i] == '/')
7568 path [i] = '\\';
7570 #endif
7571 mcpath = mono_string_new (mono_domain_get (), path);
7572 g_free (path);
7574 return mcpath;
7577 /* this is an icall */
7578 static MonoString *
7579 get_bundled_app_config (void)
7581 MonoError error;
7582 const gchar *app_config;
7583 MonoDomain *domain;
7584 MonoString *file;
7585 gchar *config_file_name, *config_file_path;
7586 gsize len, config_file_path_length, config_ext_length;
7587 gchar *module;
7589 domain = mono_domain_get ();
7590 file = domain->setup->configuration_file;
7591 if (!file || file->length == 0)
7592 return NULL;
7594 // Retrieve config file and remove the extension
7595 config_file_name = mono_string_to_utf8_checked (file, &error);
7596 if (mono_error_set_pending_exception (&error))
7597 return NULL;
7598 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7599 if (!config_file_path)
7600 config_file_path = config_file_name;
7602 config_file_path_length = strlen (config_file_path);
7603 config_ext_length = strlen (".config");
7604 if (config_file_path_length <= config_ext_length)
7605 return NULL;
7607 len = config_file_path_length - config_ext_length;
7608 module = (gchar *)g_malloc0 (len + 1);
7609 memcpy (module, config_file_path, len);
7610 // Get the config file from the module name
7611 app_config = mono_config_string_for_assembly_file (module);
7612 // Clean-up
7613 g_free (module);
7614 if (config_file_name != config_file_path)
7615 g_free (config_file_name);
7616 g_free (config_file_path);
7618 if (!app_config)
7619 return NULL;
7621 return mono_string_new (mono_domain_get (), app_config);
7624 static MonoString *
7625 get_bundled_machine_config (void)
7627 const gchar *machine_config;
7629 machine_config = mono_get_machine_config ();
7631 if (!machine_config)
7632 return NULL;
7634 return mono_string_new (mono_domain_get (), machine_config);
7637 ICALL_EXPORT MonoString *
7638 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7640 MonoString *ipath;
7641 gchar *path;
7643 path = g_path_get_dirname (mono_get_config_dir ());
7645 #if defined (HOST_WIN32)
7646 /* Avoid mixing '/' and '\\' */
7648 gint i;
7649 for (i = strlen (path) - 1; i >= 0; i--)
7650 if (path [i] == '/')
7651 path [i] = '\\';
7653 #endif
7654 ipath = mono_string_new (mono_domain_get (), path);
7655 g_free (path);
7657 return ipath;
7660 ICALL_EXPORT gboolean
7661 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7663 MonoPEResourceDataEntry *entry;
7664 MonoImage *image;
7666 if (!assembly || !result || !size)
7667 return FALSE;
7669 *result = NULL;
7670 *size = 0;
7671 image = assembly->assembly->image;
7672 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7673 if (!entry)
7674 return FALSE;
7676 *result = mono_image_rva_map (image, entry->rde_data_offset);
7677 if (!(*result)) {
7678 g_free (entry);
7679 return FALSE;
7681 *size = entry->rde_size;
7682 g_free (entry);
7683 return TRUE;
7686 ICALL_EXPORT MonoBoolean
7687 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7689 return mono_is_debugger_attached ();
7692 ICALL_EXPORT MonoBoolean
7693 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7695 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7696 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7697 else
7698 return FALSE;
7701 ICALL_EXPORT void
7702 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7704 if (mono_get_runtime_callbacks ()->debug_log)
7705 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7708 ICALL_EXPORT void
7709 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7711 #if defined (HOST_WIN32)
7712 OutputDebugString (mono_string_chars (message));
7713 #else
7714 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7715 #endif
7718 /* Only used for value types */
7719 ICALL_EXPORT MonoObject *
7720 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7722 MonoError error;
7723 MonoObject *result;
7724 MonoClass *klass;
7725 MonoDomain *domain;
7727 domain = mono_object_domain (type);
7728 klass = mono_class_from_mono_type (type->type);
7729 mono_class_init_checked (klass, &error);
7730 if (mono_error_set_pending_exception (&error))
7731 return NULL;
7733 if (mono_class_is_nullable (klass))
7734 /* No arguments -> null */
7735 return NULL;
7737 result = mono_object_new_checked (domain, klass, &error);
7738 mono_error_set_pending_exception (&error);
7739 return result;
7742 ICALL_EXPORT MonoReflectionMethod *
7743 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7745 MonoReflectionMethod *ret = NULL;
7746 MonoError error;
7748 MonoClass *klass, *parent;
7749 MonoGenericContext *generic_inst = NULL;
7750 MonoMethod *method = m->method;
7751 MonoMethod *result = NULL;
7752 int slot;
7754 if (method->klass == NULL)
7755 return m;
7757 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7758 MONO_CLASS_IS_INTERFACE (method->klass) ||
7759 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7760 return m;
7762 slot = mono_method_get_vtable_slot (method);
7763 if (slot == -1)
7764 return m;
7766 klass = method->klass;
7767 if (klass->generic_class) {
7768 generic_inst = mono_class_get_context (klass);
7769 klass = klass->generic_class->container_class;
7772 if (definition) {
7773 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7774 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7775 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7776 or klass is the generic container class and generic_inst is the instantiation.
7778 when we go to the parent, if the parent is an open constructed type, we need to
7779 replace the type parameters by the definitions from the generic_inst, and then take it
7780 apart again into the klass and the generic_inst.
7782 For cases like this:
7783 class C<T> : B<T, int> {
7784 public override void Foo () { ... }
7786 class B<U,V> : A<HashMap<U,V>> {
7787 public override void Foo () { ... }
7789 class A<X> {
7790 public virtual void Foo () { ... }
7793 if at each iteration the parent isn't open, we can skip inflating it. if at some
7794 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7795 NULL;
7797 MonoGenericContext *parent_inst = NULL;
7798 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7799 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7800 if (!mono_error_ok (&error)) {
7801 mono_error_set_pending_exception (&error);
7802 return NULL;
7805 if (parent->generic_class) {
7806 parent_inst = mono_class_get_context (parent);
7807 parent = parent->generic_class->container_class;
7810 mono_class_setup_vtable (parent);
7811 if (parent->vtable_size <= slot)
7812 break;
7813 klass = parent;
7814 generic_inst = parent_inst;
7816 } else {
7817 klass = klass->parent;
7818 if (!klass)
7819 return m;
7820 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7821 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7822 if (!mono_error_ok (&error)) {
7823 mono_error_set_pending_exception (&error);
7824 return NULL;
7827 generic_inst = NULL;
7829 if (klass->generic_class) {
7830 generic_inst = mono_class_get_context (klass);
7831 klass = klass->generic_class->container_class;
7836 if (generic_inst) {
7837 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7838 if (!mono_error_ok (&error)) {
7839 mono_error_set_pending_exception (&error);
7840 return NULL;
7844 if (klass == method->klass)
7845 return m;
7847 /*This is possible if definition == FALSE.
7848 * Do it here to be really sure we don't read invalid memory.
7850 if (slot >= klass->vtable_size)
7851 return m;
7853 mono_class_setup_vtable (klass);
7855 result = klass->vtable [slot];
7856 if (result == NULL) {
7857 /* It is an abstract method */
7858 gpointer iter = NULL;
7859 while ((result = mono_class_get_methods (klass, &iter)))
7860 if (result->slot == slot)
7861 break;
7864 if (result == NULL)
7865 return m;
7867 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7868 mono_error_set_pending_exception (&error);
7869 return ret;
7872 ICALL_EXPORT MonoString*
7873 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7875 MonoMethod *method = m->method;
7877 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7878 return m->name;
7881 ICALL_EXPORT void
7882 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7884 iter->sig = *(MonoMethodSignature**)argsp;
7886 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7887 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7889 iter->next_arg = 0;
7890 /* FIXME: it's not documented what start is exactly... */
7891 if (start) {
7892 iter->args = start;
7893 } else {
7894 iter->args = argsp + sizeof (gpointer);
7896 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7898 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7901 ICALL_EXPORT MonoTypedRef
7902 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7904 guint32 i, arg_size;
7905 gint32 align;
7906 MonoTypedRef res;
7908 i = iter->sig->sentinelpos + iter->next_arg;
7910 g_assert (i < iter->sig->param_count);
7912 res.type = iter->sig->params [i];
7913 res.klass = mono_class_from_mono_type (res.type);
7914 arg_size = mono_type_stack_size (res.type, &align);
7915 #if defined(__arm__) || defined(__mips__)
7916 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7917 #endif
7918 res.value = iter->args;
7919 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7920 /* Values are stored as 8 byte register sized objects, but 'value'
7921 * is dereferenced as a pointer in other routines.
7923 res.value = (char*)res.value + 4;
7924 #endif
7925 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7926 if (arg_size <= sizeof (gpointer)) {
7927 int dummy;
7928 int padding = arg_size - mono_type_size (res.type, &dummy);
7929 res.value = (guint8*)res.value + padding;
7931 #endif
7932 iter->args = (char*)iter->args + arg_size;
7933 iter->next_arg++;
7935 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7937 return res;
7940 ICALL_EXPORT MonoTypedRef
7941 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7943 guint32 i, arg_size;
7944 gint32 align;
7945 MonoTypedRef res;
7947 i = iter->sig->sentinelpos + iter->next_arg;
7949 g_assert (i < iter->sig->param_count);
7951 while (i < iter->sig->param_count) {
7952 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7953 continue;
7954 res.type = iter->sig->params [i];
7955 res.klass = mono_class_from_mono_type (res.type);
7956 /* FIXME: endianess issue... */
7957 arg_size = mono_type_stack_size (res.type, &align);
7958 #if defined(__arm__) || defined(__mips__)
7959 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7960 #endif
7961 res.value = iter->args;
7962 iter->args = (char*)iter->args + arg_size;
7963 iter->next_arg++;
7964 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7965 return res;
7967 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7969 res.type = NULL;
7970 res.value = NULL;
7971 res.klass = NULL;
7972 return res;
7975 ICALL_EXPORT MonoType*
7976 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7978 gint i;
7980 i = iter->sig->sentinelpos + iter->next_arg;
7982 g_assert (i < iter->sig->param_count);
7984 return iter->sig->params [i];
7987 ICALL_EXPORT MonoObject*
7988 mono_TypedReference_ToObject (MonoTypedRef* tref)
7990 MonoError error;
7991 MonoObject *result = NULL;
7992 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7993 MonoObject** objp = (MonoObject **)tref->value;
7994 return *objp;
7997 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7998 mono_error_set_pending_exception (&error);
7999 return result;
8002 ICALL_EXPORT MonoTypedRef
8003 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
8005 MonoTypedRef res;
8006 MonoReflectionField *f;
8007 MonoClass *klass;
8008 MonoType *ftype = NULL;
8009 guint8 *p = NULL;
8010 int i;
8012 memset (&res, 0, sizeof (res));
8014 g_assert (fields);
8015 g_assert (mono_array_length (fields) > 0);
8017 klass = target->vtable->klass;
8019 for (i = 0; i < mono_array_length (fields); ++i) {
8020 f = mono_array_get (fields, MonoReflectionField*, i);
8021 if (f == NULL) {
8022 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
8023 return res;
8025 if (f->field->parent != klass) {
8026 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
8027 return res;
8029 if (i == 0)
8030 p = (guint8*)target + f->field->offset;
8031 else
8032 p += f->field->offset - sizeof (MonoObject);
8033 klass = mono_class_from_mono_type (f->field->type);
8034 ftype = f->field->type;
8037 res.type = ftype;
8038 res.klass = mono_class_from_mono_type (ftype);
8039 res.value = p;
8041 return res;
8044 static void
8045 prelink_method (MonoMethod *method, MonoError *error)
8047 const char *exc_class, *exc_arg;
8049 mono_error_init (error);
8050 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
8051 return;
8052 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
8053 if (exc_class) {
8054 mono_error_set_exception_instance (error,
8055 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
8056 return;
8058 /* create the wrapper, too? */
8061 ICALL_EXPORT void
8062 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
8064 MonoError error;
8066 prelink_method (method->method, &error);
8067 mono_error_set_pending_exception (&error);
8070 ICALL_EXPORT void
8071 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
8073 MonoError error;
8074 MonoClass *klass = mono_class_from_mono_type (type->type);
8075 MonoMethod* m;
8076 gpointer iter = NULL;
8078 mono_class_init_checked (klass, &error);
8079 if (mono_error_set_pending_exception (&error))
8080 return;
8082 while ((m = mono_class_get_methods (klass, &iter))) {
8083 prelink_method (m, &error);
8084 if (mono_error_set_pending_exception (&error))
8085 return;
8089 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8090 ICALL_EXPORT void
8091 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
8092 gint32 const **exponents,
8093 gunichar2 const **digitLowerTable,
8094 gunichar2 const **digitUpperTable,
8095 gint64 const **tenPowersList,
8096 gint32 const **decHexDigits)
8098 *mantissas = Formatter_MantissaBitsTable;
8099 *exponents = Formatter_TensExponentTable;
8100 *digitLowerTable = Formatter_DigitLowerTable;
8101 *digitUpperTable = Formatter_DigitUpperTable;
8102 *tenPowersList = Formatter_TenPowersList;
8103 *decHexDigits = Formatter_DecHexDigits;
8107 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8108 * and avoid useless allocations.
8110 static MonoArray*
8111 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
8113 MonoReflectionType *rt;
8114 MonoArray *res;
8115 int i, count = 0;
8117 mono_error_init (error);
8118 for (i = 0; i < type->num_mods; ++i) {
8119 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
8120 count++;
8122 if (!count)
8123 return NULL;
8124 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
8125 return_val_if_nok (error, NULL);
8126 count = 0;
8127 for (i = 0; i < type->num_mods; ++i) {
8128 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
8129 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
8130 return_val_if_nok (error, NULL);
8132 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8133 return_val_if_nok (error, NULL);
8135 mono_array_setref (res, count, rt);
8136 count++;
8139 return res;
8142 ICALL_EXPORT MonoArray*
8143 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
8145 MonoError error;
8146 MonoType *type = param->ClassImpl->type;
8147 MonoClass *member_class = mono_object_class (param->MemberImpl);
8148 MonoMethod *method = NULL;
8149 MonoImage *image;
8150 int pos;
8151 MonoMethodSignature *sig;
8152 MonoArray *res;
8154 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8155 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8156 method = rmethod->method;
8157 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
8158 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8159 if (!(method = prop->property->get))
8160 method = prop->property->set;
8161 g_assert (method);
8162 } else {
8163 char *type_name = mono_type_get_full_name (member_class);
8164 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
8165 MonoException *ex = mono_get_exception_not_supported (msg);
8166 g_free (type_name);
8167 g_free (msg);
8168 mono_set_pending_exception (ex);
8169 return NULL;
8172 image = method->klass->image;
8173 pos = param->PositionImpl;
8174 sig = mono_method_signature (method);
8175 if (pos == -1)
8176 type = sig->ret;
8177 else
8178 type = sig->params [pos];
8180 res = type_array_from_modifiers (image, type, optional, &error);
8181 mono_error_set_pending_exception (&error);
8182 return res;
8185 static MonoType*
8186 get_property_type (MonoProperty *prop)
8188 MonoMethodSignature *sig;
8189 if (prop->get) {
8190 sig = mono_method_signature (prop->get);
8191 return sig->ret;
8192 } else if (prop->set) {
8193 sig = mono_method_signature (prop->set);
8194 return sig->params [sig->param_count - 1];
8196 return NULL;
8199 ICALL_EXPORT MonoArray*
8200 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
8202 MonoError error;
8203 MonoType *type = get_property_type (property->property);
8204 MonoImage *image = property->klass->image;
8205 MonoArray *res;
8207 if (!type)
8208 return NULL;
8209 res = type_array_from_modifiers (image, type, optional, &error);
8210 mono_error_set_pending_exception (&error);
8211 return res;
8215 *Construct a MonoType suited to be used to decode a constant blob object.
8217 * @type is the target type which will be constructed
8218 * @blob_type is the blob type, for example, that comes from the constant table
8219 * @real_type is the expected constructed type.
8221 static void
8222 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8224 type->type = blob_type;
8225 type->data.klass = NULL;
8226 if (blob_type == MONO_TYPE_CLASS)
8227 type->data.klass = mono_defaults.object_class;
8228 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8229 /* For enums, we need to use the base type */
8230 type->type = MONO_TYPE_VALUETYPE;
8231 type->data.klass = mono_class_from_mono_type (real_type);
8232 } else
8233 type->data.klass = mono_class_from_mono_type (real_type);
8236 ICALL_EXPORT MonoObject*
8237 property_info_get_default_value (MonoReflectionProperty *property)
8239 MonoError error;
8240 MonoType blob_type;
8241 MonoProperty *prop = property->property;
8242 MonoType *type = get_property_type (prop);
8243 MonoDomain *domain = mono_object_domain (property);
8244 MonoTypeEnum def_type;
8245 const char *def_value;
8246 MonoObject *o;
8248 mono_class_init (prop->parent);
8250 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8251 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8252 return NULL;
8255 def_value = mono_class_get_property_default_value (prop, &def_type);
8257 mono_type_from_blob_type (&blob_type, def_type, type);
8258 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8260 mono_error_set_pending_exception (&error);
8261 return o;
8264 ICALL_EXPORT MonoBoolean
8265 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8267 MonoError error;
8268 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8269 MonoCustomAttrInfo *cinfo;
8270 gboolean found;
8272 mono_class_init_checked (attr_class, &error);
8273 if (mono_error_set_pending_exception (&error))
8274 return FALSE;
8276 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8277 if (!is_ok (&error)) {
8278 mono_error_set_pending_exception (&error);
8279 return FALSE;
8281 if (!cinfo)
8282 return FALSE;
8283 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8284 if (!cinfo->cached)
8285 mono_custom_attrs_free (cinfo);
8286 return found;
8289 ICALL_EXPORT MonoArray*
8290 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8292 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8293 MonoArray *res;
8294 MonoError error;
8296 if (attr_class) {
8297 mono_class_init_checked (attr_class, &error);
8298 if (mono_error_set_pending_exception (&error))
8299 return NULL;
8302 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8303 if (!mono_error_ok (&error)) {
8304 mono_error_set_pending_exception (&error);
8305 return NULL;
8308 return res;
8311 ICALL_EXPORT MonoArray*
8312 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8314 MonoError error;
8315 MonoArray *result;
8316 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8317 mono_error_set_pending_exception (&error);
8318 return result;
8322 ICALL_EXPORT MonoString*
8323 ves_icall_Mono_Runtime_GetDisplayName (void)
8325 char *info;
8326 MonoString *display_name;
8328 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8329 display_name = mono_string_new (mono_domain_get (), info);
8330 g_free (info);
8331 return display_name;
8334 ICALL_EXPORT MonoString*
8335 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8337 MonoError error;
8338 MonoString *message;
8339 guint32 ret;
8340 gunichar2 buf[256];
8342 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8343 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8344 buf, 255, NULL);
8345 if (ret == 0) {
8346 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8347 } else {
8348 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8349 if (mono_error_set_pending_exception (&error))
8350 return NULL;
8353 return message;
8356 ICALL_EXPORT gpointer
8357 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8359 return GetCurrentProcess ();
8362 ICALL_EXPORT MonoBoolean
8363 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8365 return GetExitCodeProcess (handle, (guint32*) exitcode);
8368 ICALL_EXPORT MonoBoolean
8369 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8371 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8372 return CloseHandle (handle);
8373 #else
8374 return CloseProcess (handle);
8375 #endif
8378 ICALL_EXPORT MonoBoolean
8379 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8381 return TerminateProcess (handle, exitcode);
8384 ICALL_EXPORT gint32
8385 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8387 return WaitForInputIdle (handle, milliseconds);
8390 ICALL_EXPORT MonoBoolean
8391 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8393 return GetProcessWorkingSetSize (handle, min, max);
8396 ICALL_EXPORT MonoBoolean
8397 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8399 return SetProcessWorkingSetSize (handle, min, max);
8402 ICALL_EXPORT MonoBoolean
8403 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8405 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8408 ICALL_EXPORT gint32
8409 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8411 return mono_process_current_pid ();
8414 ICALL_EXPORT gint32
8415 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8417 return GetPriorityClass (handle);
8420 ICALL_EXPORT MonoBoolean
8421 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8423 return SetPriorityClass (handle, priorityClass);
8426 #ifndef DISABLE_ICALL_TABLES
8428 #define ICALL_TYPE(id,name,first)
8429 #define ICALL(id,name,func) Icall_ ## id,
8431 enum {
8432 #include "metadata/icall-def.h"
8433 Icall_last
8436 #undef ICALL_TYPE
8437 #undef ICALL
8438 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8439 #define ICALL(id,name,func)
8440 enum {
8441 #include "metadata/icall-def.h"
8442 Icall_type_num
8445 #undef ICALL_TYPE
8446 #undef ICALL
8447 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8448 #define ICALL(id,name,func)
8449 typedef struct {
8450 guint16 first_icall;
8451 } IcallTypeDesc;
8453 static const IcallTypeDesc
8454 icall_type_descs [] = {
8455 #include "metadata/icall-def.h"
8456 {Icall_last}
8459 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8461 #undef ICALL_TYPE
8462 #define ICALL_TYPE(id,name,first)
8463 #undef ICALL
8465 #ifdef HAVE_ARRAY_ELEM_INIT
8466 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8467 #define MSGSTRFIELD1(line) str##line
8469 static const struct msgstrtn_t {
8470 #define ICALL(id,name,func)
8471 #undef ICALL_TYPE
8472 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8473 #include "metadata/icall-def.h"
8474 #undef ICALL_TYPE
8475 } icall_type_names_str = {
8476 #define ICALL_TYPE(id,name,first) (name),
8477 #include "metadata/icall-def.h"
8478 #undef ICALL_TYPE
8480 static const guint16 icall_type_names_idx [] = {
8481 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8482 #include "metadata/icall-def.h"
8483 #undef ICALL_TYPE
8485 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8487 static const struct msgstr_t {
8488 #undef ICALL
8489 #define ICALL_TYPE(id,name,first)
8490 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8491 #include "metadata/icall-def.h"
8492 #undef ICALL
8493 } icall_names_str = {
8494 #define ICALL(id,name,func) (name),
8495 #include "metadata/icall-def.h"
8496 #undef ICALL
8498 static const guint16 icall_names_idx [] = {
8499 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8500 #include "metadata/icall-def.h"
8501 #undef ICALL
8503 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8505 #else
8507 #undef ICALL_TYPE
8508 #undef ICALL
8509 #define ICALL_TYPE(id,name,first) name,
8510 #define ICALL(id,name,func)
8511 static const char* const
8512 icall_type_names [] = {
8513 #include "metadata/icall-def.h"
8514 NULL
8517 #define icall_type_name_get(id) (icall_type_names [(id)])
8519 #undef ICALL_TYPE
8520 #undef ICALL
8521 #define ICALL_TYPE(id,name,first)
8522 #define ICALL(id,name,func) name,
8523 static const char* const
8524 icall_names [] = {
8525 #include "metadata/icall-def.h"
8526 NULL
8528 #define icall_name_get(id) icall_names [(id)]
8530 #endif /* !HAVE_ARRAY_ELEM_INIT */
8532 #undef ICALL_TYPE
8533 #undef ICALL
8534 #define ICALL_TYPE(id,name,first)
8535 #define ICALL(id,name,func) func,
8536 static const gconstpointer
8537 icall_functions [] = {
8538 #include "metadata/icall-def.h"
8539 NULL
8542 #ifdef ENABLE_ICALL_SYMBOL_MAP
8543 #undef ICALL_TYPE
8544 #undef ICALL
8545 #define ICALL_TYPE(id,name,first)
8546 #define ICALL(id,name,func) #func,
8547 static const gconstpointer
8548 icall_symbols [] = {
8549 #include "metadata/icall-def.h"
8550 NULL
8552 #endif
8554 #endif /* DISABLE_ICALL_TABLES */
8556 static mono_mutex_t icall_mutex;
8557 static GHashTable *icall_hash = NULL;
8558 static GHashTable *jit_icall_hash_name = NULL;
8559 static GHashTable *jit_icall_hash_addr = NULL;
8561 void
8562 mono_icall_init (void)
8564 #ifndef DISABLE_ICALL_TABLES
8565 int i = 0;
8567 /* check that tables are sorted: disable in release */
8568 if (TRUE) {
8569 int j;
8570 const char *prev_class = NULL;
8571 const char *prev_method;
8573 for (i = 0; i < Icall_type_num; ++i) {
8574 const IcallTypeDesc *desc;
8575 int num_icalls;
8576 prev_method = NULL;
8577 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8578 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8579 prev_class = icall_type_name_get (i);
8580 desc = &icall_type_descs [i];
8581 num_icalls = icall_desc_num_icalls (desc);
8582 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8583 for (j = 0; j < num_icalls; ++j) {
8584 const char *methodn = icall_name_get (desc->first_icall + j);
8585 if (prev_method && strcmp (prev_method, methodn) >= 0)
8586 g_print ("method %s should come before method %s\n", methodn, prev_method);
8587 prev_method = methodn;
8591 #endif
8593 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8594 mono_os_mutex_init (&icall_mutex);
8597 static void
8598 mono_icall_lock (void)
8600 mono_locks_os_acquire (&icall_mutex, IcallLock);
8603 static void
8604 mono_icall_unlock (void)
8606 mono_locks_os_release (&icall_mutex, IcallLock);
8609 void
8610 mono_icall_cleanup (void)
8612 g_hash_table_destroy (icall_hash);
8613 g_hash_table_destroy (jit_icall_hash_name);
8614 g_hash_table_destroy (jit_icall_hash_addr);
8615 mono_os_mutex_destroy (&icall_mutex);
8619 * mono_add_internal_call:
8620 * @name: method specification to surface to the managed world
8621 * @method: pointer to a C method to invoke when the method is called
8623 * This method surfaces the C function pointed by @method as a method
8624 * that has been surfaced in managed code with the method specified in
8625 * @name as an internal call.
8627 * Internal calls are surfaced to all app domains loaded and they are
8628 * accessibly by a type with the specified name.
8630 * You must provide a fully qualified type name, that is namespaces
8631 * and type name, followed by a colon and the method name, with an
8632 * optional signature to bind.
8634 * For example, the following are all valid declarations:
8636 * "MyApp.Services.ScriptService:Accelerate"
8637 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8639 * You use method parameters in cases where there might be more than
8640 * one surface method to managed code. That way you can register different
8641 * internal calls for different method overloads.
8643 * The internal calls are invoked with no marshalling. This means that .NET
8644 * types like System.String are exposed as `MonoString *` parameters. This is
8645 * different than the way that strings are surfaced in P/Invoke.
8647 * For more information on how the parameters are marshalled, see the
8648 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8649 * page.
8651 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8652 * reference for more information on the format of method descriptions.
8654 void
8655 mono_add_internal_call (const char *name, gconstpointer method)
8657 mono_icall_lock ();
8659 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8661 mono_icall_unlock ();
8664 #ifndef DISABLE_ICALL_TABLES
8666 #ifdef HAVE_ARRAY_ELEM_INIT
8667 static int
8668 compare_method_imap (const void *key, const void *elem)
8670 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8671 return strcmp (key, method_name);
8674 static gpointer
8675 find_method_icall (const IcallTypeDesc *imap, const char *name)
8677 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);
8678 if (!nameslot)
8679 return NULL;
8680 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8683 static int
8684 compare_class_imap (const void *key, const void *elem)
8686 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8687 return strcmp (key, class_name);
8690 static const IcallTypeDesc*
8691 find_class_icalls (const char *name)
8693 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);
8694 if (!nameslot)
8695 return NULL;
8696 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8699 #else /* HAVE_ARRAY_ELEM_INIT */
8701 static int
8702 compare_method_imap (const void *key, const void *elem)
8704 const char** method_name = (const char**)elem;
8705 return strcmp (key, *method_name);
8708 static gpointer
8709 find_method_icall (const IcallTypeDesc *imap, const char *name)
8711 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8712 if (!nameslot)
8713 return NULL;
8714 return (gpointer)icall_functions [(nameslot - icall_names)];
8717 static int
8718 compare_class_imap (const void *key, const void *elem)
8720 const char** class_name = (const char**)elem;
8721 return strcmp (key, *class_name);
8724 static const IcallTypeDesc*
8725 find_class_icalls (const char *name)
8727 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8728 if (!nameslot)
8729 return NULL;
8730 return &icall_type_descs [nameslot - icall_type_names];
8733 #endif /* HAVE_ARRAY_ELEM_INIT */
8735 #endif /* DISABLE_ICALL_TABLES */
8738 * we should probably export this as an helper (handle nested types).
8739 * Returns the number of chars written in buf.
8741 static int
8742 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8744 int nspacelen, cnamelen;
8745 nspacelen = strlen (klass->name_space);
8746 cnamelen = strlen (klass->name);
8747 if (nspacelen + cnamelen + 2 > bufsize)
8748 return 0;
8749 if (nspacelen) {
8750 memcpy (buf, klass->name_space, nspacelen);
8751 buf [nspacelen ++] = '.';
8753 memcpy (buf + nspacelen, klass->name, cnamelen);
8754 buf [nspacelen + cnamelen] = 0;
8755 return nspacelen + cnamelen;
8758 #ifdef DISABLE_ICALL_TABLES
8759 static void
8760 no_icall_table (void)
8762 g_assert_not_reached ();
8764 #endif
8766 gpointer
8767 mono_lookup_internal_call (MonoMethod *method)
8769 char *sigstart;
8770 char *tmpsig;
8771 char mname [2048];
8772 int typelen = 0, mlen, siglen;
8773 gpointer res;
8774 #ifndef DISABLE_ICALL_TABLES
8775 const IcallTypeDesc *imap = NULL;
8776 #endif
8778 g_assert (method != NULL);
8780 if (method->is_inflated)
8781 method = ((MonoMethodInflated *) method)->declaring;
8783 if (method->klass->nested_in) {
8784 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8785 if (!pos)
8786 return NULL;
8788 mname [pos++] = '/';
8789 mname [pos] = 0;
8791 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8792 if (!typelen)
8793 return NULL;
8795 typelen += pos;
8796 } else {
8797 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8798 if (!typelen)
8799 return NULL;
8802 #ifndef DISABLE_ICALL_TABLES
8803 imap = find_class_icalls (mname);
8804 #endif
8806 mname [typelen] = ':';
8807 mname [typelen + 1] = ':';
8809 mlen = strlen (method->name);
8810 memcpy (mname + typelen + 2, method->name, mlen);
8811 sigstart = mname + typelen + 2 + mlen;
8812 *sigstart = 0;
8814 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8815 siglen = strlen (tmpsig);
8816 if (typelen + mlen + siglen + 6 > sizeof (mname))
8817 return NULL;
8818 sigstart [0] = '(';
8819 memcpy (sigstart + 1, tmpsig, siglen);
8820 sigstart [siglen + 1] = ')';
8821 sigstart [siglen + 2] = 0;
8822 g_free (tmpsig);
8824 mono_icall_lock ();
8826 res = g_hash_table_lookup (icall_hash, mname);
8827 if (res) {
8828 mono_icall_unlock ();;
8829 return res;
8831 /* try without signature */
8832 *sigstart = 0;
8833 res = g_hash_table_lookup (icall_hash, mname);
8834 if (res) {
8835 mono_icall_unlock ();
8836 return res;
8839 #ifdef DISABLE_ICALL_TABLES
8840 mono_icall_unlock ();
8841 /* Fail only when the result is actually used */
8842 /* mono_marshal_get_native_wrapper () depends on this */
8843 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8844 return ves_icall_System_String_ctor_RedirectToCreateString;
8845 else
8846 return no_icall_table;
8847 #else
8848 /* it wasn't found in the static call tables */
8849 if (!imap) {
8850 mono_icall_unlock ();
8851 return NULL;
8853 res = find_method_icall (imap, sigstart - mlen);
8854 if (res) {
8855 mono_icall_unlock ();
8856 return res;
8858 /* try _with_ signature */
8859 *sigstart = '(';
8860 res = find_method_icall (imap, sigstart - mlen);
8861 if (res) {
8862 mono_icall_unlock ();
8863 return res;
8866 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8867 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8868 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8869 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8870 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");
8871 g_print ("If you see other errors or faults after this message they are probably related\n");
8872 g_print ("and you need to fix your mono install first.\n");
8874 mono_icall_unlock ();
8876 return NULL;
8877 #endif
8880 #ifdef ENABLE_ICALL_SYMBOL_MAP
8881 static int
8882 func_cmp (gconstpointer key, gconstpointer p)
8884 return (gsize)key - (gsize)*(gsize*)p;
8886 #endif
8889 * mono_lookup_icall_symbol:
8891 * Given the icall METHOD, returns its C symbol.
8893 const char*
8894 mono_lookup_icall_symbol (MonoMethod *m)
8896 #ifdef DISABLE_ICALL_TABLES
8897 g_assert_not_reached ();
8898 return NULL;
8899 #else
8900 #ifdef ENABLE_ICALL_SYMBOL_MAP
8901 gpointer func;
8902 int i;
8903 gpointer slot;
8904 static gconstpointer *functions_sorted;
8905 static const char**symbols_sorted;
8906 static gboolean inited;
8908 if (!inited) {
8909 gboolean changed;
8911 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8912 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8913 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8914 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8915 /* Bubble sort the two arrays */
8916 changed = TRUE;
8917 while (changed) {
8918 changed = FALSE;
8919 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8920 if (functions_sorted [i] > functions_sorted [i + 1]) {
8921 gconstpointer tmp;
8923 tmp = functions_sorted [i];
8924 functions_sorted [i] = functions_sorted [i + 1];
8925 functions_sorted [i + 1] = tmp;
8926 tmp = symbols_sorted [i];
8927 symbols_sorted [i] = symbols_sorted [i + 1];
8928 symbols_sorted [i + 1] = tmp;
8929 changed = TRUE;
8935 func = mono_lookup_internal_call (m);
8936 if (!func)
8937 return NULL;
8938 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8939 if (!slot)
8940 return NULL;
8941 g_assert (slot);
8942 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8943 #else
8944 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8945 g_assert_not_reached ();
8946 return 0;
8947 #endif
8948 #endif
8951 static MonoType*
8952 type_from_typename (char *type_name)
8954 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8956 if (!strcmp (type_name, "int"))
8957 klass = mono_defaults.int_class;
8958 else if (!strcmp (type_name, "ptr"))
8959 klass = mono_defaults.int_class;
8960 else if (!strcmp (type_name, "void"))
8961 klass = mono_defaults.void_class;
8962 else if (!strcmp (type_name, "int32"))
8963 klass = mono_defaults.int32_class;
8964 else if (!strcmp (type_name, "uint32"))
8965 klass = mono_defaults.uint32_class;
8966 else if (!strcmp (type_name, "int8"))
8967 klass = mono_defaults.sbyte_class;
8968 else if (!strcmp (type_name, "uint8"))
8969 klass = mono_defaults.byte_class;
8970 else if (!strcmp (type_name, "int16"))
8971 klass = mono_defaults.int16_class;
8972 else if (!strcmp (type_name, "uint16"))
8973 klass = mono_defaults.uint16_class;
8974 else if (!strcmp (type_name, "long"))
8975 klass = mono_defaults.int64_class;
8976 else if (!strcmp (type_name, "ulong"))
8977 klass = mono_defaults.uint64_class;
8978 else if (!strcmp (type_name, "float"))
8979 klass = mono_defaults.single_class;
8980 else if (!strcmp (type_name, "double"))
8981 klass = mono_defaults.double_class;
8982 else if (!strcmp (type_name, "object"))
8983 klass = mono_defaults.object_class;
8984 else if (!strcmp (type_name, "obj"))
8985 klass = mono_defaults.object_class;
8986 else if (!strcmp (type_name, "string"))
8987 klass = mono_defaults.string_class;
8988 else if (!strcmp (type_name, "bool"))
8989 klass = mono_defaults.boolean_class;
8990 else if (!strcmp (type_name, "boolean"))
8991 klass = mono_defaults.boolean_class;
8992 else {
8993 g_error ("%s", type_name);
8994 g_assert_not_reached ();
8996 return &klass->byval_arg;
9000 * LOCKING: Take the corlib image lock.
9002 MonoMethodSignature*
9003 mono_create_icall_signature (const char *sigstr)
9005 gchar **parts;
9006 int i, len;
9007 gchar **tmp;
9008 MonoMethodSignature *res, *res2;
9009 MonoImage *corlib = mono_defaults.corlib;
9011 mono_image_lock (corlib);
9012 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
9013 mono_image_unlock (corlib);
9015 if (res)
9016 return res;
9018 parts = g_strsplit (sigstr, " ", 256);
9020 tmp = parts;
9021 len = 0;
9022 while (*tmp) {
9023 len ++;
9024 tmp ++;
9027 res = mono_metadata_signature_alloc (corlib, len - 1);
9028 res->pinvoke = 1;
9030 #ifdef HOST_WIN32
9032 * Under windows, the default pinvoke calling convention is STDCALL but
9033 * we need CDECL.
9035 res->call_convention = MONO_CALL_C;
9036 #endif
9038 res->ret = type_from_typename (parts [0]);
9039 for (i = 1; i < len; ++i) {
9040 res->params [i - 1] = type_from_typename (parts [i]);
9043 g_strfreev (parts);
9045 mono_image_lock (corlib);
9046 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
9047 if (res2)
9048 res = res2; /*Value is allocated in the image pool*/
9049 else
9050 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
9051 mono_image_unlock (corlib);
9053 return res;
9056 MonoJitICallInfo *
9057 mono_find_jit_icall_by_name (const char *name)
9059 MonoJitICallInfo *info;
9060 g_assert (jit_icall_hash_name);
9062 mono_icall_lock ();
9063 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9064 mono_icall_unlock ();
9065 return info;
9068 MonoJitICallInfo *
9069 mono_find_jit_icall_by_addr (gconstpointer addr)
9071 MonoJitICallInfo *info;
9072 g_assert (jit_icall_hash_addr);
9074 mono_icall_lock ();
9075 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
9076 mono_icall_unlock ();
9078 return info;
9082 * mono_get_jit_icall_info:
9084 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9085 * caller should access it while holding the icall lock.
9087 GHashTable*
9088 mono_get_jit_icall_info (void)
9090 return jit_icall_hash_name;
9094 * mono_lookup_jit_icall_symbol:
9096 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9098 const char*
9099 mono_lookup_jit_icall_symbol (const char *name)
9101 MonoJitICallInfo *info;
9102 const char *res = NULL;
9104 mono_icall_lock ();
9105 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
9106 if (info)
9107 res = info->c_symbol;
9108 mono_icall_unlock ();
9109 return res;
9112 void
9113 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
9115 mono_icall_lock ();
9116 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
9117 mono_icall_unlock ();
9121 * 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
9122 * icalls without wrappers in some cases.
9124 MonoJitICallInfo *
9125 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9127 MonoJitICallInfo *info;
9129 g_assert (func);
9130 g_assert (name);
9132 mono_icall_lock ();
9134 if (!jit_icall_hash_name) {
9135 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9136 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9139 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9140 g_warning ("jit icall already defined \"%s\"\n", name);
9141 g_assert_not_reached ();
9144 info = g_new0 (MonoJitICallInfo, 1);
9146 info->name = name;
9147 info->func = func;
9148 info->sig = sig;
9149 info->c_symbol = c_symbol;
9150 info->no_raise = no_raise;
9152 if (is_save) {
9153 info->wrapper = func;
9154 } else {
9155 info->wrapper = NULL;
9158 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9159 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9161 mono_icall_unlock ();
9162 return info;
9165 MonoJitICallInfo *
9166 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9168 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);