[sdks] Compile support/{zlib-helper,nl}.c so XI/XM/XA does not have to cherry-pick...
[mono-project.git] / mono / metadata / icall.c
blobe009a94bdf77d304290f324aa4f344f4a7ba8a47
1 /**
2 * \file
4 * Authors:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
17 #include <config.h>
18 #include <glib.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <ctype.h>
22 #ifdef HAVE_ALLOCA_H
23 #include <alloca.h>
24 #endif
25 #ifdef HAVE_SYS_TIME_H
26 #include <sys/time.h>
27 #endif
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #if defined (HAVE_WCHAR_H)
32 #include <wchar.h>
33 #endif
34 #include "mono/metadata/icall-internals.h"
35 #include "mono/utils/mono-membar.h"
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/threads.h>
38 #include <mono/metadata/threads-types.h>
39 #include <mono/metadata/threadpool.h>
40 #include <mono/metadata/threadpool-io.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/image-internals.h>
44 #include <mono/metadata/assembly.h>
45 #include <mono/metadata/assembly-internals.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/exception-internals.h>
49 #include <mono/metadata/w32file.h>
50 #include <mono/metadata/console-io.h>
51 #include <mono/metadata/mono-route.h>
52 #include <mono/metadata/w32socket.h>
53 #include <mono/metadata/mono-endian.h>
54 #include <mono/metadata/tokentype.h>
55 #include <mono/metadata/metadata-internals.h>
56 #include <mono/metadata/class-internals.h>
57 #include <mono/metadata/class-init.h>
58 #include <mono/metadata/reflection-internals.h>
59 #include <mono/metadata/marshal.h>
60 #include <mono/metadata/gc-internals.h>
61 #include <mono/metadata/mono-gc.h>
62 #include <mono/metadata/rand.h>
63 #include <mono/metadata/appdomain-icalls.h>
64 #include <mono/metadata/string-icalls.h>
65 #include <mono/metadata/debug-helpers.h>
66 #include <mono/metadata/w32process.h>
67 #include <mono/metadata/environment.h>
68 #include <mono/metadata/profiler-private.h>
69 #include <mono/metadata/locales.h>
70 #include <mono/metadata/filewatcher.h>
71 #include <mono/metadata/security.h>
72 #include <mono/metadata/mono-config.h>
73 #include <mono/metadata/cil-coff.h>
74 #include <mono/metadata/number-formatter.h>
75 #include <mono/metadata/security-manager.h>
76 #include <mono/metadata/security-core-clr.h>
77 #include <mono/metadata/mono-perfcounters.h>
78 #include <mono/metadata/mono-debug.h>
79 #include <mono/metadata/mono-ptr-array.h>
80 #include <mono/metadata/verify-internals.h>
81 #include <mono/metadata/runtime.h>
82 #include <mono/metadata/file-mmap.h>
83 #include <mono/metadata/seq-points-data.h>
84 #include <mono/metadata/icall-table.h>
85 #include <mono/metadata/handle.h>
86 #include <mono/metadata/w32mutex.h>
87 #include <mono/metadata/w32semaphore.h>
88 #include <mono/metadata/w32event.h>
89 #include <mono/metadata/abi-details.h>
90 #include <mono/utils/monobitset.h>
91 #include <mono/utils/mono-time.h>
92 #include <mono/utils/mono-proclib.h>
93 #include <mono/utils/mono-string.h>
94 #include <mono/utils/mono-error-internals.h>
95 #include <mono/utils/mono-mmap.h>
96 #include <mono/utils/mono-io-portability.h>
97 #include <mono/utils/mono-digest.h>
98 #include <mono/utils/bsearch.h>
99 #include <mono/utils/mono-os-mutex.h>
100 #include <mono/utils/mono-threads.h>
101 #include <mono/metadata/w32error.h>
102 #include <mono/utils/w32api.h>
103 #include <mono/utils/mono-merp.h>
104 #include <mono/utils/mono-state.h>
105 #include <mono/utils/mono-logger-internals.h>
106 #include <mono/metadata/environment-internal.h>
107 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
108 #include <sys/utsname.h>
109 #endif
110 #include "icall-decl.h"
112 //#define MONO_DEBUG_ICALLARRAY
114 #ifdef MONO_DEBUG_ICALLARRAY
116 static char debug_icallarray; // 0:uninitialized 1:true 2:false
118 static gboolean
119 icallarray_print_enabled (void)
121 if (!debug_icallarray)
122 debug_icallarray = MONO_TRACE_IS_TRACED (G_LOG_LEVEL_DEBUG, MONO_TRACE_ICALLARRAY) ? 1 : 2;
123 return debug_icallarray == 1;
126 static void
127 icallarray_print (const char *format, ...)
129 if (!icallarray_print_enabled ())
130 return;
131 va_list args;
132 va_start (args, format);
133 g_printv (format, args);
134 va_end (args);
137 #else
138 #define icallarray_print_enabled() (FALSE)
139 #define icallarray_print(...) /* nothing */
140 #endif
142 /* Lazy class loading functions */
143 static GENERATE_GET_CLASS_WITH_CACHE (module, "System.Reflection", "Module")
145 static void
146 array_set_value_impl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, MonoError *error);
148 static MonoArrayHandle
149 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
151 static inline MonoBoolean
152 is_generic_parameter (MonoType *type)
154 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
157 #ifndef HOST_WIN32
158 static inline void
159 mono_icall_make_platform_path (gchar *path)
161 return;
164 static inline const gchar *
165 mono_icall_get_file_path_prefix (const gchar *path)
167 return "file://";
169 #endif /* HOST_WIN32 */
171 MonoObjectHandle
172 ves_icall_System_Array_GetValueImpl (MonoArrayHandle array, guint32 pos, MonoError *error)
174 MonoClass * const array_class = mono_handle_class (array);
175 MonoClass * const element_class = m_class_get_element_class (array_class);
177 if (m_class_is_valuetype (element_class)) {
178 gsize element_size = mono_array_element_size (array_class);
179 gpointer element_address = mono_array_addr_with_size_fast (MONO_HANDLE_RAW (array), element_size, (gsize)pos);
180 return mono_value_box_handle (MONO_HANDLE_DOMAIN (array), element_class, element_address, error);
182 MonoObjectHandle result = mono_new_null ();
183 mono_handle_array_getref (result, array, pos);
184 return result;
187 MonoObjectHandle
188 ves_icall_System_Array_GetValue (MonoArrayHandle arr, MonoArrayHandle indices, MonoError *error)
190 MONO_CHECK_ARG_NULL_HANDLE (indices, NULL_HANDLE);
192 MonoClass * const indices_class = mono_handle_class (indices);
193 MonoClass * const array_class = mono_handle_class (arr);
195 g_assert (m_class_get_rank (indices_class) == 1);
197 if (MONO_HANDLE_GETVAL (indices, bounds) || MONO_HANDLE_GETVAL (indices, max_length) != m_class_get_rank (array_class)) {
198 mono_error_set_argument (error, NULL, NULL);
199 return NULL_HANDLE;
202 gint32 index = 0;
204 if (!MONO_HANDLE_GETVAL (arr, bounds)) {
205 MONO_HANDLE_ARRAY_GETVAL (index, indices, gint32, 0);
206 if (index < 0 || index >= MONO_HANDLE_GETVAL (arr, max_length)) {
207 mono_error_set_index_out_of_range (error);
208 return NULL_HANDLE;
211 return ves_icall_System_Array_GetValueImpl (arr, index, error);
214 for (gint32 i = 0; i < m_class_get_rank (array_class); i++) {
215 MONO_HANDLE_ARRAY_GETVAL (index, indices, gint32, i);
216 if ((index < MONO_HANDLE_GETVAL (arr, bounds [i].lower_bound)) ||
217 (index >= (mono_array_lower_bound_t)MONO_HANDLE_GETVAL (arr, bounds [i].length) + MONO_HANDLE_GETVAL (arr, bounds [i].lower_bound))) {
218 mono_error_set_index_out_of_range (error);
219 return NULL_HANDLE;
223 MONO_HANDLE_ARRAY_GETVAL (index, indices, gint32, 0);
224 gint32 pos = index - MONO_HANDLE_GETVAL (arr, bounds [0].lower_bound);
225 for (gint32 i = 1; i < m_class_get_rank (array_class); i++) {
226 MONO_HANDLE_ARRAY_GETVAL (index, indices, gint32, i);
227 pos = pos * MONO_HANDLE_GETVAL (arr, bounds [i].length) + index -
228 MONO_HANDLE_GETVAL (arr, bounds [i].lower_bound);
231 return ves_icall_System_Array_GetValueImpl (arr, pos, error);
234 void
235 ves_icall_System_Array_SetValueImpl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, MonoError *error)
237 array_set_value_impl (arr, value, pos, error);
240 static void
241 array_set_value_impl (MonoArrayHandle arr, MonoObjectHandle value, guint32 pos, MonoError *error)
243 MonoClass *ac, *vc, *ec;
244 gint32 esize, vsize;
245 gpointer *ea, *va;
247 guint64 u64 = 0;
248 gint64 i64 = 0;
249 gdouble r64 = 0;
251 uint32_t arr_gchandle = 0;
252 uint32_t value_gchandle = 0;
254 error_init (error);
256 if (!MONO_HANDLE_IS_NULL (value))
257 vc = mono_handle_class (value);
258 else
259 vc = NULL;
261 ac = mono_handle_class (arr);
262 ec = m_class_get_element_class (ac);
264 esize = mono_array_element_size (ac);
265 ea = (gpointer*)mono_array_handle_pin_with_size (arr, esize, pos, &arr_gchandle);
267 if (mono_class_is_nullable (ec)) {
268 mono_nullable_init_from_handle ((guint8*)ea, value, ec);
269 goto leave;
272 if (MONO_HANDLE_IS_NULL (value)) {
273 mono_gc_bzero_atomic (ea, esize);
274 goto leave;
277 #define NO_WIDENING_CONVERSION G_STMT_START{ \
278 mono_error_set_argument (error, "value", "not a widening conversion"); \
279 goto leave; \
280 }G_STMT_END
282 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{ \
283 if (esize < vsize + (extra)) { \
284 mono_error_set_argument (error, "value", "not a widening conversion"); \
285 goto leave; \
287 }G_STMT_END
289 #define INVALID_CAST G_STMT_START{ \
290 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
291 mono_error_set_invalid_cast (error); \
292 goto leave; \
293 }G_STMT_END
295 MonoTypeEnum et;
296 et = m_class_get_byval_arg (ec)->type;
297 MonoTypeEnum vt;
298 vt = m_class_get_byval_arg (vc)->type;
299 /* Check element (destination) type. */
300 switch (et) {
301 case MONO_TYPE_STRING:
302 switch (vt) {
303 case MONO_TYPE_STRING:
304 break;
305 default:
306 INVALID_CAST;
308 break;
309 case MONO_TYPE_BOOLEAN:
310 switch (vt) {
311 case MONO_TYPE_BOOLEAN:
312 break;
313 case MONO_TYPE_CHAR:
314 case MONO_TYPE_U1:
315 case MONO_TYPE_U2:
316 case MONO_TYPE_U4:
317 case MONO_TYPE_U8:
318 case MONO_TYPE_I1:
319 case MONO_TYPE_I2:
320 case MONO_TYPE_I4:
321 case MONO_TYPE_I8:
322 case MONO_TYPE_R4:
323 case MONO_TYPE_R8:
324 NO_WIDENING_CONVERSION;
325 default:
326 INVALID_CAST;
328 break;
329 default:
330 break;
333 MonoObjectHandle inst;
334 inst = mono_object_handle_isinst (value, ec, error);
335 goto_if_nok (error, leave);
336 gboolean castOk;
337 castOk = !MONO_HANDLE_IS_NULL (inst);
339 if (!m_class_is_valuetype (ec)) {
340 if (!castOk)
341 INVALID_CAST;
342 MONO_HANDLE_ARRAY_SETREF (arr, pos, value);
343 goto leave;
346 if (castOk) {
347 va = (gpointer*)mono_object_handle_pin_unbox (value, &value_gchandle);
348 if (m_class_has_references (ec))
349 mono_value_copy_internal (ea, va, ec);
350 else
351 mono_gc_memmove_atomic (ea, va, esize);
352 mono_gchandle_free_internal (value_gchandle);
353 value_gchandle = 0;
354 goto leave;
357 if (!m_class_is_valuetype (vc))
358 INVALID_CAST;
360 va = (gpointer*)mono_object_handle_pin_unbox (value, &value_gchandle);
362 vsize = mono_class_value_size (vc, NULL);
364 if (et == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_class_get_byval_arg (ec)->data.klass))
365 et = mono_class_enum_basetype_internal (m_class_get_byval_arg (ec)->data.klass)->type;
367 if (vt == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_class_get_byval_arg (vc)->data.klass))
368 vt = mono_class_enum_basetype_internal (m_class_get_byval_arg (vc)->data.klass)->type;
370 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
371 switch (vt) { \
372 case MONO_TYPE_U1: \
373 case MONO_TYPE_U2: \
374 case MONO_TYPE_U4: \
375 case MONO_TYPE_U8: \
376 case MONO_TYPE_CHAR: \
377 CHECK_WIDENING_CONVERSION(0); \
378 *(etype *) ea = (etype) u64; \
379 goto leave; \
380 /* You can't assign a signed value to an unsigned array. */ \
381 case MONO_TYPE_I1: \
382 case MONO_TYPE_I2: \
383 case MONO_TYPE_I4: \
384 case MONO_TYPE_I8: \
385 /* You can't assign a floating point number to an integer array. */ \
386 case MONO_TYPE_R4: \
387 case MONO_TYPE_R8: \
388 NO_WIDENING_CONVERSION; \
390 }G_STMT_END
392 #define ASSIGN_SIGNED(etype) G_STMT_START{\
393 switch (vt) { \
394 case MONO_TYPE_I1: \
395 case MONO_TYPE_I2: \
396 case MONO_TYPE_I4: \
397 case MONO_TYPE_I8: \
398 CHECK_WIDENING_CONVERSION(0); \
399 *(etype *) ea = (etype) i64; \
400 goto leave; \
401 /* You can assign an unsigned value to a signed array if the array's */ \
402 /* element size is larger than the value size. */ \
403 case MONO_TYPE_U1: \
404 case MONO_TYPE_U2: \
405 case MONO_TYPE_U4: \
406 case MONO_TYPE_U8: \
407 case MONO_TYPE_CHAR: \
408 CHECK_WIDENING_CONVERSION(1); \
409 *(etype *) ea = (etype) u64; \
410 goto leave; \
411 /* You can't assign a floating point number to an integer array. */ \
412 case MONO_TYPE_R4: \
413 case MONO_TYPE_R8: \
414 NO_WIDENING_CONVERSION; \
416 }G_STMT_END
418 #define ASSIGN_REAL(etype) G_STMT_START{\
419 switch (vt) { \
420 case MONO_TYPE_R4: \
421 case MONO_TYPE_R8: \
422 CHECK_WIDENING_CONVERSION(0); \
423 *(etype *) ea = (etype) r64; \
424 goto leave; \
425 /* All integer values fit into a floating point array, so we don't */ \
426 /* need to CHECK_WIDENING_CONVERSION here. */ \
427 case MONO_TYPE_I1: \
428 case MONO_TYPE_I2: \
429 case MONO_TYPE_I4: \
430 case MONO_TYPE_I8: \
431 *(etype *) ea = (etype) i64; \
432 goto leave; \
433 case MONO_TYPE_U1: \
434 case MONO_TYPE_U2: \
435 case MONO_TYPE_U4: \
436 case MONO_TYPE_U8: \
437 case MONO_TYPE_CHAR: \
438 *(etype *) ea = (etype) u64; \
439 goto leave; \
441 }G_STMT_END
443 switch (vt) {
444 case MONO_TYPE_U1:
445 u64 = *(guint8 *) va;
446 break;
447 case MONO_TYPE_U2:
448 u64 = *(guint16 *) va;
449 break;
450 case MONO_TYPE_U4:
451 u64 = *(guint32 *) va;
452 break;
453 case MONO_TYPE_U8:
454 u64 = *(guint64 *) va;
455 break;
456 case MONO_TYPE_I1:
457 i64 = *(gint8 *) va;
458 break;
459 case MONO_TYPE_I2:
460 i64 = *(gint16 *) va;
461 break;
462 case MONO_TYPE_I4:
463 i64 = *(gint32 *) va;
464 break;
465 case MONO_TYPE_I8:
466 i64 = *(gint64 *) va;
467 break;
468 case MONO_TYPE_R4:
469 r64 = *(gfloat *) va;
470 break;
471 case MONO_TYPE_R8:
472 r64 = *(gdouble *) va;
473 break;
474 case MONO_TYPE_CHAR:
475 u64 = *(guint16 *) va;
476 break;
477 case MONO_TYPE_BOOLEAN:
478 /* Boolean is only compatible with itself. */
479 switch (et) {
480 case MONO_TYPE_CHAR:
481 case MONO_TYPE_U1:
482 case MONO_TYPE_U2:
483 case MONO_TYPE_U4:
484 case MONO_TYPE_U8:
485 case MONO_TYPE_I1:
486 case MONO_TYPE_I2:
487 case MONO_TYPE_I4:
488 case MONO_TYPE_I8:
489 case MONO_TYPE_R4:
490 case MONO_TYPE_R8:
491 NO_WIDENING_CONVERSION;
492 default:
493 INVALID_CAST;
495 break;
498 /* If we can't do a direct copy, let's try a widening conversion. */
499 switch (et) {
500 case MONO_TYPE_CHAR:
501 ASSIGN_UNSIGNED (guint16);
502 case MONO_TYPE_U1:
503 ASSIGN_UNSIGNED (guint8);
504 case MONO_TYPE_U2:
505 ASSIGN_UNSIGNED (guint16);
506 case MONO_TYPE_U4:
507 ASSIGN_UNSIGNED (guint32);
508 case MONO_TYPE_U8:
509 ASSIGN_UNSIGNED (guint64);
510 case MONO_TYPE_I1:
511 ASSIGN_SIGNED (gint8);
512 case MONO_TYPE_I2:
513 ASSIGN_SIGNED (gint16);
514 case MONO_TYPE_I4:
515 ASSIGN_SIGNED (gint32);
516 case MONO_TYPE_I8:
517 ASSIGN_SIGNED (gint64);
518 case MONO_TYPE_R4:
519 ASSIGN_REAL (gfloat);
520 case MONO_TYPE_R8:
521 ASSIGN_REAL (gdouble);
524 INVALID_CAST;
525 /* Not reached, INVALID_CAST does fall thru. */
526 g_assert_not_reached ();
528 #undef INVALID_CAST
529 #undef NO_WIDENING_CONVERSION
530 #undef CHECK_WIDENING_CONVERSION
531 #undef ASSIGN_UNSIGNED
532 #undef ASSIGN_SIGNED
533 #undef ASSIGN_REAL
534 leave:
535 if (arr_gchandle)
536 mono_gchandle_free_internal (arr_gchandle);
537 if (value_gchandle)
538 mono_gchandle_free_internal (value_gchandle);
539 return;
542 void
543 ves_icall_System_Array_SetValue (MonoArrayHandle arr, MonoObjectHandle value,
544 MonoArrayHandle idxs, MonoError *error)
546 icallarray_print ("%s\n", __func__);
548 MonoArrayBounds dim;
549 MonoClass *ac, *ic;
550 gint32 idx;
551 gint32 i, pos;
553 error_init (error);
555 if (MONO_HANDLE_IS_NULL (idxs)) {
556 mono_error_set_argument_null (error, "idxs", "");
557 return;
560 ic = mono_handle_class (idxs);
561 ac = mono_handle_class (arr);
563 g_assert (m_class_get_rank (ic) == 1);
564 if (mono_handle_array_has_bounds (idxs) || MONO_HANDLE_GETVAL (idxs, max_length) != m_class_get_rank (ac)) {
565 mono_error_set_argument (error, "idxs", "");
566 return;
569 if (!mono_handle_array_has_bounds (arr)) {
570 MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, 0);
571 if (idx < 0 || idx >= MONO_HANDLE_GETVAL (arr, max_length)) {
572 mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
573 return;
576 array_set_value_impl (arr, value, idx, error);
577 return;
580 gint32 ac_rank = m_class_get_rank (ac);
581 for (i = 0; i < ac_rank; i++) {
582 mono_handle_array_get_bounds_dim (arr, i, &dim);
583 MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, i);
584 if ((idx < dim.lower_bound) ||
585 (idx >= (mono_array_lower_bound_t)dim.length + dim.lower_bound)) {
586 mono_error_set_exception_instance (error, mono_get_exception_index_out_of_range ());
587 return;
591 MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, 0);
592 mono_handle_array_get_bounds_dim (arr, 0, &dim);
593 pos = idx - dim.lower_bound;
594 for (i = 1; i < ac_rank; i++) {
595 mono_handle_array_get_bounds_dim (arr, i, &dim);
596 MONO_HANDLE_ARRAY_GETVAL (idx, idxs, gint32, i);
597 pos = pos * dim.length + idx - dim.lower_bound;
600 array_set_value_impl (arr, value, pos, error);
603 MonoArrayHandle
604 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionTypeHandle type, MonoArrayHandle lengths, MonoArrayHandle bounds, MonoError *error)
606 // FIXME? fixed could be used for lengths, bounds.
608 icallarray_print ("%s type:%p length:%p bounds:%p\n", __func__, type, lengths, bounds);
610 MONO_CHECK_ARG_NULL_HANDLE (type, NULL_HANDLE_ARRAY);
611 MONO_CHECK_ARG_NULL_HANDLE (lengths, NULL_HANDLE_ARRAY);
613 MONO_CHECK_ARG (lengths, mono_array_handle_length (lengths) > 0, NULL_HANDLE_ARRAY);
614 if (!MONO_HANDLE_IS_NULL (bounds))
615 MONO_CHECK_ARG (bounds, mono_array_handle_length (lengths) == mono_array_handle_length (bounds), NULL_HANDLE_ARRAY);
617 for (uintptr_t i = 0; i < mono_array_handle_length (lengths); ++i) {
618 gint32 length = 0;
619 MONO_HANDLE_ARRAY_GETVAL (length, lengths, gint32, i);
620 if (length < 0) {
621 mono_error_set_argument_out_of_range (error, NULL);
622 return NULL_HANDLE_ARRAY;
626 MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type));
627 if (!mono_class_init_checked (klass, error))
628 return NULL_HANDLE_ARRAY;
630 if (m_class_get_byval_arg (m_class_get_element_class (klass))->type == MONO_TYPE_VOID) {
631 mono_error_set_not_supported (error, "Arrays of System.Void are not supported.");
632 return NULL_HANDLE_ARRAY;
635 /* vectors are not the same as one dimensional arrays with non-zero bounds */
636 gboolean bounded = FALSE;
637 if (!MONO_HANDLE_IS_NULL (bounds) && mono_array_handle_length (bounds) == 1) {
638 gint32 bound0 = 0;
639 MONO_HANDLE_ARRAY_GETVAL (bound0, bounds, gint32, 0);
640 bounded = bound0 != 0;
643 MonoClass * const aklass = mono_class_create_bounded_array (klass, mono_array_handle_length (lengths), bounded);
644 uintptr_t const aklass_rank = m_class_get_rank (aklass);
645 uintptr_t * const sizes = g_newa (uintptr_t, aklass_rank);
646 intptr_t * const lower_bounds = g_newa (intptr_t, aklass_rank);
648 // Copy lengths and lower_bounds from gint32 to [u]intptr_t.
650 for (uintptr_t i = 0; i < aklass_rank; ++i) {
651 MONO_HANDLE_ARRAY_GETVAL (sizes [i], lengths, gint32, i);
652 if (!MONO_HANDLE_IS_NULL (bounds))
653 MONO_HANDLE_ARRAY_GETVAL (lower_bounds [i], bounds, gint32, i);
654 else
655 lower_bounds [i] = 0;
658 return mono_array_new_full_handle (MONO_HANDLE_DOMAIN (type), aklass, sizes, lower_bounds, error);
661 gint32
662 ves_icall_System_Array_GetRank (MonoObjectHandle arr, MonoError *error)
664 gint32 const result = m_class_get_rank (mono_handle_class (arr));
666 icallarray_print ("%s arr:%p res:%d\n", __func__, MONO_HANDLE_RAW (arr), result);
668 return result;
671 static mono_array_size_t
672 mono_array_get_length (MonoArrayHandle arr, gint32 dimension, MonoError *error)
674 if (dimension < 0 || dimension >= m_class_get_rank (mono_handle_class (arr))) {
675 mono_error_set_index_out_of_range (error);
676 return 0;
679 return MONO_HANDLE_GETVAL (arr, bounds) ? MONO_HANDLE_GETVAL (arr, bounds [dimension].length)
680 : MONO_HANDLE_GETVAL (arr, max_length);
683 gint32
684 ves_icall_System_Array_GetLength (MonoArrayHandle arr, gint32 dimension, MonoError *error)
686 icallarray_print ("%s arr:%p dimension:%d\n", __func__, MONO_HANDLE_RAW (arr), (int)dimension);
688 mono_array_size_t const length = mono_array_get_length (arr, dimension, error);
689 if (length > G_MAXINT32) {
690 mono_error_set_overflow (error);
691 return 0;
693 return (gint32)length;
696 gint64
697 ves_icall_System_Array_GetLongLength (MonoArrayHandle arr, gint32 dimension, MonoError *error)
699 icallarray_print ("%s arr:%p dimension:%d\n", __func__, MONO_HANDLE_RAW (arr), (int)dimension);
701 return (gint64)mono_array_get_length (arr, dimension, error);
704 gint32
705 ves_icall_System_Array_GetLowerBound (MonoArrayHandle arr, gint32 dimension, MonoError *error)
707 icallarray_print ("%s arr:%p dimension:%d\n", __func__, MONO_HANDLE_RAW (arr), (int)dimension);
709 if (dimension < 0 || dimension >= m_class_get_rank (mono_handle_class (arr))) {
710 mono_error_set_index_out_of_range (error);
711 return 0;
714 return MONO_HANDLE_GETVAL (arr, bounds) ? MONO_HANDLE_GETVAL (arr, bounds [dimension].lower_bound)
715 : 0;
718 void
719 ves_icall_System_Array_ClearInternal (MonoArrayHandle arr, int idx, int length, MonoError *error)
721 icallarray_print ("%s arr:%p idx:%d len:%d\n", __func__, MONO_HANDLE_RAW (arr), (int)idx, (int)length);
723 int sz = mono_array_element_size (mono_handle_class (arr));
724 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (MONO_HANDLE_RAW (arr), sz, idx), length * sz);
728 MonoBoolean
729 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
731 int element_size;
732 void * dest_addr;
733 void * source_addr;
734 MonoVTable *src_vtable;
735 MonoVTable *dest_vtable;
736 MonoClass *src_class;
737 MonoClass *dest_class;
739 src_vtable = source->obj.vtable;
740 dest_vtable = dest->obj.vtable;
742 if (src_vtable->rank != dest_vtable->rank)
743 return FALSE;
745 if (source->bounds || dest->bounds)
746 return FALSE;
748 /* there's no integer overflow since mono_array_length_internal returns an unsigned integer */
749 if ((dest_idx + length > mono_array_length_internal (dest)) ||
750 (source_idx + length > mono_array_length_internal (source)))
751 return FALSE;
753 src_class = m_class_get_element_class (src_vtable->klass);
754 dest_class = m_class_get_element_class (dest_vtable->klass);
757 * Handle common cases.
760 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
761 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
763 if (src_class == mono_defaults.object_class && m_class_is_valuetype (dest_class))
764 return FALSE;
766 /* Check if we're copying a char[] <==> (u)short[] */
767 if (src_class != dest_class) {
768 if (m_class_is_valuetype (dest_class) || m_class_is_enumtype (dest_class) ||
769 m_class_is_valuetype (src_class) || m_class_is_valuetype (src_class))
770 return FALSE;
772 /* 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. */
773 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
774 return FALSE;
777 if (m_class_is_valuetype (dest_class)) {
778 element_size = mono_array_element_size (source->obj.vtable->klass);
779 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
780 if (m_class_has_references (dest_class)) {
781 mono_value_copy_array_internal (dest, dest_idx, source_addr, length);
782 } else {
783 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
784 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
786 } else {
787 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
790 return TRUE;
793 void
794 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
796 // Generic ref/out parameters are not supported by HANDLES(), so NOHANDLES().
798 icallarray_print ("%s arr:%p pos:%u value:%p\n", __func__, arr, pos, value);
800 MONO_REQ_GC_UNSAFE_MODE; // because of gpointer value
802 MonoClass *ac;
803 gint32 esize;
804 gpointer *ea;
806 ac = mono_object_class (arr);
808 esize = mono_array_element_size (ac);
809 ea = (gpointer*)((char*)arr->vector + (pos * esize));
811 mono_gc_memmove_atomic (value, ea, esize);
814 void
815 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
817 // Generic ref/out parameters are not supported by HANDLES(), so NOHANDLES().
819 icallarray_print ("%s arr:%p pos:%u value:%p\n", __func__, arr, pos, value);
821 MONO_REQ_GC_UNSAFE_MODE; // because of gpointer value
823 MonoClass *ac, *ec;
824 gint32 esize;
825 gpointer *ea;
827 ac = mono_object_class (arr);
828 ec = m_class_get_element_class (ac);
830 esize = mono_array_element_size (ac);
831 ea = (gpointer*)((char*)arr->vector + (pos * esize));
833 if (MONO_TYPE_IS_REFERENCE (m_class_get_byval_arg (ec))) {
834 g_assert (esize == sizeof (gpointer));
835 mono_gc_wbarrier_generic_store_internal (ea, *(MonoObject **)value);
836 } else {
837 g_assert (m_class_is_inited (ec));
838 g_assert (esize == mono_class_value_size (ec, NULL));
839 if (m_class_has_references (ec))
840 mono_gc_wbarrier_value_copy_internal (ea, value, 1, ec);
841 else
842 mono_gc_memmove_atomic (ea, value, esize);
846 void
847 ves_icall_System_Runtime_RuntimeImports_Memmove (guint8 *destination, guint8 *source, guint byte_count)
849 mono_gc_memmove_atomic (destination, source, byte_count);
852 void
853 ves_icall_System_Runtime_RuntimeImports_Memmove_wbarrier (guint8 *destination, guint8 *source, guint len, MonoType *type)
855 if (MONO_TYPE_IS_REFERENCE (type))
856 mono_gc_wbarrier_arrayref_copy_internal (destination, source, len);
857 else
858 mono_gc_wbarrier_value_copy_internal (destination, source, len, mono_class_from_mono_type_internal (type));
861 void
862 ves_icall_System_Runtime_RuntimeImports_ZeroMemory (guint8 *p, guint byte_length)
864 memset (p, 0, byte_length);
867 void
868 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArrayHandle array, MonoClassField *field_handle, MonoError *error)
870 MonoClass *klass = mono_handle_class (array);
871 guint32 size = mono_array_element_size (klass);
872 MonoType *type = mono_type_get_underlying_type (m_class_get_byval_arg (m_class_get_element_class (klass)));
873 int align;
874 const char *field_data;
876 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
877 mono_error_set_argument (error, "array", "Cannot initialize array of non-primitive type");
878 return;
881 MonoType *field_type = mono_field_get_type_checked (field_handle, error);
882 if (!field_type)
883 return;
885 if (!(field_type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
886 mono_error_set_argument_format (error, "field_handle", "Field '%s' doesn't have an RVA", mono_field_get_name (field_handle));
887 return;
890 size *= MONO_HANDLE_GETVAL(array, max_length);
891 field_data = mono_field_get_data (field_handle);
893 if (size > mono_type_size (field_handle->type, &align)) {
894 mono_error_set_argument (error, "field_handle", "Field not large enough to fill array");
895 return;
898 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
899 #define SWAP(n) { \
900 guint ## n *data = (guint ## n *) mono_array_addr_internal (MONO_HANDLE_RAW(array), char, 0); \
901 guint ## n *src = (guint ## n *) field_data; \
902 int i, \
903 nEnt = (size / sizeof(guint ## n)); \
905 for (i = 0; i < nEnt; i++) { \
906 data[i] = read ## n (&src[i]); \
910 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
912 switch (type->type) {
913 case MONO_TYPE_CHAR:
914 case MONO_TYPE_I2:
915 case MONO_TYPE_U2:
916 SWAP (16);
917 break;
918 case MONO_TYPE_I4:
919 case MONO_TYPE_U4:
920 case MONO_TYPE_R4:
921 SWAP (32);
922 break;
923 case MONO_TYPE_I8:
924 case MONO_TYPE_U8:
925 case MONO_TYPE_R8:
926 SWAP (64);
927 break;
928 default:
929 memcpy (mono_array_addr_internal (MONO_HANDLE_RAW(array), char, 0), field_data, size);
930 break;
932 #else
933 memcpy (mono_array_addr_internal (MONO_HANDLE_RAW(array), char, 0), field_data, size);
934 #endif
937 gint
938 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
940 return offsetof (MonoString, chars);
943 MonoObjectHandle
944 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObjectHandle obj, MonoError *error)
946 if (MONO_HANDLE_IS_NULL (obj) || !m_class_is_valuetype (mono_handle_class (obj)))
947 return obj;
949 return mono_object_clone_handle (obj, error);
952 void
953 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle, MonoError *error)
955 MonoClass *klass;
956 MonoVTable *vtable;
958 MONO_CHECK_ARG_NULL (handle,);
960 klass = mono_class_from_mono_type_internal (handle);
961 MONO_CHECK_ARG (handle, klass,);
963 if (mono_class_is_gtd (klass))
964 return;
966 vtable = mono_class_vtable_checked (mono_domain_get (), klass, error);
967 return_if_nok (error);
969 /* This will call the type constructor */
970 mono_runtime_class_init_full (vtable, error);
973 void
974 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image, MonoError *error)
976 mono_image_check_for_module_cctor (image);
977 if (!image->has_module_cctor)
978 return;
980 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, error);
981 return_if_nok (error);
983 MonoVTable * vtable = mono_class_vtable_checked (mono_domain_get (), module_klass, error);
984 return_if_nok (error);
986 mono_runtime_class_init_full (vtable, error);
989 MonoBoolean
990 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
992 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
993 // It does not work on win32
994 #elif defined(TARGET_ANDROID) || defined(__linux__)
995 // No need for now
996 #else
997 guint8 *stack_addr;
998 guint8 *current;
999 size_t stack_size;
1000 int min_size;
1001 MonoInternalThread *thread;
1003 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
1004 /* if we have no info we are optimistic and assume there is enough room */
1005 if (!stack_addr)
1006 return TRUE;
1008 thread = mono_thread_internal_current ();
1009 // .net seems to check that at least 50% of stack is available
1010 min_size = thread->stack_size / 2;
1012 // TODO: It's not always set
1013 if (!min_size)
1014 return TRUE;
1016 current = (guint8 *)&stack_addr;
1017 if (current > stack_addr) {
1018 if ((current - stack_addr) < min_size)
1019 return FALSE;
1020 } else {
1021 if (current - (stack_addr - stack_size) < min_size)
1022 return FALSE;
1024 #endif
1025 return TRUE;
1028 MonoObjectHandle
1029 ves_icall_System_Object_MemberwiseClone (MonoObjectHandle this_obj, MonoError *error)
1031 return mono_object_clone_handle (this_obj, error);
1034 gint32
1035 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1037 ERROR_DECL (error);
1038 MonoClass *klass;
1039 MonoObject **values = NULL;
1040 MonoObject *o;
1041 int count = 0;
1042 gint32 result = (int)(gsize)mono_defaults.int32_class;
1043 MonoClassField* field;
1044 gpointer iter;
1046 klass = mono_object_class (this_obj);
1048 if (mono_class_num_fields (klass) == 0)
1049 return result;
1052 * Compute the starting value of the hashcode for fields of primitive
1053 * types, and return the remaining fields in an array to the managed side.
1054 * This way, we can avoid costly reflection operations in managed code.
1056 iter = NULL;
1057 while ((field = mono_class_get_fields_internal (klass, &iter))) {
1058 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1059 continue;
1060 if (mono_field_is_deleted (field))
1061 continue;
1062 /* FIXME: Add more types */
1063 switch (field->type->type) {
1064 case MONO_TYPE_I4:
1065 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1066 break;
1067 case MONO_TYPE_PTR:
1068 result ^= mono_aligned_addr_hash (*(gpointer*)((guint8*)this_obj + field->offset));
1069 break;
1070 case MONO_TYPE_STRING: {
1071 MonoString *s;
1072 s = *(MonoString**)((guint8*)this_obj + field->offset);
1073 if (s != NULL)
1074 result ^= mono_string_hash_internal (s);
1075 break;
1077 default:
1078 if (!values)
1079 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1080 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, error);
1081 if (!is_ok (error)) {
1082 mono_error_set_pending_exception (error);
1083 return 0;
1085 values [count++] = o;
1089 if (values) {
1090 int i;
1091 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, error);
1092 if (mono_error_set_pending_exception (error))
1093 return 0;
1094 mono_gc_wbarrier_generic_store_internal (fields, (MonoObject*) fields_arr);
1095 for (i = 0; i < count; ++i)
1096 mono_array_setref_internal (*fields, i, values [i]);
1097 } else {
1098 *fields = NULL;
1100 return result;
1103 MonoBoolean
1104 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1106 ERROR_DECL (error);
1107 MonoClass *klass;
1108 MonoObject **values = NULL;
1109 MonoObject *o;
1110 MonoClassField* field;
1111 gpointer iter;
1112 int count = 0;
1114 *fields = NULL;
1116 MONO_CHECK_ARG_NULL (that, FALSE);
1118 if (this_obj->vtable != that->vtable)
1119 return FALSE;
1121 klass = mono_object_class (this_obj);
1123 if (m_class_is_enumtype (klass) && mono_class_enum_basetype_internal (klass) && mono_class_enum_basetype_internal (klass)->type == MONO_TYPE_I4)
1124 return *(gint32*)mono_object_get_data (this_obj) == *(gint32*)mono_object_get_data (that);
1127 * Do the comparison for fields of primitive type and return a result if
1128 * possible. Otherwise, return the remaining fields in an array to the
1129 * managed side. This way, we can avoid costly reflection operations in
1130 * managed code.
1132 iter = NULL;
1133 while ((field = mono_class_get_fields_internal (klass, &iter))) {
1134 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1135 continue;
1136 if (mono_field_is_deleted (field))
1137 continue;
1138 guint8 *this_field = (guint8 *) this_obj + field->offset;
1139 guint8 *that_field = (guint8 *) that + field->offset;
1141 #define UNALIGNED_COMPARE(type) \
1142 do { \
1143 type left, right; \
1144 memcpy (&left, this_field, sizeof (type)); \
1145 memcpy (&right, that_field, sizeof (type)); \
1146 if (left != right) \
1147 return FALSE; \
1148 } while (0)
1150 /* FIXME: Add more types */
1151 switch (field->type->type) {
1152 case MONO_TYPE_U1:
1153 case MONO_TYPE_I1:
1154 case MONO_TYPE_BOOLEAN:
1155 if (*this_field != *that_field)
1156 return FALSE;
1157 break;
1158 case MONO_TYPE_U2:
1159 case MONO_TYPE_I2:
1160 case MONO_TYPE_CHAR:
1161 #ifdef NO_UNALIGNED_ACCESS
1162 if (G_UNLIKELY ((intptr_t) this_field & 1 || (intptr_t) that_field & 1))
1163 UNALIGNED_COMPARE (gint16);
1164 else
1165 #endif
1166 if (*(gint16 *) this_field != *(gint16 *) that_field)
1167 return FALSE;
1168 break;
1169 case MONO_TYPE_U4:
1170 case MONO_TYPE_I4:
1171 #ifdef NO_UNALIGNED_ACCESS
1172 if (G_UNLIKELY ((intptr_t) this_field & 3 || (intptr_t) that_field & 3))
1173 UNALIGNED_COMPARE (gint32);
1174 else
1175 #endif
1176 if (*(gint32 *) this_field != *(gint32 *) that_field)
1177 return FALSE;
1178 break;
1179 case MONO_TYPE_U8:
1180 case MONO_TYPE_I8:
1181 #ifdef NO_UNALIGNED_ACCESS
1182 if (G_UNLIKELY ((intptr_t) this_field & 7 || (intptr_t) that_field & 7))
1183 UNALIGNED_COMPARE (gint64);
1184 else
1185 #endif
1186 if (*(gint64 *) this_field != *(gint64 *) that_field)
1187 return FALSE;
1188 break;
1190 case MONO_TYPE_R4:
1191 #ifdef NO_UNALIGNED_ACCESS
1192 if (G_UNLIKELY ((intptr_t) this_field & 3 || (intptr_t) that_field & 3))
1193 UNALIGNED_COMPARE (float);
1194 else
1195 #endif
1196 if (*(float *) this_field != *(float *) that_field)
1197 return FALSE;
1198 break;
1199 case MONO_TYPE_R8:
1200 #ifdef NO_UNALIGNED_ACCESS
1201 if (G_UNLIKELY ((intptr_t) this_field & 7 || (intptr_t) that_field & 7))
1202 UNALIGNED_COMPARE (double);
1203 else
1204 #endif
1205 if (*(double *) this_field != *(double *) that_field)
1206 return FALSE;
1207 break;
1208 case MONO_TYPE_PTR:
1209 #ifdef NO_UNALIGNED_ACCESS
1210 if (G_UNLIKELY ((intptr_t) this_field & 7 || (intptr_t) that_field & 7))
1211 UNALIGNED_COMPARE (gpointer);
1212 else
1213 #endif
1214 if (*(gpointer *) this_field != *(gpointer *) that_field)
1215 return FALSE;
1216 break;
1217 case MONO_TYPE_STRING: {
1218 MonoString *s1, *s2;
1219 guint32 s1len, s2len;
1220 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1221 s2 = *(MonoString**)((guint8*)that + field->offset);
1222 if (s1 == s2)
1223 break;
1224 if ((s1 == NULL) || (s2 == NULL))
1225 return FALSE;
1226 s1len = mono_string_length_internal (s1);
1227 s2len = mono_string_length_internal (s2);
1228 if (s1len != s2len)
1229 return FALSE;
1231 if (memcmp (mono_string_chars_internal (s1), mono_string_chars_internal (s2), s1len * sizeof (gunichar2)) != 0)
1232 return FALSE;
1233 break;
1235 default:
1236 if (!values)
1237 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1238 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, error);
1239 if (!is_ok (error)) {
1240 mono_error_set_pending_exception (error);
1241 return FALSE;
1243 values [count++] = o;
1244 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, error);
1245 if (!is_ok (error)) {
1246 mono_error_set_pending_exception (error);
1247 return FALSE;
1249 values [count++] = o;
1252 #undef UNALIGNED_COMPARE
1254 if (m_class_is_enumtype (klass))
1255 /* enums only have one non-static field */
1256 break;
1259 if (values) {
1260 int i;
1261 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, error);
1262 if (mono_error_set_pending_exception (error))
1263 return FALSE;
1264 mono_gc_wbarrier_generic_store_internal (fields, (MonoObject*) fields_arr);
1265 for (i = 0; i < count; ++i)
1266 mono_array_setref_fast (*fields, i, values [i]);
1267 return FALSE;
1268 } else {
1269 return TRUE;
1273 MonoReflectionTypeHandle
1274 ves_icall_System_Object_GetType (MonoObjectHandle obj, MonoError *error)
1276 MonoDomain *domain = MONO_HANDLE_DOMAIN (obj);
1277 MonoClass *klass = mono_handle_class (obj);
1278 #ifndef DISABLE_REMOTING
1279 if (mono_class_is_transparent_proxy (klass)) {
1280 MonoTransparentProxyHandle proxy_obj = MONO_HANDLE_CAST (MonoTransparentProxy, obj);
1281 MonoRemoteClass *remote_class = MONO_HANDLE_GETVAL (proxy_obj, remote_class);
1282 /* If it's a transparent proxy for an interface, return the
1283 * interface type, not the unhelpful proxy_class class (which
1284 * is just MarshalByRefObject). */
1285 MonoType *proxy_type =
1286 mono_remote_class_is_interface_proxy (remote_class) ?
1287 m_class_get_byval_arg (remote_class->interfaces[0]) :
1288 m_class_get_byval_arg (remote_class->proxy_class);
1289 return mono_type_get_object_handle (domain, proxy_type, error);
1290 } else
1291 #endif
1292 return mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
1295 static gboolean
1296 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1298 MonoMethod **dest = (MonoMethod **)data;
1300 /* skip unmanaged frames */
1301 if (!managed)
1302 return FALSE;
1304 if (!(*dest)) {
1305 if (!strcmp (m_class_get_name_space (m->klass), "System.Reflection"))
1306 return FALSE;
1307 *dest = m;
1308 return TRUE;
1310 return FALSE;
1313 static gboolean
1314 in_corlib_name_space (MonoClass *klass, const char *name_space)
1316 return m_class_get_image (klass) == mono_defaults.corlib &&
1317 !strcmp (m_class_get_name_space (klass), name_space);
1320 static gboolean
1321 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1323 MonoMethod **dest = (MonoMethod **)data;
1325 /* skip unmanaged frames */
1326 if (!managed)
1327 return FALSE;
1329 if (m->wrapper_type != MONO_WRAPPER_NONE)
1330 return FALSE;
1332 if (m == *dest) {
1333 *dest = NULL;
1334 return FALSE;
1337 if (in_corlib_name_space (m->klass, "System.Reflection"))
1338 return FALSE;
1340 if (!(*dest)) {
1341 *dest = m;
1342 return TRUE;
1344 return FALSE;
1347 static gboolean
1348 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1350 MonoMethod **dest = (MonoMethod **)data;
1352 /* skip unmanaged frames */
1353 if (!managed)
1354 return FALSE;
1356 if (m->wrapper_type != MONO_WRAPPER_NONE)
1357 return FALSE;
1359 if (m == *dest) {
1360 *dest = NULL;
1361 return FALSE;
1364 if (in_corlib_name_space (m->klass, "System.Reflection") || in_corlib_name_space (m->klass, "System"))
1365 return FALSE;
1367 if (!(*dest)) {
1368 *dest = m;
1369 return TRUE;
1371 return FALSE;
1375 * mono_runtime_get_caller_no_system_or_reflection:
1377 * Walk the stack of the current thread and find the first managed method that
1378 * is not in the mscorlib System or System.Reflection namespace. This skips
1379 * unmanaged callers and wrapper methods.
1381 * \returns a pointer to the \c MonoMethod or NULL if we walked past all the
1382 * callers.
1384 MonoMethod*
1385 mono_runtime_get_caller_no_system_or_reflection (void)
1387 MonoMethod *dest = NULL;
1388 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1389 return dest;
1392 static MonoReflectionTypeHandle
1393 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoAssembly **caller_assembly, MonoError *error)
1395 MonoMethod *m, *dest;
1397 MonoType *type = NULL;
1398 MonoAssembly *assembly = NULL;
1399 gboolean type_resolve = FALSE;
1400 MonoImage *rootimage = NULL;
1402 error_init (error);
1405 * We must compute the calling assembly as type loading must happen under a metadata context.
1406 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1407 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1409 m = mono_method_get_last_managed ();
1410 dest = m;
1411 if (m && m_class_get_image (m->klass) != mono_defaults.corlib) {
1412 /* Happens with inlining */
1413 } else {
1414 /* Ugly hack: type_from_parsed_name is called from
1415 * System.Type.internal_from_name, which is called most
1416 * directly from System.Type.GetType(string,bool,bool) but
1417 * also indirectly from places such as
1418 * System.Type.GetType(string,func,func) (via
1419 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1420 * so we need to skip over all of those to find the true caller.
1422 * It would be nice if we had stack marks.
1424 dest = mono_runtime_get_caller_no_system_or_reflection ();
1425 if (!dest)
1426 dest = m;
1430 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1431 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1432 * to crash. This only seems to happen in some strange remoting
1433 * scenarios and I was unable to figure out what's happening there.
1434 * Dec 10, 2005 - Martin.
1437 if (dest) {
1438 assembly = m_class_get_image (dest->klass)->assembly;
1439 type_resolve = TRUE;
1440 rootimage = assembly->image;
1441 } else {
1442 g_warning (G_STRLOC);
1444 *caller_assembly = assembly;
1446 if (info->assembly.name)
1447 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1449 if (assembly) {
1450 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1451 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1452 goto_if_nok (error, fail);
1455 // XXXX - aleksey -
1456 // Say we're looking for System.Generic.Dict<int, Local>
1457 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1458 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1459 // is messed up when we go to construct the Local as the type arg...
1461 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1462 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1463 if (!info->assembly.name && !type) {
1464 /* try mscorlib */
1465 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1466 goto_if_nok (error, fail);
1468 if (assembly && !type && type_resolve) {
1469 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1470 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1471 goto_if_nok (error, fail);
1474 if (!type)
1475 goto fail;
1477 return mono_type_get_object_handle (mono_domain_get (), type, error);
1478 fail:
1479 return MONO_HANDLE_NEW (MonoReflectionType, NULL);
1482 MonoReflectionTypeHandle
1483 ves_icall_System_Type_internal_from_name (MonoStringHandle name,
1484 MonoBoolean throwOnError,
1485 MonoBoolean ignoreCase,
1486 MonoError *error)
1488 MonoTypeNameParse info;
1489 gboolean free_info = FALSE;
1490 MonoAssembly *caller_assembly;
1491 MonoReflectionTypeHandle type = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1493 char *str = mono_string_handle_to_utf8 (name, error);
1494 goto_if_nok (error, leave);
1496 free_info = TRUE;
1497 if (!mono_reflection_parse_type_checked (str, &info, error))
1498 goto leave;
1500 /* mono_reflection_parse_type() mangles the string */
1502 MONO_HANDLE_ASSIGN (type, type_from_parsed_name (&info, ignoreCase, &caller_assembly, error));
1504 goto_if_nok (error, leave);
1506 if (MONO_HANDLE_IS_NULL (type)) {
1507 if (throwOnError) {
1508 char *tname = info.name_space ? g_strdup_printf ("%s.%s", info.name_space, info.name) : g_strdup (info.name);
1509 char *aname;
1510 if (info.assembly.name)
1511 aname = mono_stringify_assembly_name (&info.assembly);
1512 else if (caller_assembly)
1513 aname = mono_stringify_assembly_name (mono_assembly_get_name_internal (caller_assembly));
1514 else
1515 aname = g_strdup ("");
1516 mono_error_set_type_load_name (error, tname, aname, "");
1518 goto leave;
1521 leave:
1522 if (free_info)
1523 mono_reflection_free_type_info (&info);
1524 g_free (str);
1525 if (!is_ok (error)) {
1526 if (!throwOnError) {
1527 mono_error_cleanup (error);
1528 error_init (error);
1530 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
1531 } else
1532 return type;
1536 MonoReflectionTypeHandle
1537 ves_icall_System_Type_internal_from_handle (MonoType *handle, MonoError *error)
1539 MonoDomain *domain = mono_domain_get ();
1541 return mono_type_get_object_handle (domain, handle, error);
1544 MonoType*
1545 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass, MonoError *error)
1547 return m_class_get_byval_arg (klass);
1550 void
1551 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array, MonoError *error)
1553 g_ptr_array_free (ptr_array, TRUE);
1556 void
1557 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str, MonoError *error)
1559 g_free (c_str);
1562 char*
1563 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoStringHandle s, MonoError *error)
1565 return mono_string_handle_to_utf8 (s, error);
1568 /* System.TypeCode */
1569 typedef enum {
1570 TYPECODE_EMPTY,
1571 TYPECODE_OBJECT,
1572 TYPECODE_DBNULL,
1573 TYPECODE_BOOLEAN,
1574 TYPECODE_CHAR,
1575 TYPECODE_SBYTE,
1576 TYPECODE_BYTE,
1577 TYPECODE_INT16,
1578 TYPECODE_UINT16,
1579 TYPECODE_INT32,
1580 TYPECODE_UINT32,
1581 TYPECODE_INT64,
1582 TYPECODE_UINT64,
1583 TYPECODE_SINGLE,
1584 TYPECODE_DOUBLE,
1585 TYPECODE_DECIMAL,
1586 TYPECODE_DATETIME,
1587 TYPECODE_STRING = 18
1588 } TypeCode;
1590 guint32
1591 ves_icall_type_GetTypeCodeInternal (MonoReflectionTypeHandle ref_type, MonoError *error)
1593 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
1594 int t = type->type;
1596 if (type->byref)
1597 return TYPECODE_OBJECT;
1599 handle_enum:
1600 switch (t) {
1601 case MONO_TYPE_VOID:
1602 return TYPECODE_OBJECT;
1603 case MONO_TYPE_BOOLEAN:
1604 return TYPECODE_BOOLEAN;
1605 case MONO_TYPE_U1:
1606 return TYPECODE_BYTE;
1607 case MONO_TYPE_I1:
1608 return TYPECODE_SBYTE;
1609 case MONO_TYPE_U2:
1610 return TYPECODE_UINT16;
1611 case MONO_TYPE_I2:
1612 return TYPECODE_INT16;
1613 case MONO_TYPE_CHAR:
1614 return TYPECODE_CHAR;
1615 case MONO_TYPE_PTR:
1616 case MONO_TYPE_U:
1617 case MONO_TYPE_I:
1618 return TYPECODE_OBJECT;
1619 case MONO_TYPE_U4:
1620 return TYPECODE_UINT32;
1621 case MONO_TYPE_I4:
1622 return TYPECODE_INT32;
1623 case MONO_TYPE_U8:
1624 return TYPECODE_UINT64;
1625 case MONO_TYPE_I8:
1626 return TYPECODE_INT64;
1627 case MONO_TYPE_R4:
1628 return TYPECODE_SINGLE;
1629 case MONO_TYPE_R8:
1630 return TYPECODE_DOUBLE;
1631 case MONO_TYPE_VALUETYPE: {
1632 MonoClass *klass = type->data.klass;
1634 if (m_class_is_enumtype (klass)) {
1635 t = mono_class_enum_basetype_internal (klass)->type;
1636 goto handle_enum;
1637 } else if (mono_is_corlib_image (m_class_get_image (klass))) {
1638 if (strcmp (m_class_get_name_space (klass), "System") == 0) {
1639 if (strcmp (m_class_get_name (klass), "Decimal") == 0)
1640 return TYPECODE_DECIMAL;
1641 else if (strcmp (m_class_get_name (klass), "DateTime") == 0)
1642 return TYPECODE_DATETIME;
1645 return TYPECODE_OBJECT;
1647 case MONO_TYPE_STRING:
1648 return TYPECODE_STRING;
1649 case MONO_TYPE_SZARRAY:
1650 case MONO_TYPE_ARRAY:
1651 case MONO_TYPE_OBJECT:
1652 case MONO_TYPE_VAR:
1653 case MONO_TYPE_MVAR:
1654 case MONO_TYPE_TYPEDBYREF:
1655 return TYPECODE_OBJECT;
1656 case MONO_TYPE_CLASS:
1658 MonoClass *klass = type->data.klass;
1659 if (m_class_get_image (klass) == mono_defaults.corlib && strcmp (m_class_get_name_space (klass), "System") == 0) {
1660 if (strcmp (m_class_get_name (klass), "DBNull") == 0)
1661 return TYPECODE_DBNULL;
1664 return TYPECODE_OBJECT;
1665 case MONO_TYPE_GENERICINST:
1666 return TYPECODE_OBJECT;
1667 default:
1668 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1670 return 0;
1673 static MonoType*
1674 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1676 if (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (type->data.klass))
1677 return mono_class_enum_basetype_internal (type->data.klass);
1678 if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype (type->data.generic_class->container_class))
1679 return mono_class_enum_basetype_internal (type->data.generic_class->container_class);
1680 return type;
1683 guint32
1684 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionTypeHandle ref_type, MonoReflectionTypeHandle ref_c, MonoError *error)
1686 g_assert (!MONO_HANDLE_IS_NULL (ref_type));
1688 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
1689 MonoClass *klass = mono_class_from_mono_type_internal (type);
1690 MonoType *ctype = MONO_HANDLE_GETVAL (ref_c, type);
1691 MonoClass *klassc = mono_class_from_mono_type_internal (ctype);
1693 if (type->byref ^ ctype->byref)
1694 return FALSE;
1696 if (type->byref) {
1697 MonoType *t = mono_type_get_underlying_type_ignore_byref (type);
1698 MonoType *ot = mono_type_get_underlying_type_ignore_byref (ctype);
1700 klass = mono_class_from_mono_type_internal (t);
1701 klassc = mono_class_from_mono_type_internal (ot);
1703 if (mono_type_is_primitive (t)) {
1704 return mono_type_is_primitive (ot) && m_class_get_instance_size (klass) == m_class_get_instance_size (klassc);
1705 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1706 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1707 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1708 return t->type == ot->type;
1709 } else {
1710 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1711 return FALSE;
1713 if (m_class_is_valuetype (klass))
1714 return klass == klassc;
1715 return m_class_is_valuetype (klass) == m_class_is_valuetype (klassc);
1718 return mono_class_is_assignable_from_internal (klass, klassc);
1721 MonoBoolean
1722 ves_icall_RuntimeTypeHandle_is_subclass_of (MonoType *childType, MonoType *baseType)
1724 ERROR_DECL (error);
1725 mono_bool result = FALSE;
1726 MonoClass *childClass;
1727 MonoClass *baseClass;
1729 childClass = mono_class_from_mono_type_internal (childType);
1730 baseClass = mono_class_from_mono_type_internal (baseType);
1732 if (G_UNLIKELY (childType->byref)) {
1733 result = !baseType->byref && baseClass == mono_defaults.object_class;
1734 goto done;
1737 if (G_UNLIKELY (baseType->byref)) {
1738 result = FALSE;
1739 goto done;
1742 if (childType == baseType) {
1743 /* .NET IsSubclassOf is not reflexive */
1744 result = FALSE;
1745 goto done;
1748 if (G_UNLIKELY (is_generic_parameter (childType))) {
1749 /* slow path: walk the type hierarchy looking at base types
1750 * until we see baseType. If the current type is not a gparam,
1751 * break out of the loop and use is_subclass_of.
1753 MonoClass *c = mono_generic_param_get_base_type (childClass);
1755 result = FALSE;
1756 while (c != NULL) {
1757 if (c == baseClass) {
1758 result = TRUE;
1759 break;
1761 if (!is_generic_parameter (m_class_get_byval_arg (c))) {
1762 result = mono_class_is_subclass_of (c, baseClass, FALSE);
1763 break;
1764 } else
1765 c = mono_generic_param_get_base_type (c);
1767 } else {
1768 result = mono_class_is_subclass_of (childClass, baseClass, FALSE);
1770 done:
1771 mono_error_set_pending_exception (error);
1772 return result;
1775 guint32
1776 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionTypeHandle ref_type, MonoObjectHandle obj, MonoError *error)
1778 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
1779 MonoClass *klass = mono_class_from_mono_type_internal (type);
1780 mono_class_init_checked (klass, error);
1781 return_val_if_nok (error, FALSE);
1782 MonoObjectHandle inst = mono_object_handle_isinst (obj, klass, error);
1783 return_val_if_nok (error, FALSE);
1784 return !MONO_HANDLE_IS_NULL (inst);
1787 guint32
1788 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionTypeHandle ref_type, MonoError *error)
1790 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
1791 MonoClass *klass = mono_class_from_mono_type_internal (type);
1792 return mono_class_get_flags (klass);
1795 MonoReflectionMarshalAsAttributeHandle
1796 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionFieldHandle field_h, MonoError *error)
1798 MonoDomain *domain = MONO_HANDLE_DOMAIN (field_h);
1799 MonoClassField *field = MONO_HANDLE_GETVAL (field_h, field);
1800 MonoClass *klass = field->parent;
1802 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1803 if (mono_class_is_gtd (klass) ||
1804 (gklass && gklass->context.class_inst->is_open))
1805 return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
1807 MonoType *ftype = mono_field_get_type_internal (field);
1808 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1809 return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
1811 MonoMarshalType *info = mono_marshal_load_type_info (klass);
1813 for (int i = 0; i < info->num_fields; ++i) {
1814 if (info->fields [i].field == field) {
1815 if (!info->fields [i].mspec)
1816 return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
1817 else {
1818 return mono_reflection_marshal_as_attribute_from_marshal_spec (domain, klass, info->fields [i].mspec, error);
1823 return MONO_HANDLE_CAST (MonoReflectionMarshalAsAttribute, NULL_HANDLE);
1826 MonoReflectionFieldHandle
1827 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type, MonoError *error)
1829 MonoClass *klass;
1831 g_assert (handle);
1833 if (!type) {
1834 klass = handle->parent;
1835 } else {
1836 klass = mono_class_from_mono_type_internal (type);
1838 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1840 if (!found)
1841 /* The managed code will throw the exception */
1842 return MONO_HANDLE_CAST (MonoReflectionField, NULL_HANDLE);
1845 return mono_field_get_object_handle (mono_domain_get (), klass, handle, error);
1848 MonoReflectionEventHandle
1849 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type, MonoError *error)
1851 MonoClass *klass;
1853 g_assert (handle);
1855 if (!type) {
1856 klass = handle->parent;
1857 } else {
1858 klass = mono_class_from_mono_type_internal (type);
1860 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1861 if (!found)
1862 /* Managed code will throw an exception */
1863 return MONO_HANDLE_CAST (MonoReflectionEvent, NULL_HANDLE);
1866 return mono_event_get_object_handle (mono_domain_get (), klass, handle, error);
1870 MonoReflectionPropertyHandle
1871 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type, MonoError *error)
1873 MonoClass *klass;
1875 g_assert (handle);
1877 if (!type) {
1878 klass = handle->parent;
1879 } else {
1880 klass = mono_class_from_mono_type_internal (type);
1882 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1883 if (!found)
1884 /* Managed code will throw an exception */
1885 return MONO_HANDLE_CAST (MonoReflectionProperty, NULL_HANDLE);
1888 return mono_property_get_object_handle (mono_domain_get (), klass, handle, error);
1891 MonoArrayHandle
1892 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionFieldHandle field_h, MonoBoolean optional, MonoError *error)
1894 MonoClassField *field = MONO_HANDLE_GETVAL (field_h, field);
1896 MonoType *type = mono_field_get_type_checked (field, error);
1897 return_val_if_nok (error, NULL_HANDLE_ARRAY);
1899 return type_array_from_modifiers (m_class_get_image (field->parent), type, optional, error);
1903 ves_icall_get_method_attributes (MonoMethod *method)
1905 return method->flags;
1908 void
1909 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info, MonoError *error)
1911 MonoDomain *domain = mono_domain_get ();
1913 MonoMethodSignature* sig = mono_method_signature_checked (method, error);
1914 return_if_nok (error);
1916 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (method->klass), error);
1917 return_if_nok (error);
1919 MONO_STRUCT_SETREF_INTERNAL (info, parent, MONO_HANDLE_RAW (rt));
1921 MONO_HANDLE_ASSIGN (rt, mono_type_get_object_handle (domain, sig->ret, error));
1922 return_if_nok (error);
1924 MONO_STRUCT_SETREF_INTERNAL (info, ret, MONO_HANDLE_RAW (rt));
1926 info->attrs = method->flags;
1927 info->implattrs = method->iflags;
1928 guint32 callconv;
1929 if (sig->call_convention == MONO_CALL_DEFAULT)
1930 callconv = sig->sentinelpos >= 0 ? 2 : 1;
1931 else {
1932 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1933 callconv = 2;
1934 else
1935 callconv = 1;
1937 callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1938 info->callconv = callconv;
1941 MonoArrayHandle
1942 ves_icall_System_Reflection_MonoMethodInfo_get_parameter_info (MonoMethod *method, MonoReflectionMethodHandle member, MonoError *error)
1944 MonoDomain *domain = mono_domain_get ();
1946 MonoReflectionTypeHandle reftype = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1947 MONO_HANDLE_GET (reftype, member, reftype);
1948 MonoClass *klass = NULL;
1949 if (!MONO_HANDLE_IS_NULL (reftype))
1950 klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (reftype, type));
1951 return mono_param_get_objects_internal (domain, method, klass, error);
1954 MonoReflectionMarshalAsAttributeHandle
1955 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method, MonoError *error)
1957 MonoDomain *domain = mono_domain_get ();
1958 MonoReflectionMarshalAsAttributeHandle res = MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute, NULL);
1960 MonoMarshalSpec **mspecs = g_new (MonoMarshalSpec*, mono_method_signature_internal (method)->param_count + 1);
1961 mono_method_get_marshal_info (method, mspecs);
1963 if (mspecs [0]) {
1964 MONO_HANDLE_ASSIGN (res, mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], error));
1965 goto_if_nok (error, leave);
1968 leave:
1969 for (int i = mono_method_signature_internal (method)->param_count; i >= 0; i--)
1970 if (mspecs [i])
1971 mono_metadata_free_marshal_spec (mspecs [i]);
1972 g_free (mspecs);
1974 return res;
1977 gint32
1978 ves_icall_MonoField_GetFieldOffset (MonoReflectionFieldHandle field, MonoError *error)
1980 MonoClassField *class_field = MONO_HANDLE_GETVAL (field, field);
1981 mono_class_setup_fields (class_field->parent);
1983 return class_field->offset - MONO_ABI_SIZEOF (MonoObject);
1986 MonoReflectionTypeHandle
1987 ves_icall_MonoField_GetParentType (MonoReflectionFieldHandle field, MonoBoolean declaring, MonoError *error)
1989 MonoDomain *domain = MONO_HANDLE_DOMAIN (field);
1990 MonoClass *parent;
1992 if (declaring) {
1993 MonoClassField *f = MONO_HANDLE_GETVAL (field, field);
1994 parent = f->parent;
1995 } else {
1996 parent = MONO_HANDLE_GETVAL (field, klass);
1999 return mono_type_get_object_handle (domain, m_class_get_byval_arg (parent), error);
2002 MonoObject *
2003 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
2005 ERROR_DECL (error);
2006 MonoClass *fklass = field->klass;
2007 MonoClassField *cf = field->field;
2008 MonoDomain *domain = mono_object_domain (field);
2010 if (mono_asmctx_get_kind (&m_class_get_image (fklass)->assembly->context) == MONO_ASMCTX_REFONLY) {
2011 mono_error_set_invalid_operation (error,
2012 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods.");
2013 mono_error_set_pending_exception (error);
2014 return NULL;
2017 if (mono_security_core_clr_enabled () &&
2018 !mono_security_core_clr_ensure_reflection_access_field (cf, error)) {
2019 mono_error_set_pending_exception (error);
2020 return NULL;
2023 #ifndef DISABLE_REMOTING
2024 if (G_UNLIKELY (obj != NULL && mono_class_is_transparent_proxy (mono_object_class (obj)))) {
2025 /* We get here if someone used a
2026 * System.Reflection.FieldInfo:GetValue on a
2027 * ContextBoundObject's or cross-domain MarshalByRefObject's
2028 * transparent proxy. */
2029 MonoObject *result = mono_load_remote_field_new_checked (obj, fklass, cf, error);
2030 mono_error_set_pending_exception (error);
2031 return result;
2033 #endif
2035 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, error);
2036 mono_error_set_pending_exception (error);
2037 return result;
2040 void
2041 ves_icall_MonoField_SetValueInternal (MonoReflectionFieldHandle field, MonoObjectHandle obj, MonoObjectHandle value, MonoError *error)
2043 MonoClassField *cf = MONO_HANDLE_GETVAL (field, field);
2045 MonoClass *field_klass = MONO_HANDLE_GETVAL (field, klass);
2046 if (mono_asmctx_get_kind (&m_class_get_image (field_klass)->assembly->context) == MONO_ASMCTX_REFONLY) {
2047 mono_error_set_invalid_operation (error, "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods.");
2048 return;
2051 if (mono_security_core_clr_enabled () &&
2052 !mono_security_core_clr_ensure_reflection_access_field (cf, error)) {
2053 return;
2056 #ifndef DISABLE_REMOTING
2057 if (G_UNLIKELY (!MONO_HANDLE_IS_NULL (obj) && mono_class_is_transparent_proxy (mono_handle_class (obj)))) {
2058 /* We get here if someone used a
2059 * System.Reflection.FieldInfo:SetValue on a
2060 * ContextBoundObject's or cross-domain MarshalByRefObject's
2061 * transparent proxy. */
2062 /* FIXME: use handles for mono_store_remote_field_new_checked */
2063 MonoObject *v = MONO_HANDLE_RAW (value);
2064 MonoObject *o = MONO_HANDLE_RAW (obj);
2065 mono_store_remote_field_new_checked (o, field_klass, cf, v, error);
2066 return;
2068 #endif
2070 MonoType *type = mono_field_get_type_checked (cf, error);
2071 return_if_nok (error);
2073 gboolean isref = FALSE;
2074 uint32_t value_gchandle = 0;
2075 gchar *v = NULL;
2076 if (!type->byref) {
2077 switch (type->type) {
2078 case MONO_TYPE_U1:
2079 case MONO_TYPE_I1:
2080 case MONO_TYPE_BOOLEAN:
2081 case MONO_TYPE_U2:
2082 case MONO_TYPE_I2:
2083 case MONO_TYPE_CHAR:
2084 case MONO_TYPE_U:
2085 case MONO_TYPE_I:
2086 case MONO_TYPE_U4:
2087 case MONO_TYPE_I4:
2088 case MONO_TYPE_R4:
2089 case MONO_TYPE_U8:
2090 case MONO_TYPE_I8:
2091 case MONO_TYPE_R8:
2092 case MONO_TYPE_VALUETYPE:
2093 case MONO_TYPE_PTR:
2094 isref = FALSE;
2095 if (!MONO_HANDLE_IS_NULL (value))
2096 v = (char*)mono_object_handle_pin_unbox (value, &value_gchandle);
2097 break;
2098 case MONO_TYPE_STRING:
2099 case MONO_TYPE_OBJECT:
2100 case MONO_TYPE_CLASS:
2101 case MONO_TYPE_ARRAY:
2102 case MONO_TYPE_SZARRAY:
2103 /* Do nothing */
2104 isref = TRUE;
2105 break;
2106 case MONO_TYPE_GENERICINST: {
2107 MonoGenericClass *gclass = type->data.generic_class;
2108 g_assert (!gclass->context.class_inst->is_open);
2110 if (mono_class_is_nullable (mono_class_from_mono_type_internal (type))) {
2111 MonoClass *nklass = mono_class_from_mono_type_internal (type);
2114 * Convert the boxed vtype into a Nullable structure.
2115 * This is complicated by the fact that Nullables have
2116 * a variable structure.
2118 MonoObjectHandle nullable = mono_object_new_handle (mono_domain_get (), nklass, error);
2119 return_if_nok (error);
2121 uint32_t nullable_gchandle = 0;
2122 guint8 *nval = (guint8*)mono_object_handle_pin_unbox (nullable, &nullable_gchandle);
2123 mono_nullable_init_from_handle (nval, value, nklass);
2125 isref = FALSE;
2126 value_gchandle = nullable_gchandle;
2127 v = (gchar*)nval;
2129 else {
2130 isref = !m_class_is_valuetype (gclass->container_class);
2131 if (!isref && !MONO_HANDLE_IS_NULL (value)) {
2132 v = (char*)mono_object_handle_pin_unbox (value, &value_gchandle);
2135 break;
2137 default:
2138 g_error ("type 0x%x not handled in "
2139 "ves_icall_FieldInfo_SetValueInternal", type->type);
2140 return;
2144 /* either value is a reference type, or it's a value type and we pinned
2145 * it and v points to the payload. */
2146 g_assert ((isref && v == NULL && value_gchandle == 0) ||
2147 (!isref && v != NULL && value_gchandle != 0) ||
2148 (!isref && v == NULL && value_gchandle == 0));
2150 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2151 MonoVTable *vtable = mono_class_vtable_checked (MONO_HANDLE_DOMAIN (field), cf->parent, error);
2152 goto_if_nok (error, leave);
2154 if (!vtable->initialized) {
2155 if (!mono_runtime_class_init_full (vtable, error))
2156 goto leave;
2158 if (isref)
2159 mono_field_static_set_value_internal (vtable, cf, MONO_HANDLE_RAW (value)); /* FIXME make mono_field_static_set_value work with handles for value */
2160 else
2161 mono_field_static_set_value_internal (vtable, cf, v);
2162 } else {
2164 if (isref)
2165 MONO_HANDLE_SET_FIELD_REF (obj, cf, value);
2166 else
2167 mono_field_set_value_internal (MONO_HANDLE_RAW (obj), cf, v); /* FIXME: make mono_field_set_value take a handle for obj */
2169 leave:
2170 if (value_gchandle)
2171 mono_gchandle_free_internal (value_gchandle);
2174 static MonoObjectHandle
2175 typed_reference_to_object (MonoTypedRef *tref, MonoError *error)
2177 HANDLE_FUNCTION_ENTER ();
2178 MonoObjectHandle result;
2179 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
2180 MonoObject** objp = (MonoObject **)tref->value;
2181 result = MONO_HANDLE_NEW (MonoObject, *objp);
2182 } else {
2183 result = mono_value_box_handle (mono_domain_get (), tref->klass, tref->value, error);
2185 HANDLE_FUNCTION_RETURN_REF (MonoObject, result);
2188 void
2189 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2191 ICALL_ENTRY ();
2193 MonoClassField *f;
2195 g_assert (field);
2196 g_assert (obj);
2197 g_assert (value);
2199 f = field->field;
2200 if (!MONO_TYPE_ISSTRUCT (m_class_get_byval_arg (f->parent))) {
2201 MonoReflectionFieldHandle fieldHandle = MONO_HANDLE_NEW (MonoReflectionField, field);
2202 MonoObjectHandle objHandle = typed_reference_to_object (obj, error),
2203 valueHandle = MONO_HANDLE_NEW (MonoObject, value);
2204 goto_if_nok (error, leave);
2205 ves_icall_MonoField_SetValueInternal (fieldHandle, objHandle, valueHandle, error);
2206 } else if (MONO_TYPE_IS_REFERENCE (f->type))
2207 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2208 else
2209 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox_internal (value), FALSE);
2211 leave:
2212 ICALL_RETURN ();
2215 MonoObject *
2216 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2218 MonoObject *o = NULL;
2219 MonoClassField *field = rfield->field;
2220 MonoClass *klass;
2221 MonoDomain *domain = mono_object_domain (rfield);
2222 gchar *v;
2223 MonoTypeEnum def_type;
2224 const char *def_value;
2225 MonoType *t;
2226 ERROR_DECL (error);
2228 mono_class_init (field->parent);
2230 t = mono_field_get_type_checked (field, error);
2231 if (!is_ok (error)) {
2232 mono_error_set_pending_exception (error);
2233 return NULL;
2236 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2237 mono_error_set_invalid_operation (error, NULL);
2238 mono_error_set_pending_exception (error);
2239 return NULL;
2242 if (image_is_dynamic (m_class_get_image (field->parent))) {
2243 MonoClass *klass = field->parent;
2244 int fidx = field - m_class_get_fields (klass);
2245 MonoFieldDefaultValue *def_values = mono_class_get_field_def_values (klass);
2247 g_assert (def_values);
2248 def_type = def_values [fidx].def_type;
2249 def_value = def_values [fidx].data;
2251 if (def_type == MONO_TYPE_END) {
2252 mono_error_set_invalid_operation (error, NULL);
2253 mono_error_set_pending_exception (error);
2254 return NULL;
2256 } else {
2257 def_value = mono_class_get_field_default_value (field, &def_type);
2258 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2259 if (!def_value) {
2260 mono_error_set_invalid_operation (error, NULL);
2261 mono_error_set_pending_exception (error);
2262 return NULL;
2266 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2267 switch (def_type) {
2268 case MONO_TYPE_U1:
2269 case MONO_TYPE_I1:
2270 case MONO_TYPE_BOOLEAN:
2271 case MONO_TYPE_U2:
2272 case MONO_TYPE_I2:
2273 case MONO_TYPE_CHAR:
2274 case MONO_TYPE_U:
2275 case MONO_TYPE_I:
2276 case MONO_TYPE_U4:
2277 case MONO_TYPE_I4:
2278 case MONO_TYPE_R4:
2279 case MONO_TYPE_U8:
2280 case MONO_TYPE_I8:
2281 case MONO_TYPE_R8: {
2282 MonoType *t;
2284 /* boxed value type */
2285 t = g_new0 (MonoType, 1);
2286 t->type = def_type;
2287 klass = mono_class_from_mono_type_internal (t);
2288 g_free (t);
2289 o = mono_object_new_checked (domain, klass, error);
2290 if (!is_ok (error)) {
2291 mono_error_set_pending_exception (error);
2292 return NULL;
2294 v = ((gchar *) o) + sizeof (MonoObject);
2295 mono_get_constant_value_from_blob (domain, def_type, def_value, v, error);
2296 if (mono_error_set_pending_exception (error))
2297 return NULL;
2298 break;
2300 case MONO_TYPE_STRING:
2301 case MONO_TYPE_CLASS:
2302 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, error);
2303 if (mono_error_set_pending_exception (error))
2304 return NULL;
2305 break;
2306 default:
2307 g_assert_not_reached ();
2310 return o;
2313 MonoReflectionTypeHandle
2314 ves_icall_MonoField_ResolveType (MonoReflectionFieldHandle ref_field, MonoError *error)
2316 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_field);
2317 MonoClassField *field = MONO_HANDLE_GETVAL (ref_field, field);
2318 MonoType *type = mono_field_get_type_checked (field, error);
2319 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
2320 return mono_type_get_object_handle (domain, type, error);
2323 void
2324 ves_icall_MonoPropertyInfo_get_property_info (MonoReflectionPropertyHandle property, MonoPropertyInfo *info, PInfo req_info, MonoError *error)
2326 MonoDomain *domain = MONO_HANDLE_DOMAIN (property);
2327 const MonoProperty *pproperty = MONO_HANDLE_GETVAL (property, property);
2329 if ((req_info & PInfo_ReflectedType) != 0) {
2330 MonoClass *klass = MONO_HANDLE_GETVAL (property, klass);
2331 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
2332 return_if_nok (error);
2334 MONO_STRUCT_SETREF_INTERNAL (info, parent, MONO_HANDLE_RAW (rt));
2336 if ((req_info & PInfo_DeclaringType) != 0) {
2337 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (pproperty->parent), error);
2338 return_if_nok (error);
2340 MONO_STRUCT_SETREF_INTERNAL (info, declaring_type, MONO_HANDLE_RAW (rt));
2343 if ((req_info & PInfo_Name) != 0) {
2344 MonoStringHandle name = mono_string_new_handle (domain, pproperty->name, error);
2345 return_if_nok (error);
2347 MONO_STRUCT_SETREF_INTERNAL (info, name, MONO_HANDLE_RAW (name));
2350 if ((req_info & PInfo_Attributes) != 0)
2351 info->attrs = pproperty->attrs;
2353 if ((req_info & PInfo_GetMethod) != 0) {
2354 MonoClass *property_klass = MONO_HANDLE_GETVAL (property, klass);
2355 MonoReflectionMethodHandle rm;
2356 if (pproperty->get &&
2357 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2358 pproperty->get->klass == property_klass)) {
2359 rm = mono_method_get_object_handle (domain, pproperty->get, property_klass, error);
2360 return_if_nok (error);
2361 } else {
2362 rm = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
2365 MONO_STRUCT_SETREF_INTERNAL (info, get, MONO_HANDLE_RAW (rm));
2367 if ((req_info & PInfo_SetMethod) != 0) {
2368 MonoClass *property_klass = MONO_HANDLE_GETVAL (property, klass);
2369 MonoReflectionMethodHandle rm;
2370 if (pproperty->set &&
2371 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2372 pproperty->set->klass == property_klass)) {
2373 rm = mono_method_get_object_handle (domain, pproperty->set, property_klass, error);
2374 return_if_nok (error);
2375 } else {
2376 rm = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
2379 MONO_STRUCT_SETREF_INTERNAL (info, set, MONO_HANDLE_RAW (rm));
2382 * There may be other methods defined for properties, though, it seems they are not exposed
2383 * in the reflection API
2387 static gboolean
2388 add_event_other_methods_to_array (MonoDomain *domain, MonoMethod *m, MonoArrayHandle dest, int i, MonoError *error)
2390 HANDLE_FUNCTION_ENTER ();
2391 error_init (error);
2392 MonoReflectionMethodHandle rm = mono_method_get_object_handle (domain, m, NULL, error);
2393 goto_if_nok (error, leave);
2394 MONO_HANDLE_ARRAY_SETREF (dest, i, rm);
2395 leave:
2396 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2399 void
2400 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEventHandle ref_event, MonoEventInfo *info, MonoError *error)
2402 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_event);
2404 MonoClass *klass = MONO_HANDLE_GETVAL (ref_event, klass);
2405 MonoEvent *event = MONO_HANDLE_GETVAL (ref_event, event);
2407 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
2408 return_if_nok (error);
2409 MONO_STRUCT_SETREF_INTERNAL (info, reflected_type, MONO_HANDLE_RAW (rt));
2411 rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (event->parent), error);
2412 return_if_nok (error);
2413 MONO_STRUCT_SETREF_INTERNAL (info, declaring_type, MONO_HANDLE_RAW (rt));
2415 MonoStringHandle ev_name = mono_string_new_handle (domain, event->name, error);
2416 return_if_nok (error);
2417 MONO_STRUCT_SETREF_INTERNAL (info, name, MONO_HANDLE_RAW (ev_name));
2419 info->attrs = event->attrs;
2421 MonoReflectionMethodHandle rm;
2422 if (event->add) {
2423 rm = mono_method_get_object_handle (domain, event->add, NULL, error);
2424 return_if_nok (error);
2425 } else {
2426 rm = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
2429 MONO_STRUCT_SETREF_INTERNAL (info, add_method, MONO_HANDLE_RAW (rm));
2431 if (event->remove) {
2432 rm = mono_method_get_object_handle (domain, event->remove, NULL, error);
2433 return_if_nok (error);
2434 } else {
2435 rm = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
2438 MONO_STRUCT_SETREF_INTERNAL (info, remove_method, MONO_HANDLE_RAW (rm));
2440 if (event->raise) {
2441 rm = mono_method_get_object_handle (domain, event->raise, NULL, error);
2442 return_if_nok (error);
2443 } else {
2444 rm = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
2447 MONO_STRUCT_SETREF_INTERNAL (info, raise_method, MONO_HANDLE_RAW (rm));
2449 #ifndef MONO_SMALL_CONFIG
2450 if (event->other) {
2451 int i, n = 0;
2452 while (event->other [n])
2453 n++;
2454 MonoArrayHandle info_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, n, error);
2455 return_if_nok (error);
2457 MONO_STRUCT_SETREF_INTERNAL (info, other_methods, MONO_HANDLE_RAW (info_arr));
2459 for (i = 0; i < n; i++)
2460 if (!add_event_other_methods_to_array (domain, event->other [i], info_arr, i, error))
2461 return;
2463 #endif
2466 static void
2467 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2469 int i;
2470 MonoClass *ic;
2472 mono_class_setup_interfaces (klass, error);
2473 return_if_nok (error);
2475 int klass_interface_count = m_class_get_interface_count (klass);
2476 MonoClass **klass_interfaces = m_class_get_interfaces (klass);
2477 for (i = 0; i < klass_interface_count; i++) {
2478 ic = klass_interfaces [i];
2479 g_hash_table_insert (ifaces, ic, ic);
2481 collect_interfaces (ic, ifaces, error);
2482 return_if_nok (error);
2486 typedef struct {
2487 MonoArrayHandle iface_array;
2488 MonoGenericContext *context;
2489 MonoError *error;
2490 MonoDomain *domain;
2491 int next_idx;
2492 } FillIfaceArrayData;
2494 static void
2495 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2497 HANDLE_FUNCTION_ENTER ();
2498 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2499 MonoClass *ic = (MonoClass *)key;
2500 MonoType *ret = m_class_get_byval_arg (ic), *inflated = NULL;
2501 MonoError *error = data->error;
2503 goto_if_nok (error, leave);
2505 if (data->context && mono_class_is_ginst (ic) && mono_class_get_generic_class (ic)->context.class_inst->is_open) {
2506 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, error);
2507 goto_if_nok (error, leave);
2510 MonoReflectionTypeHandle rt;
2511 rt = mono_type_get_object_handle (data->domain, ret, error);
2512 goto_if_nok (error, leave);
2514 MONO_HANDLE_ARRAY_SETREF (data->iface_array, data->next_idx, rt);
2515 data->next_idx++;
2517 if (inflated)
2518 mono_metadata_free_type (inflated);
2519 leave:
2520 HANDLE_FUNCTION_RETURN ();
2523 static guint
2524 get_interfaces_hash (gconstpointer v1)
2526 MonoClass *k = (MonoClass*)v1;
2528 return m_class_get_type_token (k);
2531 MonoArrayHandle
2532 ves_icall_RuntimeType_GetInterfaces (MonoReflectionTypeHandle ref_type, MonoError *error)
2534 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2535 MonoClass *klass = mono_class_from_mono_type_internal (type);
2537 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2539 MonoGenericContext *context = NULL;
2540 if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open) {
2541 context = mono_class_get_context (klass);
2542 klass = mono_class_get_generic_class (klass)->container_class;
2545 for (MonoClass *parent = klass; parent; parent = m_class_get_parent (parent)) {
2546 mono_class_setup_interfaces (parent, error);
2547 goto_if_nok (error, fail);
2548 collect_interfaces (parent, iface_hash, error);
2549 goto_if_nok (error, fail);
2552 MonoDomain *domain;
2553 domain = MONO_HANDLE_DOMAIN (ref_type);
2555 int len;
2556 len = g_hash_table_size (iface_hash);
2557 if (len == 0) {
2558 g_hash_table_destroy (iface_hash);
2559 if (!domain->empty_types) {
2560 domain->empty_types = mono_array_new_cached (domain, mono_defaults.runtimetype_class, 0, error);
2561 goto_if_nok (error, fail);
2563 return MONO_HANDLE_NEW (MonoArray, domain->empty_types);
2566 FillIfaceArrayData data;
2567 data.iface_array = MONO_HANDLE_NEW (MonoArray, mono_array_new_cached (domain, mono_defaults.runtimetype_class, len, error));
2568 goto_if_nok (error, fail);
2569 data.context = context;
2570 data.error = error;
2571 data.domain = domain;
2572 data.next_idx = 0;
2574 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2576 goto_if_nok (error, fail);
2578 g_hash_table_destroy (iface_hash);
2579 return data.iface_array;
2581 fail:
2582 g_hash_table_destroy (iface_hash);
2583 return NULL_HANDLE_ARRAY;
2586 static gboolean
2587 set_interface_map_data_method_object (MonoDomain *domain, MonoMethod *method, MonoClass *iclass, int ioffset, MonoClass *klass, MonoArrayHandle targets, MonoArrayHandle methods, int i, MonoError *error)
2589 HANDLE_FUNCTION_ENTER ();
2590 error_init (error);
2591 MonoReflectionMethodHandle member = mono_method_get_object_handle (domain, method, iclass, error);
2592 goto_if_nok (error, leave);
2594 MONO_HANDLE_ARRAY_SETREF (methods, i, member);
2596 MONO_HANDLE_ASSIGN (member, mono_method_get_object_handle (domain, m_class_get_vtable (klass) [i + ioffset], klass, error));
2597 goto_if_nok (error, leave);
2599 MONO_HANDLE_ARRAY_SETREF (targets, i, member);
2601 leave:
2602 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2605 void
2606 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionTypeHandle ref_type, MonoReflectionTypeHandle ref_iface, MonoArrayHandleOut targets, MonoArrayHandleOut methods, MonoError *error)
2608 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2609 MonoClass *klass = mono_class_from_mono_type_internal (type);
2610 MonoType *iface = MONO_HANDLE_GETVAL (ref_iface, type);
2611 MonoClass *iclass = mono_class_from_mono_type_internal (iface);
2613 mono_class_init_checked (klass, error);
2614 return_if_nok (error);
2615 mono_class_init_checked (iclass, error);
2616 return_if_nok (error);
2618 mono_class_setup_vtable (klass);
2620 gboolean variance_used;
2621 int ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2622 if (ioffset == -1)
2623 return;
2625 int len = mono_class_num_methods (iclass);
2626 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2627 MonoArrayHandle targets_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, len, error);
2628 return_if_nok (error);
2629 MONO_HANDLE_ASSIGN (targets, targets_arr);
2631 MonoArrayHandle methods_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, len, error);
2632 return_if_nok (error);
2633 MONO_HANDLE_ASSIGN (methods, methods_arr);
2635 MonoMethod* method;
2636 int i = 0;
2637 gpointer iter = NULL;
2638 while ((method = mono_class_get_methods (iclass, &iter))) {
2639 if (!set_interface_map_data_method_object (domain, method, iclass, ioffset, klass, targets, methods, i, error))
2640 return;
2641 i ++;
2645 void
2646 ves_icall_RuntimeType_GetPacking (MonoReflectionTypeHandle ref_type, guint32 *packing, guint32 *size, MonoError *error)
2648 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2649 MonoClass *klass = mono_class_from_mono_type_internal (type);
2651 mono_class_init_checked (klass, error);
2652 return_if_nok (error);
2654 if (image_is_dynamic (m_class_get_image (klass))) {
2655 MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_type);
2656 *packing = MONO_HANDLE_GETVAL (tb, packing_size);
2657 *size = MONO_HANDLE_GETVAL (tb, class_size);
2658 } else {
2659 mono_metadata_packing_from_typedef (m_class_get_image (klass), m_class_get_type_token (klass), packing, size);
2663 MonoReflectionTypeHandle
2664 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionTypeHandle ref_type, MonoError *error)
2666 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2667 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2669 if (!type->byref && type->type == MONO_TYPE_SZARRAY) {
2670 return mono_type_get_object_handle (domain, m_class_get_byval_arg (type->data.klass), error);
2673 MonoClass *klass = mono_class_from_mono_type_internal (type);
2674 mono_class_init_checked (klass, error);
2675 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
2677 // GetElementType should only return a type for:
2678 // Array Pointer PassedByRef
2679 if (type->byref)
2680 return mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
2681 else if (m_class_get_element_class (klass) && MONO_CLASS_IS_ARRAY (klass))
2682 return mono_type_get_object_handle (domain, m_class_get_byval_arg (m_class_get_element_class (klass)), error);
2683 else if (m_class_get_element_class (klass) && type->type == MONO_TYPE_PTR)
2684 return mono_type_get_object_handle (domain, m_class_get_byval_arg (m_class_get_element_class (klass)), error);
2685 else
2686 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2689 MonoReflectionTypeHandle
2690 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionTypeHandle ref_type, MonoError *error)
2692 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2693 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2695 if (type->byref)
2696 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2698 MonoClass *klass = mono_class_from_mono_type_internal (type);
2699 if (!m_class_get_parent (klass))
2700 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2702 return mono_type_get_object_handle (domain, m_class_get_byval_arg (m_class_get_parent (klass)), error);
2705 MonoBoolean
2706 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionTypeHandle ref_type, MonoError *error)
2708 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2709 return type->type == MONO_TYPE_PTR;
2712 MonoBoolean
2713 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionTypeHandle ref_type, MonoError *error)
2715 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2716 return (!type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U)));
2719 MonoBoolean
2720 ves_icall_RuntimeTypeHandle_HasReferences (MonoReflectionTypeHandle ref_type, MonoError *error)
2722 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2723 MonoClass *klass;
2725 klass = mono_class_from_mono_type_internal (type);
2726 mono_class_init (klass);
2727 return m_class_has_references (klass);
2730 MonoBoolean
2731 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionTypeHandle ref_type, MonoError *error)
2733 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2734 return type->byref;
2737 MonoBoolean
2738 ves_icall_RuntimeTypeHandle_IsByRefLike (MonoReflectionTypeHandle ref_type, MonoError *error)
2740 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2741 MonoClass *klass = mono_class_from_mono_type_internal (type);
2742 return m_class_is_byreflike (klass);
2745 MonoBoolean
2746 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionTypeHandle ref_type, MonoError *error)
2748 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2749 MonoClass *klass = mono_class_from_mono_type_internal (type);
2750 mono_class_init_checked (klass, error);
2751 return_val_if_nok (error, FALSE);
2753 return mono_class_is_com_object (klass);
2756 guint32
2757 ves_icall_reflection_get_token (MonoObjectHandle obj, MonoError *error)
2759 error_init (error);
2760 return mono_reflection_get_token_checked (obj, error);
2763 MonoReflectionModuleHandle
2764 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionTypeHandle type, MonoError *error)
2766 MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
2767 MonoType *t = MONO_HANDLE_GETVAL (type, type);
2768 MonoClass *klass = mono_class_from_mono_type_internal (t);
2769 return mono_module_get_object_handle (domain, m_class_get_image (klass), error);
2772 MonoReflectionAssemblyHandle
2773 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionTypeHandle type, MonoError *error)
2775 MonoDomain *domain = mono_domain_get ();
2776 MonoType *t = MONO_HANDLE_GETVAL (type, type);
2777 MonoClass *klass = mono_class_from_mono_type_internal (t);
2778 return mono_assembly_get_object_handle (domain, m_class_get_image (klass)->assembly, error);
2781 MonoReflectionTypeHandle
2782 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionTypeHandle ref_type, MonoError *error)
2784 MonoDomain *domain = mono_domain_get ();
2785 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2786 MonoClass *klass;
2788 if (type->byref)
2789 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2790 if (type->type == MONO_TYPE_VAR) {
2791 MonoGenericContainer *param = mono_type_get_generic_param_owner (type);
2792 klass = param ? param->owner.klass : NULL;
2793 } else if (type->type == MONO_TYPE_MVAR) {
2794 MonoGenericContainer *param = mono_type_get_generic_param_owner (type);
2795 klass = param ? param->owner.method->klass : NULL;
2796 } else {
2797 klass = m_class_get_nested_in (mono_class_from_mono_type_internal (type));
2800 if (!klass)
2801 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2803 return mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
2806 MonoStringHandle
2807 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2809 MonoDomain *domain = mono_domain_get ();
2810 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2811 MonoClass *klass = mono_class_from_mono_type_internal (type);
2813 if (type->byref) {
2814 char *n = g_strdup_printf ("%s&", m_class_get_name (klass));
2815 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2817 g_free (n);
2819 return res;
2820 } else {
2821 return mono_string_new_handle (domain, m_class_get_name (klass), error);
2825 MonoStringHandle
2826 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2828 MonoDomain *domain = mono_domain_get ();
2829 MonoClass *klass = mono_class_from_mono_type_handle (type);
2831 MonoClass *klass_nested_in;
2832 while ((klass_nested_in = m_class_get_nested_in (klass)))
2833 klass = klass_nested_in;
2835 if (m_class_get_name_space (klass) [0] == '\0')
2836 return NULL_HANDLE_STRING;
2837 else
2838 return mono_string_new_handle (domain, m_class_get_name_space (klass), error);
2841 gint32
2842 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionTypeHandle ref_type, MonoError *error)
2844 error_init (error);
2845 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2847 if (type->type != MONO_TYPE_ARRAY && type->type != MONO_TYPE_SZARRAY) {
2848 mono_error_set_argument (error, "type", "Type must be an array type");
2849 return 0;
2852 MonoClass *klass = mono_class_from_mono_type_internal (type);
2854 return m_class_get_rank (klass);
2857 static MonoArrayHandle
2858 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2860 return mono_array_new_handle (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2863 static gboolean
2864 set_type_object_in_array (MonoDomain *domain, MonoType *type, MonoArrayHandle dest, int i, MonoError *error)
2866 HANDLE_FUNCTION_ENTER();
2867 error_init (error);
2868 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, type, error);
2869 goto_if_nok (error, leave);
2871 MONO_HANDLE_ARRAY_SETREF (dest, i, rt);
2873 leave:
2874 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2877 MonoArrayHandle
2878 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionTypeHandle ref_type, MonoBoolean runtimeTypeArray, MonoError *error)
2880 error_init (error);
2881 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2883 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2884 MonoClass *klass = mono_class_from_mono_type_internal (type);
2886 MonoArrayHandle res = MONO_HANDLE_NEW (MonoArray, NULL);
2887 if (mono_class_is_gtd (klass)) {
2888 MonoGenericContainer *container = mono_class_get_generic_container (klass);
2889 MONO_HANDLE_ASSIGN (res, create_type_array (domain, runtimeTypeArray, container->type_argc, error));
2890 goto_if_nok (error, leave);
2891 for (int i = 0; i < container->type_argc; ++i) {
2892 MonoClass *pklass = mono_class_create_generic_parameter (mono_generic_container_get_param (container, i));
2894 if (!set_type_object_in_array (domain, m_class_get_byval_arg (pklass), res, i, error))
2895 goto leave;
2898 } else if (mono_class_is_ginst (klass)) {
2899 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
2900 MONO_HANDLE_ASSIGN (res, create_type_array (domain, runtimeTypeArray, inst->type_argc, error));
2901 goto_if_nok (error, leave);
2902 for (int i = 0; i < inst->type_argc; ++i) {
2903 if (!set_type_object_in_array (domain, inst->type_argv [i], res, i, error))
2904 goto leave;
2908 leave:
2909 return res;
2912 MonoBoolean
2913 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionTypeHandle ref_type, MonoError *error)
2915 error_init (error);
2917 if (!IS_MONOTYPE (MONO_HANDLE_RAW(ref_type)))
2918 return FALSE;
2920 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2921 if (type->byref)
2922 return FALSE;
2924 MonoClass *klass = mono_class_from_mono_type_internal (type);
2925 return mono_class_is_gtd (klass);
2928 MonoReflectionTypeHandle
2929 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionTypeHandle ref_type, MonoError *error)
2931 error_init (error);
2932 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
2934 MonoReflectionTypeHandle ret = MONO_HANDLE_NEW (MonoReflectionType, NULL);
2936 if (type->byref)
2937 goto leave;
2939 MonoClass *klass;
2940 klass = mono_class_from_mono_type_internal (type);
2942 if (mono_class_is_gtd (klass)) {
2943 /* check this one */
2944 MONO_HANDLE_ASSIGN (ret, ref_type);
2945 goto leave;
2947 if (mono_class_is_ginst (klass)) {
2948 MonoClass *generic_class = mono_class_get_generic_class (klass)->container_class;
2950 guint32 ref_info_handle = mono_class_get_ref_info_handle (generic_class);
2952 if (m_class_was_typebuilder (generic_class) && ref_info_handle) {
2953 MonoObjectHandle tb = mono_gchandle_get_target_handle (ref_info_handle);
2954 g_assert (!MONO_HANDLE_IS_NULL (tb));
2955 MONO_HANDLE_ASSIGN (ret, tb);
2956 } else {
2957 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
2958 MONO_HANDLE_ASSIGN (ret, mono_type_get_object_handle (domain, m_class_get_byval_arg (generic_class), error));
2961 leave:
2962 return ret;
2965 MonoReflectionTypeHandle
2966 ves_icall_RuntimeType_MakeGenericType (MonoReflectionTypeHandle reftype, MonoArrayHandle type_array, MonoError *error)
2968 error_init (error);
2969 MonoDomain *domain = MONO_HANDLE_DOMAIN (reftype);
2971 g_assert (IS_MONOTYPE_HANDLE (reftype));
2972 MonoType *type = MONO_HANDLE_GETVAL (reftype, type);
2973 mono_class_init_checked (mono_class_from_mono_type_internal (type), error);
2974 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
2976 int count = mono_array_handle_length (type_array);
2977 MonoType **types = g_new0 (MonoType *, count);
2979 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
2980 for (int i = 0; i < count; i++) {
2981 MONO_HANDLE_ARRAY_GETREF (t, type_array, i);
2982 types [i] = MONO_HANDLE_GETVAL (t, type);
2985 MonoType *geninst = mono_reflection_bind_generic_parameters (reftype, count, types, error);
2986 g_free (types);
2987 if (!geninst) {
2988 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2991 MonoClass *klass = mono_class_from_mono_type_internal (geninst);
2993 /*we might inflate to the GTD*/
2994 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2995 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
2996 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
2999 return mono_type_get_object_handle (domain, geninst, error);
3002 MonoBoolean
3003 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionTypeHandle ref_type, MonoError *error)
3005 error_init (error);
3006 MonoClass *klass;
3008 if (!IS_MONOTYPE (MONO_HANDLE_RAW (ref_type)))
3009 return FALSE;
3011 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
3012 if (type->byref)
3013 return FALSE;
3015 klass = mono_class_from_mono_type_internal (type);
3016 return mono_class_is_ginst (klass) || mono_class_is_gtd (klass);
3019 gint32
3020 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionTypeHandle ref_type, MonoError *error)
3022 error_init (error);
3023 if (!IS_MONOTYPE_HANDLE (ref_type))
3024 return -1;
3025 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
3027 if (is_generic_parameter (type))
3028 return mono_type_get_generic_param_num (type);
3029 return -1;
3032 MonoGenericParamInfo *
3033 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionTypeHandle ref_type, MonoError *error)
3035 error_init (error);
3036 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
3037 return mono_generic_param_info (type->data.generic_param);
3040 MonoBoolean
3041 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionTypeHandle ref_type, MonoError *error)
3043 MonoType *type = MONO_HANDLE_GETVAL(ref_type, type);
3044 return is_generic_parameter (type);
3047 MonoReflectionMethodHandle
3048 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionTypeHandle ref_type,
3049 MonoReflectionMethodHandle generic,
3050 MonoError *error)
3052 error_init (error);
3053 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
3054 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
3055 MonoClass *klass = mono_class_from_mono_type_internal (type);
3057 mono_class_init_checked (klass, error);
3058 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
3060 MonoMethod *generic_method = MONO_HANDLE_GETVAL (generic, method);
3062 MonoReflectionMethodHandle ret = MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
3063 MonoMethod *method;
3064 gpointer iter = NULL;
3065 while ((method = mono_class_get_methods (klass, &iter))) {
3066 if (method->token == generic_method->token) {
3067 ret = mono_method_get_object_handle (domain, method, klass, error);
3068 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
3072 return ret;
3075 MonoReflectionMethodHandle
3076 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionTypeHandle ref_type, MonoError *error)
3078 error_init (error);
3079 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
3080 MonoReflectionMethodHandle ret = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
3082 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
3083 mono_error_set_invalid_operation (error, "DeclaringMethod can only be used on generic arguments");
3084 goto leave;
3086 if (type->type == MONO_TYPE_VAR)
3087 goto leave;
3089 MonoMethod *method;
3090 method = mono_type_get_generic_param_owner (type)->owner.method;
3091 g_assert (method);
3093 MonoDomain *domain;
3094 domain = MONO_HANDLE_DOMAIN (ref_type);
3096 MONO_HANDLE_ASSIGN (ret, mono_method_get_object_handle (domain, method, method->klass, error));
3097 leave:
3098 return ret;
3101 MonoBoolean
3102 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (MonoError *error)
3104 error_init (error);
3105 mono_error_set_not_implemented (error, "%s", "System.RuntimeType.IsTypeExportedToWindowsRuntime");
3106 return FALSE;
3109 MonoBoolean
3110 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (MonoError *error)
3112 error_init (error);
3113 mono_error_set_not_implemented (error, "%s", "System.RuntimeType.IsWindowsRuntimeObjectType");
3114 return FALSE;
3117 void
3118 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethodHandle ref_method, int* flags, MonoStringHandleOut entry_point, MonoStringHandleOut dll_name, MonoError *error)
3120 MonoDomain *domain = mono_domain_get ();
3121 MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
3122 MonoImage *image = m_class_get_image (method->klass);
3123 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
3124 MonoTableInfo *tables = image->tables;
3125 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3126 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3127 guint32 im_cols [MONO_IMPLMAP_SIZE];
3128 guint32 scope_token;
3129 const char *import = NULL;
3130 const char *scope = NULL;
3132 error_init (error);
3134 if (image_is_dynamic (image)) {
3135 MonoReflectionMethodAux *method_aux =
3136 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method);
3137 if (method_aux) {
3138 import = method_aux->dllentry;
3139 scope = method_aux->dll;
3142 if (!import || !scope) {
3143 mono_error_set_argument (error, "method", "System.Refleciton.Emit method with invalid pinvoke information");
3144 return;
3147 else {
3148 if (piinfo->implmap_idx) {
3149 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3151 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3152 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3153 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3154 scope = mono_metadata_string_heap (image, scope_token);
3158 *flags = piinfo->piflags;
3159 MONO_HANDLE_ASSIGN (entry_point, mono_string_new_handle (domain, import, error));
3160 return_if_nok (error);
3161 MONO_HANDLE_ASSIGN (dll_name, mono_string_new_handle (domain, scope, error));
3164 MonoReflectionMethodHandle
3165 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethodHandle ref_method, MonoError *error)
3167 error_init (error);
3168 MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
3170 if (method->is_generic)
3171 return ref_method;
3173 if (!method->is_inflated)
3174 return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
3176 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
3178 MonoMethod *result = imethod->declaring;
3179 /* Not a generic method. */
3180 if (!result->is_generic)
3181 return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
3183 if (image_is_dynamic (m_class_get_image (method->klass))) {
3184 MonoDynamicImage *image = (MonoDynamicImage*)m_class_get_image (method->klass);
3187 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3188 * the dynamic case as well ?
3190 mono_image_lock ((MonoImage*)image);
3191 MonoReflectionMethodHandle res = MONO_HANDLE_NEW (MonoReflectionMethod, (MonoReflectionMethod*)mono_g_hash_table_lookup (image->generic_def_objects, imethod));
3192 mono_image_unlock ((MonoImage*)image);
3194 if (!MONO_HANDLE_IS_NULL (res))
3195 return res;
3198 if (imethod->context.class_inst) {
3199 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3200 /*Generic methods gets the context of the GTD.*/
3201 if (mono_class_get_context (klass)) {
3202 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), error);
3203 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
3207 return mono_method_get_object_handle (MONO_HANDLE_DOMAIN (ref_method), result, NULL, error);
3210 MonoBoolean
3211 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethodHandle ref_method, MonoError *erro)
3213 MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
3214 return mono_method_signature_internal (method)->generic_param_count != 0;
3217 MonoBoolean
3218 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethodHandle ref_method, MonoError *Error)
3220 MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
3221 return method->is_generic;
3224 static gboolean
3225 set_array_generic_argument_handle_inflated (MonoDomain *domain, MonoGenericInst *inst, int i, MonoArrayHandle arr, MonoError *error)
3227 HANDLE_FUNCTION_ENTER ();
3228 error_init (error);
3229 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, inst->type_argv [i], error);
3230 goto_if_nok (error, leave);
3231 MONO_HANDLE_ARRAY_SETREF (arr, i, rt);
3232 leave:
3233 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
3236 static gboolean
3237 set_array_generic_argument_handle_gparam (MonoDomain *domain, MonoGenericContainer *container, int i, MonoArrayHandle arr, MonoError *error)
3239 HANDLE_FUNCTION_ENTER ();
3240 error_init (error);
3241 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3242 MonoClass *pklass = mono_class_create_generic_parameter (param);
3243 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (pklass), error);
3244 goto_if_nok (error, leave);
3245 MONO_HANDLE_ARRAY_SETREF (arr, i, rt);
3246 leave:
3247 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
3250 MonoArrayHandle
3251 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethodHandle ref_method, MonoError *error)
3253 error_init (error);
3254 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_method);
3255 MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
3257 if (method->is_inflated) {
3258 MonoGenericInst *inst = mono_method_get_context (method)->method_inst;
3260 if (inst) {
3261 int count = inst->type_argc;
3262 MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.systemtype_class, count, error);
3263 return_val_if_nok (error, NULL_HANDLE_ARRAY);
3265 for (int i = 0; i < count; i++) {
3266 if (!set_array_generic_argument_handle_inflated (domain, inst, i, res, error))
3267 break;
3269 return_val_if_nok (error, NULL_HANDLE_ARRAY);
3270 return res;
3274 int count = mono_method_signature_internal (method)->generic_param_count;
3275 MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.systemtype_class, count, error);
3276 return_val_if_nok (error, NULL_HANDLE_ARRAY);
3278 MonoGenericContainer *container = mono_method_get_generic_container (method);
3279 for (int i = 0; i < count; i++) {
3280 if (!set_array_generic_argument_handle_gparam (domain, container, i, res, error))
3281 break;
3283 return_val_if_nok (error, NULL_HANDLE_ARRAY);
3284 return res;
3287 MonoObject *
3288 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3290 ERROR_DECL (error);
3292 * Invoke from reflection is supposed to always be a virtual call (the API
3293 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3294 * greater flexibility.
3296 MonoMethod *m = method->method;
3297 MonoMethodSignature *sig = mono_method_signature_internal (m);
3298 MonoImage *image;
3299 int pcount;
3300 void *obj = this_arg;
3302 *exc = NULL;
3304 if (mono_security_core_clr_enabled () &&
3305 !mono_security_core_clr_ensure_reflection_access_method (m, error)) {
3306 mono_error_set_pending_exception (error);
3307 return NULL;
3310 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3311 if (!mono_class_vtable_checked (mono_object_domain (method), m->klass, error)) {
3312 mono_error_cleanup (error); /* FIXME does this make sense? */
3313 mono_gc_wbarrier_generic_store_internal (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3314 return NULL;
3317 if (this_arg) {
3318 if (!mono_object_isinst_checked (this_arg, m->klass, error)) {
3319 if (!is_ok (error)) {
3320 mono_gc_wbarrier_generic_store_internal (exc, (MonoObject*) mono_error_convert_to_exception (error));
3321 return NULL;
3323 char *this_name = mono_type_get_full_name (mono_object_class (this_arg));
3324 char *target_name = mono_type_get_full_name (m->klass);
3325 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3326 mono_gc_wbarrier_generic_store_internal (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3327 g_free (msg);
3328 g_free (target_name);
3329 g_free (this_name);
3330 return NULL;
3332 m = mono_object_get_virtual_method_internal (this_arg, m);
3333 /* must pass the pointer to the value for valuetype methods */
3334 if (m_class_is_valuetype (m->klass))
3335 obj = mono_object_unbox_internal (this_arg);
3336 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3337 mono_gc_wbarrier_generic_store_internal (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3338 return NULL;
3342 if (sig->ret->byref) {
3343 mono_gc_wbarrier_generic_store_internal (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
3344 return NULL;
3347 pcount = params? mono_array_length_internal (params): 0;
3348 if (pcount != sig->param_count) {
3349 mono_gc_wbarrier_generic_store_internal (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3350 return NULL;
3353 if (mono_class_is_abstract (m->klass) && !strcmp (m->name, ".ctor") && !this_arg) {
3354 mono_gc_wbarrier_generic_store_internal (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
3355 return NULL;
3358 image = m_class_get_image (m->klass);
3359 if (mono_asmctx_get_kind (&image->assembly->context) == MONO_ASMCTX_REFONLY) {
3360 mono_gc_wbarrier_generic_store_internal (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
3361 return NULL;
3364 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3365 mono_gc_wbarrier_generic_store_internal (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3366 return NULL;
3369 if (m_class_get_rank (m->klass) && !strcmp (m->name, ".ctor")) {
3370 MonoArray *arr;
3371 int i;
3372 uintptr_t *lengths;
3373 intptr_t *lower_bounds;
3374 pcount = mono_array_length_internal (params);
3375 lengths = g_newa (uintptr_t, pcount);
3376 /* Note: the synthetized array .ctors have int32 as argument type */
3377 for (i = 0; i < pcount; ++i)
3378 lengths [i] = *(int32_t*) ((char*)mono_array_get_internal (params, gpointer, i) + sizeof (MonoObject));
3380 if (m_class_get_rank (m->klass) == 1 && sig->param_count == 2 && m_class_get_rank (m_class_get_element_class (m->klass))) {
3381 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3382 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, error);
3383 if (!is_ok (error)) {
3384 mono_error_set_pending_exception (error);
3385 return NULL;
3388 for (i = 0; i < mono_array_length_internal (arr); ++i) {
3389 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m_class_get_element_class (m->klass), &lengths [1], NULL, error);
3390 if (!is_ok (error)) {
3391 mono_error_set_pending_exception (error);
3392 return NULL;
3394 mono_array_setref_fast (arr, i, subarray);
3396 return (MonoObject*)arr;
3399 if (m_class_get_rank (m->klass) == pcount) {
3400 /* Only lengths provided. */
3401 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, error);
3402 if (!is_ok (error)) {
3403 mono_error_set_pending_exception (error);
3404 return NULL;
3407 return (MonoObject*)arr;
3408 } else {
3409 g_assert (pcount == (m_class_get_rank (m->klass) * 2));
3410 /* The arguments are lower-bound-length pairs */
3411 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3413 for (i = 0; i < pcount / 2; ++i) {
3414 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get_internal (params, gpointer, (i * 2)) + sizeof (MonoObject));
3415 lengths [i] = *(int32_t*) ((char*)mono_array_get_internal (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3418 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, error);
3419 if (!is_ok (error)) {
3420 mono_error_set_pending_exception (error);
3421 return NULL;
3424 return (MonoObject*)arr;
3427 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, error);
3428 mono_error_set_pending_exception (error);
3429 return result;
3432 #ifndef DISABLE_REMOTING
3433 static void
3434 internal_execute_field_getter (MonoDomain *domain, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs, MonoError *error)
3436 error_init (error);
3437 MonoArray *out_args;
3438 MonoClass *k = mono_object_class (this_arg);
3439 MonoString *name;
3440 char *str;
3442 /* If this is a proxy, then it must be a CBO */
3443 if (mono_class_is_transparent_proxy (k)) {
3444 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3445 this_arg = tp->rp->unwrapped_server;
3446 g_assert (this_arg);
3447 k = mono_object_class (this_arg);
3450 name = mono_array_get_internal (params, MonoString *, 1);
3451 str = mono_string_to_utf8_checked_internal (name, error);
3452 return_if_nok (error);
3454 do {
3455 MonoClassField* field = mono_class_get_field_from_name_full (k, str, NULL);
3456 if (field) {
3457 g_free (str);
3458 MonoClass *field_klass = mono_class_from_mono_type_internal (field->type);
3459 MonoObject *result;
3460 if (m_class_is_valuetype (field_klass)) {
3461 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, error);
3462 return_if_nok (error);
3463 } else
3464 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3466 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, error);
3467 return_if_nok (error);
3468 mono_gc_wbarrier_generic_store_internal (outArgs, (MonoObject*) out_args);
3469 mono_array_setref_internal (out_args, 0, result);
3470 return;
3472 k = m_class_get_parent (k);
3473 } while (k);
3475 g_free (str);
3476 g_assert_not_reached ();
3479 static void
3480 internal_execute_field_setter (MonoDomain *domain, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs, MonoError *error)
3482 error_init (error);
3483 MonoArray *out_args;
3484 MonoClass *k = mono_object_class (this_arg);
3485 MonoString *name;
3486 guint32 size;
3487 gint32 align;
3488 char *str;
3490 /* If this is a proxy, then it must be a CBO */
3491 if (mono_class_is_transparent_proxy (k)) {
3492 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3493 this_arg = tp->rp->unwrapped_server;
3494 g_assert (this_arg);
3495 k = mono_object_class (this_arg);
3498 name = mono_array_get_internal (params, MonoString *, 1);
3499 str = mono_string_to_utf8_checked_internal (name, error);
3500 return_if_nok (error);
3502 do {
3503 MonoClassField* field = mono_class_get_field_from_name_full (k, str, NULL);
3504 if (field) {
3505 g_free (str);
3506 MonoClass *field_klass = mono_class_from_mono_type_internal (field->type);
3507 MonoObject *val = (MonoObject *)mono_array_get_internal (params, gpointer, 2);
3509 if (m_class_is_valuetype (field_klass)) {
3510 size = mono_type_size (field->type, &align);
3511 g_assert (size == mono_class_value_size (field_klass, NULL));
3512 mono_gc_wbarrier_value_copy_internal ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3513 } else {
3514 mono_gc_wbarrier_set_field_internal (this_arg, (char*)this_arg + field->offset, val);
3517 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, error);
3518 return_if_nok (error);
3519 mono_gc_wbarrier_generic_store_internal (outArgs, (MonoObject*) out_args);
3520 return;
3523 k = m_class_get_parent (k);
3524 } while (k);
3526 g_free (str);
3527 g_assert_not_reached ();
3530 MonoObject *
3531 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3533 ERROR_DECL (error);
3534 MonoDomain *domain = mono_object_domain (method);
3535 MonoMethod *m = method->method;
3536 MonoMethodSignature *sig = mono_method_signature_internal (m);
3537 MonoArray *out_args;
3538 MonoObject *result;
3539 int i, j, outarg_count = 0;
3541 if (m->klass == mono_defaults.object_class) {
3542 if (!strcmp (m->name, "FieldGetter")) {
3543 internal_execute_field_getter (domain, this_arg, params, outArgs, error);
3544 mono_error_set_pending_exception (error);
3545 return NULL;
3546 } else if (!strcmp (m->name, "FieldSetter")) {
3547 internal_execute_field_setter (domain, this_arg, params, outArgs, error);
3548 mono_error_set_pending_exception (error);
3549 return NULL;
3553 for (i = 0; i < mono_array_length_internal (params); i++) {
3554 if (sig->params [i]->byref)
3555 outarg_count++;
3558 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, error);
3559 if (mono_error_set_pending_exception (error))
3560 return NULL;
3562 /* handle constructors only for objects already allocated */
3563 if (!strcmp (method->method->name, ".ctor"))
3564 g_assert (this_arg);
3566 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3567 g_assert (!m_class_is_valuetype (method->method->klass));
3568 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, error);
3569 if (mono_error_set_pending_exception (error))
3570 return NULL;
3572 for (i = 0, j = 0; i < mono_array_length_internal (params); i++) {
3573 if (sig->params [i]->byref) {
3574 gpointer arg;
3575 arg = mono_array_get_internal (params, gpointer, i);
3576 mono_array_setref_internal (out_args, j, arg);
3577 j++;
3581 mono_gc_wbarrier_generic_store_internal (outArgs, (MonoObject*) out_args);
3583 return result;
3585 #endif
3587 static guint64
3588 read_enum_value (const char *mem, int type)
3590 switch (type) {
3591 case MONO_TYPE_BOOLEAN:
3592 case MONO_TYPE_U1:
3593 return *(guint8*)mem;
3594 case MONO_TYPE_I1:
3595 return *(gint8*)mem;
3596 case MONO_TYPE_CHAR:
3597 case MONO_TYPE_U2:
3598 return read16 (mem);
3599 case MONO_TYPE_I2:
3600 return (gint16) read16 (mem);
3601 case MONO_TYPE_U4:
3602 return read32 (mem);
3603 case MONO_TYPE_I4:
3604 return (gint32) read32 (mem);
3605 case MONO_TYPE_U8:
3606 case MONO_TYPE_I8:
3607 return read64 (mem);
3608 default:
3609 g_assert_not_reached ();
3611 return 0;
3614 static void
3615 write_enum_value (void *mem, int type, guint64 value)
3617 switch (type) {
3618 case MONO_TYPE_U1:
3619 case MONO_TYPE_I1: {
3620 guint8 *p = (guint8*)mem;
3621 *p = value;
3622 break;
3624 case MONO_TYPE_U2:
3625 case MONO_TYPE_I2:
3626 case MONO_TYPE_CHAR: {
3627 guint16 *p = (guint16 *)mem;
3628 *p = value;
3629 break;
3631 case MONO_TYPE_U4:
3632 case MONO_TYPE_I4: {
3633 guint32 *p = (guint32 *)mem;
3634 *p = value;
3635 break;
3637 case MONO_TYPE_U8:
3638 case MONO_TYPE_I8: {
3639 guint64 *p = (guint64 *)mem;
3640 *p = value;
3641 break;
3643 default:
3644 g_assert_not_reached ();
3646 return;
3649 MonoObjectHandle
3650 ves_icall_System_Enum_ToObject (MonoReflectionTypeHandle enumType, guint64 value, MonoError *error)
3652 MonoDomain *domain;
3653 MonoClass *enumc;
3654 MonoObjectHandle resultHandle;
3655 MonoType *etype;
3657 domain = MONO_HANDLE_DOMAIN (enumType);
3658 enumc = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (enumType, type));
3660 mono_class_init_checked (enumc, error);
3661 goto_if_nok (error, return_null);
3663 etype = mono_class_enum_basetype_internal (enumc);
3665 resultHandle = mono_object_new_handle (domain, enumc, error);
3666 goto_if_nok (error, return_null);
3668 write_enum_value (mono_handle_unbox_unsafe (resultHandle), etype->type, value);
3670 return resultHandle;
3672 return_null:
3673 return MONO_HANDLE_NEW (MonoObject, NULL);
3676 MonoBoolean
3677 ves_icall_System_Enum_InternalHasFlag (MonoObjectHandle a, MonoObjectHandle b, MonoError *error)
3679 int size = mono_class_value_size (mono_handle_class (a), NULL);
3680 guint64 a_val = 0, b_val = 0;
3682 memcpy (&a_val, mono_handle_unbox_unsafe (a), size);
3683 memcpy (&b_val, mono_handle_unbox_unsafe (b), size);
3685 return (a_val & b_val) == b_val;
3688 MonoObjectHandle
3689 ves_icall_System_Enum_get_value (MonoObjectHandle ehandle, MonoError *error)
3691 MonoObjectHandle resultHandle;
3692 MonoClass *enumc;
3693 int size;
3695 goto_if (MONO_HANDLE_IS_NULL (ehandle), return_null);
3697 g_assert (m_class_is_enumtype (mono_handle_class (ehandle)));
3699 enumc = mono_class_from_mono_type_internal (mono_class_enum_basetype_internal (mono_handle_class (ehandle)));
3701 resultHandle = mono_object_new_handle (MONO_HANDLE_DOMAIN (ehandle), enumc, error);
3702 goto_if_nok (error, return_null);
3703 size = mono_class_value_size (enumc, NULL);
3705 memcpy (mono_handle_unbox_unsafe (resultHandle), mono_handle_unbox_unsafe (ehandle), size);
3707 return resultHandle;
3708 return_null:
3709 return MONO_HANDLE_NEW (MonoObject, NULL);
3712 MonoReflectionTypeHandle
3713 ves_icall_System_Enum_get_underlying_type (MonoReflectionTypeHandle type, MonoError *error)
3715 MonoType *etype;
3716 MonoClass *klass;
3718 klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type));
3719 mono_class_init_checked (klass, error);
3720 goto_if_nok (error, return_null);
3722 etype = mono_class_enum_basetype_internal (klass);
3723 if (!etype) {
3724 mono_error_set_argument (error, "enumType", "Type provided must be an Enum.");
3725 goto return_null;
3728 return mono_type_get_object_handle (MONO_HANDLE_DOMAIN (type), etype, error);
3730 return_null:
3731 return MONO_HANDLE_NEW (MonoReflectionType, NULL);
3735 ves_icall_System_Enum_compare_value_to (MonoObjectHandle enumHandle, MonoObjectHandle otherHandle, MonoError *error)
3737 if (MONO_HANDLE_IS_NULL (otherHandle))
3738 return 1;
3740 if (MONO_HANDLE_GETVAL (enumHandle, vtable)->klass != MONO_HANDLE_GETVAL (otherHandle, vtable)->klass)
3741 return 2;
3743 gpointer tdata = mono_handle_unbox_unsafe (enumHandle);
3744 gpointer odata = mono_handle_unbox_unsafe (otherHandle);
3745 MonoType *basetype = mono_class_enum_basetype_internal (MONO_HANDLE_GETVAL (enumHandle, vtable)->klass);
3746 g_assert (basetype);
3748 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3749 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3750 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3751 if (me == other) \
3752 return 0; \
3753 return me > other ? 1 : -1; \
3754 } while (0)
3756 switch (basetype->type) {
3757 case MONO_TYPE_U1:
3758 COMPARE_ENUM_VALUES (guint8);
3759 case MONO_TYPE_I1:
3760 COMPARE_ENUM_VALUES (gint8);
3761 case MONO_TYPE_CHAR:
3762 case MONO_TYPE_U2:
3763 COMPARE_ENUM_VALUES (guint16);
3764 case MONO_TYPE_I2:
3765 COMPARE_ENUM_VALUES (gint16);
3766 case MONO_TYPE_U4:
3767 COMPARE_ENUM_VALUES (guint32);
3768 case MONO_TYPE_I4:
3769 COMPARE_ENUM_VALUES (gint32);
3770 case MONO_TYPE_U8:
3771 COMPARE_ENUM_VALUES (guint64);
3772 case MONO_TYPE_I8:
3773 COMPARE_ENUM_VALUES (gint64);
3775 #undef COMPARE_ENUM_VALUES
3776 /* indicates that the enum was of an unsupported underlying type */
3777 return 3;
3781 ves_icall_System_Enum_get_hashcode (MonoObjectHandle enumHandle, MonoError *error)
3783 gpointer data = mono_handle_unbox_unsafe (enumHandle);
3784 MonoType *basetype = mono_class_enum_basetype_internal (MONO_HANDLE_GETVAL (enumHandle, vtable)->klass);
3785 g_assert (basetype);
3787 switch (basetype->type) {
3788 case MONO_TYPE_I1: {
3789 gint8 value = *((gint8*)data);
3790 return ((int)value ^ (int)value << 8);
3792 case MONO_TYPE_U1:
3793 return *((guint8*)data);
3794 case MONO_TYPE_CHAR:
3795 case MONO_TYPE_U2:
3796 return *((guint16*)data);
3798 case MONO_TYPE_I2: {
3799 gint16 value = *((gint16*)data);
3800 return ((int)(guint16)value | (((int)value) << 16));
3802 case MONO_TYPE_U4:
3803 return *((guint32*)data);
3804 case MONO_TYPE_I4:
3805 return *((gint32*)data);
3806 case MONO_TYPE_U8:
3807 case MONO_TYPE_I8: {
3808 gint64 value = *((gint64*)data);
3809 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3811 default:
3812 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3814 return 0;
3817 static void
3818 get_enum_field (MonoDomain *domain, MonoArrayHandle names, MonoArrayHandle values, int base_type, MonoClassField *field, guint* j, guint64 *previous_value, gboolean *sorted, MonoError *error)
3820 error_init (error);
3821 HANDLE_FUNCTION_ENTER();
3822 guint64 field_value;
3823 const char *p;
3824 MonoTypeEnum def_type;
3826 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3827 goto leave;
3828 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3829 goto leave;
3830 if (mono_field_is_deleted (field))
3831 goto leave;
3832 MonoStringHandle name;
3833 name = mono_string_new_handle (domain, mono_field_get_name (field), error);
3834 goto_if_nok (error, leave);
3835 MONO_HANDLE_ARRAY_SETREF (names, *j, name);
3837 p = mono_class_get_field_default_value (field, &def_type);
3838 /* len = */ mono_metadata_decode_blob_size (p, &p);
3840 field_value = read_enum_value (p, base_type);
3841 MONO_HANDLE_ARRAY_SETVAL (values, guint64, *j, field_value);
3843 if (*previous_value > field_value)
3844 *sorted = FALSE;
3846 *previous_value = field_value;
3847 (*j)++;
3848 leave:
3849 HANDLE_FUNCTION_RETURN();
3852 MonoBoolean
3853 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionTypeHandle type, MonoArrayHandleOut values, MonoArrayHandleOut names, MonoError *error)
3855 MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
3856 MonoClass *enumc = mono_class_from_mono_type_internal (MONO_HANDLE_RAW(type)->type);
3857 guint j = 0, nvalues;
3858 gpointer iter;
3859 MonoClassField *field;
3860 int base_type;
3861 guint64 previous_value = 0;
3862 gboolean sorted = TRUE;
3864 error_init (error);
3865 mono_class_init_checked (enumc, error);
3866 return_val_if_nok (error, FALSE);
3868 if (!m_class_is_enumtype (enumc)) {
3869 mono_error_set_argument (error, "enumType", "Type provided must be an Enum.");
3870 return TRUE;
3873 base_type = mono_class_enum_basetype_internal (enumc)->type;
3875 nvalues = mono_class_num_fields (enumc) > 0 ? mono_class_num_fields (enumc) - 1 : 0;
3876 MONO_HANDLE_ASSIGN(names, mono_array_new_handle (domain, mono_defaults.string_class, nvalues, error));
3877 return_val_if_nok (error, FALSE);
3878 MONO_HANDLE_ASSIGN(values, mono_array_new_handle (domain, mono_defaults.uint64_class, nvalues, error));
3879 return_val_if_nok (error, FALSE);
3881 iter = NULL;
3882 while ((field = mono_class_get_fields_internal (enumc, &iter))) {
3883 get_enum_field(domain, names, values, base_type, field, &j, &previous_value, &sorted, error);
3884 if (!is_ok (error))
3885 break;
3887 return_val_if_nok (error, FALSE);
3889 return sorted;
3892 enum {
3893 BFLAGS_IgnoreCase = 1,
3894 BFLAGS_DeclaredOnly = 2,
3895 BFLAGS_Instance = 4,
3896 BFLAGS_Static = 8,
3897 BFLAGS_Public = 0x10,
3898 BFLAGS_NonPublic = 0x20,
3899 BFLAGS_FlattenHierarchy = 0x40,
3900 BFLAGS_InvokeMethod = 0x100,
3901 BFLAGS_CreateInstance = 0x200,
3902 BFLAGS_GetField = 0x400,
3903 BFLAGS_SetField = 0x800,
3904 BFLAGS_GetProperty = 0x1000,
3905 BFLAGS_SetProperty = 0x2000,
3906 BFLAGS_ExactBinding = 0x10000,
3907 BFLAGS_SuppressChangeType = 0x20000,
3908 BFLAGS_OptionalParamBinding = 0x40000
3911 enum {
3912 MLISTTYPE_All = 0,
3913 MLISTTYPE_CaseSensitive = 1,
3914 MLISTTYPE_CaseInsensitive = 2,
3915 MLISTTYPE_HandleToInfo = 3
3918 GPtrArray*
3919 ves_icall_RuntimeType_GetFields_native (MonoReflectionTypeHandle ref_type, char *utf8_name, guint32 bflags, guint32 mlisttype, MonoError *error)
3921 error_init (error);
3922 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
3924 if (type->byref) {
3925 return g_ptr_array_new ();
3928 int (*compare_func) (const char *s1, const char *s2) = NULL;
3929 compare_func = ((bflags & BFLAGS_IgnoreCase) || (mlisttype == MLISTTYPE_CaseInsensitive)) ? mono_utf8_strcasecmp : strcmp;
3931 MonoClass *startklass, *klass;
3932 klass = startklass = mono_class_from_mono_type_internal (type);
3934 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3936 handle_parent:
3937 if (mono_class_has_failure (klass)) {
3938 mono_error_set_for_class_failure (error, klass);
3939 goto fail;
3942 MonoClassField *field;
3943 gpointer iter;
3944 iter = NULL;
3945 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3946 guint32 flags = mono_field_get_flags (field);
3947 int match = 0;
3948 if (mono_field_is_deleted_with_flags (field, flags))
3949 continue;
3950 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3951 if (bflags & BFLAGS_Public)
3952 match++;
3953 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3954 if (bflags & BFLAGS_NonPublic) {
3955 match++;
3958 if (!match)
3959 continue;
3960 match = 0;
3961 if (flags & FIELD_ATTRIBUTE_STATIC) {
3962 if (bflags & BFLAGS_Static)
3963 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3964 match++;
3965 } else {
3966 if (bflags & BFLAGS_Instance)
3967 match++;
3970 if (!match)
3971 continue;
3973 if (((mlisttype != MLISTTYPE_All) && (utf8_name != NULL)) && compare_func (mono_field_get_name (field), utf8_name))
3974 continue;
3976 g_ptr_array_add (ptr_array, field);
3978 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = m_class_get_parent (klass)))
3979 goto handle_parent;
3981 return ptr_array;
3983 fail:
3984 g_ptr_array_free (ptr_array, TRUE);
3985 return NULL;
3988 static gboolean
3989 method_nonpublic (MonoMethod* method, gboolean start_klass)
3991 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3992 case METHOD_ATTRIBUTE_ASSEM:
3993 return (start_klass || mono_defaults.generic_ilist_class);
3994 case METHOD_ATTRIBUTE_PRIVATE:
3995 return start_klass;
3996 case METHOD_ATTRIBUTE_PUBLIC:
3997 return FALSE;
3998 default:
3999 return TRUE;
4003 GPtrArray*
4004 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, guint32 mlisttype, gboolean allow_ctors, MonoError *error)
4006 GPtrArray *array;
4007 MonoClass *startklass;
4008 MonoMethod *method;
4009 gpointer iter;
4010 int match, nslots;
4011 /*FIXME, use MonoBitSet*/
4012 guint32 method_slots_default [8];
4013 guint32 *method_slots = NULL;
4014 int (*compare_func) (const char *s1, const char *s2) = NULL;
4016 array = g_ptr_array_new ();
4017 startklass = klass;
4018 error_init (error);
4020 compare_func = ((bflags & BFLAGS_IgnoreCase) || (mlisttype == MLISTTYPE_CaseInsensitive)) ? mono_utf8_strcasecmp : strcmp;
4022 /* An optimization for calls made from Delegate:CreateDelegate () */
4023 if (m_class_is_delegate (klass) && klass != mono_defaults.delegate_class && klass != mono_defaults.multicastdelegate_class && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
4024 method = mono_get_delegate_invoke_internal (klass);
4025 g_assert (method);
4027 g_ptr_array_add (array, method);
4028 return array;
4031 mono_class_setup_methods (klass);
4032 mono_class_setup_vtable (klass);
4033 if (mono_class_has_failure (klass))
4034 goto loader_error;
4036 if (is_generic_parameter (m_class_get_byval_arg (klass)))
4037 nslots = mono_class_get_vtable_size (m_class_get_parent (klass));
4038 else
4039 nslots = MONO_CLASS_IS_INTERFACE_INTERNAL (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
4040 if (nslots >= sizeof (method_slots_default) * 8) {
4041 method_slots = g_new0 (guint32, nslots / 32 + 1);
4042 } else {
4043 method_slots = method_slots_default;
4044 memset (method_slots, 0, sizeof (method_slots_default));
4046 handle_parent:
4047 mono_class_setup_methods (klass);
4048 mono_class_setup_vtable (klass);
4049 if (mono_class_has_failure (klass))
4050 goto loader_error;
4052 iter = NULL;
4053 while ((method = mono_class_get_methods (klass, &iter))) {
4054 match = 0;
4055 if (method->slot != -1) {
4056 g_assert (method->slot < nslots);
4057 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
4058 continue;
4059 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
4060 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
4063 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
4064 continue;
4065 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4066 if (bflags & BFLAGS_Public)
4067 match++;
4068 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
4069 match++;
4071 if (!match)
4072 continue;
4073 match = 0;
4074 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4075 if (bflags & BFLAGS_Static)
4076 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4077 match++;
4078 } else {
4079 if (bflags & BFLAGS_Instance)
4080 match++;
4083 if (!match)
4084 continue;
4086 if ((mlisttype != MLISTTYPE_All) && (name != NULL)) {
4087 if (compare_func (name, method->name))
4088 continue;
4091 match = 0;
4092 g_ptr_array_add (array, method);
4094 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = m_class_get_parent (klass)))
4095 goto handle_parent;
4096 if (method_slots != method_slots_default)
4097 g_free (method_slots);
4099 return array;
4101 loader_error:
4102 if (method_slots != method_slots_default)
4103 g_free (method_slots);
4104 g_ptr_array_free (array, TRUE);
4106 g_assert (mono_class_has_failure (klass));
4107 mono_error_set_for_class_failure (error, klass);
4108 return NULL;
4111 GPtrArray*
4112 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionTypeHandle ref_type, const char *mname, guint32 bflags, guint32 mlisttype, MonoError *error)
4114 error_init (error);
4115 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
4117 MonoClass *klass = mono_class_from_mono_type_internal (type);
4118 if (type->byref) {
4119 return g_ptr_array_new ();
4122 return mono_class_get_methods_by_name (klass, mname, bflags, mlisttype, FALSE, error);
4125 GPtrArray*
4126 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionTypeHandle ref_type, guint32 bflags, MonoError *error)
4128 error_init (error);
4129 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
4130 if (type->byref) {
4131 return g_ptr_array_new ();
4134 MonoClass *startklass, *klass;
4135 klass = startklass = mono_class_from_mono_type_internal (type);
4137 mono_class_setup_methods (klass);
4138 if (mono_class_has_failure (klass)) {
4139 mono_error_set_for_class_failure (error, klass);
4140 return NULL;
4144 GPtrArray *res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
4146 MonoMethod *method;
4147 gpointer iter = NULL;
4148 while ((method = mono_class_get_methods (klass, &iter))) {
4149 int match = 0;
4150 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4151 continue;
4152 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4153 if (bflags & BFLAGS_Public)
4154 match++;
4155 } else {
4156 if (bflags & BFLAGS_NonPublic)
4157 match++;
4159 if (!match)
4160 continue;
4161 match = 0;
4162 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4163 if (bflags & BFLAGS_Static)
4164 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4165 match++;
4166 } else {
4167 if (bflags & BFLAGS_Instance)
4168 match++;
4171 if (!match)
4172 continue;
4173 g_ptr_array_add (res_array, method);
4176 return res_array;
4179 static guint
4180 property_hash (gconstpointer data)
4182 MonoProperty *prop = (MonoProperty*)data;
4184 return g_str_hash (prop->name);
4187 static gboolean
4188 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4190 if (method1->slot != -1 && method1->slot == method2->slot)
4191 return TRUE;
4193 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4194 if (method1->is_inflated)
4195 method1 = ((MonoMethodInflated*) method1)->declaring;
4196 if (method2->is_inflated)
4197 method2 = ((MonoMethodInflated*) method2)->declaring;
4200 return mono_metadata_signature_equal (mono_method_signature_internal (method1), mono_method_signature_internal (method2));
4203 static gboolean
4204 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4206 // Properties are hide-by-name-and-signature
4207 if (!g_str_equal (prop1->name, prop2->name))
4208 return FALSE;
4210 /* If we see a property in a generic method, we want to
4211 compare the generic signatures, not the inflated signatures
4212 because we might conflate two properties that were
4213 distinct:
4215 class Foo<T,U> {
4216 public T this[T t] { getter { return t; } } // method 1
4217 public U this[U u] { getter { return u; } } // method 2
4220 If we see int Foo<int,int>::Item[int] we need to know if
4221 the indexer came from method 1 or from method 2, and we
4222 shouldn't conflate them. (Bugzilla 36283)
4224 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4225 return FALSE;
4227 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4228 return FALSE;
4230 return TRUE;
4233 static gboolean
4234 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4236 if (!accessor)
4237 return FALSE;
4239 return method_nonpublic (accessor, start_klass);
4242 GPtrArray*
4243 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionTypeHandle ref_type, gchar *propname, guint32 bflags, guint32 mlisttype, MonoError *error)
4245 error_init (error);
4246 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
4249 if (type->byref) {
4250 return g_ptr_array_new ();
4254 MonoClass *startklass, *klass;
4255 klass = startklass = mono_class_from_mono_type_internal (type);
4257 int (*compare_func) (const char *s1, const char *s2) = (mlisttype == MLISTTYPE_CaseInsensitive) ? mono_utf8_strcasecmp : strcmp;
4259 GPtrArray *res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4261 GHashTable *properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4263 handle_parent:
4264 mono_class_setup_methods (klass);
4265 mono_class_setup_vtable (klass);
4266 if (mono_class_has_failure (klass)) {
4267 mono_error_set_for_class_failure (error, klass);
4268 goto loader_error;
4271 MonoProperty *prop;
4272 gpointer iter;
4273 iter = NULL;
4274 while ((prop = mono_class_get_properties (klass, &iter))) {
4275 int match = 0;
4276 MonoMethod *method = prop->get;
4277 if (!method)
4278 method = prop->set;
4279 guint32 flags = 0;
4280 if (method)
4281 flags = method->flags;
4282 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4283 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4284 if (bflags & BFLAGS_Public)
4285 match++;
4286 } else if (bflags & BFLAGS_NonPublic) {
4287 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4288 property_accessor_nonpublic(prop->set, startklass == klass)) {
4289 match++;
4292 if (!match)
4293 continue;
4294 match = 0;
4295 if (flags & METHOD_ATTRIBUTE_STATIC) {
4296 if (bflags & BFLAGS_Static)
4297 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4298 match++;
4299 } else {
4300 if (bflags & BFLAGS_Instance)
4301 match++;
4304 if (!match)
4305 continue;
4306 match = 0;
4308 if ((mlisttype != MLISTTYPE_All) && (propname != NULL) && compare_func (propname, prop->name))
4309 continue;
4311 if (g_hash_table_lookup (properties, prop))
4312 continue;
4314 g_ptr_array_add (res_array, prop);
4316 g_hash_table_insert (properties, prop, prop);
4318 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = m_class_get_parent (klass)))
4319 goto handle_parent;
4321 g_hash_table_destroy (properties);
4323 return res_array;
4326 loader_error:
4327 if (properties)
4328 g_hash_table_destroy (properties);
4329 g_ptr_array_free (res_array, TRUE);
4331 return NULL;
4334 static guint
4335 event_hash (gconstpointer data)
4337 MonoEvent *event = (MonoEvent*)data;
4339 return g_str_hash (event->name);
4342 static gboolean
4343 event_equal (MonoEvent *event1, MonoEvent *event2)
4345 // Events are hide-by-name
4346 return g_str_equal (event1->name, event2->name);
4349 GPtrArray*
4350 ves_icall_RuntimeType_GetEvents_native (MonoReflectionTypeHandle ref_type, char *utf8_name, guint32 bflags, guint32 mlisttype, MonoError *error)
4352 error_init (error);
4353 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
4355 if (type->byref) {
4356 return g_ptr_array_new ();
4359 int (*compare_func) (const char *s1, const char *s2) = ((bflags & BFLAGS_IgnoreCase) || (mlisttype == MLISTTYPE_CaseInsensitive)) ? mono_utf8_strcasecmp : strcmp;
4361 GPtrArray *res_array = g_ptr_array_sized_new (4);
4363 MonoClass *startklass, *klass;
4364 klass = startklass = mono_class_from_mono_type_internal (type);
4366 GHashTable *events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4367 handle_parent:
4368 mono_class_setup_methods (klass);
4369 mono_class_setup_vtable (klass);
4370 if (mono_class_has_failure (klass)) {
4371 mono_error_set_for_class_failure (error, klass);
4372 goto failure;
4375 MonoEvent *event;
4376 gpointer iter;
4377 iter = NULL;
4378 while ((event = mono_class_get_events (klass, &iter))) {
4379 int match = 0;
4380 MonoMethod *method = event->add;
4381 if (!method)
4382 method = event->remove;
4383 if (!method)
4384 method = event->raise;
4385 if (method) {
4386 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4387 if (bflags & BFLAGS_Public)
4388 match++;
4389 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4390 if (bflags & BFLAGS_NonPublic)
4391 match++;
4394 else
4395 if (bflags & BFLAGS_NonPublic)
4396 match ++;
4397 if (!match)
4398 continue;
4399 match = 0;
4400 if (method) {
4401 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4402 if (bflags & BFLAGS_Static)
4403 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4404 match++;
4405 } else {
4406 if (bflags & BFLAGS_Instance)
4407 match++;
4410 else
4411 if (bflags & BFLAGS_Instance)
4412 match ++;
4413 if (!match)
4414 continue;
4416 if ((mlisttype != MLISTTYPE_All) && (utf8_name != NULL) && compare_func (event->name, utf8_name))
4417 continue;
4419 if (g_hash_table_lookup (events, event))
4420 continue;
4422 g_ptr_array_add (res_array, event);
4424 g_hash_table_insert (events, event, event);
4426 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = m_class_get_parent (klass)))
4427 goto handle_parent;
4429 g_hash_table_destroy (events);
4431 return res_array;
4433 failure:
4434 if (events != NULL)
4435 g_hash_table_destroy (events);
4437 g_ptr_array_free (res_array, TRUE);
4439 return NULL;
4442 GPtrArray *
4443 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionTypeHandle ref_type, char *str, guint32 bflags, guint32 mlisttype, MonoError *error)
4445 error_init (error);
4446 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
4448 if (type->byref) {
4449 return g_ptr_array_new ();
4452 int (*compare_func) (const char *s1, const char *s2) = ((bflags & BFLAGS_IgnoreCase) || (mlisttype == MLISTTYPE_CaseInsensitive)) ? mono_utf8_strcasecmp : strcmp;
4454 MonoClass *klass = mono_class_from_mono_type_internal (type);
4457 * If a nested type is generic, return its generic type definition.
4458 * Note that this means that the return value is essentially the set
4459 * of nested types of the generic type definition of @klass.
4461 * A note in MSDN claims that a generic type definition can have
4462 * nested types that aren't generic. In any case, the container of that
4463 * nested type would be the generic type definition.
4465 if (mono_class_is_ginst (klass))
4466 klass = mono_class_get_generic_class (klass)->container_class;
4468 GPtrArray *res_array = g_ptr_array_new ();
4470 MonoClass *nested;
4471 gpointer iter = NULL;
4472 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4473 int match = 0;
4474 if ((mono_class_get_flags (nested) & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4475 if (bflags & BFLAGS_Public)
4476 match++;
4477 } else {
4478 if (bflags & BFLAGS_NonPublic)
4479 match++;
4481 if (!match)
4482 continue;
4484 if ((mlisttype != MLISTTYPE_All) && (str != NULL) && compare_func (m_class_get_name (nested), str))
4485 continue;
4487 g_ptr_array_add (res_array, m_class_get_byval_arg (nested));
4490 return res_array;
4493 static MonoType*
4494 get_type_from_module_builder_module (MonoArrayHandle modules, int i, MonoTypeNameParse *info, MonoBoolean ignoreCase, gboolean *type_resolve, MonoError *error)
4496 HANDLE_FUNCTION_ENTER ();
4497 error_init (error);
4498 MonoType *type = NULL;
4499 MonoReflectionModuleBuilderHandle mb = MONO_HANDLE_NEW (MonoReflectionModuleBuilder, NULL);
4500 MONO_HANDLE_ARRAY_GETREF (mb, modules, i);
4501 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
4502 type = mono_reflection_get_type_checked (&dynamic_image->image, &dynamic_image->image, info, ignoreCase, type_resolve, error);
4503 HANDLE_FUNCTION_RETURN_VAL (type);
4506 static MonoType*
4507 get_type_from_module_builder_loaded_modules (MonoArrayHandle loaded_modules, int i, MonoTypeNameParse *info, MonoBoolean ignoreCase, gboolean *type_resolve, MonoError *error)
4509 HANDLE_FUNCTION_ENTER ();
4510 error_init (error);
4511 MonoType *type = NULL;
4512 MonoReflectionModuleHandle mod = MONO_HANDLE_NEW (MonoReflectionModule, NULL);
4513 MONO_HANDLE_ARRAY_GETREF (mod, loaded_modules, i);
4514 MonoImage *image = MONO_HANDLE_GETVAL (mod, image);
4515 type = mono_reflection_get_type_checked (image, image, info, ignoreCase, type_resolve, error);
4516 HANDLE_FUNCTION_RETURN_VAL (type);
4519 MonoReflectionTypeHandle
4520 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssemblyHandle assembly_h, MonoReflectionModuleHandle module, MonoStringHandle name, MonoBoolean throwOnError, MonoBoolean ignoreCase, MonoError *error)
4522 error_init (error);
4524 MonoTypeNameParse info;
4525 gboolean type_resolve;
4527 /* On MS.NET, this does not fire a TypeResolve event */
4528 type_resolve = TRUE;
4529 char *str = mono_string_handle_to_utf8 (name, error);
4530 goto_if_nok (error, fail);
4532 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4533 ERROR_DECL_VALUE (parse_error);
4534 if (!mono_reflection_parse_type_checked (str, &info, &parse_error)) {
4535 g_free (str);
4536 mono_reflection_free_type_info (&info);
4537 mono_error_cleanup (&parse_error);
4538 if (throwOnError) {
4539 mono_error_set_argument (error, "typeName", "failed to parse the type");
4540 goto fail;
4542 /*g_print ("failed parse\n");*/
4543 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
4546 if (info.assembly.name) {
4547 g_free (str);
4548 mono_reflection_free_type_info (&info);
4549 if (throwOnError) {
4550 /* 1.0 and 2.0 throw different exceptions */
4551 if (mono_defaults.generic_ilist_class)
4552 mono_error_set_argument (error, NULL, "Type names passed to Assembly.GetType() must not specify an assembly.");
4553 else
4554 mono_error_set_type_load_name (error, g_strdup (""), g_strdup (""), "Type names passed to Assembly.GetType() must not specify an assembly.");
4555 goto fail;
4557 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
4560 MonoType *type;
4561 type = NULL;
4562 if (!MONO_HANDLE_IS_NULL (module)) {
4563 MonoImage *image = MONO_HANDLE_GETVAL (module, image);
4564 if (image) {
4565 type = mono_reflection_get_type_checked (image, image, &info, ignoreCase, &type_resolve, error);
4566 if (!is_ok (error)) {
4567 g_free (str);
4568 mono_reflection_free_type_info (&info);
4569 goto fail;
4573 else {
4574 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
4575 if (assembly_is_dynamic (assembly)) {
4576 /* Enumerate all modules */
4577 MonoReflectionAssemblyBuilderHandle abuilder = MONO_HANDLE_NEW (MonoReflectionAssemblyBuilder, NULL);
4578 MONO_HANDLE_ASSIGN (abuilder, assembly_h);
4579 int i;
4581 MonoArrayHandle modules = MONO_HANDLE_NEW (MonoArray, NULL);
4582 MONO_HANDLE_GET (modules, abuilder, modules);
4583 if (!MONO_HANDLE_IS_NULL (modules)) {
4584 int n = mono_array_handle_length (modules);
4585 for (i = 0; i < n; ++i) {
4586 type = get_type_from_module_builder_module (modules, i, &info, ignoreCase, &type_resolve, error);
4587 if (!is_ok (error)) {
4588 g_free (str);
4589 mono_reflection_free_type_info (&info);
4590 goto fail;
4592 if (type)
4593 break;
4597 MonoArrayHandle loaded_modules = MONO_HANDLE_NEW (MonoArray, NULL);
4598 MONO_HANDLE_GET (loaded_modules, abuilder, loaded_modules);
4599 if (!type && !MONO_HANDLE_IS_NULL (loaded_modules)) {
4600 int n = mono_array_handle_length (loaded_modules);
4601 for (i = 0; i < n; ++i) {
4602 type = get_type_from_module_builder_loaded_modules (loaded_modules, i, &info, ignoreCase, &type_resolve, error);
4604 if (!is_ok (error)) {
4605 g_free (str);
4606 mono_reflection_free_type_info (&info);
4607 goto fail;
4609 if (type)
4610 break;
4614 else {
4615 type = mono_reflection_get_type_checked (assembly->image, assembly->image, &info, ignoreCase, &type_resolve, error);
4616 if (!is_ok (error)) {
4617 g_free (str);
4618 mono_reflection_free_type_info (&info);
4619 goto fail;
4623 g_free (str);
4624 mono_reflection_free_type_info (&info);
4626 if (!type) {
4627 if (throwOnError) {
4628 ERROR_DECL_VALUE (inner_error);
4629 char *type_name = mono_string_handle_to_utf8 (name, &inner_error);
4630 mono_error_assert_ok (&inner_error);
4631 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
4632 char *assmname = mono_stringify_assembly_name (&assembly->aname);
4633 mono_error_set_type_load_name (error, type_name, assmname, "%s", "");
4634 goto fail;
4637 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
4640 if (type->type == MONO_TYPE_CLASS) {
4641 MonoClass *klass = mono_type_get_class (type);
4643 /* need to report exceptions ? */
4644 if (throwOnError && mono_class_has_failure (klass)) {
4645 /* report SecurityException (or others) that occured when loading the assembly */
4646 mono_error_set_for_class_failure (error, klass);
4647 goto fail;
4651 /* g_print ("got it\n"); */
4652 return mono_type_get_object_handle (MONO_HANDLE_DOMAIN (assembly_h), type, error);
4653 fail:
4654 g_assert (!is_ok (error));
4655 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
4658 static gboolean
4659 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4661 gchar *content;
4662 gchar *shadow_ini_file;
4663 gsize len;
4665 /* Check for shadow-copied assembly */
4666 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4667 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4668 content = NULL;
4669 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4670 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4671 g_free (content);
4672 content = NULL;
4674 g_free (shadow_ini_file);
4675 if (content != NULL) {
4676 g_free (*filename);
4677 *filename = content;
4678 return TRUE;
4681 return FALSE;
4684 MonoStringHandle
4685 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssemblyHandle assembly, MonoBoolean escaped, MonoError *error)
4687 error_init (error);
4688 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
4689 MonoAssembly *mass = MONO_HANDLE_GETVAL (assembly, assembly);
4690 gchar *absolute;
4691 gchar *dirname;
4693 if (g_path_is_absolute (mass->image->name)) {
4694 absolute = g_strdup (mass->image->name);
4695 dirname = g_path_get_dirname (absolute);
4696 } else {
4697 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4698 dirname = g_strdup (mass->basedir);
4701 replace_shadow_path (domain, dirname, &absolute);
4702 g_free (dirname);
4704 mono_icall_make_platform_path (absolute);
4706 gchar *uri;
4707 if (escaped) {
4708 uri = g_filename_to_uri (absolute, NULL, NULL);
4709 } else {
4710 const gchar *prepend = mono_icall_get_file_path_prefix (absolute);
4711 uri = g_strconcat (prepend, absolute, NULL);
4714 g_free (absolute);
4716 MonoStringHandle res;
4717 if (uri) {
4718 res = mono_string_new_handle (domain, uri, error);
4719 g_free (uri);
4720 } else {
4721 res = MONO_HANDLE_NEW (MonoString, NULL);
4723 return res;
4726 MonoBoolean
4727 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssemblyHandle assembly, MonoError *error)
4729 error_init (error);
4730 MonoAssembly *mass = MONO_HANDLE_GETVAL (assembly,assembly);
4732 return mass->in_gac;
4735 MonoReflectionAssemblyHandle
4736 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoStringHandle mname, MonoObjectHandle evidence, MonoError *error)
4738 gchar *name;
4739 MonoImageOpenStatus status;
4740 MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
4742 name = mono_string_handle_to_utf8 (mname, error);
4743 goto_if_nok (error, leave);
4744 MonoAssembly *res;
4745 res = mono_assembly_load_with_partial_name_internal (name, &status);
4747 g_free (name);
4749 if (res == NULL)
4750 goto leave;
4751 result = mono_assembly_get_object_handle (mono_domain_get (), res, error);
4752 leave:
4753 return result;
4756 MonoStringHandle
4757 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4759 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4760 MonoAssembly *assembly = MONO_HANDLE_GETVAL (refassembly, assembly);
4761 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4764 MonoBoolean
4765 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
4767 error_init (error);
4768 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
4769 return mono_asmctx_get_kind (&assembly->context) == MONO_ASMCTX_REFONLY;
4772 MonoStringHandle
4773 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4775 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4776 MonoAssembly *assembly = MONO_HANDLE_GETVAL (refassembly, assembly);
4778 return mono_string_new_handle (domain, assembly->image->version, error);
4781 MonoReflectionMethodHandle
4782 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
4784 error_init (error);
4785 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
4786 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
4787 MonoMethod *method;
4789 MonoReflectionMethodHandle res = MONO_HANDLE_NEW (MonoReflectionMethod, NULL);
4790 guint32 token = mono_image_get_entry_point (assembly->image);
4792 if (!token)
4793 goto leave;
4794 method = mono_get_method_checked (assembly->image, token, NULL, NULL, error);
4795 goto_if_nok (error, leave);
4797 MONO_HANDLE_ASSIGN (res, mono_method_get_object_handle (domain, method, NULL, error));
4798 leave:
4799 return res;
4802 MonoReflectionModuleHandle
4803 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssemblyHandle assembly, MonoError *error)
4805 error_init (error);
4806 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
4807 MonoAssembly *a = MONO_HANDLE_GETVAL (assembly, assembly);
4808 return mono_module_get_object_handle (domain, a->image, error);
4811 static gboolean
4812 add_manifest_resource_name_to_array (MonoDomain *domain, MonoImage *image, MonoTableInfo *table, int i, MonoArrayHandle dest, MonoError *error)
4814 HANDLE_FUNCTION_ENTER ();
4815 error_init (error);
4816 const char *val = mono_metadata_string_heap (image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4817 MonoStringHandle str = mono_string_new_handle (domain, val, error);
4818 goto_if_nok (error, leave);
4819 MONO_HANDLE_ARRAY_SETREF (dest, i, str);
4820 leave:
4821 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
4824 MonoArrayHandle
4825 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
4827 error_init (error);
4828 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
4829 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
4830 MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4831 MonoArrayHandle result = mono_array_new_handle (domain, mono_defaults.string_class, table->rows, error);
4832 goto_if_nok (error, fail);
4833 int i;
4835 for (i = 0; i < table->rows; ++i) {
4836 if (!add_manifest_resource_name_to_array (domain, assembly->image, table, i, result, error))
4837 goto fail;
4839 return result;
4840 fail:
4841 return NULL_HANDLE_ARRAY;
4844 MonoStringHandle
4845 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4847 char *guid = mono_runtime_get_aotid ();
4848 if (guid == NULL)
4849 return MONO_HANDLE_CAST (MonoString, mono_new_null ());
4850 MonoStringHandle res = mono_string_new_handle (mono_domain_get (), guid, error);
4851 g_free (guid);
4852 return res;
4855 static MonoAssemblyName*
4856 create_referenced_assembly_name (MonoDomain *domain, MonoImage *image, MonoTableInfo *t, int i, MonoError *error)
4858 error_init (error);
4859 MonoAssemblyName *aname = g_new0 (MonoAssemblyName, 1);
4861 mono_assembly_get_assemblyref_checked (image, i, aname, error);
4862 return_val_if_nok (error, NULL);
4863 aname->hash_alg = ASSEMBLY_HASH_SHA1 /* SHA1 (default) */;
4864 /* name and culture are pointers into the image tables, but we need
4865 * real malloc'd strings (so that we can g_free() them later from
4866 * Mono.RuntimeMarshal.FreeAssemblyName) */
4867 aname->name = g_strdup (aname->name);
4868 aname->culture = g_strdup (aname->culture);
4869 /* Don't need the hash value in managed */
4870 aname->hash_value = NULL;
4871 aname->hash_len = 0;
4872 g_assert (aname->public_key == NULL);
4874 /* note: this function doesn't return the codebase on purpose (i.e. it can
4875 be used under partial trust as path information isn't present). */
4876 return aname;
4879 GPtrArray*
4880 ves_icall_System_Reflection_Assembly_InternalGetReferencedAssemblies (MonoReflectionAssemblyHandle assembly, MonoError *error)
4882 error_init (error);
4883 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
4884 MonoAssembly *ass = MONO_HANDLE_GETVAL(assembly, assembly);
4885 MonoImage *image = ass->image;
4887 MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLYREF];
4888 int count = t->rows;
4890 GPtrArray *result = g_ptr_array_sized_new (count);
4892 for (int i = 0; i < count; i++) {
4893 MonoAssemblyName *aname = create_referenced_assembly_name (domain, image, t, i, error);
4894 if (!is_ok (error))
4895 break;
4896 g_ptr_array_add (result, aname);
4898 return result;
4901 /* move this in some file in mono/util/ */
4902 static char *
4903 g_concat_dir_and_file (const char *dir, const char *file)
4905 g_return_val_if_fail (dir != NULL, NULL);
4906 g_return_val_if_fail (file != NULL, NULL);
4909 * If the directory name doesn't have a / on the end, we need
4910 * to add one so we get a proper path to the file
4912 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4913 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4914 else
4915 return g_strconcat (dir, file, NULL);
4918 void *
4919 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, gint32 *size, MonoReflectionModuleHandleOut ref_module, MonoError *error)
4921 error_init (error);
4922 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
4923 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
4924 MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4925 guint32 i;
4926 guint32 cols [MONO_MANIFEST_SIZE];
4927 guint32 impl, file_idx;
4928 const char *val;
4929 MonoImage *module;
4931 char *n = mono_string_handle_to_utf8 (name, error);
4932 return_val_if_nok (error, NULL);
4934 for (i = 0; i < table->rows; ++i) {
4935 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4936 val = mono_metadata_string_heap (assembly->image, cols [MONO_MANIFEST_NAME]);
4937 if (strcmp (val, n) == 0)
4938 break;
4940 g_free (n);
4941 if (i == table->rows)
4942 return NULL;
4943 /* FIXME */
4944 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4945 if (impl) {
4947 * this code should only be called after obtaining the
4948 * ResourceInfo and handling the other cases.
4950 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4951 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4953 module = mono_image_load_file_for_image_checked (assembly->image, file_idx, error);
4954 if (!is_ok (error) || !module)
4955 return NULL;
4957 else
4958 module = assembly->image;
4961 MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, module, error);
4962 return_val_if_nok (error, NULL);
4963 MONO_HANDLE_ASSIGN (ref_module, rm);
4965 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4968 static gboolean
4969 get_manifest_resource_info_internal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, MonoManifestResourceInfoHandle info, MonoError *error)
4971 HANDLE_FUNCTION_ENTER ();
4972 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
4973 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
4974 MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4975 int i;
4976 guint32 cols [MONO_MANIFEST_SIZE];
4977 guint32 file_cols [MONO_FILE_SIZE];
4978 const char *val;
4979 char *n;
4981 gboolean result = FALSE;
4983 n = mono_string_handle_to_utf8 (name, error);
4984 goto_if_nok (error, leave);
4986 for (i = 0; i < table->rows; ++i) {
4987 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4988 val = mono_metadata_string_heap (assembly->image, cols [MONO_MANIFEST_NAME]);
4989 if (strcmp (val, n) == 0)
4990 break;
4992 g_free (n);
4993 if (i == table->rows)
4994 goto leave;
4996 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4997 MONO_HANDLE_SETVAL (info, location, guint32, RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST);
4999 else {
5000 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
5001 case MONO_IMPLEMENTATION_FILE:
5002 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5003 table = &assembly->image->tables [MONO_TABLE_FILE];
5004 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
5005 val = mono_metadata_string_heap (assembly->image, file_cols [MONO_FILE_NAME]);
5006 MONO_HANDLE_SET (info, filename, mono_string_new_handle (domain, val, error));
5007 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
5008 MONO_HANDLE_SETVAL (info, location, guint32, 0);
5009 else
5010 MONO_HANDLE_SETVAL (info, location, guint32, RESOURCE_LOCATION_EMBEDDED);
5011 break;
5013 case MONO_IMPLEMENTATION_ASSEMBLYREF:
5014 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
5015 mono_assembly_load_reference (assembly->image, i - 1);
5016 if (assembly->image->references [i - 1] == REFERENCE_MISSING) {
5017 mono_error_set_file_not_found (error, NULL, "Assembly %d referenced from assembly %s not found ", i - 1, assembly->image->name);
5018 goto leave;
5020 MonoReflectionAssemblyHandle assm_obj;
5021 assm_obj = mono_assembly_get_object_handle (mono_domain_get (), assembly->image->references [i - 1], error);
5022 goto_if_nok (error, leave);
5023 MONO_HANDLE_SET (info, assembly, assm_obj);
5025 /* Obtain info recursively */
5026 get_manifest_resource_info_internal (assm_obj, name, info, error);
5027 goto_if_nok (error, leave);
5028 guint32 location;
5029 location = MONO_HANDLE_GETVAL (info, location);
5030 location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5031 MONO_HANDLE_SETVAL (info, location, guint32, location);
5032 break;
5034 case MONO_IMPLEMENTATION_EXP_TYPE:
5035 g_assert_not_reached ();
5036 break;
5040 result = TRUE;
5041 leave:
5042 HANDLE_FUNCTION_RETURN_VAL (result);
5045 MonoBoolean
5046 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, MonoManifestResourceInfoHandle info_h, MonoError *error)
5048 error_init (error);
5049 return get_manifest_resource_info_internal (assembly_h, name, info_h, error);
5052 static gboolean
5053 add_filename_to_files_array (MonoDomain *domain, MonoAssembly * assembly, MonoTableInfo *table, int i, MonoArrayHandle dest, int dest_idx, MonoError *error)
5055 HANDLE_FUNCTION_ENTER();
5056 error_init (error);
5057 const char *val = mono_metadata_string_heap (assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5058 char *n = g_concat_dir_and_file (assembly->basedir, val);
5059 MonoStringHandle str = mono_string_new_handle (domain, n, error);
5060 g_free (n);
5061 goto_if_nok (error, leave);
5062 MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, str);
5063 leave:
5064 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
5067 MonoObjectHandle
5068 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, MonoBoolean resource_modules, MonoError *error)
5070 error_init (error);
5071 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
5072 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
5073 MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_FILE];
5074 int i, count;
5076 /* check hash if needed */
5077 if (!MONO_HANDLE_IS_NULL(name)) {
5078 char *n = mono_string_handle_to_utf8 (name, error);
5079 goto_if_nok (error, fail);
5081 for (i = 0; i < table->rows; ++i) {
5082 const char *val = mono_metadata_string_heap (assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5083 if (strcmp (val, n) == 0) {
5084 g_free (n);
5085 n = g_concat_dir_and_file (assembly->basedir, val);
5086 MonoStringHandle fn = mono_string_new_handle (domain, n, error);
5087 g_free (n);
5088 goto_if_nok (error, fail);
5089 return MONO_HANDLE_CAST (MonoObject, fn);
5092 g_free (n);
5093 return NULL_HANDLE;
5096 count = 0;
5097 for (i = 0; i < table->rows; ++i) {
5098 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5099 count ++;
5102 MonoArrayHandle result;
5103 result = mono_array_new_handle (domain, mono_defaults.string_class, count, error);
5104 goto_if_nok (error, fail);
5106 count = 0;
5107 for (i = 0; i < table->rows; ++i) {
5108 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5109 if (!add_filename_to_files_array (domain, assembly, table, i, result, count, error))
5110 goto fail;
5111 count++;
5114 return MONO_HANDLE_CAST (MonoObject, result);
5115 fail:
5116 return NULL_HANDLE;
5119 static gboolean
5120 add_module_to_modules_array (MonoDomain *domain, MonoArrayHandle dest, int *dest_idx, MonoImage* module, MonoError *error)
5122 HANDLE_FUNCTION_ENTER ();
5123 error_init (error);
5124 if (module) {
5125 MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, module, error);
5126 goto_if_nok (error, leave);
5128 MONO_HANDLE_ARRAY_SETREF (dest, *dest_idx, rm);
5129 ++(*dest_idx);
5132 leave:
5133 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
5136 static gboolean
5137 add_file_to_modules_array (MonoDomain *domain, MonoArrayHandle dest, int dest_idx, MonoImage *image, MonoTableInfo *table, int table_idx, MonoError *error)
5139 HANDLE_FUNCTION_ENTER ();
5140 error_init (error);
5142 guint32 cols [MONO_FILE_SIZE];
5143 mono_metadata_decode_row (table, table_idx, cols, MONO_FILE_SIZE);
5144 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5145 MonoReflectionModuleHandle rm = mono_module_file_get_object_handle (domain, image, table_idx, error);
5146 goto_if_nok (error, leave);
5147 MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rm);
5148 } else {
5149 MonoImage *m = mono_image_load_file_for_image_checked (image, table_idx + 1, error);
5150 goto_if_nok (error, leave);
5151 if (!m) {
5152 const char *filename = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5153 mono_error_set_file_not_found (error, filename, "%s", "");
5154 goto leave;
5156 MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, m, error);
5157 goto_if_nok (error, leave);
5158 MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rm);
5161 leave:
5162 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
5165 MonoArrayHandle
5166 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
5168 error_init (error);
5169 MonoDomain *domain = mono_domain_get();
5170 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
5171 MonoClass *klass;
5172 int i, j, file_count = 0;
5173 MonoImage **modules;
5174 guint32 module_count, real_module_count;
5175 MonoTableInfo *table;
5176 MonoImage *image = assembly->image;
5178 g_assert (image != NULL);
5179 g_assert (!assembly_is_dynamic (assembly));
5181 table = &image->tables [MONO_TABLE_FILE];
5182 file_count = table->rows;
5184 modules = image->modules;
5185 module_count = image->module_count;
5187 real_module_count = 0;
5188 for (i = 0; i < module_count; ++i)
5189 if (modules [i])
5190 real_module_count ++;
5192 klass = mono_class_get_module_class ();
5193 MonoArrayHandle res = mono_array_new_handle (domain, klass, 1 + real_module_count + file_count, error);
5194 goto_if_nok (error, fail);
5196 MonoReflectionModuleHandle image_obj;
5197 image_obj = mono_module_get_object_handle (domain, image, error);
5198 goto_if_nok (error, fail);
5200 MONO_HANDLE_ARRAY_SETREF (res, 0, image_obj);
5202 j = 1;
5203 for (i = 0; i < module_count; ++i)
5204 if (!add_module_to_modules_array (domain, res, &j, modules[i], error))
5205 goto fail;
5207 for (i = 0; i < file_count; ++i, ++j) {
5208 if (!add_file_to_modules_array (domain, res, j, image, table, i, error))
5209 goto fail;
5212 return res;
5213 fail:
5214 return NULL_HANDLE_ARRAY;
5217 MonoReflectionMethodHandle
5218 ves_icall_GetCurrentMethod (MonoError *error)
5220 error_init (error);
5222 MonoMethod *m = mono_method_get_last_managed ();
5224 if (!m) {
5225 mono_error_set_not_supported (error, "Stack walks are not supported on this platform.");
5226 return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
5229 while (m->is_inflated)
5230 m = ((MonoMethodInflated*)m)->declaring;
5232 return mono_method_get_object_handle (mono_domain_get (), m, NULL, error);
5236 static MonoMethod*
5237 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5239 int offset = -1, i;
5240 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5241 ERROR_DECL (error);
5242 MonoMethod *result;
5243 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5244 //method is inflated, we should inflate it on the other class
5245 MonoGenericContext ctx;
5246 ctx.method_inst = inflated->context.method_inst;
5247 ctx.class_inst = inflated->context.class_inst;
5248 if (mono_class_is_ginst (klass))
5249 ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
5250 else if (mono_class_is_gtd (klass))
5251 ctx.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
5252 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, error);
5253 g_assert (is_ok (error)); /* FIXME don't swallow the error */
5254 return result;
5257 mono_class_setup_methods (method->klass);
5258 if (mono_class_has_failure (method->klass))
5259 return NULL;
5260 int mcount = mono_class_get_method_count (method->klass);
5261 MonoMethod **method_klass_methods = m_class_get_methods (method->klass);
5262 for (i = 0; i < mcount; ++i) {
5263 if (method_klass_methods [i] == method) {
5264 offset = i;
5265 break;
5268 mono_class_setup_methods (klass);
5269 if (mono_class_has_failure (klass))
5270 return NULL;
5271 g_assert (offset >= 0 && offset < mono_class_get_method_count (klass));
5272 return m_class_get_methods (klass) [offset];
5275 MonoReflectionMethodHandle
5276 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check, MonoError *error)
5278 error_init (error);
5279 MonoClass *klass;
5280 if (type && generic_check) {
5281 klass = mono_class_from_mono_type_internal (type);
5282 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5283 return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
5285 if (method->klass != klass) {
5286 method = mono_method_get_equivalent_method (method, klass);
5287 if (!method)
5288 return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
5290 } else if (type)
5291 klass = mono_class_from_mono_type_internal (type);
5292 else
5293 klass = method->klass;
5294 return mono_method_get_object_handle (mono_domain_get (), method, klass, error);
5297 MonoReflectionMethodBodyHandle
5298 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method, MonoError *error)
5300 error_init (error);
5301 return mono_method_body_get_object_handle (mono_domain_get (), method, error);
5304 MonoReflectionAssemblyHandle
5305 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (MonoError *error)
5307 error_init (error);
5309 MonoMethod *dest = NULL;
5310 mono_stack_walk_no_il (get_executing, &dest);
5311 g_assert (dest);
5312 return mono_assembly_get_object_handle (mono_domain_get (), m_class_get_image (dest->klass)->assembly, error);
5316 MonoReflectionAssemblyHandle
5317 ves_icall_System_Reflection_Assembly_GetEntryAssembly (MonoError *error)
5319 error_init (error);
5321 MonoDomain* domain = mono_domain_get ();
5323 if (!domain->entry_assembly)
5324 return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
5326 return mono_assembly_get_object_handle (domain, domain->entry_assembly, error);
5329 MonoReflectionAssemblyHandle
5330 ves_icall_System_Reflection_Assembly_GetCallingAssembly (MonoError *error)
5332 error_init (error);
5333 MonoMethod *m;
5334 MonoMethod *dest;
5336 dest = NULL;
5337 mono_stack_walk_no_il (get_executing, &dest);
5338 m = dest;
5339 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5340 if (!dest)
5341 dest = m;
5342 if (!m) {
5343 mono_error_set_not_supported (error, "Stack walks are not supported on this platform.");
5344 return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
5346 return mono_assembly_get_object_handle (mono_domain_get (), m_class_get_image (dest->klass)->assembly, error);
5349 MonoStringHandle
5350 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, MonoBoolean full_name,
5351 MonoBoolean assembly_qualified, MonoError *error)
5353 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5354 MonoType *type = MONO_HANDLE_RAW (object)->type;
5355 MonoTypeNameFormat format;
5356 MonoStringHandle res;
5357 gchar *name;
5359 if (full_name)
5360 format = assembly_qualified ?
5361 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5362 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5363 else
5364 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5366 name = mono_type_get_name_full (type, format);
5367 if (!name)
5368 return NULL_HANDLE_STRING;
5370 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5371 g_free (name);
5372 return NULL_HANDLE_STRING;
5375 res = mono_string_new_handle (domain, name, error);
5376 g_free (name);
5378 return res;
5382 ves_icall_RuntimeType_get_core_clr_security_level (MonoReflectionTypeHandle rfield, MonoError *error)
5384 error_init (error);
5385 MonoType *type = MONO_HANDLE_GETVAL (rfield, type);
5386 MonoClass *klass = mono_class_from_mono_type_internal (type);
5388 mono_class_init_checked (klass, error);
5389 return_val_if_nok (error, -1);
5390 return mono_security_core_clr_class_level (klass);
5394 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionFieldHandle rfield, MonoError *error)
5396 MonoClassField *field = MONO_HANDLE_GETVAL (rfield, field);
5397 return mono_security_core_clr_field_level (field, TRUE);
5401 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethodHandle rfield, MonoError *error)
5403 MonoMethod *method = MONO_HANDLE_GETVAL (rfield, method);
5404 return mono_security_core_clr_method_level (method, TRUE);
5407 MonoStringHandle
5408 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssemblyHandle assembly, MonoError *error)
5410 error_init (error);
5411 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
5412 MonoAssembly *mass = MONO_HANDLE_GETVAL (assembly, assembly);
5413 gchar *name;
5415 name = mono_stringify_assembly_name (&mass->aname);
5416 MonoStringHandle res = mono_string_new_handle (domain, name, error);
5417 g_free (name);
5418 return res;
5421 MonoAssemblyName *
5422 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5424 return &mass->aname;
5427 void
5428 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoStringHandle fname, MonoAssemblyName *name, MonoStringHandleOut normalized_codebase, MonoError *error)
5430 char *filename;
5431 MonoImageOpenStatus status = MONO_IMAGE_OK;
5432 char *codebase = NULL;
5433 gboolean res;
5434 MonoImage *image;
5435 char *dirname;
5437 error_init (error);
5439 filename = mono_string_handle_to_utf8 (fname, error);
5440 return_if_nok (error);
5442 dirname = g_path_get_dirname (filename);
5443 replace_shadow_path (mono_domain_get (), dirname, &filename);
5444 g_free (dirname);
5446 mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "InternalGetAssemblyName (\"%s\")", filename);
5448 image = mono_image_open_full (filename, &status, TRUE);
5450 if (!image){
5451 if (status == MONO_IMAGE_IMAGE_INVALID)
5452 mono_error_set_bad_image_by_name (error, filename, "Invalid Image");
5453 else
5454 mono_error_set_file_not_found (error, filename, "%s", "");
5455 g_free (filename);
5456 return;
5459 res = mono_assembly_fill_assembly_name_full (image, name, TRUE);
5460 if (!res) {
5461 mono_image_close (image);
5462 g_free (filename);
5463 mono_error_set_argument (error, "assemblyFile", "The file does not contain a manifest");
5464 return;
5467 if (filename != NULL && *filename != '\0') {
5468 gchar *result;
5470 codebase = g_strdup (filename);
5472 mono_icall_make_platform_path (codebase);
5474 const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
5476 result = g_strconcat (prepend, codebase, NULL);
5477 g_free (codebase);
5478 codebase = result;
5480 MONO_HANDLE_ASSIGN (normalized_codebase, mono_string_new_handle (mono_domain_get (), codebase, error));
5481 g_free (codebase);
5483 mono_image_close (image);
5484 g_free (filename);
5487 MonoBoolean
5488 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssemblyHandle assembly_h,
5489 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength, MonoError *error)
5491 error_init (error);
5492 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
5493 MonoBoolean result = FALSE;
5494 MonoDeclSecurityEntry entry;
5496 /* SecurityAction.RequestMinimum */
5497 if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQMIN, &entry)) {
5498 *minimum = entry.blob;
5499 *minLength = entry.size;
5500 result = TRUE;
5502 /* SecurityAction.RequestOptional */
5503 if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQOPT, &entry)) {
5504 *optional = entry.blob;
5505 *optLength = entry.size;
5506 result = TRUE;
5508 /* SecurityAction.RequestRefuse */
5509 if (mono_declsec_get_assembly_action (assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5510 *refused = entry.blob;
5511 *refLength = entry.size;
5512 result = TRUE;
5515 return result;
5518 static gboolean
5519 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5521 guint32 attrs, visibility;
5522 do {
5523 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5524 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5525 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5526 return FALSE;
5528 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5530 return TRUE;
5533 static void
5534 image_get_type (MonoDomain *domain, MonoImage *image, MonoTableInfo *tdef, int table_idx, int count, MonoArrayHandle res, MonoArrayHandle exceptions, MonoBoolean exportedOnly, MonoError *error)
5536 error_init (error);
5537 HANDLE_FUNCTION_ENTER ();
5538 ERROR_DECL_VALUE (klass_error);
5539 MonoClass *klass = mono_class_get_checked (image, table_idx | MONO_TOKEN_TYPE_DEF, &klass_error);
5541 if (klass) {
5542 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
5543 return_if_nok (error);
5545 MONO_HANDLE_ARRAY_SETREF (res, count, rt);
5546 } else {
5547 MonoException *ex = mono_error_convert_to_exception (&klass_error);
5548 MONO_HANDLE_ARRAY_SETRAW (exceptions, count, ex);
5550 HANDLE_FUNCTION_RETURN ();
5553 static MonoArrayHandle
5554 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArrayHandleOut exceptions, MonoBoolean exportedOnly, MonoError *error)
5556 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5557 int i, count;
5559 error_init (error);
5561 /* we start the count from 1 because we skip the special type <Module> */
5562 if (exportedOnly) {
5563 count = 0;
5564 for (i = 1; i < tdef->rows; ++i) {
5565 if (mono_module_type_is_visible (tdef, image, i + 1))
5566 count++;
5568 } else {
5569 count = tdef->rows - 1;
5571 MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.runtimetype_class, count, error);
5572 return_val_if_nok (error, NULL_HANDLE_ARRAY);
5573 MONO_HANDLE_ASSIGN (exceptions, mono_array_new_handle (domain, mono_defaults.exception_class, count, error));
5574 return_val_if_nok (error, NULL_HANDLE_ARRAY);
5575 count = 0;
5576 for (i = 1; i < tdef->rows; ++i) {
5577 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i+1)) {
5578 image_get_type (domain, image, tdef, i + 1, count, res, exceptions, exportedOnly, error);
5579 return_val_if_nok (error, NULL_HANDLE_ARRAY);
5580 count++;
5584 return res;
5587 static void
5588 append_module_types (MonoDomain *domain, MonoArrayHandleOut res, MonoArrayHandleOut exceptions, MonoImage *image, MonoBoolean exportedOnly, MonoError *error)
5590 HANDLE_FUNCTION_ENTER ();
5591 error_init (error);
5592 MonoArrayHandle ex2 = MONO_HANDLE_NEW (MonoArray, NULL);
5593 MonoArrayHandle res2 = mono_module_get_types (domain, image, ex2, exportedOnly, error);
5594 goto_if_nok (error, leave);
5596 /* Append the new types to the end of the array */
5597 if (mono_array_handle_length (res2) > 0) {
5598 guint32 len1, len2;
5600 len1 = mono_array_handle_length (res);
5601 len2 = mono_array_handle_length (res2);
5603 MonoArrayHandle res3 = mono_array_new_handle (domain, mono_defaults.runtimetype_class, len1 + len2, error);
5604 goto_if_nok (error, leave);
5606 mono_array_handle_memcpy_refs (res3, 0, res, 0, len1);
5607 mono_array_handle_memcpy_refs (res3, len1, res2, 0, len2);
5608 MONO_HANDLE_ASSIGN (res, res3);
5610 MonoArrayHandle ex3 = mono_array_new_handle (domain, mono_defaults.runtimetype_class, len1 + len2, error);
5611 goto_if_nok (error, leave);
5613 mono_array_handle_memcpy_refs (ex3, 0, exceptions, 0, len1);
5614 mono_array_handle_memcpy_refs (ex3, len1, ex2, 0, len2);
5615 MONO_HANDLE_ASSIGN (exceptions, ex3);
5617 leave:
5618 HANDLE_FUNCTION_RETURN ();
5621 static void
5622 set_class_failure_in_array (MonoArrayHandle exl, int i, MonoClass *klass)
5624 HANDLE_FUNCTION_ENTER ();
5625 ERROR_DECL_VALUE (unboxed_error);
5626 error_init (&unboxed_error);
5627 mono_error_set_for_class_failure (&unboxed_error, klass);
5629 MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, mono_error_convert_to_exception (&unboxed_error));
5630 MONO_HANDLE_ARRAY_SETREF (exl, i, exc);
5631 HANDLE_FUNCTION_RETURN ();
5634 MonoArrayHandle
5635 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssemblyHandle assembly_handle, MonoBoolean exportedOnly, MonoError *error)
5637 MonoArrayHandle exceptions = MONO_HANDLE_NEW(MonoArray, NULL);
5638 int i;
5640 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_handle);
5641 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_handle, assembly);
5643 g_assert (!assembly_is_dynamic (assembly));
5644 MonoImage *image = assembly->image;
5645 MonoTableInfo *table = &image->tables [MONO_TABLE_FILE];
5646 MonoArrayHandle res = mono_module_get_types (domain, image, exceptions, exportedOnly, error);
5647 return_val_if_nok (error, NULL_HANDLE_ARRAY);
5649 /* Append data from all modules in the assembly */
5650 for (i = 0; i < table->rows; ++i) {
5651 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5652 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, error);
5653 return_val_if_nok (error, NULL_HANDLE_ARRAY);
5655 if (loaded_image) {
5656 append_module_types (domain, res, exceptions, loaded_image, exportedOnly, error);
5657 return_val_if_nok (error, NULL_HANDLE_ARRAY);
5662 /* the ReflectionTypeLoadException must have all the types (Types property),
5663 * NULL replacing types which throws an exception. The LoaderException must
5664 * contain all exceptions for NULL items.
5667 int len = mono_array_handle_length (res);
5669 int ex_count = 0;
5670 GList *list = NULL;
5671 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
5672 for (i = 0; i < len; i++) {
5673 MONO_HANDLE_ARRAY_GETREF (t, res, i);
5675 if (!MONO_HANDLE_IS_NULL (t)) {
5676 MonoClass *klass = mono_type_get_class (MONO_HANDLE_GETVAL (t, type));
5677 if ((klass != NULL) && mono_class_has_failure (klass)) {
5678 /* keep the class in the list */
5679 list = g_list_append (list, klass);
5680 /* and replace Type with NULL */
5681 MONO_HANDLE_ARRAY_SETRAW (res, i, NULL);
5683 } else {
5684 ex_count ++;
5688 if (list || ex_count) {
5689 GList *tmp = NULL;
5690 int j, length = g_list_length (list) + ex_count;
5692 MonoArrayHandle exl = mono_array_new_handle (domain, mono_defaults.exception_class, length, error);
5693 if (!is_ok (error)) {
5694 g_list_free (list);
5695 return NULL_HANDLE_ARRAY;
5697 /* Types for which mono_class_get_checked () succeeded */
5698 MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, NULL);
5699 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5700 set_class_failure_in_array (exl, i, (MonoClass*)tmp->data);
5702 /* Types for which it don't */
5703 for (j = 0; j < mono_array_handle_length (exceptions); ++j) {
5704 MONO_HANDLE_ARRAY_GETREF (exc, exceptions, j);
5705 if (!MONO_HANDLE_IS_NULL (exc)) {
5706 g_assert (i < length);
5707 MONO_HANDLE_ARRAY_SETREF (exl, i, exc);
5708 i ++;
5711 g_list_free (list);
5712 list = NULL;
5714 MONO_HANDLE_ASSIGN (exc, mono_get_exception_reflection_type_load_checked (res, exl, error));
5715 return_val_if_nok (error, NULL_HANDLE_ARRAY);
5716 mono_error_set_exception_handle (error, exc);
5717 return NULL_HANDLE_ARRAY;
5720 return res;
5723 void
5724 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname, MonoBoolean free_struct, MonoError *error)
5726 mono_assembly_name_free (aname);
5727 if (free_struct)
5728 g_free (aname);
5731 void
5732 ves_icall_Mono_Runtime_DisableMicrosoftTelemetry (MonoError *error)
5734 #ifdef TARGET_OSX
5735 mono_merp_disable ();
5736 #else
5737 // Icall has platform check in managed too.
5738 g_assert_not_reached ();
5739 #endif
5742 void
5743 ves_icall_Mono_Runtime_EnableMicrosoftTelemetry (char *appBundleID, char *appSignature, char *appVersion, char *merpGUIPath, char *eventType, char *appPath, MonoError *error)
5745 #ifdef TARGET_OSX
5746 mono_merp_enable (appBundleID, appSignature, appVersion, merpGUIPath, eventType, appPath);
5748 mono_get_runtime_callbacks ()->install_state_summarizer ();
5749 #else
5750 // Icall has platform check in managed too.
5751 g_assert_not_reached ();
5752 #endif
5755 MonoStringHandle
5756 ves_icall_Mono_Runtime_ExceptionToState (MonoExceptionHandle exc_handle, guint64 *portable_hash_out, guint64 *unportable_hash_out, MonoError *error)
5758 MonoStringHandle result;
5760 #ifndef DISABLE_CRASH_REPORTING
5761 // FIXME: Push handles down into mini/mini-exceptions.c
5762 MonoException *exc = MONO_HANDLE_RAW (exc_handle);
5763 MonoThreadSummary out;
5764 mono_get_eh_callbacks ()->mono_summarize_exception (exc, &out);
5766 *portable_hash_out = (guint64) out.hashes.offset_free_hash;
5767 *unportable_hash_out = (guint64) out.hashes.offset_rich_hash;
5769 JsonWriter writer;
5770 mono_json_writer_init (&writer);
5771 mono_native_state_init (&writer);
5772 gboolean first_thread_added = TRUE;
5773 mono_native_state_add_thread (&writer, &out, NULL, first_thread_added, TRUE);
5774 char *output = mono_native_state_free (&writer, FALSE);
5775 result = mono_string_new_handle (mono_domain_get (), output, error);
5776 g_free (output);
5777 #else
5778 *portable_hash_out = 0;
5779 *unportable_hash_out = 0;
5780 result = mono_string_new_handle (mono_domain_get (), "", error);
5781 #endif
5783 return result;
5786 void
5787 ves_icall_Mono_Runtime_SendMicrosoftTelemetry (char *payload, guint64 portable_hash, guint64 unportable_hash, MonoError *error)
5789 #ifdef TARGET_OSX
5790 if (!mono_merp_enabled ())
5791 g_error ("Cannot send telemetry without registering parameters first");
5793 pid_t crashed_pid = getpid ();
5795 MonoStackHash hashes;
5796 memset (&hashes, 0, sizeof (MonoStackHash));
5797 hashes.offset_free_hash = portable_hash;
5798 hashes.offset_rich_hash = unportable_hash;
5800 // Tells mono that we want to send the HANG EXC_TYPE.
5801 const char *signal = "SIGTERM";
5803 mono_merp_invoke (crashed_pid, signal, payload, &hashes);
5804 #else
5805 // Icall has platform check in managed too.
5806 g_assert_not_reached ();
5807 #endif
5810 void
5811 ves_icall_Mono_Runtime_DumpTelemetry (char *payload, guint64 portable_hash, guint64 unportable_hash, MonoError *error)
5813 #ifndef DISABLE_CRASH_REPORTING
5814 MonoStackHash hashes;
5815 memset (&hashes, 0, sizeof (MonoStackHash));
5816 hashes.offset_free_hash = portable_hash;
5817 hashes.offset_rich_hash = unportable_hash;
5818 mono_crash_dump (payload, &hashes);
5819 #else
5820 return;
5821 #endif
5824 MonoStringHandle
5825 ves_icall_Mono_Runtime_DumpStateSingle (guint64 *portable_hash, guint64 *unportable_hash, MonoError *error)
5827 MonoStringHandle result;
5829 #ifndef DISABLE_CRASH_REPORTING
5830 MonoStackHash hashes;
5831 memset (&hashes, 0, sizeof (MonoStackHash));
5832 MonoContext *ctx = NULL;
5834 MonoThreadSummary this_thread;
5835 if (!mono_threads_summarize_one (&this_thread, ctx))
5836 return mono_string_new_handle (mono_domain_get (), "", error);
5838 *portable_hash = (guint64) this_thread.hashes.offset_free_hash;
5839 *unportable_hash = (guint64) this_thread.hashes.offset_rich_hash;
5841 JsonWriter writer;
5842 mono_json_writer_init (&writer);
5843 mono_native_state_init (&writer);
5844 gboolean first_thread_added = TRUE;
5845 mono_native_state_add_thread (&writer, &this_thread, NULL, first_thread_added, TRUE);
5846 char *output = mono_native_state_free (&writer, FALSE);
5847 result = mono_string_new_handle (mono_domain_get (), output, error);
5848 g_free (output);
5849 #else
5850 *portable_hash = 0;
5851 *unportable_hash = 0;
5852 result = mono_string_new_handle (mono_domain_get (), "", error);
5853 #endif
5855 return result;
5859 void
5860 ves_icall_Mono_Runtime_RegisterReportingForNativeLib (const char *path_suffix, const char *module_name)
5862 #ifndef DISABLE_CRASH_REPORTING
5863 mono_get_eh_callbacks ()->mono_register_native_library (path_suffix, module_name);
5864 #endif
5867 // Number derived from trials on relevant hardware.
5868 // If it seems large, please confirm it's safe to shrink
5869 // before doing so.
5870 #define MONO_MAX_SUMMARY_LEN_ICALL 500000
5872 MonoStringHandle
5873 ves_icall_Mono_Runtime_DumpStateTotal (guint64 *portable_hash, guint64 *unportable_hash, MonoError *error)
5875 MonoStringHandle result;
5877 #ifndef DISABLE_CRASH_REPORTING
5878 char *scratch = g_new0 (gchar, MONO_MAX_SUMMARY_LEN_ICALL);
5880 char *out;
5881 MonoStackHash hashes;
5882 memset (&hashes, 0, sizeof (MonoStackHash));
5883 MonoContext *ctx = NULL;
5885 mono_get_runtime_callbacks ()->install_state_summarizer ();
5887 gboolean success = mono_threads_summarize (ctx, &out, &hashes, TRUE, FALSE, scratch, MONO_MAX_SUMMARY_LEN_ICALL);
5889 if (!success)
5890 return mono_string_new_handle (mono_domain_get (), "", error);
5892 *portable_hash = (guint64) hashes.offset_free_hash;
5893 *unportable_hash = (guint64) hashes.offset_rich_hash;
5894 result = mono_string_new_handle (mono_domain_get (), out, error);
5896 // out is now a pointer into garbage memory
5897 g_free (scratch);
5898 #else
5899 *portable_hash = 0;
5900 *unportable_hash = 0;
5901 result = mono_string_new_handle (mono_domain_get (), "", error);
5902 #endif
5904 return result;
5907 MonoBoolean
5908 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, MonoBoolean *is_version_defined_arg, MonoBoolean *is_token_defined_arg)
5910 gboolean is_version_defined = FALSE;
5911 gboolean is_token_defined = FALSE;
5912 gboolean result = FALSE;
5914 result = mono_assembly_name_parse_full (name, aname, TRUE, &is_version_defined, &is_token_defined);
5916 *is_version_defined_arg = (MonoBoolean)is_version_defined;
5917 *is_token_defined_arg = (MonoBoolean)is_token_defined;
5919 return result;
5922 MonoReflectionTypeHandle
5923 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModuleHandle module, MonoError *error)
5925 MonoDomain *domain = MONO_HANDLE_DOMAIN (module);
5926 MonoImage *image = MONO_HANDLE_GETVAL (module, image);
5927 MonoClass *klass;
5929 g_assert (image);
5931 MonoReflectionTypeHandle ret = MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
5933 if (image_is_dynamic (image) && ((MonoDynamicImage*)image)->initial_image)
5934 /* These images do not have a global type */
5935 goto leave;
5937 klass = mono_class_get_checked (image, 1 | MONO_TOKEN_TYPE_DEF, error);
5938 goto_if_nok (error, leave);
5940 ret = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
5941 leave:
5942 return ret;
5945 void
5946 ves_icall_System_Reflection_Module_Close (MonoReflectionModuleHandle module, MonoError *error)
5948 /*if (module->image)
5949 mono_image_close (module->image);*/
5952 MonoStringHandle
5953 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5955 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5956 MonoImage *image = MONO_HANDLE_GETVAL (refmodule, image);
5958 g_assert (image);
5959 return mono_string_new_handle (domain, image->guid, error);
5962 #ifndef HOST_WIN32
5963 static inline gpointer
5964 mono_icall_module_get_hinstance (MonoReflectionModuleHandle module)
5966 return (gpointer) (-1);
5968 #endif /* HOST_WIN32 */
5970 gpointer
5971 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModuleHandle module, MonoError *error)
5973 return mono_icall_module_get_hinstance (module);
5976 void
5977 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine, MonoError *error)
5979 if (image_is_dynamic (image)) {
5980 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5981 *pe_kind = dyn->pe_kind;
5982 *machine = dyn->machine;
5984 else {
5985 *pe_kind = (image->image_info->cli_cli_header.ch_flags & 0x3);
5986 *machine = image->image_info->cli_header.coff.coff_machine;
5990 gint32
5991 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image, MonoError *error)
5993 return (image->md_version_major << 16) | (image->md_version_minor);
5996 MonoArrayHandle
5997 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModuleHandle module, MonoError *error)
5999 error_init (error);
6001 MonoImage *image = MONO_HANDLE_GETVAL (module, image);
6002 MonoDomain *domain = MONO_HANDLE_DOMAIN (module);
6004 if (!image) {
6005 MonoArrayHandle arr = mono_array_new_handle (domain, mono_defaults.runtimetype_class, 0, error);
6006 return arr;
6007 } else {
6008 MonoArrayHandle exceptions = MONO_HANDLE_NEW (MonoArray, NULL);
6009 MonoArrayHandle res = mono_module_get_types (domain, image, exceptions, FALSE, error);
6010 return_val_if_nok (error, MONO_HANDLE_CAST(MonoArray, NULL_HANDLE));
6012 int n = mono_array_handle_length (exceptions);
6013 MonoExceptionHandle ex = MONO_HANDLE_NEW (MonoException, NULL);
6014 for (int i = 0; i < n; ++i) {
6015 MONO_HANDLE_ARRAY_GETREF(ex, exceptions, i);
6016 if (!MONO_HANDLE_IS_NULL (ex)) {
6017 mono_error_set_exception_handle (error, ex);
6018 return MONO_HANDLE_CAST(MonoArray, NULL_HANDLE);
6021 return res;
6025 static gboolean
6026 mono_memberref_is_method (MonoImage *image, guint32 token)
6028 if (!image_is_dynamic (image)) {
6029 guint32 cols [MONO_MEMBERREF_SIZE];
6030 const char *sig;
6031 const MonoTableInfo *table = &image->tables [MONO_TABLE_MEMBERREF];
6032 int idx = mono_metadata_token_index (token) - 1;
6033 if (idx < 0 || table->rows <= idx) {
6034 return FALSE;
6036 mono_metadata_decode_row (table, idx, cols, MONO_MEMBERREF_SIZE);
6037 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
6038 mono_metadata_decode_blob_size (sig, &sig);
6039 return (*sig != 0x6);
6040 } else {
6041 ERROR_DECL (error);
6042 MonoClass *handle_class;
6044 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, error)) {
6045 mono_error_cleanup (error); /* just probing, ignore error */
6046 return FALSE;
6049 return mono_defaults.methodhandle_class == handle_class;
6053 static MonoGenericInst *
6054 get_generic_inst_from_array_handle (MonoArrayHandle type_args)
6056 int type_argc = mono_array_handle_length (type_args);
6057 int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *);
6059 MonoGenericInst *ginst = (MonoGenericInst *)g_alloca (size);
6060 memset (ginst, 0, sizeof (MonoGenericInst));
6061 ginst->type_argc = type_argc;
6062 for (int i = 0; i < type_argc; i++) {
6063 MONO_HANDLE_ARRAY_GETVAL (ginst->type_argv[i], type_args, MonoType*, i);
6065 ginst->is_open = FALSE;
6066 for (int i = 0; i < type_argc; i++) {
6067 if (mono_class_is_open_constructed_type (ginst->type_argv[i])) {
6068 ginst->is_open = TRUE;
6069 break;
6073 return mono_metadata_get_canonical_generic_inst (ginst);
6076 static void
6077 init_generic_context_from_args_handles (MonoGenericContext *context, MonoArrayHandle type_args, MonoArrayHandle method_args)
6079 if (!MONO_HANDLE_IS_NULL (type_args)) {
6080 context->class_inst = get_generic_inst_from_array_handle (type_args);
6081 } else {
6082 context->class_inst = NULL;
6084 if (!MONO_HANDLE_IS_NULL (method_args)) {
6085 context->method_inst = get_generic_inst_from_array_handle (method_args);
6086 } else {
6087 context->method_inst = NULL;
6092 static MonoType*
6093 module_resolve_type_token (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
6095 HANDLE_FUNCTION_ENTER ();
6096 error_init (error);
6097 MonoType *result = NULL;
6098 MonoClass *klass;
6099 int table = mono_metadata_token_table (token);
6100 int index = mono_metadata_token_index (token);
6101 MonoGenericContext context;
6103 *resolve_error = ResolveTokenError_Other;
6105 /* Validate token */
6106 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
6107 (table != MONO_TABLE_TYPESPEC)) {
6108 *resolve_error = ResolveTokenError_BadTable;
6109 goto leave;
6112 if (image_is_dynamic (image)) {
6113 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
6114 ERROR_DECL_VALUE (inner_error);
6115 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &inner_error);
6116 mono_error_cleanup (&inner_error);
6117 result = klass ? m_class_get_byval_arg (klass) : NULL;
6118 goto leave;
6121 init_generic_context_from_args_handles (&context, type_args, method_args);
6122 ERROR_DECL_VALUE (inner_error);
6123 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &inner_error);
6124 mono_error_cleanup (&inner_error);
6125 result = klass ? m_class_get_byval_arg (klass) : NULL;
6126 goto leave;
6129 if ((index <= 0) || (index > image->tables [table].rows)) {
6130 *resolve_error = ResolveTokenError_OutOfRange;
6131 goto leave;
6134 init_generic_context_from_args_handles (&context, type_args, method_args);
6135 klass = mono_class_get_checked (image, token, error);
6136 if (klass)
6137 klass = mono_class_inflate_generic_class_checked (klass, &context, error);
6138 goto_if_nok (error, leave);
6140 if (klass)
6141 result = m_class_get_byval_arg (klass);
6142 leave:
6143 HANDLE_FUNCTION_RETURN_VAL (result);
6146 MonoType*
6147 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
6149 return module_resolve_type_token (image, token, type_args, method_args, resolve_error, error);
6152 static MonoMethod*
6153 module_resolve_method_token (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
6155 HANDLE_FUNCTION_ENTER ();
6156 error_init (error);
6157 MonoMethod *method = NULL;
6158 int table = mono_metadata_token_table (token);
6159 int index = mono_metadata_token_index (token);
6160 MonoGenericContext context;
6162 *resolve_error = ResolveTokenError_Other;
6164 /* Validate token */
6165 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
6166 (table != MONO_TABLE_MEMBERREF)) {
6167 *resolve_error = ResolveTokenError_BadTable;
6168 goto leave;
6171 if (image_is_dynamic (image)) {
6172 if (table == MONO_TABLE_METHOD) {
6173 ERROR_DECL_VALUE (inner_error);
6174 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &inner_error);
6175 mono_error_cleanup (&inner_error);
6176 goto leave;
6179 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
6180 *resolve_error = ResolveTokenError_BadTable;
6181 goto leave;
6184 init_generic_context_from_args_handles (&context, type_args, method_args);
6185 ERROR_DECL_VALUE (inner_error);
6186 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &inner_error);
6187 mono_error_cleanup (&inner_error);
6188 goto leave;
6191 if ((index <= 0) || (index > image->tables [table].rows)) {
6192 *resolve_error = ResolveTokenError_OutOfRange;
6193 goto leave;
6195 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6196 *resolve_error = ResolveTokenError_BadTable;
6197 goto leave;
6200 init_generic_context_from_args_handles (&context, type_args, method_args);
6201 method = mono_get_method_checked (image, token, NULL, &context, error);
6203 leave:
6204 HANDLE_FUNCTION_RETURN_VAL (method);
6207 MonoMethod*
6208 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
6210 return module_resolve_method_token (image, token, type_args, method_args, resolve_error, error);
6213 MonoStringHandle
6214 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error, MonoError *error)
6216 int index = mono_metadata_token_index (token);
6218 *resolve_error = ResolveTokenError_Other;
6220 /* Validate token */
6221 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6222 *resolve_error = ResolveTokenError_BadTable;
6223 return NULL_HANDLE_STRING;
6226 if (image_is_dynamic (image)) {
6227 ERROR_DECL (ignore_inner_error);
6228 // FIXME ignoring error
6229 // FIXME Push MONO_HANDLE_NEW to lower layers.
6230 MonoStringHandle result = MONO_HANDLE_NEW (MonoString, (MonoString*)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, ignore_inner_error));
6231 mono_error_cleanup (ignore_inner_error);
6232 return result;
6235 if ((index <= 0) || (index >= image->heap_us.size)) {
6236 *resolve_error = ResolveTokenError_OutOfRange;
6237 return NULL_HANDLE_STRING;
6240 /* FIXME: What to do if the index points into the middle of a string ? */
6241 return mono_ldstr_handle (mono_domain_get (), image, index, error);
6244 static MonoClassField*
6245 module_resolve_field_token (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
6247 HANDLE_FUNCTION_ENTER ();
6248 MonoClass *klass;
6249 int table = mono_metadata_token_table (token);
6250 int index = mono_metadata_token_index (token);
6251 MonoGenericContext context;
6252 MonoClassField *field = NULL;
6254 error_init (error);
6255 *resolve_error = ResolveTokenError_Other;
6257 /* Validate token */
6258 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6259 *resolve_error = ResolveTokenError_BadTable;
6260 goto leave;
6263 if (image_is_dynamic (image)) {
6264 if (table == MONO_TABLE_FIELD) {
6265 ERROR_DECL_VALUE (inner_error);
6266 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &inner_error);
6267 mono_error_cleanup (&inner_error);
6268 goto leave;
6271 if (mono_memberref_is_method (image, token)) {
6272 *resolve_error = ResolveTokenError_BadTable;
6273 goto leave;
6276 init_generic_context_from_args_handles (&context, type_args, method_args);
6277 ERROR_DECL_VALUE (inner_error);
6278 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &inner_error);
6279 mono_error_cleanup (&inner_error);
6280 goto leave;
6283 if ((index <= 0) || (index > image->tables [table].rows)) {
6284 *resolve_error = ResolveTokenError_OutOfRange;
6285 goto leave;
6287 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6288 *resolve_error = ResolveTokenError_BadTable;
6289 goto leave;
6292 init_generic_context_from_args_handles (&context, type_args, method_args);
6293 field = mono_field_from_token_checked (image, token, &klass, &context, error);
6295 leave:
6296 HANDLE_FUNCTION_RETURN_VAL (field);
6299 MonoClassField*
6300 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *resolve_error, MonoError *error)
6302 return module_resolve_field_token (image, token, type_args, method_args, resolve_error, error);
6305 MonoObjectHandle
6306 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArrayHandle type_args, MonoArrayHandle method_args, MonoResolveTokenError *error, MonoError *merror)
6308 int table = mono_metadata_token_table (token);
6310 error_init (merror);
6311 *error = ResolveTokenError_Other;
6313 switch (table) {
6314 case MONO_TABLE_TYPEDEF:
6315 case MONO_TABLE_TYPEREF:
6316 case MONO_TABLE_TYPESPEC: {
6317 MonoType *t = module_resolve_type_token (image, token, type_args, method_args, error, merror);
6318 if (t) {
6319 return MONO_HANDLE_CAST (MonoObject, mono_type_get_object_handle (mono_domain_get (), t, merror));
6321 else
6322 return NULL_HANDLE;
6324 case MONO_TABLE_METHOD:
6325 case MONO_TABLE_METHODSPEC: {
6326 MonoMethod *m = module_resolve_method_token (image, token, type_args, method_args, error, merror);
6327 if (m) {
6328 return MONO_HANDLE_CAST (MonoObject, mono_method_get_object_handle (mono_domain_get (), m, m->klass, merror));
6329 } else
6330 return NULL_HANDLE;
6332 case MONO_TABLE_FIELD: {
6333 MonoClassField *f = module_resolve_field_token (image, token, type_args, method_args, error, merror);
6334 if (f) {
6335 return MONO_HANDLE_CAST (MonoObject, mono_field_get_object_handle (mono_domain_get (), f->parent, f, merror));
6337 else
6338 return NULL_HANDLE;
6340 case MONO_TABLE_MEMBERREF:
6341 if (mono_memberref_is_method (image, token)) {
6342 MonoMethod *m = module_resolve_method_token (image, token, type_args, method_args, error, merror);
6343 if (m) {
6344 return MONO_HANDLE_CAST (MonoObject, mono_method_get_object_handle (mono_domain_get (), m, m->klass, merror));
6345 } else
6346 return NULL_HANDLE;
6348 else {
6349 MonoClassField *f = module_resolve_field_token (image, token, type_args, method_args, error, merror);
6350 if (f) {
6351 return MONO_HANDLE_CAST (MonoObject, mono_field_get_object_handle (mono_domain_get (), f->parent, f, merror));
6353 else
6354 return NULL_HANDLE;
6356 break;
6358 default:
6359 *error = ResolveTokenError_BadTable;
6362 return NULL_HANDLE;
6365 MonoArrayHandle
6366 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error, MonoError *error)
6368 error_init (error);
6369 int table = mono_metadata_token_table (token);
6370 int idx = mono_metadata_token_index (token);
6371 MonoTableInfo *tables = image->tables;
6372 guint32 sig, len;
6373 const char *ptr;
6375 *resolve_error = ResolveTokenError_OutOfRange;
6377 /* FIXME: Support other tables ? */
6378 if (table != MONO_TABLE_STANDALONESIG)
6379 return NULL_HANDLE_ARRAY;
6381 if (image_is_dynamic (image))
6382 return NULL_HANDLE_ARRAY;
6384 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6385 return NULL_HANDLE_ARRAY;
6387 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6389 ptr = mono_metadata_blob_heap (image, sig);
6390 len = mono_metadata_decode_blob_size (ptr, &ptr);
6392 MonoArrayHandle res = mono_array_new_handle (mono_domain_get (), mono_defaults.byte_class, len, error);
6393 return_val_if_nok (error, NULL_HANDLE_ARRAY);
6394 uint32_t h;
6395 gpointer array_base = MONO_ARRAY_HANDLE_PIN (res, guint8, 0, &h);
6396 memcpy (array_base, ptr, len);
6397 mono_gchandle_free_internal (h);
6398 return res;
6401 MonoBoolean
6402 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionTypeHandle ref_type, MonoError *error)
6404 error_init (error);
6405 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
6407 MonoBoolean res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6409 return res;
6412 static void
6413 check_for_invalid_type (MonoClass *klass, MonoError *error)
6415 char *name;
6417 error_init (error);
6419 if (m_class_get_byval_arg (klass)->type != MONO_TYPE_TYPEDBYREF)
6420 return;
6422 name = mono_type_get_full_name (klass);
6423 mono_error_set_type_load_name (error, name, g_strdup (""), "");
6426 MonoReflectionTypeHandle
6427 ves_icall_RuntimeType_make_array_type (MonoReflectionTypeHandle ref_type, int rank, MonoError *error)
6429 error_init (error);
6430 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
6432 MonoClass *klass = mono_class_from_mono_type_internal (type);
6433 check_for_invalid_type (klass, error);
6434 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
6436 MonoClass *aklass;
6437 if (rank == 0) //single dimension array
6438 aklass = mono_class_create_array (klass, 1);
6439 else
6440 aklass = mono_class_create_bounded_array (klass, rank, TRUE);
6442 if (mono_class_has_failure (aklass)) {
6443 mono_error_set_for_class_failure (error, aklass);
6444 return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
6447 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
6448 return mono_type_get_object_handle (domain, m_class_get_byval_arg (aklass), error);
6451 MonoReflectionTypeHandle
6452 ves_icall_RuntimeType_make_byref_type (MonoReflectionTypeHandle ref_type, MonoError *error)
6454 error_init (error);
6455 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
6457 MonoClass *klass = mono_class_from_mono_type_internal (type);
6458 mono_class_init_checked (klass, error);
6459 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
6461 check_for_invalid_type (klass, error);
6462 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
6464 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
6465 return mono_type_get_object_handle (domain, m_class_get_this_arg (klass), error);
6468 MonoReflectionTypeHandle
6469 ves_icall_RuntimeType_MakePointerType (MonoReflectionTypeHandle ref_type, MonoError *error)
6471 error_init (error);
6472 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
6473 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
6474 MonoClass *klass = mono_class_from_mono_type_internal (type);
6475 mono_class_init_checked (klass, error);
6476 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
6478 check_for_invalid_type (klass, error);
6479 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE));
6481 MonoClass *pklass = mono_class_create_ptr (type);
6483 return mono_type_get_object_handle (domain, m_class_get_byval_arg (pklass), error);
6486 MonoObjectHandle
6487 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionTypeHandle ref_type, MonoObjectHandle target,
6488 MonoReflectionMethodHandle info, MonoBoolean throwOnBindFailure, MonoError *error)
6490 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
6491 MonoClass *delegate_class = mono_class_from_mono_type_internal (type);
6492 gpointer func;
6493 MonoMethod *method = MONO_HANDLE_GETVAL (info, method);
6494 MonoMethodSignature *sig = mono_method_signature_internal (method);
6496 mono_class_init_checked (delegate_class, error);
6497 return_val_if_nok (error, NULL_HANDLE);
6499 if (!(m_class_get_parent (delegate_class) == mono_defaults.multicastdelegate_class)) {
6500 /* FIXME improve this exception message */
6501 mono_error_set_execution_engine (error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6502 __func__,
6503 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6504 return NULL_HANDLE;
6507 if (mono_security_core_clr_enabled ()) {
6508 ERROR_DECL_VALUE (security_error);
6509 if (!mono_security_core_clr_ensure_delegate_creation (method, &security_error)) {
6510 if (throwOnBindFailure)
6511 mono_error_move (error, &security_error);
6512 else
6513 mono_error_cleanup (&security_error);
6514 return NULL_HANDLE;
6518 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6519 if (!method->is_inflated) {
6520 mono_error_set_argument (error, "method", " Cannot bind to the target method because its signature differs from that of the delegate type");
6521 return NULL_HANDLE;
6525 MonoObjectHandle delegate = mono_object_new_handle (MONO_HANDLE_DOMAIN (ref_type), delegate_class, error);
6526 return_val_if_nok (error, NULL_HANDLE);
6528 if (method_is_dynamic (method)) {
6529 /* Creating a trampoline would leak memory */
6530 func = mono_compile_method_checked (method, error);
6531 return_val_if_nok (error, NULL_HANDLE);
6532 } else {
6533 if (!MONO_HANDLE_IS_NULL (target) && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_handle_class (target)) {
6534 method = mono_object_handle_get_virtual_method (target, method, error);
6535 return_val_if_nok (error, NULL_HANDLE);
6537 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, error);
6538 return_val_if_nok (error, NULL_HANDLE);
6539 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6542 mono_delegate_ctor_with_method (delegate, target, func, method, error);
6543 return_val_if_nok (error, NULL_HANDLE);
6544 return delegate;
6547 MonoMulticastDelegateHandle
6548 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegateHandle delegate, MonoError *error)
6550 error_init (error);
6552 MonoClass *klass = mono_handle_class (delegate);
6553 g_assert (mono_class_has_parent (klass, mono_defaults.multicastdelegate_class));
6555 MonoMulticastDelegateHandle ret = MONO_HANDLE_CAST (MonoMulticastDelegate, mono_object_new_handle (MONO_HANDLE_DOMAIN (delegate), klass, error));
6556 return_val_if_nok (error, MONO_HANDLE_CAST (MonoMulticastDelegate, NULL_HANDLE));
6558 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoDelegate, ret), invoke_impl, gpointer, mono_runtime_create_delegate_trampoline (klass));
6560 return ret;
6563 MonoReflectionMethodHandle
6564 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegateHandle delegate, MonoError *error)
6566 error_init (error);
6568 MonoObjectHandle delegate_target = MONO_HANDLE_NEW_GET (MonoObject, delegate, target);
6569 MonoMethod *m = mono_object_handle_get_virtual_method (delegate_target, MONO_HANDLE_GETVAL (delegate, method), error);
6570 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
6571 return mono_method_get_object_handle (mono_domain_get (), m, m->klass, error);
6574 /* System.Buffer */
6576 static inline gint32
6577 mono_array_get_byte_length (MonoArray *array)
6579 MonoClass *klass;
6580 int length;
6581 int i;
6583 klass = array->obj.vtable->klass;
6585 if (array->bounds == NULL)
6586 length = array->max_length;
6587 else {
6588 length = 1;
6589 int klass_rank = m_class_get_rank (klass);
6590 for (i = 0; i < klass_rank; ++ i)
6591 length *= array->bounds [i].length;
6594 switch (m_class_get_byval_arg (m_class_get_element_class (klass))->type) {
6595 case MONO_TYPE_I1:
6596 case MONO_TYPE_U1:
6597 case MONO_TYPE_BOOLEAN:
6598 return length;
6599 case MONO_TYPE_I2:
6600 case MONO_TYPE_U2:
6601 case MONO_TYPE_CHAR:
6602 return length << 1;
6603 case MONO_TYPE_I4:
6604 case MONO_TYPE_U4:
6605 case MONO_TYPE_R4:
6606 return length << 2;
6607 case MONO_TYPE_I:
6608 case MONO_TYPE_U:
6609 return length * sizeof (gpointer);
6610 case MONO_TYPE_I8:
6611 case MONO_TYPE_U8:
6612 case MONO_TYPE_R8:
6613 return length << 3;
6614 default:
6615 return -1;
6619 gint32
6620 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6622 return mono_array_get_byte_length (array);
6625 gint8
6626 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6628 return mono_array_get_internal (array, gint8, idx);
6631 void
6632 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6634 mono_array_set_internal (array, gint8, idx, value);
6637 void
6638 ves_icall_System_Buffer_MemcpyInternal (gpointer dest, gconstpointer src, gint32 count)
6640 memcpy (dest, src, count);
6643 MonoBoolean
6644 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6646 guint8 *src_buf, *dest_buf;
6648 if (count < 0) {
6649 ERROR_DECL (error);
6650 mono_error_set_argument (error, "count", "is negative");
6651 mono_error_set_pending_exception (error);
6652 return FALSE;
6655 g_assert (count >= 0);
6657 /* This is called directly from the class libraries without going through the managed wrapper */
6658 MONO_CHECK_ARG_NULL (src, FALSE);
6659 MONO_CHECK_ARG_NULL (dest, FALSE);
6661 /* watch out for integer overflow */
6662 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6663 return FALSE;
6665 src_buf = (guint8 *)src->vector + src_offset;
6666 dest_buf = (guint8 *)dest->vector + dest_offset;
6668 if (src != dest)
6669 memcpy (dest_buf, src_buf, count);
6670 else
6671 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6673 return TRUE;
6676 #ifndef DISABLE_REMOTING
6677 MonoObjectHandle
6678 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObjectHandle this_obj, MonoStringHandle class_name, MonoError *error)
6680 error_init (error);
6681 MonoDomain *domain = MONO_HANDLE_DOMAIN (this_obj);
6682 MonoRealProxyHandle rp = MONO_HANDLE_CAST (MonoRealProxy, this_obj);
6684 MonoObjectHandle res = mono_object_new_handle (domain, mono_defaults.transparent_proxy_class, error);
6685 return_val_if_nok (error, NULL_HANDLE);
6687 MonoTransparentProxyHandle tp = MONO_HANDLE_CAST (MonoTransparentProxy, res);
6689 MONO_HANDLE_SET (tp, rp, rp);
6691 MonoReflectionTypeHandle reftype = MONO_HANDLE_NEW (MonoReflectionType, NULL);
6692 MONO_HANDLE_GET (reftype, rp, class_to_proxy);
6693 MonoType *type = MONO_HANDLE_GETVAL (reftype, type);
6694 MonoClass *klass = mono_class_from_mono_type_internal (type);
6696 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6697 mono_class_setup_vtable (klass);
6698 if (mono_class_has_failure (klass)) {
6699 mono_error_set_for_class_failure (error, klass);
6700 return NULL_HANDLE;
6703 MonoObjectHandle remoting_obj = mono_object_handle_isinst (this_obj, mono_defaults.iremotingtypeinfo_class, error);
6704 return_val_if_nok (error, NULL_HANDLE);
6705 MONO_HANDLE_SETVAL (tp, custom_type_info, MonoBoolean, !MONO_HANDLE_IS_NULL (remoting_obj));
6707 MonoRemoteClass *remote_class = (MonoRemoteClass*)mono_remote_class (domain, class_name, klass, error);
6708 return_val_if_nok (error, NULL_HANDLE);
6709 MONO_HANDLE_SETVAL (tp, remote_class, MonoRemoteClass*, remote_class);
6711 MONO_HANDLE_SETVAL (res, vtable, MonoVTable*, (MonoVTable*)mono_remote_class_vtable (domain, remote_class, rp, error));
6712 return_val_if_nok (error, NULL_HANDLE);
6713 return res;
6716 MonoReflectionType *
6717 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6719 ERROR_DECL (error);
6720 g_assert (tp != NULL && mono_object_class (tp) == mono_defaults.transparent_proxy_class);
6721 g_assert (tp->remote_class != NULL && tp->remote_class->proxy_class != NULL);
6722 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), m_class_get_byval_arg (tp->remote_class->proxy_class), error);
6723 mono_error_set_pending_exception (error);
6725 return ret;
6727 #endif
6729 /* System.Environment */
6731 MonoStringHandle
6732 ves_icall_System_Environment_get_UserName (MonoError *error)
6734 error_init (error);
6735 /* using glib is more portable */
6736 return mono_string_new_handle (mono_domain_get (), g_get_user_name (), error);
6739 #ifndef HOST_WIN32
6740 static MonoStringHandle
6741 mono_icall_get_machine_name (MonoError *error)
6743 error_init (error);
6744 #if !defined(DISABLE_SOCKETS)
6745 MonoStringHandle result;
6746 char *buf;
6747 int n, i;
6748 #if defined _SC_HOST_NAME_MAX
6749 n = sysconf (_SC_HOST_NAME_MAX);
6750 if (n == -1)
6751 #endif
6752 n = 512;
6753 buf = (char*)g_malloc (n + 1);
6755 if (gethostname (buf, n) == 0){
6756 buf [n] = 0;
6757 // try truncating the string at the first dot
6758 for (i = 0; i < n; i++) {
6759 if (buf [i] == '.') {
6760 buf [i] = 0;
6761 break;
6764 result = mono_string_new_handle (mono_domain_get (), buf, error);
6765 } else
6766 result = MONO_HANDLE_CAST (MonoString, NULL_HANDLE);
6767 g_free (buf);
6769 return result;
6770 #else
6771 return mono_string_new_handle (mono_domain_get (), "mono", error);
6772 #endif
6774 #endif /* !HOST_WIN32 */
6776 MonoStringHandle
6777 ves_icall_System_Environment_get_MachineName (MonoError *error)
6779 error_init (error);
6780 return mono_icall_get_machine_name (error);
6783 #ifndef HOST_WIN32
6784 static inline int
6785 mono_icall_get_platform (void)
6787 #if defined(__MACH__)
6788 /* OSX */
6790 // Notice that the value is hidden from user code, and only exposed
6791 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6792 // define and making assumptions based on Unix/128/4 values before there
6793 // was a MacOS define. Lots of code would assume that not-Unix meant
6794 // Windows, but in this case, it would be OSX.
6796 return 6;
6797 #else
6798 /* Unix */
6799 return 4;
6800 #endif
6802 #endif /* !HOST_WIN32 */
6805 ves_icall_System_Environment_get_Platform (void)
6807 return mono_icall_get_platform ();
6810 #ifndef HOST_WIN32
6811 static inline MonoStringHandle
6812 mono_icall_get_new_line (MonoError *error)
6814 error_init (error);
6815 return mono_string_new_handle (mono_domain_get (), "\n", error);
6817 #endif /* !HOST_WIN32 */
6819 MonoStringHandle
6820 ves_icall_System_Environment_get_NewLine (MonoError *error)
6822 return mono_icall_get_new_line (error);
6825 #ifndef HOST_WIN32
6826 static inline MonoBoolean
6827 mono_icall_is_64bit_os (void)
6829 #if SIZEOF_VOID_P == 8
6830 return TRUE;
6831 #else
6832 #if defined(HAVE_SYS_UTSNAME_H)
6833 struct utsname name;
6835 if (uname (&name) >= 0) {
6836 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0 || strncmp (name.machine, "riscv64", 7) == 0;
6838 #endif
6839 return FALSE;
6840 #endif
6842 #endif /* !HOST_WIN32 */
6844 MonoBoolean
6845 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6847 return mono_icall_is_64bit_os ();
6850 MonoStringHandle
6851 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6853 gchar *value;
6855 if (utf8_name == NULL)
6856 return NULL_HANDLE_STRING;
6858 value = g_getenv (utf8_name);
6860 if (value == 0)
6861 return NULL_HANDLE_STRING;
6863 MonoStringHandle res = mono_string_new_handle (mono_domain_get (), value, error);
6864 g_free (value);
6865 return res;
6869 * There is no standard way to get at environ.
6871 #ifndef _MSC_VER
6872 #ifndef __MINGW32_VERSION
6873 #if defined(__APPLE__)
6874 #if defined (TARGET_OSX)
6875 /* Apple defines this in crt_externs.h but doesn't provide that header for
6876 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6877 * in fact exist on all implementations (so far)
6879 G_BEGIN_DECLS
6880 gchar ***_NSGetEnviron(void);
6881 G_END_DECLS
6882 #define environ (*_NSGetEnviron())
6883 #else
6884 static char *mono_environ[1] = { NULL };
6885 #define environ mono_environ
6886 #endif /* defined (TARGET_OSX) */
6887 #else
6888 G_BEGIN_DECLS
6889 extern
6890 char **environ;
6891 G_END_DECLS
6892 #endif
6893 #endif
6894 #endif
6896 MonoArrayHandle
6897 ves_icall_System_Environment_GetCommandLineArgs (MonoError *error)
6899 error_init (error);
6900 MonoArrayHandle result = mono_runtime_get_main_args_handle (error);
6901 return result;
6904 #ifndef HOST_WIN32
6905 static MonoArray *
6906 mono_icall_get_environment_variable_names (MonoError *error)
6908 MonoArray *names;
6909 MonoDomain *domain;
6910 MonoString *str;
6911 gchar **e, **parts;
6912 int n;
6914 error_init (error);
6915 n = 0;
6916 for (e = environ; *e != 0; ++ e)
6917 ++ n;
6919 domain = mono_domain_get ();
6920 names = mono_array_new_checked (domain, mono_defaults.string_class, n, error);
6921 return_val_if_nok (error, NULL);
6923 n = 0;
6924 for (e = environ; *e != 0; ++ e) {
6925 parts = g_strsplit (*e, "=", 2);
6926 if (*parts != 0) {
6927 str = mono_string_new_checked (domain, *parts, error);
6928 if (!is_ok (error)) {
6929 g_strfreev (parts);
6930 return NULL;
6932 mono_array_setref_internal (names, n, str);
6935 g_strfreev (parts);
6937 ++ n;
6940 return names;
6942 #endif /* !HOST_WIN32 */
6944 MonoArray *
6945 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6947 ERROR_DECL (error);
6948 MonoArray *result = mono_icall_get_environment_variable_names (error);
6949 mono_error_set_pending_exception (error);
6950 return result;
6953 void
6954 ves_icall_System_Environment_InternalSetEnvironmentVariable (const gunichar2 *name, gint32 name_length,
6955 const gunichar2 *value, gint32 value_length, MonoError *error)
6957 #ifdef HOST_WIN32
6958 if (!value || !value_length || !value [0])
6959 value = NULL;
6961 SetEnvironmentVariableW (name, value);
6962 #else
6963 char *utf8_name = NULL;
6964 char *utf8_value = NULL;
6966 utf8_name = mono_utf16_to_utf8 (name, name_length, error); // FIXME: this should be ascii
6967 goto_if_nok (error, exit);
6969 if (!value || !value_length || !value [0]) {
6970 g_unsetenv (utf8_name);
6971 goto exit;
6974 utf8_value = mono_utf16_to_utf8 (value, value_length, error);
6975 goto_if_nok (error, exit);
6977 g_setenv (utf8_name, utf8_value, TRUE);
6978 exit:
6979 g_free (utf8_name);
6980 g_free (utf8_value);
6981 #endif
6984 void
6985 ves_icall_System_Environment_Exit (int result)
6987 mono_environment_exitcode_set (result);
6989 if (!mono_runtime_try_shutdown ())
6990 mono_thread_exit ();
6992 /* Suspend all managed threads since the runtime is going away */
6993 mono_thread_suspend_all_other_threads ();
6995 mono_runtime_quit ();
6997 /* we may need to do some cleanup here... */
6998 exit (result);
7001 MonoStringHandle
7002 ves_icall_System_Environment_GetGacPath (MonoError *error)
7004 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
7007 #ifndef HOST_WIN32
7008 static inline MonoStringHandle
7009 mono_icall_get_windows_folder_path (int folder, MonoError *error)
7011 error_init (error);
7012 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7013 return mono_string_new_handle (mono_domain_get (), "", error);
7015 #endif /* !HOST_WIN32 */
7017 MonoStringHandle
7018 ves_icall_System_Environment_GetWindowsFolderPath (int folder, MonoError *error)
7020 return mono_icall_get_windows_folder_path (folder, error);
7023 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
7024 static MonoArray *
7025 mono_icall_get_logical_drives (void)
7027 ERROR_DECL (error);
7028 gunichar2 buf [256], *ptr, *dname;
7029 gunichar2 *u16;
7030 guint initial_size = 127, size = 128;
7031 gint ndrives;
7032 MonoArray *result;
7033 MonoString *drivestr;
7034 MonoDomain *domain = mono_domain_get ();
7035 gint len;
7037 buf [0] = '\0';
7038 ptr = buf;
7040 while (size > initial_size) {
7041 size = (guint) mono_w32file_get_logical_drive (initial_size, ptr);
7042 if (size > initial_size) {
7043 if (ptr != buf)
7044 g_free (ptr);
7045 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
7046 initial_size = size;
7047 size++;
7051 /* Count strings */
7052 dname = ptr;
7053 ndrives = 0;
7054 do {
7055 while (*dname++);
7056 ndrives++;
7057 } while (*dname);
7059 dname = ptr;
7060 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, error);
7061 if (mono_error_set_pending_exception (error))
7062 goto leave;
7064 ndrives = 0;
7065 do {
7066 len = 0;
7067 u16 = dname;
7068 while (*u16) { u16++; len ++; }
7069 drivestr = mono_string_new_utf16_checked (domain, dname, len, error);
7070 if (mono_error_set_pending_exception (error))
7071 goto leave;
7073 mono_array_setref_internal (result, ndrives++, drivestr);
7074 while (*dname++);
7075 } while (*dname);
7077 leave:
7078 if (ptr != buf)
7079 g_free (ptr);
7081 return result;
7083 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
7085 MonoArray *
7086 ves_icall_System_Environment_GetLogicalDrives (void)
7088 return mono_icall_get_logical_drives ();
7091 MonoString *
7092 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7094 ERROR_DECL (error);
7095 gunichar2 volume_name [MAX_PATH + 1];
7097 if (mono_w32file_get_file_system_type (mono_string_chars_internal (path), volume_name, MAX_PATH + 1) == FALSE)
7098 return NULL;
7099 MonoString *result = mono_string_from_utf16_checked (volume_name, error);
7100 mono_error_set_pending_exception (error);
7101 return result;
7104 MonoStringHandle
7105 ves_icall_System_Environment_InternalGetHome (MonoError *error)
7107 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
7110 static const char *encodings [] = {
7111 (char *) 1,
7112 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7113 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7114 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7115 (char *) 2,
7116 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7117 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7118 "x_unicode_2_0_utf_7",
7119 (char *) 3,
7120 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7121 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7122 (char *) 4,
7123 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7124 "iso_10646_ucs2",
7125 (char *) 5,
7126 "unicodefffe", "utf_16be",
7127 (char *) 6,
7128 "iso_8859_1",
7129 (char *) 0
7133 * Returns the internal codepage, if the value of "int_code_page" is
7134 * 1 at entry, and we can not compute a suitable code page number,
7135 * returns the code page as a string
7137 MonoStringHandle
7138 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page, MonoError *error)
7140 error_init (error);
7141 const char *cset;
7142 const char *p;
7143 char *c;
7144 char *codepage = NULL;
7145 int code;
7146 int want_name = *int_code_page;
7147 int i;
7149 *int_code_page = -1;
7151 g_get_charset (&cset);
7152 c = codepage = g_strdup (cset);
7153 for (c = codepage; *c; c++){
7154 if (isascii (*c) && isalpha (*c))
7155 *c = tolower (*c);
7156 if (*c == '-')
7157 *c = '_';
7159 /* g_print ("charset: %s\n", cset); */
7161 /* handle some common aliases */
7162 p = encodings [0];
7163 code = 0;
7164 for (i = 0; p != 0; ){
7165 if ((gsize) p < 7){
7166 code = (gssize) p;
7167 p = encodings [++i];
7168 continue;
7170 if (strcmp (p, codepage) == 0){
7171 *int_code_page = code;
7172 break;
7174 p = encodings [++i];
7177 if (strstr (codepage, "utf_8") != NULL)
7178 *int_code_page |= 0x10000000;
7179 g_free (codepage);
7181 if (want_name && *int_code_page == -1)
7182 return mono_string_new_handle (mono_domain_get (), cset, error);
7183 else
7184 return MONO_HANDLE_CAST (MonoString, NULL_HANDLE);
7187 MonoBoolean
7188 ves_icall_System_Environment_get_HasShutdownStarted (void)
7190 return mono_runtime_is_shutting_down () || mono_domain_is_unloading (mono_domain_get ());
7193 #ifndef HOST_WIN32
7195 void
7196 ves_icall_System_Environment_BroadcastSettingChange (MonoError *error)
7200 #endif
7202 gint32
7203 ves_icall_System_Environment_get_TickCount (void)
7205 /* this will overflow after ~24 days */
7206 return (gint32) (mono_msec_boottime () & 0xffffffff);
7209 gint32
7210 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (MonoError *error)
7212 return 9;
7215 #ifndef DISABLE_REMOTING
7216 MonoBoolean
7217 ves_icall_IsTransparentProxy (MonoObjectHandle proxy, MonoError *error)
7219 if (MONO_HANDLE_IS_NULL (proxy))
7220 return 0;
7222 if (mono_class_is_transparent_proxy (mono_handle_class (proxy)))
7223 return 1;
7225 return 0;
7228 MonoReflectionMethodHandle
7229 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7230 MonoReflectionTypeHandle rtype, MonoReflectionMethodHandle rmethod, MonoError *error)
7232 MonoReflectionMethodHandle ret = MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
7234 if (MONO_HANDLE_IS_NULL (rtype)) {
7235 mono_error_set_argument_null (error, "type", "");
7236 return ret;
7238 if (MONO_HANDLE_IS_NULL (rmethod)) {
7239 mono_error_set_argument_null (error, "method", "");
7240 return ret;
7243 MonoMethod *method = MONO_HANDLE_GETVAL (rmethod, method);
7244 MonoType *type = MONO_HANDLE_GETVAL (rtype, type);
7245 MonoClass *klass = mono_class_from_mono_type_internal (type);
7246 mono_class_init_checked (klass, error);
7247 return_val_if_nok (error, ret);
7249 if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass))
7250 return ret;
7252 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7253 return ret;
7255 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7256 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7257 ret = rmethod;
7258 return ret;
7261 mono_class_setup_vtable (klass);
7262 MonoMethod **vtable = m_class_get_vtable (klass);
7264 MonoMethod *res = NULL;
7265 if (mono_class_is_interface (method->klass)) {
7266 gboolean variance_used = FALSE;
7267 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7268 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7269 if (offs >= 0)
7270 res = vtable [offs + method->slot];
7271 } else {
7272 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7273 return ret;
7275 if (method->slot != -1)
7276 res = vtable [method->slot];
7279 if (!res)
7280 return ret;
7282 ret = mono_method_get_object_handle (mono_domain_get (), res, NULL, error);
7283 return ret;
7286 void
7287 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionTypeHandle type, MonoBoolean enable, MonoError *error)
7289 MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type));
7290 MonoVTable *vtable = mono_class_vtable_checked (mono_domain_get (), klass, error);
7291 return_if_nok (error);
7293 mono_vtable_set_is_remote (vtable, enable);
7296 #else /* DISABLE_REMOTING */
7298 void
7299 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionTypeHandle type, MonoBoolean enable, MonoError *error)
7301 g_assert_not_reached ();
7304 #endif
7306 MonoObjectHandle
7307 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionTypeHandle type, MonoError *error)
7309 MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
7310 MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type));
7311 mono_class_init_checked (klass, error);
7312 return_val_if_nok (error, NULL_HANDLE);
7314 if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass) || mono_class_is_abstract (klass)) {
7315 mono_error_set_argument (error, "type", "Type cannot be instantiated");
7316 return NULL_HANDLE;
7319 if (m_class_get_rank (klass) >= 1) {
7320 g_assert (m_class_get_rank (klass) == 1);
7321 return MONO_HANDLE_CAST (MonoObject, mono_array_new_handle (domain, m_class_get_element_class (klass), 0, error));
7322 } else {
7323 MonoVTable *vtable = mono_class_vtable_checked (domain, klass, error);
7324 return_val_if_nok (error, NULL_HANDLE);
7326 /* Bypass remoting object creation check */
7327 return MONO_HANDLE_NEW (MonoObject, mono_object_new_alloc_specific_checked (vtable, error));
7331 MonoStringHandle
7332 ves_icall_System_IO_get_temp_path (MonoError *error)
7334 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7337 #if defined(ENABLE_MONODROID) || defined(ENABLE_MONOTOUCH)
7339 G_EXTERN_C gpointer CreateZStream (gint32 compress, MonoBoolean gzip, gpointer feeder, gpointer data);
7340 G_EXTERN_C gint32 CloseZStream (gpointer stream);
7341 G_EXTERN_C gint32 Flush (gpointer stream);
7342 G_EXTERN_C gint32 ReadZStream (gpointer stream, gpointer buffer, gint32 length);
7343 G_EXTERN_C gint32 WriteZStream (gpointer stream, gpointer buffer, gint32 length);
7345 gpointer
7346 ves_icall_System_IO_Compression_DeflateStreamNative_CreateZStream (gint32 compress, MonoBoolean gzip, gpointer feeder, gpointer data)
7348 return CreateZStream (compress, gzip, feeder, data);
7351 gint32
7352 ves_icall_System_IO_Compression_DeflateStreamNative_CloseZStream (gpointer stream)
7354 return CloseZStream (stream);
7357 gint32
7358 ves_icall_System_IO_Compression_DeflateStreamNative_Flush (gpointer stream)
7360 return Flush (stream);
7363 gint32
7364 ves_icall_System_IO_Compression_DeflateStreamNative_ReadZStream (gpointer stream, gpointer buffer, gint32 length)
7366 return ReadZStream (stream, buffer, length);
7369 gint32
7370 ves_icall_System_IO_Compression_DeflateStreamNative_WriteZStream (gpointer stream, gpointer buffer, gint32 length)
7372 return WriteZStream (stream, buffer, length);
7375 #endif
7377 #ifndef PLATFORM_NO_DRIVEINFO
7378 MonoBoolean
7379 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7380 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7381 gint32 *error)
7383 gboolean result;
7385 *error = ERROR_SUCCESS;
7387 result = mono_w32file_get_disk_free_space (mono_string_chars_internal (path_name), free_bytes_avail, total_number_of_bytes, total_number_of_free_bytes);
7388 if (!result)
7389 *error = mono_w32error_get_last ();
7391 return result;
7394 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) || G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
7395 static inline guint32
7396 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
7398 return mono_w32file_get_drive_type (mono_string_chars_internal (root_path_name));
7400 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
7402 guint32
7403 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7405 return mono_icall_drive_info_get_drive_type (root_path_name);
7408 #endif /* PLATFORM_NO_DRIVEINFO */
7410 gpointer
7411 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method, MonoError *error)
7413 return mono_compile_method_checked (method, error);
7416 MonoStringHandle
7417 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (MonoError *error)
7419 gchar *path;
7421 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7423 mono_icall_make_platform_path (path);
7425 MonoStringHandle mcpath = mono_string_new_handle (mono_domain_get (), path, error);
7426 g_free (path);
7428 mono_error_assert_ok (error);
7430 return mcpath;
7433 MonoStringHandle
7434 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_app_config (MonoError *error)
7436 const gchar *app_config;
7437 MonoDomain *domain;
7438 gchar *config_file_name, *config_file_path;
7439 gsize len, config_file_path_length, config_ext_length;
7440 gchar *module;
7442 domain = mono_domain_get ();
7443 MonoStringHandle file = MONO_HANDLE_NEW (MonoString, domain->setup->configuration_file);
7444 if (MONO_HANDLE_IS_NULL (file) || MONO_HANDLE_GETVAL (file, length) == 0)
7445 return MONO_HANDLE_CAST (MonoString, mono_new_null ());
7447 // Retrieve config file and remove the extension
7448 config_file_name = mono_string_handle_to_utf8 (file, error);
7449 return_val_if_nok (error, MONO_HANDLE_CAST (MonoString, NULL_HANDLE));
7451 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7452 if (!config_file_path)
7453 config_file_path = config_file_name;
7455 config_file_path_length = strlen (config_file_path);
7456 config_ext_length = strlen (".config");
7457 if (config_file_path_length <= config_ext_length) {
7458 if (config_file_name != config_file_path)
7459 g_free (config_file_name);
7460 return MONO_HANDLE_CAST (MonoString, NULL_HANDLE);
7463 len = config_file_path_length - config_ext_length;
7464 module = (gchar *)g_malloc0 (len + 1);
7465 memcpy (module, config_file_path, len);
7466 // Get the config file from the module name
7467 app_config = mono_config_string_for_assembly_file (module);
7468 // Clean-up
7469 g_free (module);
7470 if (config_file_name != config_file_path)
7471 g_free (config_file_name);
7472 g_free (config_file_path);
7474 if (!app_config)
7475 return MONO_HANDLE_CAST (MonoString, NULL_HANDLE);
7477 return mono_string_new_handle (mono_domain_get (), app_config, error);
7480 static MonoStringHandle
7481 get_bundled_machine_config (MonoError *error)
7483 const gchar *machine_config;
7485 machine_config = mono_get_machine_config ();
7487 if (!machine_config)
7488 return NULL_HANDLE_STRING;
7490 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7493 MonoStringHandle
7494 ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
7496 return get_bundled_machine_config (error);
7500 MonoStringHandle
7501 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7503 return get_bundled_machine_config (error);
7506 MonoStringHandle
7507 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7509 return get_bundled_machine_config (error);
7513 MonoStringHandle
7514 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (MonoError *error)
7516 char *path = g_path_get_dirname (mono_get_config_dir ());
7518 mono_icall_make_platform_path (path);
7520 MonoStringHandle ipath = mono_string_new_handle (mono_domain_get (), path, error);
7521 g_free (path);
7523 return ipath;
7526 MonoBoolean
7527 ves_icall_get_resources_ptr (MonoReflectionAssemblyHandle assembly, gpointer *result, gint32 *size, MonoError *error)
7529 MonoPEResourceDataEntry *entry;
7530 MonoImage *image;
7532 if (MONO_HANDLE_IS_NULL (assembly) || !result || !size)
7533 return FALSE;
7535 *result = NULL;
7536 *size = 0;
7537 MonoAssembly *assm = MONO_HANDLE_GETVAL (assembly, assembly);
7538 image = assm->image;
7539 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7540 if (!entry)
7541 return FALSE;
7543 *result = mono_image_rva_map (image, entry->rde_data_offset);
7544 if (!(*result)) {
7545 g_free (entry);
7546 return FALSE;
7548 *size = entry->rde_size;
7549 g_free (entry);
7550 return TRUE;
7553 MonoBoolean
7554 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (MonoError *error)
7556 return mono_is_debugger_attached ();
7559 MonoBoolean
7560 ves_icall_System_Diagnostics_Debugger_IsLogging (MonoError *error)
7562 return mono_get_runtime_callbacks ()->debug_log_is_enabled
7563 && mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7566 void
7567 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoStringHandle category, MonoStringHandle message, MonoError *error)
7569 if (mono_get_runtime_callbacks ()->debug_log)
7570 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7573 #ifndef HOST_WIN32
7574 static inline void
7575 mono_icall_write_windows_debug_string (const gunichar2 *message)
7577 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7579 #endif /* !HOST_WIN32 */
7581 void
7582 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (const gunichar2 *message, MonoError *error)
7584 mono_icall_write_windows_debug_string (message);
7587 /* Only used for value types */
7588 MonoObjectHandle
7589 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionTypeHandle ref_type, MonoError *error)
7591 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
7592 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
7593 MonoClass *klass = mono_class_from_mono_type_internal (type);
7595 mono_class_init_checked (klass, error);
7596 return_val_if_nok (error, NULL_HANDLE);
7598 if (mono_class_is_nullable (klass))
7599 /* No arguments -> null */
7600 return NULL_HANDLE;
7602 return mono_object_new_handle (domain, klass, error);
7605 MonoReflectionMethodHandle
7606 ves_icall_MonoMethod_get_base_method (MonoReflectionMethodHandle m, MonoBoolean definition, MonoError *error)
7608 MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
7610 MonoMethod *base = mono_method_get_base_method (method, definition, error);
7611 return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
7612 if (base == method) {
7613 /* we want to short-circuit and return 'm' here. But we should
7614 return the same method object that
7615 mono_method_get_object_handle, below would return. Since
7616 that call takes NULL for the reftype argument, it will take
7617 base->klass as the reflected type for the MonoMethod. So we
7618 need to check that m also has base->klass as the reflected
7619 type. */
7620 MonoReflectionTypeHandle orig_reftype = MONO_HANDLE_NEW_GET (MonoReflectionType, m, reftype);
7621 MonoClass *orig_klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (orig_reftype, type));
7622 if (base->klass == orig_klass)
7623 return m;
7625 return mono_method_get_object_handle (mono_domain_get (), base, NULL, error);
7628 MonoStringHandle
7629 ves_icall_MonoMethod_get_name (MonoReflectionMethodHandle m, MonoError *error)
7631 MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
7633 MonoStringHandle s = mono_string_new_handle (MONO_HANDLE_DOMAIN (m), method->name, error);
7634 return_val_if_nok (error, NULL_HANDLE_STRING);
7635 MONO_HANDLE_SET (m, name, s);
7636 return s;
7639 void
7640 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7642 iter->sig = *(MonoMethodSignature**)argsp;
7644 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7645 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7647 iter->next_arg = 0;
7648 /* FIXME: it's not documented what start is exactly... */
7649 if (start) {
7650 iter->args = start;
7651 } else {
7652 iter->args = argsp + sizeof (gpointer);
7654 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7656 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7659 MonoTypedRef
7660 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7662 guint32 i, arg_size;
7663 gint32 align;
7664 MonoTypedRef res;
7666 i = iter->sig->sentinelpos + iter->next_arg;
7668 g_assert (i < iter->sig->param_count);
7670 res.type = iter->sig->params [i];
7671 res.klass = mono_class_from_mono_type_internal (res.type);
7672 arg_size = mono_type_stack_size (res.type, &align);
7673 #if defined(__arm__) || defined(__mips__)
7674 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7675 #endif
7676 res.value = iter->args;
7677 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7678 if (arg_size <= sizeof (gpointer)) {
7679 int dummy;
7680 int padding = arg_size - mono_type_size (res.type, &dummy);
7681 res.value = (guint8*)res.value + padding;
7683 #endif
7684 iter->args = (char*)iter->args + arg_size;
7685 iter->next_arg++;
7687 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7689 return res;
7692 MonoTypedRef
7693 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7695 guint32 i, arg_size;
7696 gint32 align;
7697 MonoTypedRef res;
7699 i = iter->sig->sentinelpos + iter->next_arg;
7701 g_assert (i < iter->sig->param_count);
7703 while (i < iter->sig->param_count) {
7704 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7705 continue;
7706 res.type = iter->sig->params [i];
7707 res.klass = mono_class_from_mono_type_internal (res.type);
7708 /* FIXME: endianess issue... */
7709 arg_size = mono_type_stack_size (res.type, &align);
7710 #if defined(__arm__) || defined(__mips__)
7711 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7712 #endif
7713 res.value = iter->args;
7714 iter->args = (char*)iter->args + arg_size;
7715 iter->next_arg++;
7716 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7717 return res;
7719 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7721 res.type = NULL;
7722 res.value = NULL;
7723 res.klass = NULL;
7724 return res;
7727 MonoType*
7728 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7730 gint i;
7732 i = iter->sig->sentinelpos + iter->next_arg;
7734 g_assert (i < iter->sig->param_count);
7736 return iter->sig->params [i];
7739 MonoObjectHandle
7740 mono_TypedReference_ToObject (MonoTypedRef* tref, MonoError *error)
7742 return typed_reference_to_object (tref, error);
7745 MonoTypedRef
7746 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7748 MonoTypedRef res;
7749 MonoReflectionField *f;
7750 MonoClass *klass;
7751 MonoType *ftype = NULL;
7752 guint8 *p = NULL;
7753 int i;
7755 memset (&res, 0, sizeof (res));
7757 g_assert (fields);
7758 g_assert (mono_array_length_internal (fields) > 0);
7760 klass = target->vtable->klass;
7762 for (i = 0; i < mono_array_length_internal (fields); ++i) {
7763 f = mono_array_get_internal (fields, MonoReflectionField*, i);
7764 g_assert (f);
7766 if (i == 0)
7767 p = (guint8*)target + f->field->offset;
7768 else
7769 p += f->field->offset - sizeof (MonoObject);
7770 klass = mono_class_from_mono_type_internal (f->field->type);
7771 ftype = f->field->type;
7774 res.type = ftype;
7775 res.klass = mono_class_from_mono_type_internal (ftype);
7776 res.value = p;
7778 return res;
7781 static void
7782 prelink_method (MonoMethod *method, MonoError *error)
7784 const char *exc_class, *exc_arg;
7786 error_init (error);
7787 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7788 return;
7789 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7790 if (exc_class) {
7791 mono_error_set_generic_error (error, "System", exc_class, "%s", exc_arg);
7792 return;
7794 /* create the wrapper, too? */
7797 void
7798 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethodHandle method, MonoError *error)
7800 error_init (error);
7802 prelink_method (MONO_HANDLE_GETVAL (method, method), error);
7805 void
7806 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionTypeHandle type, MonoError *error)
7808 error_init (error);
7809 MonoClass *klass = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (type, type));
7810 MonoMethod* m;
7811 gpointer iter = NULL;
7813 mono_class_init_checked (klass, error);
7814 return_if_nok (error);
7816 while ((m = mono_class_get_methods (klass, &iter))) {
7817 prelink_method (m, error);
7818 return_if_nok (error);
7823 * used by System.Runtime.InteropServices.RuntimeInformation.(OS|Process)Architecture;
7824 * which use them in different ways for filling in an enum
7826 MonoStringHandle
7827 ves_icall_System_Runtime_InteropServices_RuntimeInformation_get_RuntimeArchitecture (MonoError *error)
7829 error_init (error);
7830 return mono_string_new_handle (mono_domain_get (), mono_config_get_cpu (), error);
7834 ves_icall_Interop_Sys_DoubleToString(double value, char *format, char *buffer, int bufferLength)
7836 return snprintf(buffer, bufferLength, format, value);
7839 void
7840 ves_icall_System_Runtime_RuntimeImports_ecvt_s(char *buffer, size_t sizeInBytes, double value, int count, int* dec, int* sign)
7842 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7843 _ecvt_s(buffer, sizeInBytes, value, count, dec, sign);
7844 #endif
7848 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7849 void
7850 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7851 gint32 const **exponents,
7852 gunichar2 const **digitLowerTable,
7853 gunichar2 const **digitUpperTable,
7854 gint64 const **tenPowersList,
7855 gint32 const **decHexDigits)
7857 *mantissas = Formatter_MantissaBitsTable;
7858 *exponents = Formatter_TensExponentTable;
7859 *digitLowerTable = Formatter_DigitLowerTable;
7860 *digitUpperTable = Formatter_DigitUpperTable;
7861 *tenPowersList = Formatter_TenPowersList;
7862 *decHexDigits = Formatter_DecHexDigits;
7865 static gboolean
7866 add_modifier_to_array (MonoDomain *domain, MonoImage *image, MonoCustomMod *modifier, MonoArrayHandle dest, int dest_idx, MonoError *error)
7868 HANDLE_FUNCTION_ENTER ();
7869 error_init (error);
7870 MonoClass *klass = mono_class_get_checked (image, modifier->token, error);
7871 goto_if_nok (error, leave);
7873 MonoReflectionTypeHandle rt;
7874 rt = mono_type_get_object_handle (domain, m_class_get_byval_arg (klass), error);
7875 goto_if_nok (error, leave);
7877 MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rt);
7878 leave:
7879 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
7883 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7884 * and avoid useless allocations.
7886 static MonoArrayHandle
7887 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7889 int i, count = 0;
7890 MonoDomain *domain = mono_domain_get ();
7892 MonoCustomModContainer *cmods = mono_type_get_cmods (type);
7893 if (!cmods)
7894 goto fail;
7896 error_init (error);
7897 for (i = 0; i < cmods->count; ++i) {
7898 if ((optional && !cmods->modifiers [i].required) || (!optional && cmods->modifiers [i].required))
7899 count++;
7901 if (!count)
7902 goto fail;
7904 MonoArrayHandle res;
7905 res = mono_array_new_handle (domain, mono_defaults.systemtype_class, count, error);
7906 goto_if_nok (error, fail);
7907 count = 0;
7908 for (i = cmods->count - 1; i >= 0; --i) {
7909 if ((optional && !cmods->modifiers [i].required) || (!optional && cmods->modifiers [i].required)) {
7910 if (!add_modifier_to_array (domain, image, &cmods->modifiers [i], res, count , error))
7911 goto fail;
7912 count++;
7915 return res;
7916 fail:
7917 return MONO_HANDLE_NEW (MonoArray, NULL);
7920 MonoArrayHandle
7921 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameterHandle param, MonoBoolean optional, MonoError *error)
7923 error_init (error);
7924 MonoReflectionTypeHandle rt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
7925 MONO_HANDLE_GET (rt, param, ClassImpl);
7926 MonoType *type = MONO_HANDLE_GETVAL (rt, type);
7927 MonoObjectHandle member = MONO_HANDLE_NEW (MonoObject, NULL);
7928 MONO_HANDLE_GET (member, param, MemberImpl);
7929 MonoClass *member_class = mono_handle_class (member);
7930 MonoMethod *method = NULL;
7931 MonoImage *image;
7932 int pos;
7933 MonoMethodSignature *sig;
7935 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7936 method = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionMethod, member), method);
7937 } else if (m_class_get_image (member_class) == mono_defaults.corlib && !strcmp ("MonoProperty", m_class_get_name (member_class))) {
7938 MonoProperty *prop = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionProperty, member), property);
7939 if (!(method = prop->get))
7940 method = prop->set;
7941 g_assert (method);
7942 } else {
7943 char *type_name = mono_type_get_full_name (member_class);
7944 mono_error_set_not_supported (error, "Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7945 g_free (type_name);
7946 return NULL_HANDLE_ARRAY;
7949 image = m_class_get_image (method->klass);
7950 pos = MONO_HANDLE_GETVAL (param, PositionImpl);
7951 sig = mono_method_signature_internal (method);
7952 if (pos == -1)
7953 type = sig->ret;
7954 else
7955 type = sig->params [pos];
7957 return type_array_from_modifiers (image, type, optional, error);
7960 static MonoType*
7961 get_property_type (MonoProperty *prop)
7963 MonoMethodSignature *sig;
7964 if (prop->get) {
7965 sig = mono_method_signature_internal (prop->get);
7966 return sig->ret;
7967 } else if (prop->set) {
7968 sig = mono_method_signature_internal (prop->set);
7969 return sig->params [sig->param_count - 1];
7971 return NULL;
7974 MonoArrayHandle
7975 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionPropertyHandle property, MonoBoolean optional, MonoError *error)
7977 error_init (error);
7978 MonoProperty *prop = MONO_HANDLE_GETVAL (property, property);
7979 MonoClass *klass = MONO_HANDLE_GETVAL (property, klass);
7980 MonoType *type = get_property_type (prop);
7981 MonoImage *image = m_class_get_image (klass);
7983 if (!type)
7984 return NULL_HANDLE_ARRAY;
7985 return type_array_from_modifiers (image, type, optional, error);
7989 *Construct a MonoType suited to be used to decode a constant blob object.
7991 * @type is the target type which will be constructed
7992 * @blob_type is the blob type, for example, that comes from the constant table
7993 * @real_type is the expected constructed type.
7995 static void
7996 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7998 type->type = blob_type;
7999 type->data.klass = NULL;
8000 if (blob_type == MONO_TYPE_CLASS)
8001 type->data.klass = mono_defaults.object_class;
8002 else if (real_type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (real_type->data.klass)) {
8003 /* For enums, we need to use the base type */
8004 type->type = MONO_TYPE_VALUETYPE;
8005 type->data.klass = mono_class_from_mono_type_internal (real_type);
8006 } else
8007 type->data.klass = mono_class_from_mono_type_internal (real_type);
8010 MonoObject*
8011 ves_icall_property_info_get_default_value (MonoReflectionProperty *property)
8013 ERROR_DECL (error);
8014 MonoType blob_type;
8015 MonoProperty *prop = property->property;
8016 MonoType *type = get_property_type (prop);
8017 MonoDomain *domain = mono_object_domain (property);
8018 MonoTypeEnum def_type;
8019 const char *def_value;
8020 MonoObject *o;
8022 mono_class_init (prop->parent);
8024 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8025 mono_error_set_invalid_operation (error, NULL);
8026 mono_error_set_pending_exception (error);
8027 return NULL;
8030 def_value = mono_class_get_property_default_value (prop, &def_type);
8032 mono_type_from_blob_type (&blob_type, def_type, type);
8033 o = mono_get_object_from_blob (domain, &blob_type, def_value, error);
8035 mono_error_set_pending_exception (error);
8036 return o;
8039 MonoBoolean
8040 ves_icall_MonoCustomAttrs_IsDefinedInternal (MonoObjectHandle obj, MonoReflectionTypeHandle attr_type, MonoError *error)
8042 error_init (error);
8043 MonoClass *attr_class = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (attr_type, type));
8045 mono_class_init_checked (attr_class, error);
8046 return_val_if_nok (error, FALSE);
8048 MonoCustomAttrInfo *cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
8049 return_val_if_nok (error, FALSE);
8051 if (!cinfo)
8052 return FALSE;
8053 gboolean found = mono_custom_attrs_has_attr (cinfo, attr_class);
8054 if (!cinfo->cached)
8055 mono_custom_attrs_free (cinfo);
8056 return found;
8059 MonoArrayHandle
8060 ves_icall_MonoCustomAttrs_GetCustomAttributesInternal (MonoObjectHandle obj, MonoReflectionTypeHandle attr_type, MonoBoolean pseudoattrs, MonoError *error)
8062 MonoClass *attr_class;
8063 if (MONO_HANDLE_IS_NULL (attr_type))
8064 attr_class = NULL;
8065 else
8066 attr_class = mono_class_from_mono_type_internal (MONO_HANDLE_GETVAL (attr_type, type));
8068 if (attr_class) {
8069 mono_class_init_checked (attr_class, error);
8070 return_val_if_nok (error, NULL_HANDLE_ARRAY);
8073 return mono_reflection_get_custom_attrs_by_type_handle (obj, attr_class, error);
8076 MonoArrayHandle
8077 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObjectHandle obj, MonoError *error)
8079 error_init (error);
8080 return mono_reflection_get_custom_attrs_data_checked (obj, error);
8084 MonoStringHandle
8085 ves_icall_Mono_Runtime_GetDisplayName (MonoError *error)
8087 char *info;
8088 MonoStringHandle display_name;
8090 error_init (error);
8091 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8092 display_name = mono_string_new_handle (mono_domain_get (), info, error);
8093 g_free (info);
8094 return display_name;
8097 #ifndef HOST_WIN32
8098 static inline gint32
8099 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
8101 return WAIT_TIMEOUT;
8103 #endif /* !HOST_WIN32 */
8105 gint32
8106 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds, MonoError *error)
8108 return mono_icall_wait_for_input_idle (handle, milliseconds);
8111 gint32
8112 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (MonoError *error)
8114 return mono_process_current_pid ();
8117 MonoBoolean
8118 ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (MonoError *error)
8120 #if HAVE_BTLS
8121 return TRUE;
8122 #else
8123 return FALSE;
8124 #endif
8127 #ifndef DISABLE_COM
8130 ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoExceptionHandle ex, MonoError *error)
8132 mono_error_set_not_implemented (error, "System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented.");
8133 return 0;
8136 MonoObjectHandle
8137 ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObjectHandle type, MonoError *error)
8139 mono_error_set_not_implemented (error, "System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented.");
8140 return NULL_HANDLE;
8143 void*
8144 ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObjectHandle obj, MonoError *error)
8146 mono_error_set_not_implemented (error, "System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented.");
8147 return NULL;
8150 MonoObjectHandle
8151 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo(MonoError *error)
8153 mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented.");
8154 return NULL_HANDLE;
8157 MonoBoolean
8158 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException (int ierr, MonoStringHandle message, void* languageException, MonoError *error)
8160 mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented.");
8161 return FALSE;
8164 void
8165 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError (MonoObjectHandle oerr, MonoError *error)
8167 mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented.");
8171 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoStringHandle sourceString, int length, void** hstring, MonoError *error)
8173 mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented.");
8174 return 0;
8178 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring, MonoError *error)
8180 mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented.");
8181 return 0;
8184 mono_unichar2*
8185 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length, MonoError *error)
8187 mono_error_set_not_implemented (error, "System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented.");
8188 return NULL;
8191 #endif
8193 void
8194 ves_icall_System_IO_LogcatTextWriter_Log (const char *appname, gint32 level, const char *message)
8196 g_log (appname, (GLogLevelFlags)level, "%s", message);
8199 static MonoIcallTableCallbacks icall_table;
8200 static mono_mutex_t icall_mutex;
8201 static GHashTable *icall_hash = NULL;
8202 static GHashTable *icall_hash_foreign = NULL;
8203 static GHashTable *jit_icall_hash_name = NULL;
8204 static GHashTable *jit_icall_hash_addr = NULL;
8206 void
8207 mono_install_icall_table_callbacks (MonoIcallTableCallbacks *cb)
8209 g_assert (cb->version == MONO_ICALL_TABLE_CALLBACKS_VERSION);
8210 memcpy (&icall_table, cb, sizeof (MonoIcallTableCallbacks));
8213 void
8214 mono_icall_init (void)
8216 #ifndef DISABLE_ICALL_TABLES
8217 mono_icall_table_init ();
8218 #endif
8219 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8220 icall_hash_foreign = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8221 mono_os_mutex_init (&icall_mutex);
8224 static void
8225 mono_icall_lock (void)
8227 mono_locks_os_acquire (&icall_mutex, IcallLock);
8230 static void
8231 mono_icall_unlock (void)
8233 mono_locks_os_release (&icall_mutex, IcallLock);
8236 void
8237 mono_icall_cleanup (void)
8239 g_hash_table_destroy (icall_hash);
8240 g_hash_table_destroy (icall_hash_foreign);
8241 g_hash_table_destroy (jit_icall_hash_name);
8242 g_hash_table_destroy (jit_icall_hash_addr);
8243 mono_os_mutex_destroy (&icall_mutex);
8247 * mono_add_internal_call:
8248 * \param name method specification to surface to the managed world
8249 * \param method pointer to a C method to invoke when the method is called
8251 * This method surfaces the C function pointed by \p method as a method
8252 * that has been surfaced in managed code with the method specified in
8253 * \p name as an internal call.
8255 * Internal calls are surfaced to all app domains loaded and they are
8256 * accessibly by a type with the specified name.
8258 * You must provide a fully qualified type name, that is namespaces
8259 * and type name, followed by a colon and the method name, with an
8260 * optional signature to bind.
8262 * For example, the following are all valid declarations:
8264 * \c MyApp.Services.ScriptService:Accelerate
8266 * \c MyApp.Services.ScriptService:Slowdown(int,bool)
8268 * You use method parameters in cases where there might be more than
8269 * one surface method to managed code. That way you can register different
8270 * internal calls for different method overloads.
8272 * The internal calls are invoked with no marshalling. This means that .NET
8273 * types like \c System.String are exposed as \c MonoString* parameters. This is
8274 * different than the way that strings are surfaced in P/Invoke.
8276 * For more information on how the parameters are marshalled, see the
8277 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8278 * page.
8280 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8281 * reference for more information on the format of method descriptions.
8283 void
8284 mono_add_internal_call (const char *name, gconstpointer method)
8286 mono_add_internal_call_with_flags (name, method, FALSE);
8290 * mono_dangerous_add_raw_internal_call:
8291 * \param name method specification to surface to the managed world
8292 * \param method pointer to a C method to invoke when the method is called
8294 * Similar to \c mono_add_internal_call but with more requirements for correct
8295 * operation.
8297 * A thread running a dangerous raw internal call will avoid a thread state
8298 * transition on entry and exit, but it must take responsiblity for cooperating
8299 * with the Mono runtime.
8301 * The \p method must NOT:
8303 * Run for an unbounded amount of time without calling the mono runtime.
8304 * Additionally, the method must switch to GC Safe mode to perform all blocking
8305 * operations: performing blocking I/O, taking locks, etc.
8308 void
8309 mono_dangerous_add_raw_internal_call (const char *name, gconstpointer method)
8311 mono_add_internal_call_with_flags (name, method, TRUE);
8315 * mono_add_internal_call_with_flags:
8316 * \param name method specification to surface to the managed world
8317 * \param method pointer to a C method to invoke when the method is called
8318 * \param cooperative if \c TRUE, run icall in GC Unsafe (cooperatively suspended) mode,
8319 * otherwise GC Safe (blocking)
8321 * Like \c mono_add_internal_call, but if \p cooperative is \c TRUE the added
8322 * icall promises that it will use the coopertive API to inform the runtime
8323 * when it is running blocking operations, that it will not run for unbounded
8324 * amounts of time without safepointing, and that it will not hold managed
8325 * object references across suspend safepoints.
8327 * If \p cooperative is \c FALSE, run the icall in GC Safe mode - the icall may
8328 * block. The icall must obey the GC Safe rules, e.g. it must not touch
8329 * unpinned managed memory.
8332 void
8333 mono_add_internal_call_with_flags (const char *name, gconstpointer method, gboolean cooperative)
8335 mono_icall_lock ();
8337 g_hash_table_insert (cooperative ? icall_hash : icall_hash_foreign , g_strdup (name), (gpointer) method);
8339 mono_icall_unlock ();
8342 void
8343 mono_add_internal_call_internal (const char *name, gconstpointer method)
8345 mono_add_internal_call_with_flags (name, method, TRUE);
8349 * we should probably export this as an helper (handle nested types).
8350 * Returns the number of chars written in buf.
8352 static int
8353 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8355 int nspacelen, cnamelen;
8356 nspacelen = strlen (m_class_get_name_space (klass));
8357 cnamelen = strlen (m_class_get_name (klass));
8358 if (nspacelen + cnamelen + 2 > bufsize)
8359 return 0;
8360 if (nspacelen) {
8361 memcpy (buf, m_class_get_name_space (klass), nspacelen);
8362 buf [nspacelen ++] = '.';
8364 memcpy (buf + nspacelen, m_class_get_name (klass), cnamelen);
8365 buf [nspacelen + cnamelen] = 0;
8366 return nspacelen + cnamelen;
8369 static void
8370 no_icall_table (void)
8372 g_assert_not_reached ();
8376 * mono_lookup_internal_call_full:
8377 * \param method the method to look up
8378 * \param uses_handles out argument if method needs handles around managed objects.
8379 * \returns a pointer to the icall code for the given method. If
8380 * \p uses_handles is not NULL, it will be set to TRUE if the method
8381 * needs managed objects wrapped using the infrastructure in handle.h
8383 * If the method is not found, warns and returns NULL.
8385 gpointer
8386 mono_lookup_internal_call_full (MonoMethod *method, gboolean warn_on_missing, mono_bool *uses_handles, mono_bool *foreign)
8388 char *sigstart;
8389 char *tmpsig;
8390 char mname [2048];
8391 char *classname;
8392 int typelen = 0, mlen, siglen;
8393 gpointer res;
8395 if (uses_handles)
8396 *uses_handles = FALSE;
8397 if (foreign)
8398 *foreign = FALSE;
8400 g_assert (method != NULL);
8402 if (method->is_inflated)
8403 method = ((MonoMethodInflated *) method)->declaring;
8405 if (m_class_get_nested_in (method->klass)) {
8406 int pos = concat_class_name (mname, sizeof (mname)-2, m_class_get_nested_in (method->klass));
8407 if (!pos)
8408 return NULL;
8410 mname [pos++] = '/';
8411 mname [pos] = 0;
8413 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8414 if (!typelen)
8415 return NULL;
8417 typelen += pos;
8418 } else {
8419 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8420 if (!typelen)
8421 return NULL;
8424 classname = g_strdup (mname);
8426 mname [typelen] = ':';
8427 mname [typelen + 1] = ':';
8429 mlen = strlen (method->name);
8430 memcpy (mname + typelen + 2, method->name, mlen);
8431 sigstart = mname + typelen + 2 + mlen;
8432 *sigstart = 0;
8434 tmpsig = mono_signature_get_desc (mono_method_signature_internal (method), TRUE);
8435 siglen = strlen (tmpsig);
8436 if (typelen + mlen + siglen + 6 > sizeof (mname)) {
8437 g_free (classname);
8438 return NULL;
8440 sigstart [0] = '(';
8441 memcpy (sigstart + 1, tmpsig, siglen);
8442 sigstart [siglen + 1] = ')';
8443 sigstart [siglen + 2] = 0;
8444 g_free (tmpsig);
8446 mono_icall_lock ();
8448 res = g_hash_table_lookup (icall_hash, mname);
8449 if (res) {
8450 g_free (classname);
8451 mono_icall_unlock ();
8452 return res;
8454 res = g_hash_table_lookup (icall_hash_foreign, mname);
8455 if (res) {
8456 if (foreign)
8457 *foreign = TRUE;
8458 g_free (classname);
8459 mono_icall_unlock ();
8460 return res;
8463 /* try without signature */
8464 *sigstart = 0;
8465 res = g_hash_table_lookup (icall_hash, mname);
8466 if (res) {
8467 g_free (classname);
8468 mono_icall_unlock ();
8469 return res;
8471 res = g_hash_table_lookup (icall_hash_foreign, mname);
8472 if (res) {
8473 if (foreign)
8474 *foreign = TRUE;
8475 g_free (classname);
8476 mono_icall_unlock ();
8477 return res;
8481 if (!icall_table.lookup) {
8482 mono_icall_unlock ();
8483 g_free (classname);
8484 /* Fail only when the result is actually used */
8485 /* mono_marshal_get_native_wrapper () depends on this */
8486 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8487 return (gpointer)ves_icall_System_String_ctor_RedirectToCreateString;
8488 else
8489 return (gpointer)no_icall_table;
8490 } else {
8491 res = icall_table.lookup (classname, sigstart - mlen, sigstart, uses_handles);
8492 g_free (classname);
8494 mono_icall_unlock ();
8496 if (res)
8497 return res;
8499 if (warn_on_missing) {
8500 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8501 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8502 g_print ("The out of sync library is: %s\n", m_class_get_image (method->klass)->name);
8503 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8504 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");
8505 g_print ("If you see other errors or faults after this message they are probably related\n");
8506 g_print ("and you need to fix your mono install first.\n");
8509 return NULL;
8514 * mono_lookup_internal_call:
8516 gpointer
8517 mono_lookup_internal_call (MonoMethod *method)
8519 return mono_lookup_internal_call_full (method, TRUE, NULL, NULL);
8523 * mono_lookup_icall_symbol:
8525 * Given the icall METHOD, returns its C symbol.
8527 const char*
8528 mono_lookup_icall_symbol (MonoMethod *m)
8530 if (!icall_table.lookup_icall_symbol)
8531 return NULL;
8533 gpointer func;
8534 func = mono_lookup_internal_call_full (m, FALSE, NULL, NULL);
8535 if (!func)
8536 return NULL;
8537 return icall_table.lookup_icall_symbol (func);
8540 static MonoType*
8541 type_from_typename (char *type_name)
8543 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8545 if (!strcmp (type_name, "int"))
8546 klass = mono_defaults.int_class;
8547 else if (!strcmp (type_name, "ptr&"))
8548 return mono_class_get_byref_type (mono_defaults.int_class);
8549 else if (!strcmp (type_name, "ptr"))
8550 klass = mono_defaults.int_class;
8551 else if (!strcmp (type_name, "void"))
8552 klass = mono_defaults.void_class;
8553 else if (!strcmp (type_name, "int32"))
8554 klass = mono_defaults.int32_class;
8555 else if (!strcmp (type_name, "uint32"))
8556 klass = mono_defaults.uint32_class;
8557 else if (!strcmp (type_name, "int8"))
8558 klass = mono_defaults.sbyte_class;
8559 else if (!strcmp (type_name, "uint8"))
8560 klass = mono_defaults.byte_class;
8561 else if (!strcmp (type_name, "int16"))
8562 klass = mono_defaults.int16_class;
8563 else if (!strcmp (type_name, "uint16"))
8564 klass = mono_defaults.uint16_class;
8565 else if (!strcmp (type_name, "long"))
8566 klass = mono_defaults.int64_class;
8567 else if (!strcmp (type_name, "ulong"))
8568 klass = mono_defaults.uint64_class;
8569 else if (!strcmp (type_name, "float"))
8570 klass = mono_defaults.single_class;
8571 else if (!strcmp (type_name, "double"))
8572 klass = mono_defaults.double_class;
8573 else if (!strcmp (type_name, "object"))
8574 klass = mono_defaults.object_class;
8575 else if (!strcmp (type_name, "obj"))
8576 klass = mono_defaults.object_class;
8577 else if (!strcmp (type_name, "string"))
8578 klass = mono_defaults.string_class;
8579 else if (!strcmp (type_name, "bool"))
8580 klass = mono_defaults.boolean_class;
8581 else if (!strcmp (type_name, "boolean"))
8582 klass = mono_defaults.boolean_class;
8583 else {
8584 g_error ("%s", type_name);
8585 g_assert_not_reached ();
8587 return m_class_get_byval_arg (klass);
8591 * LOCKING: Take the corlib image lock.
8593 MonoMethodSignature*
8594 mono_create_icall_signature (const char *sigstr)
8596 gchar **parts;
8597 int i, len;
8598 gchar **tmp;
8599 MonoMethodSignature *res, *res2;
8600 MonoImage *corlib = mono_defaults.corlib;
8602 mono_image_lock (corlib);
8603 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8604 mono_image_unlock (corlib);
8606 if (res)
8607 return res;
8609 parts = g_strsplit (sigstr, " ", 256);
8611 tmp = parts;
8612 len = 0;
8613 while (*tmp) {
8614 len ++;
8615 tmp ++;
8618 res = mono_metadata_signature_alloc (corlib, len - 1);
8619 res->pinvoke = 1;
8621 #if defined(TARGET_WIN32) && defined(TARGET_X86)
8623 * Under windows, the default pinvoke calling convention is STDCALL but
8624 * we need CDECL.
8626 res->call_convention = MONO_CALL_C;
8627 #endif
8629 res->ret = type_from_typename (parts [0]);
8630 for (i = 1; i < len; ++i) {
8631 res->params [i - 1] = type_from_typename (parts [i]);
8634 g_strfreev (parts);
8636 mono_image_lock (corlib);
8637 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8638 if (res2)
8639 res = res2; /*Value is allocated in the image pool*/
8640 else
8641 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8642 mono_image_unlock (corlib);
8644 return res;
8647 MonoJitICallInfo *
8648 mono_find_jit_icall_by_name (const char *name)
8650 MonoJitICallInfo *info;
8651 g_assert (jit_icall_hash_name);
8653 mono_icall_lock ();
8654 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8655 mono_icall_unlock ();
8656 return info;
8659 MonoJitICallInfo *
8660 mono_find_jit_icall_by_addr (gconstpointer addr)
8662 MonoJitICallInfo *info;
8663 g_assert (jit_icall_hash_addr);
8665 mono_icall_lock ();
8666 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8667 mono_icall_unlock ();
8669 return info;
8673 * mono_get_jit_icall_info:
8675 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8676 * caller should access it while holding the icall lock.
8678 GHashTable*
8679 mono_get_jit_icall_info (void)
8681 return jit_icall_hash_name;
8685 * mono_lookup_jit_icall_symbol:
8687 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8689 const char*
8690 mono_lookup_jit_icall_symbol (const char *name)
8692 MonoJitICallInfo *info;
8693 const char *res = NULL;
8695 mono_icall_lock ();
8696 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8697 if (info)
8698 res = info->c_symbol;
8699 mono_icall_unlock ();
8700 return res;
8703 void
8704 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8706 mono_icall_lock ();
8707 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8708 mono_icall_unlock ();
8711 MonoJitICallInfo *
8712 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean avoid_wrapper, const char *c_symbol)
8714 MonoJitICallInfo *info;
8716 g_assert (func);
8717 g_assert (name);
8719 mono_icall_lock ();
8721 if (!jit_icall_hash_name) {
8722 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8723 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8726 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8727 g_warning ("jit icall already defined \"%s\"\n", name);
8728 g_assert_not_reached ();
8731 info = g_new0 (MonoJitICallInfo, 1);
8733 info->name = name;
8734 info->func = func;
8735 info->sig = sig;
8736 info->c_symbol = c_symbol;
8738 if (avoid_wrapper) {
8739 info->wrapper = func;
8740 } else {
8741 info->wrapper = NULL;
8744 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8745 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8747 mono_icall_unlock ();
8748 return info;
8751 MonoJitICallInfo *
8752 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean no_wrapper)
8754 return mono_register_jit_icall_full (func, name, sig, no_wrapper, NULL);
8758 ves_icall_System_GC_GetCollectionCount (int generation)
8760 return mono_gc_collection_count (generation);
8764 ves_icall_System_GC_GetGeneration (MonoObjectHandle object, MonoError *error)
8766 return mono_gc_get_generation (MONO_HANDLE_RAW (object));
8770 ves_icall_System_GC_GetMaxGeneration (void)
8772 return mono_gc_max_generation ();
8775 void
8776 ves_icall_System_GC_RecordPressure (gint64 value)
8778 mono_gc_add_memory_pressure (value);
8781 gint64
8782 ves_icall_System_Diagnostics_Stopwatch_GetTimestamp (void)
8784 return mono_100ns_ticks ();
8787 gint64
8788 ves_icall_System_Threading_Timer_GetTimeMonotonic (void)
8790 return mono_100ns_ticks ();
8793 gint64
8794 ves_icall_System_DateTime_GetSystemTimeAsFileTime (void)
8796 return mono_100ns_datetime ();
8800 ves_icall_System_Threading_Thread_SystemMaxStackSize (void)
8802 return mono_thread_info_get_system_max_stack_size ();
8805 MonoBoolean
8806 ves_icall_System_Threading_Thread_YieldInternal (void)
8808 mono_threads_platform_yield ();
8809 return TRUE;
8812 gint32
8813 ves_icall_System_Environment_get_ProcessorCount (void)
8815 return mono_cpu_count ();
8818 #if defined(ENABLE_MONODROID)
8820 G_EXTERN_C gint32 CreateNLSocket (void);
8821 G_EXTERN_C gint32 ReadEvents (gpointer sock, gpointer buffer, gint32 count, gint32 size);
8822 G_EXTERN_C gint32 CloseNLSocket (gpointer sock);
8824 gint32
8825 ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CreateNLSocket (void)
8827 return CreateNLSocket ();
8830 gint32
8831 ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_ReadEvents (gpointer sock, gpointer buffer, gint32 count, gint32 size)
8833 return ReadEvents (sock, buffer, count, size);
8836 gint32
8837 ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CloseNLSocket (gpointer sock)
8839 return CloseNLSocket (sock);
8842 #endif
8844 // Generate wrappers.
8846 #define ICALL_TYPE(id,name,first) /* nothing */
8847 #define ICALL(id,name,func) /* nothing */
8848 #define NOHANDLES(inner) /* nothing */
8850 // Some native functions are exposed via multiple managed names.
8851 // Producing a wrapper for these results in duplicate wrappers with the same names,
8852 // which fails to compile. Do not produce such duplicate wrappers. Alternatively,
8853 // a one line native function with a different name that calls the main one could be used.
8854 // i.e. the wrapper would also have a different name.
8855 #define HANDLES_REUSE_WRAPPER(...) /* nothing */
8857 #define HANDLES(id, name, func, ret, nargs, argtypes) \
8858 MONO_HANDLE_DECLARE (id, name, func, ret, nargs, argtypes); \
8859 MONO_HANDLE_IMPLEMENT (id, name, func, ret, nargs, argtypes)
8861 #include "metadata/icall-def.h"
8863 #undef HANDLES
8864 #undef HANDLES_REUSE_WRAPPER
8865 #undef ICALL_TYPE
8866 #undef ICALL
8867 #undef NOHANDLES