Revert "[runtime] Add support for jagged array ctors which create an array of arrays...
[mono-project.git] / mono / metadata / icall.c
blob40cac17433a0d11355545385e113f893baaf7b44
1 /*
2 * icall.c:
4 * Authors:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
10 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * Copyright 2011-2014 Xamarin Inc (http://www.xamarin.com).
15 #include <config.h>
16 #include <glib.h>
17 #include <stdarg.h>
18 #include <string.h>
19 #include <ctype.h>
20 #ifdef HAVE_ALLOCA_H
21 #include <alloca.h>
22 #endif
23 #ifdef HAVE_SYS_TIME_H
24 #include <sys/time.h>
25 #endif
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #if defined (HOST_WIN32)
30 #include <stdlib.h>
31 #endif
32 #if defined (HAVE_WCHAR_H)
33 #include <wchar.h>
34 #endif
36 #include "mono/utils/mono-membar.h"
37 #include <mono/metadata/object.h>
38 #include <mono/metadata/threads.h>
39 #include <mono/metadata/threads-types.h>
40 #include <mono/metadata/threadpool.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/assembly.h>
44 #include <mono/metadata/tabledefs.h>
45 #include <mono/metadata/exception.h>
46 #include <mono/metadata/file-io.h>
47 #include <mono/metadata/console-io.h>
48 #include <mono/metadata/socket-io.h>
49 #include <mono/metadata/mono-endian.h>
50 #include <mono/metadata/tokentype.h>
51 #include <mono/metadata/domain-internals.h>
52 #include <mono/metadata/metadata-internals.h>
53 #include <mono/metadata/class-internals.h>
54 #include <mono/metadata/marshal.h>
55 #include <mono/metadata/gc-internal.h>
56 #include <mono/metadata/mono-gc.h>
57 #include <mono/metadata/rand.h>
58 #include <mono/metadata/sysmath.h>
59 #include <mono/metadata/string-icalls.h>
60 #include <mono/metadata/debug-helpers.h>
61 #include <mono/metadata/process.h>
62 #include <mono/metadata/environment.h>
63 #include <mono/metadata/profiler-private.h>
64 #include <mono/metadata/locales.h>
65 #include <mono/metadata/filewatcher.h>
66 #include <mono/metadata/char-conversions.h>
67 #include <mono/metadata/security.h>
68 #include <mono/metadata/mono-config.h>
69 #include <mono/metadata/cil-coff.h>
70 #include <mono/metadata/number-formatter.h>
71 #include <mono/metadata/security-manager.h>
72 #include <mono/metadata/security-core-clr.h>
73 #include <mono/metadata/mono-perfcounters.h>
74 #include <mono/metadata/mono-debug.h>
75 #include <mono/metadata/mono-ptr-array.h>
76 #include <mono/metadata/verify-internals.h>
77 #include <mono/metadata/runtime.h>
78 #include <mono/io-layer/io-layer.h>
79 #include <mono/utils/strtod.h>
80 #include <mono/utils/monobitset.h>
81 #include <mono/utils/mono-time.h>
82 #include <mono/utils/mono-proclib.h>
83 #include <mono/utils/mono-string.h>
84 #include <mono/utils/mono-error-internals.h>
85 #include <mono/utils/mono-mmap.h>
86 #include <mono/utils/mono-io-portability.h>
87 #include <mono/utils/mono-digest.h>
88 #include <mono/utils/bsearch.h>
89 #include <mono/utils/mono-mutex.h>
90 #include <mono/utils/mono-threads.h>
92 #if defined (HOST_WIN32)
93 #include <windows.h>
94 #include <shlobj.h>
95 #endif
96 #include "decimal.h"
98 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
100 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
102 static MonoArray*
103 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
105 static inline MonoBoolean
106 is_generic_parameter (MonoType *type)
108 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
111 static void
112 mono_class_init_or_throw (MonoClass *klass)
114 if (!mono_class_init (klass))
115 mono_raise_exception (mono_class_get_exception_for_failure (klass));
119 * We expect a pointer to a char, not a string
121 ICALL_EXPORT gboolean
122 mono_double_ParseImpl (char *ptr, double *result)
124 gchar *endptr = NULL;
125 *result = 0.0;
127 MONO_ARCH_SAVE_REGS;
129 #ifdef __arm__
130 if (*ptr)
131 *result = strtod (ptr, &endptr);
132 #else
133 if (*ptr){
134 /* mono_strtod () is not thread-safe */
135 EnterCriticalSection (&mono_strtod_mutex);
136 *result = mono_strtod (ptr, &endptr);
137 LeaveCriticalSection (&mono_strtod_mutex);
139 #endif
141 if (!*ptr || (endptr && *endptr))
142 return FALSE;
144 return TRUE;
147 ICALL_EXPORT MonoObject *
148 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
150 MonoClass *ac;
151 MonoArray *ao;
152 gint32 esize;
153 gpointer *ea;
155 MONO_ARCH_SAVE_REGS;
157 ao = (MonoArray *)this;
158 ac = (MonoClass *)ao->obj.vtable->klass;
160 esize = mono_array_element_size (ac);
161 ea = (gpointer*)((char*)ao->vector + (pos * esize));
163 if (ac->element_class->valuetype)
164 return mono_value_box (this->vtable->domain, ac->element_class, ea);
165 else
166 return *ea;
169 ICALL_EXPORT MonoObject *
170 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
172 MonoClass *ac, *ic;
173 MonoArray *ao, *io;
174 gint32 i, pos, *ind;
176 MONO_ARCH_SAVE_REGS;
178 MONO_CHECK_ARG_NULL (idxs);
180 io = (MonoArray *)idxs;
181 ic = (MonoClass *)io->obj.vtable->klass;
183 ao = (MonoArray *)this;
184 ac = (MonoClass *)ao->obj.vtable->klass;
186 g_assert (ic->rank == 1);
187 if (io->bounds != NULL || io->max_length != ac->rank)
188 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
190 ind = (gint32 *)io->vector;
192 if (ao->bounds == NULL) {
193 if (*ind < 0 || *ind >= ao->max_length)
194 mono_raise_exception (mono_get_exception_index_out_of_range ());
196 return ves_icall_System_Array_GetValueImpl (this, *ind);
199 for (i = 0; i < ac->rank; i++)
200 if ((ind [i] < ao->bounds [i].lower_bound) ||
201 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
202 mono_raise_exception (mono_get_exception_index_out_of_range ());
204 pos = ind [0] - ao->bounds [0].lower_bound;
205 for (i = 1; i < ac->rank; i++)
206 pos = pos*ao->bounds [i].length + ind [i] -
207 ao->bounds [i].lower_bound;
209 return ves_icall_System_Array_GetValueImpl (this, pos);
212 ICALL_EXPORT void
213 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
215 MonoClass *ac, *vc, *ec;
216 gint32 esize, vsize;
217 gpointer *ea, *va;
218 int et, vt;
220 guint64 u64 = 0;
221 gint64 i64 = 0;
222 gdouble r64 = 0;
224 MONO_ARCH_SAVE_REGS;
226 if (value)
227 vc = value->vtable->klass;
228 else
229 vc = NULL;
231 ac = this->obj.vtable->klass;
232 ec = ac->element_class;
234 esize = mono_array_element_size (ac);
235 ea = (gpointer*)((char*)this->vector + (pos * esize));
236 va = (gpointer*)((char*)value + sizeof (MonoObject));
238 if (mono_class_is_nullable (ec)) {
239 mono_nullable_init ((guint8*)ea, value, ec);
240 return;
243 if (!value) {
244 mono_gc_bzero_atomic (ea, esize);
245 return;
248 #define NO_WIDENING_CONVERSION G_STMT_START{\
249 mono_raise_exception (mono_get_exception_argument ( \
250 "value", "not a widening conversion")); \
251 }G_STMT_END
253 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
254 if (esize < vsize + (extra)) \
255 mono_raise_exception (mono_get_exception_argument ( \
256 "value", "not a widening conversion")); \
257 }G_STMT_END
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_raise_exception (mono_get_exception_invalid_cast ()); \
262 }G_STMT_END
264 /* Check element (destination) type. */
265 switch (ec->byval_arg.type) {
266 case MONO_TYPE_STRING:
267 switch (vc->byval_arg.type) {
268 case MONO_TYPE_STRING:
269 break;
270 default:
271 INVALID_CAST;
273 break;
274 case MONO_TYPE_BOOLEAN:
275 switch (vc->byval_arg.type) {
276 case MONO_TYPE_BOOLEAN:
277 break;
278 case MONO_TYPE_CHAR:
279 case MONO_TYPE_U1:
280 case MONO_TYPE_U2:
281 case MONO_TYPE_U4:
282 case MONO_TYPE_U8:
283 case MONO_TYPE_I1:
284 case MONO_TYPE_I2:
285 case MONO_TYPE_I4:
286 case MONO_TYPE_I8:
287 case MONO_TYPE_R4:
288 case MONO_TYPE_R8:
289 NO_WIDENING_CONVERSION;
290 default:
291 INVALID_CAST;
293 break;
296 if (!ec->valuetype) {
297 if (!mono_object_isinst (value, ec))
298 INVALID_CAST;
299 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
300 return;
303 if (mono_object_isinst (value, ec)) {
304 if (ec->has_references)
305 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
306 else
307 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
308 return;
311 if (!vc->valuetype)
312 INVALID_CAST;
314 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
316 et = ec->byval_arg.type;
317 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
318 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
320 vt = vc->byval_arg.type;
321 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
322 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
324 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
325 switch (vt) { \
326 case MONO_TYPE_U1: \
327 case MONO_TYPE_U2: \
328 case MONO_TYPE_U4: \
329 case MONO_TYPE_U8: \
330 case MONO_TYPE_CHAR: \
331 CHECK_WIDENING_CONVERSION(0); \
332 *(etype *) ea = (etype) u64; \
333 return; \
334 /* You can't assign a signed value to an unsigned array. */ \
335 case MONO_TYPE_I1: \
336 case MONO_TYPE_I2: \
337 case MONO_TYPE_I4: \
338 case MONO_TYPE_I8: \
339 /* You can't assign a floating point number to an integer array. */ \
340 case MONO_TYPE_R4: \
341 case MONO_TYPE_R8: \
342 NO_WIDENING_CONVERSION; \
344 }G_STMT_END
346 #define ASSIGN_SIGNED(etype) G_STMT_START{\
347 switch (vt) { \
348 case MONO_TYPE_I1: \
349 case MONO_TYPE_I2: \
350 case MONO_TYPE_I4: \
351 case MONO_TYPE_I8: \
352 CHECK_WIDENING_CONVERSION(0); \
353 *(etype *) ea = (etype) i64; \
354 return; \
355 /* You can assign an unsigned value to a signed array if the array's */ \
356 /* element size is larger than the value size. */ \
357 case MONO_TYPE_U1: \
358 case MONO_TYPE_U2: \
359 case MONO_TYPE_U4: \
360 case MONO_TYPE_U8: \
361 case MONO_TYPE_CHAR: \
362 CHECK_WIDENING_CONVERSION(1); \
363 *(etype *) ea = (etype) u64; \
364 return; \
365 /* You can't assign a floating point number to an integer array. */ \
366 case MONO_TYPE_R4: \
367 case MONO_TYPE_R8: \
368 NO_WIDENING_CONVERSION; \
370 }G_STMT_END
372 #define ASSIGN_REAL(etype) G_STMT_START{\
373 switch (vt) { \
374 case MONO_TYPE_R4: \
375 case MONO_TYPE_R8: \
376 CHECK_WIDENING_CONVERSION(0); \
377 *(etype *) ea = (etype) r64; \
378 return; \
379 /* All integer values fit into a floating point array, so we don't */ \
380 /* need to CHECK_WIDENING_CONVERSION here. */ \
381 case MONO_TYPE_I1: \
382 case MONO_TYPE_I2: \
383 case MONO_TYPE_I4: \
384 case MONO_TYPE_I8: \
385 *(etype *) ea = (etype) i64; \
386 return; \
387 case MONO_TYPE_U1: \
388 case MONO_TYPE_U2: \
389 case MONO_TYPE_U4: \
390 case MONO_TYPE_U8: \
391 case MONO_TYPE_CHAR: \
392 *(etype *) ea = (etype) u64; \
393 return; \
395 }G_STMT_END
397 switch (vt) {
398 case MONO_TYPE_U1:
399 u64 = *(guint8 *) va;
400 break;
401 case MONO_TYPE_U2:
402 u64 = *(guint16 *) va;
403 break;
404 case MONO_TYPE_U4:
405 u64 = *(guint32 *) va;
406 break;
407 case MONO_TYPE_U8:
408 u64 = *(guint64 *) va;
409 break;
410 case MONO_TYPE_I1:
411 i64 = *(gint8 *) va;
412 break;
413 case MONO_TYPE_I2:
414 i64 = *(gint16 *) va;
415 break;
416 case MONO_TYPE_I4:
417 i64 = *(gint32 *) va;
418 break;
419 case MONO_TYPE_I8:
420 i64 = *(gint64 *) va;
421 break;
422 case MONO_TYPE_R4:
423 r64 = *(gfloat *) va;
424 break;
425 case MONO_TYPE_R8:
426 r64 = *(gdouble *) va;
427 break;
428 case MONO_TYPE_CHAR:
429 u64 = *(guint16 *) va;
430 break;
431 case MONO_TYPE_BOOLEAN:
432 /* Boolean is only compatible with itself. */
433 switch (et) {
434 case MONO_TYPE_CHAR:
435 case MONO_TYPE_U1:
436 case MONO_TYPE_U2:
437 case MONO_TYPE_U4:
438 case MONO_TYPE_U8:
439 case MONO_TYPE_I1:
440 case MONO_TYPE_I2:
441 case MONO_TYPE_I4:
442 case MONO_TYPE_I8:
443 case MONO_TYPE_R4:
444 case MONO_TYPE_R8:
445 NO_WIDENING_CONVERSION;
446 default:
447 INVALID_CAST;
449 break;
452 /* If we can't do a direct copy, let's try a widening conversion. */
453 switch (et) {
454 case MONO_TYPE_CHAR:
455 ASSIGN_UNSIGNED (guint16);
456 case MONO_TYPE_U1:
457 ASSIGN_UNSIGNED (guint8);
458 case MONO_TYPE_U2:
459 ASSIGN_UNSIGNED (guint16);
460 case MONO_TYPE_U4:
461 ASSIGN_UNSIGNED (guint32);
462 case MONO_TYPE_U8:
463 ASSIGN_UNSIGNED (guint64);
464 case MONO_TYPE_I1:
465 ASSIGN_SIGNED (gint8);
466 case MONO_TYPE_I2:
467 ASSIGN_SIGNED (gint16);
468 case MONO_TYPE_I4:
469 ASSIGN_SIGNED (gint32);
470 case MONO_TYPE_I8:
471 ASSIGN_SIGNED (gint64);
472 case MONO_TYPE_R4:
473 ASSIGN_REAL (gfloat);
474 case MONO_TYPE_R8:
475 ASSIGN_REAL (gdouble);
478 INVALID_CAST;
479 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
480 return;
482 #undef INVALID_CAST
483 #undef NO_WIDENING_CONVERSION
484 #undef CHECK_WIDENING_CONVERSION
485 #undef ASSIGN_UNSIGNED
486 #undef ASSIGN_SIGNED
487 #undef ASSIGN_REAL
490 ICALL_EXPORT void
491 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
492 MonoArray *idxs)
494 MonoClass *ac, *ic;
495 gint32 i, pos, *ind;
497 MONO_ARCH_SAVE_REGS;
499 MONO_CHECK_ARG_NULL (idxs);
501 ic = idxs->obj.vtable->klass;
502 ac = this->obj.vtable->klass;
504 g_assert (ic->rank == 1);
505 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
506 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
508 ind = (gint32 *)idxs->vector;
510 if (this->bounds == NULL) {
511 if (*ind < 0 || *ind >= this->max_length)
512 mono_raise_exception (mono_get_exception_index_out_of_range ());
514 ves_icall_System_Array_SetValueImpl (this, value, *ind);
515 return;
518 for (i = 0; i < ac->rank; i++)
519 if ((ind [i] < this->bounds [i].lower_bound) ||
520 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
521 mono_raise_exception (mono_get_exception_index_out_of_range ());
523 pos = ind [0] - this->bounds [0].lower_bound;
524 for (i = 1; i < ac->rank; i++)
525 pos = pos * this->bounds [i].length + ind [i] -
526 this->bounds [i].lower_bound;
528 ves_icall_System_Array_SetValueImpl (this, value, pos);
531 ICALL_EXPORT MonoArray *
532 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
534 MonoClass *aklass, *klass;
535 MonoArray *array;
536 uintptr_t *sizes, i;
537 gboolean bounded = FALSE;
539 MONO_ARCH_SAVE_REGS;
541 MONO_CHECK_ARG_NULL (type);
542 MONO_CHECK_ARG_NULL (lengths);
544 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
545 if (bounds)
546 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
548 for (i = 0; i < mono_array_length (lengths); i++)
549 if (mono_array_get (lengths, gint32, i) < 0)
550 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
552 klass = mono_class_from_mono_type (type->type);
553 mono_class_init_or_throw (klass);
555 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
556 /* vectors are not the same as one dimensional arrays with no-zero bounds */
557 bounded = TRUE;
558 else
559 bounded = FALSE;
561 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
563 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
564 for (i = 0; i < aklass->rank; ++i) {
565 sizes [i] = mono_array_get (lengths, guint32, i);
566 if (bounds)
567 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
568 else
569 sizes [i + aklass->rank] = 0;
572 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
574 return array;
577 ICALL_EXPORT MonoArray *
578 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
580 MonoClass *aklass, *klass;
581 MonoArray *array;
582 uintptr_t *sizes, i;
583 gboolean bounded = FALSE;
585 MONO_ARCH_SAVE_REGS;
587 MONO_CHECK_ARG_NULL (type);
588 MONO_CHECK_ARG_NULL (lengths);
590 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
591 if (bounds)
592 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
594 for (i = 0; i < mono_array_length (lengths); i++)
595 if ((mono_array_get (lengths, gint64, i) < 0) ||
596 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
597 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
599 klass = mono_class_from_mono_type (type->type);
600 mono_class_init_or_throw (klass);
602 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
603 /* vectors are not the same as one dimensional arrays with no-zero bounds */
604 bounded = TRUE;
605 else
606 bounded = FALSE;
608 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
610 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
611 for (i = 0; i < aklass->rank; ++i) {
612 sizes [i] = mono_array_get (lengths, guint64, i);
613 if (bounds)
614 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
615 else
616 sizes [i + aklass->rank] = 0;
619 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
621 return array;
624 ICALL_EXPORT gint32
625 ves_icall_System_Array_GetRank (MonoObject *this)
627 MONO_ARCH_SAVE_REGS;
629 return this->vtable->klass->rank;
632 ICALL_EXPORT gint32
633 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
635 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
636 uintptr_t length;
638 MONO_ARCH_SAVE_REGS;
640 if ((dimension < 0) || (dimension >= rank))
641 mono_raise_exception (mono_get_exception_index_out_of_range ());
643 if (this->bounds == NULL)
644 length = this->max_length;
645 else
646 length = this->bounds [dimension].length;
648 #ifdef MONO_BIG_ARRAYS
649 if (length > G_MAXINT32)
650 mono_raise_exception (mono_get_exception_overflow ());
651 #endif
652 return length;
655 ICALL_EXPORT gint64
656 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
658 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
660 MONO_ARCH_SAVE_REGS;
662 if ((dimension < 0) || (dimension >= rank))
663 mono_raise_exception (mono_get_exception_index_out_of_range ());
665 if (this->bounds == NULL)
666 return this->max_length;
668 return this->bounds [dimension].length;
671 ICALL_EXPORT gint32
672 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
674 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
676 MONO_ARCH_SAVE_REGS;
678 if ((dimension < 0) || (dimension >= rank))
679 mono_raise_exception (mono_get_exception_index_out_of_range ());
681 if (this->bounds == NULL)
682 return 0;
684 return this->bounds [dimension].lower_bound;
687 ICALL_EXPORT void
688 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
690 int sz = mono_array_element_size (mono_object_class (arr));
691 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
694 ICALL_EXPORT gboolean
695 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
697 int element_size;
698 void * dest_addr;
699 void * source_addr;
700 MonoVTable *src_vtable;
701 MonoVTable *dest_vtable;
702 MonoClass *src_class;
703 MonoClass *dest_class;
705 src_vtable = source->obj.vtable;
706 dest_vtable = dest->obj.vtable;
708 if (src_vtable->rank != dest_vtable->rank)
709 return FALSE;
711 if (source->bounds || dest->bounds)
712 return FALSE;
714 /* there's no integer overflow since mono_array_length returns an unsigned integer */
715 if ((dest_idx + length > mono_array_length_fast (dest)) ||
716 (source_idx + length > mono_array_length_fast (source)))
717 return FALSE;
719 src_class = src_vtable->klass->element_class;
720 dest_class = dest_vtable->klass->element_class;
723 * Handle common cases.
726 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
727 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
729 if (src_class == mono_defaults.object_class && dest_class->valuetype)
730 return FALSE;
732 /* Check if we're copying a char[] <==> (u)short[] */
733 if (src_class != dest_class) {
734 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
735 return FALSE;
737 /* 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. */
738 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
739 return FALSE;
742 if (dest_class->valuetype) {
743 element_size = mono_array_element_size (source->obj.vtable->klass);
744 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
745 if (dest_class->has_references) {
746 mono_value_copy_array (dest, dest_idx, source_addr, length);
747 } else {
748 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
749 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
751 } else {
752 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
755 return TRUE;
758 ICALL_EXPORT void
759 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
761 MonoClass *ac;
762 MonoArray *ao;
763 gint32 esize;
764 gpointer *ea;
766 MONO_ARCH_SAVE_REGS;
768 ao = (MonoArray *)this;
769 ac = (MonoClass *)ao->obj.vtable->klass;
771 esize = mono_array_element_size (ac);
772 ea = (gpointer*)((char*)ao->vector + (pos * esize));
774 mono_gc_memmove_atomic (value, ea, esize);
777 ICALL_EXPORT void
778 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
780 MonoClass *ac, *ec;
781 MonoArray *ao;
782 gint32 esize;
783 gpointer *ea;
785 MONO_ARCH_SAVE_REGS;
787 ao = (MonoArray *)this;
788 ac = (MonoClass *)ao->obj.vtable->klass;
789 ec = ac->element_class;
791 esize = mono_array_element_size (ac);
792 ea = (gpointer*)((char*)ao->vector + (pos * esize));
794 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
795 g_assert (esize == sizeof (gpointer));
796 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
797 } else {
798 g_assert (ec->inited);
799 g_assert (esize == mono_class_value_size (ec, NULL));
800 if (ec->has_references)
801 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
802 else
803 mono_gc_memmove_atomic (ea, value, esize);
807 ICALL_EXPORT void
808 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
810 MonoClass *klass = array->obj.vtable->klass;
811 guint32 size = mono_array_element_size (klass);
812 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
813 int align;
814 const char *field_data;
816 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
817 MonoException *exc = mono_get_exception_argument("array",
818 "Cannot initialize array of non-primitive type.");
819 mono_raise_exception (exc);
822 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
823 MonoException *exc = mono_get_exception_argument("field_handle",
824 "Field doesn't have an RVA");
825 mono_raise_exception (exc);
828 size *= array->max_length;
829 field_data = mono_field_get_data (field_handle);
831 if (size > mono_type_size (field_handle->type, &align)) {
832 MonoException *exc = mono_get_exception_argument("field_handle",
833 "Field not large enough to fill array");
834 mono_raise_exception (exc);
837 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
838 #define SWAP(n) {\
839 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
840 guint ## n *src = (guint ## n *) field_data; \
841 guint ## n *end = (guint ## n *)((char*)src + size); \
843 for (; src < end; data++, src++) { \
844 *data = read ## n (src); \
848 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
850 switch (type->type) {
851 case MONO_TYPE_CHAR:
852 case MONO_TYPE_I2:
853 case MONO_TYPE_U2:
854 SWAP (16);
855 break;
856 case MONO_TYPE_I4:
857 case MONO_TYPE_U4:
858 case MONO_TYPE_R4:
859 SWAP (32);
860 break;
861 case MONO_TYPE_I8:
862 case MONO_TYPE_U8:
863 case MONO_TYPE_R8:
864 SWAP (64);
865 break;
866 default:
867 memcpy (mono_array_addr (array, char, 0), field_data, size);
868 break;
870 #else
871 memcpy (mono_array_addr (array, char, 0), field_data, size);
872 #endif
875 ICALL_EXPORT gint
876 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
878 MONO_ARCH_SAVE_REGS;
880 return offsetof (MonoString, chars);
883 ICALL_EXPORT MonoObject *
884 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
886 MONO_ARCH_SAVE_REGS;
888 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
889 return obj;
890 else
891 return mono_object_clone (obj);
894 ICALL_EXPORT void
895 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
897 MonoClass *klass;
898 MonoVTable *vtable;
900 MONO_CHECK_ARG_NULL (handle);
902 klass = mono_class_from_mono_type (handle);
903 MONO_CHECK_ARG (handle, klass);
905 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
907 /* This will call the type constructor */
908 mono_runtime_class_init (vtable);
911 ICALL_EXPORT void
912 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
914 MONO_ARCH_SAVE_REGS;
916 mono_image_check_for_module_cctor (image);
917 if (image->has_module_cctor) {
918 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
919 /*It's fine to raise the exception here*/
920 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
924 ICALL_EXPORT MonoBoolean
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
927 guint8 *stack_addr;
928 guint8 *current;
929 size_t stack_size;
930 /* later make this configurable and per-arch */
931 int min_size = 4096 * 4 * sizeof (void*);
932 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
933 /* if we have no info we are optimistic and assume there is enough room */
934 if (!stack_addr)
935 return TRUE;
936 #ifdef HOST_WIN32
937 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
938 // to the current sp
939 return TRUE;
940 #endif
941 current = (guint8 *)&stack_addr;
942 if (current > stack_addr) {
943 if ((current - stack_addr) < min_size)
944 return FALSE;
945 } else {
946 if (current - (stack_addr - stack_size) < min_size)
947 return FALSE;
949 return TRUE;
952 ICALL_EXPORT MonoObject *
953 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
955 MONO_ARCH_SAVE_REGS;
957 return mono_object_clone (this);
960 ICALL_EXPORT gint32
961 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
963 MonoClass *klass;
964 MonoObject **values = NULL;
965 MonoObject *o;
966 int count = 0;
967 gint32 result = (int)(gsize)mono_defaults.int32_class;
968 MonoClassField* field;
969 gpointer iter;
971 MONO_ARCH_SAVE_REGS;
973 klass = mono_object_class (this);
975 if (mono_class_num_fields (klass) == 0)
976 return result;
979 * Compute the starting value of the hashcode for fields of primitive
980 * types, and return the remaining fields in an array to the managed side.
981 * This way, we can avoid costly reflection operations in managed code.
983 iter = NULL;
984 while ((field = mono_class_get_fields (klass, &iter))) {
985 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
986 continue;
987 if (mono_field_is_deleted (field))
988 continue;
989 /* FIXME: Add more types */
990 switch (field->type->type) {
991 case MONO_TYPE_I4:
992 result ^= *(gint32*)((guint8*)this + field->offset);
993 break;
994 case MONO_TYPE_STRING: {
995 MonoString *s;
996 s = *(MonoString**)((guint8*)this + field->offset);
997 if (s != NULL)
998 result ^= mono_string_hash (s);
999 break;
1001 default:
1002 if (!values)
1003 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1004 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1005 values [count++] = o;
1009 if (values) {
1010 int i;
1011 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1012 for (i = 0; i < count; ++i)
1013 mono_array_setref (*fields, i, values [i]);
1014 } else {
1015 *fields = NULL;
1017 return result;
1020 ICALL_EXPORT MonoBoolean
1021 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1023 MonoClass *klass;
1024 MonoObject **values = NULL;
1025 MonoObject *o;
1026 MonoClassField* field;
1027 gpointer iter;
1028 int count = 0;
1030 MONO_ARCH_SAVE_REGS;
1032 MONO_CHECK_ARG_NULL (that);
1034 if (this->vtable != that->vtable)
1035 return FALSE;
1037 klass = mono_object_class (this);
1039 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1040 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1043 * Do the comparison for fields of primitive type and return a result if
1044 * possible. Otherwise, return the remaining fields in an array to the
1045 * managed side. This way, we can avoid costly reflection operations in
1046 * managed code.
1048 *fields = NULL;
1049 iter = NULL;
1050 while ((field = mono_class_get_fields (klass, &iter))) {
1051 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1052 continue;
1053 if (mono_field_is_deleted (field))
1054 continue;
1055 /* FIXME: Add more types */
1056 switch (field->type->type) {
1057 case MONO_TYPE_U1:
1058 case MONO_TYPE_I1:
1059 case MONO_TYPE_BOOLEAN:
1060 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1061 return FALSE;
1062 break;
1063 case MONO_TYPE_U2:
1064 case MONO_TYPE_I2:
1065 case MONO_TYPE_CHAR:
1066 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1067 return FALSE;
1068 break;
1069 case MONO_TYPE_U4:
1070 case MONO_TYPE_I4:
1071 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1072 return FALSE;
1073 break;
1074 case MONO_TYPE_U8:
1075 case MONO_TYPE_I8:
1076 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1077 return FALSE;
1078 break;
1079 case MONO_TYPE_R4:
1080 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1081 return FALSE;
1082 break;
1083 case MONO_TYPE_R8:
1084 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1085 return FALSE;
1086 break;
1089 case MONO_TYPE_STRING: {
1090 MonoString *s1, *s2;
1091 guint32 s1len, s2len;
1092 s1 = *(MonoString**)((guint8*)this + field->offset);
1093 s2 = *(MonoString**)((guint8*)that + field->offset);
1094 if (s1 == s2)
1095 break;
1096 if ((s1 == NULL) || (s2 == NULL))
1097 return FALSE;
1098 s1len = mono_string_length (s1);
1099 s2len = mono_string_length (s2);
1100 if (s1len != s2len)
1101 return FALSE;
1103 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1104 return FALSE;
1105 break;
1107 default:
1108 if (!values)
1109 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1110 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1111 values [count++] = o;
1112 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1113 values [count++] = o;
1116 if (klass->enumtype)
1117 /* enums only have one non-static field */
1118 break;
1121 if (values) {
1122 int i;
1123 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1124 for (i = 0; i < count; ++i)
1125 mono_array_setref_fast (*fields, i, values [i]);
1126 return FALSE;
1127 } else {
1128 return TRUE;
1132 ICALL_EXPORT MonoReflectionType *
1133 ves_icall_System_Object_GetType (MonoObject *obj)
1135 MONO_ARCH_SAVE_REGS;
1137 #ifndef DISABLE_REMOTING
1138 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1139 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1140 else
1141 #endif
1142 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1145 ICALL_EXPORT void
1146 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1148 MONO_ARCH_SAVE_REGS;
1150 mtype->type = &obj->vtable->klass->byval_arg;
1151 g_assert (mtype->type->type);
1154 ICALL_EXPORT gint32
1155 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1157 MONO_ARCH_SAVE_REGS;
1159 MONO_CHECK_ARG_NULL (obj);
1161 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1164 ICALL_EXPORT gint32
1165 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1166 MonoReflectionMethod *method,
1167 MonoArray *opt_param_types)
1169 MONO_ARCH_SAVE_REGS;
1171 MONO_CHECK_ARG_NULL (method);
1173 return mono_image_create_method_token (
1174 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1177 ICALL_EXPORT void
1178 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1180 MONO_ARCH_SAVE_REGS;
1182 mono_image_create_pefile (mb, file);
1185 ICALL_EXPORT void
1186 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1188 MONO_ARCH_SAVE_REGS;
1190 mono_image_build_metadata (mb);
1193 ICALL_EXPORT void
1194 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1196 MONO_ARCH_SAVE_REGS;
1198 mono_image_register_token (mb->dynamic_image, token, obj);
1201 static gboolean
1202 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1204 MonoMethod **dest = data;
1206 /* skip unmanaged frames */
1207 if (!managed)
1208 return FALSE;
1210 if (m == *dest) {
1211 *dest = NULL;
1212 return FALSE;
1214 if (!(*dest)) {
1215 *dest = m;
1216 return TRUE;
1218 return FALSE;
1221 static gboolean
1222 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1224 MonoMethod **dest = data;
1226 /* skip unmanaged frames */
1227 if (!managed)
1228 return FALSE;
1230 if (!(*dest)) {
1231 if (!strcmp (m->klass->name_space, "System.Reflection"))
1232 return FALSE;
1233 *dest = m;
1234 return TRUE;
1236 return FALSE;
1239 static gboolean
1240 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1242 MonoMethod **dest = data;
1244 /* skip unmanaged frames */
1245 if (!managed)
1246 return FALSE;
1248 if (m->wrapper_type != MONO_WRAPPER_NONE)
1249 return FALSE;
1251 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1252 return FALSE;
1254 if (m == *dest) {
1255 *dest = NULL;
1256 return FALSE;
1258 if (!(*dest)) {
1259 *dest = m;
1260 return TRUE;
1262 return FALSE;
1265 static MonoReflectionType *
1266 type_from_name (const char *str, MonoBoolean ignoreCase)
1268 MonoType *type = NULL;
1269 MonoAssembly *assembly = NULL;
1270 MonoTypeNameParse info;
1271 char *temp_str = g_strdup (str);
1272 gboolean type_resolve = FALSE;
1274 MONO_ARCH_SAVE_REGS;
1276 /* mono_reflection_parse_type() mangles the string */
1277 if (!mono_reflection_parse_type (temp_str, &info)) {
1278 mono_reflection_free_type_info (&info);
1279 g_free (temp_str);
1280 return NULL;
1283 if (info.assembly.name) {
1284 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1285 } else {
1286 MonoMethod *m = mono_method_get_last_managed ();
1287 MonoMethod *dest = m;
1289 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1290 if (!dest)
1291 dest = m;
1294 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1295 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1296 * to crash. This only seems to happen in some strange remoting
1297 * scenarios and I was unable to figure out what's happening there.
1298 * Dec 10, 2005 - Martin.
1301 if (dest) {
1302 assembly = dest->klass->image->assembly;
1303 type_resolve = TRUE;
1304 } else {
1305 g_warning (G_STRLOC);
1309 if (assembly) {
1310 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1311 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1314 if (!info.assembly.name && !type) /* try mscorlib */
1315 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1317 if (assembly && !type && type_resolve) {
1318 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1319 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1322 mono_reflection_free_type_info (&info);
1323 g_free (temp_str);
1325 if (!type)
1326 return NULL;
1328 return mono_type_get_object (mono_domain_get (), type);
1331 #ifdef UNUSED
1332 MonoReflectionType *
1333 mono_type_get (const char *str)
1335 char *copy = g_strdup (str);
1336 MonoReflectionType *type = type_from_name (copy, FALSE);
1338 g_free (copy);
1339 return type;
1341 #endif
1343 ICALL_EXPORT MonoReflectionType*
1344 ves_icall_type_from_name (MonoString *name,
1345 MonoBoolean throwOnError,
1346 MonoBoolean ignoreCase)
1348 char *str = mono_string_to_utf8 (name);
1349 MonoReflectionType *type;
1351 type = type_from_name (str, ignoreCase);
1352 g_free (str);
1353 if (type == NULL){
1354 MonoException *e = NULL;
1356 if (throwOnError)
1357 e = mono_get_exception_type_load (name, NULL);
1359 mono_loader_clear_error ();
1360 if (e != NULL)
1361 mono_raise_exception (e);
1364 return type;
1368 ICALL_EXPORT MonoReflectionType*
1369 ves_icall_type_from_handle (MonoType *handle)
1371 MonoDomain *domain = mono_domain_get ();
1373 MONO_ARCH_SAVE_REGS;
1375 return mono_type_get_object (domain, handle);
1378 ICALL_EXPORT MonoBoolean
1379 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1381 MONO_ARCH_SAVE_REGS;
1383 if (c && type->type && c->type)
1384 return mono_metadata_type_equal (type->type, c->type);
1385 else
1386 return (type == c) ? TRUE : FALSE;
1389 /* System.TypeCode */
1390 typedef enum {
1391 TYPECODE_EMPTY,
1392 TYPECODE_OBJECT,
1393 TYPECODE_DBNULL,
1394 TYPECODE_BOOLEAN,
1395 TYPECODE_CHAR,
1396 TYPECODE_SBYTE,
1397 TYPECODE_BYTE,
1398 TYPECODE_INT16,
1399 TYPECODE_UINT16,
1400 TYPECODE_INT32,
1401 TYPECODE_UINT32,
1402 TYPECODE_INT64,
1403 TYPECODE_UINT64,
1404 TYPECODE_SINGLE,
1405 TYPECODE_DOUBLE,
1406 TYPECODE_DECIMAL,
1407 TYPECODE_DATETIME,
1408 TYPECODE_STRING = 18
1409 } TypeCode;
1411 ICALL_EXPORT guint32
1412 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1414 int t = type->type->type;
1416 MONO_ARCH_SAVE_REGS;
1418 if (type->type->byref)
1419 return TYPECODE_OBJECT;
1421 handle_enum:
1422 switch (t) {
1423 case MONO_TYPE_VOID:
1424 return TYPECODE_OBJECT;
1425 case MONO_TYPE_BOOLEAN:
1426 return TYPECODE_BOOLEAN;
1427 case MONO_TYPE_U1:
1428 return TYPECODE_BYTE;
1429 case MONO_TYPE_I1:
1430 return TYPECODE_SBYTE;
1431 case MONO_TYPE_U2:
1432 return TYPECODE_UINT16;
1433 case MONO_TYPE_I2:
1434 return TYPECODE_INT16;
1435 case MONO_TYPE_CHAR:
1436 return TYPECODE_CHAR;
1437 case MONO_TYPE_PTR:
1438 case MONO_TYPE_U:
1439 case MONO_TYPE_I:
1440 return TYPECODE_OBJECT;
1441 case MONO_TYPE_U4:
1442 return TYPECODE_UINT32;
1443 case MONO_TYPE_I4:
1444 return TYPECODE_INT32;
1445 case MONO_TYPE_U8:
1446 return TYPECODE_UINT64;
1447 case MONO_TYPE_I8:
1448 return TYPECODE_INT64;
1449 case MONO_TYPE_R4:
1450 return TYPECODE_SINGLE;
1451 case MONO_TYPE_R8:
1452 return TYPECODE_DOUBLE;
1453 case MONO_TYPE_VALUETYPE: {
1454 MonoClass *klass = type->type->data.klass;
1456 if (klass->enumtype) {
1457 t = mono_class_enum_basetype (klass)->type;
1458 goto handle_enum;
1459 } else if (mono_is_corlib_image (klass->image)) {
1460 if (strcmp (klass->name_space, "System") == 0) {
1461 if (strcmp (klass->name, "Decimal") == 0)
1462 return TYPECODE_DECIMAL;
1463 else if (strcmp (klass->name, "DateTime") == 0)
1464 return TYPECODE_DATETIME;
1467 return TYPECODE_OBJECT;
1469 case MONO_TYPE_STRING:
1470 return TYPECODE_STRING;
1471 case MONO_TYPE_SZARRAY:
1472 case MONO_TYPE_ARRAY:
1473 case MONO_TYPE_OBJECT:
1474 case MONO_TYPE_VAR:
1475 case MONO_TYPE_MVAR:
1476 case MONO_TYPE_TYPEDBYREF:
1477 return TYPECODE_OBJECT;
1478 case MONO_TYPE_CLASS:
1480 MonoClass *klass = type->type->data.klass;
1481 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1482 if (strcmp (klass->name, "DBNull") == 0)
1483 return TYPECODE_DBNULL;
1486 return TYPECODE_OBJECT;
1487 case MONO_TYPE_GENERICINST:
1488 return TYPECODE_OBJECT;
1489 default:
1490 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1492 return 0;
1495 ICALL_EXPORT guint32
1496 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1498 MonoDomain *domain;
1499 MonoClass *klass;
1500 MonoClass *klassc;
1502 MONO_ARCH_SAVE_REGS;
1504 g_assert (type != NULL);
1506 domain = ((MonoObject *)type)->vtable->domain;
1508 if (!c) /* FIXME: dont know what do do here */
1509 return 0;
1511 klass = mono_class_from_mono_type (type->type);
1512 klassc = mono_class_from_mono_type (c->type);
1514 /* Interface check requires a more complex setup so we
1515 * only do for them. Otherwise we simply avoid mono_class_init.
1517 if (check_interfaces) {
1518 mono_class_init_or_throw (klass);
1519 mono_class_init_or_throw (klassc);
1520 } else if (!klass->supertypes || !klassc->supertypes) {
1521 mono_class_setup_supertypes (klass);
1522 mono_class_setup_supertypes (klassc);
1525 if (type->type->byref)
1526 return klassc == mono_defaults.object_class;
1528 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1531 static gboolean
1532 mono_type_is_primitive (MonoType *type)
1534 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1535 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1538 static MonoType*
1539 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1541 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1542 return mono_class_enum_basetype (type->data.klass);
1543 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1544 return mono_class_enum_basetype (type->data.generic_class->container_class);
1545 return type;
1548 ICALL_EXPORT guint32
1549 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1551 MonoDomain *domain;
1552 MonoClass *klass;
1553 MonoClass *klassc;
1555 MONO_ARCH_SAVE_REGS;
1557 g_assert (type != NULL);
1559 domain = ((MonoObject *)type)->vtable->domain;
1561 klass = mono_class_from_mono_type (type->type);
1562 klassc = mono_class_from_mono_type (c->type);
1564 if (type->type->byref ^ c->type->byref)
1565 return FALSE;
1567 if (type->type->byref) {
1568 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1569 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1571 klass = mono_class_from_mono_type (t);
1572 klassc = mono_class_from_mono_type (ot);
1574 if (mono_type_is_primitive (t)) {
1575 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1576 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1577 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1578 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1579 return t->type == ot->type;
1580 } else {
1581 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1582 return FALSE;
1584 if (klass->valuetype)
1585 return klass == klassc;
1586 return klass->valuetype == klassc->valuetype;
1589 return mono_class_is_assignable_from (klass, klassc);
1592 ICALL_EXPORT guint32
1593 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1595 MonoClass *klass = mono_class_from_mono_type (type->type);
1596 mono_class_init_or_throw (klass);
1597 return mono_object_isinst (obj, klass) != NULL;
1600 ICALL_EXPORT guint32
1601 ves_icall_get_attributes (MonoReflectionType *type)
1603 MonoClass *klass = mono_class_from_mono_type (type->type);
1604 return klass->flags;
1607 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1608 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1610 MonoClass *klass = field->field->parent;
1611 MonoMarshalType *info;
1612 int i;
1614 if (klass->generic_container ||
1615 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1616 return NULL;
1618 info = mono_marshal_load_type_info (klass);
1620 for (i = 0; i < info->num_fields; ++i) {
1621 if (info->fields [i].field == field->field) {
1622 if (!info->fields [i].mspec)
1623 return NULL;
1624 else
1625 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1629 return NULL;
1632 ICALL_EXPORT MonoReflectionField*
1633 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1635 gboolean found = FALSE;
1636 MonoClass *klass;
1637 MonoClass *k;
1639 g_assert (handle);
1641 if (!type) {
1642 klass = handle->parent;
1643 } else {
1644 klass = mono_class_from_mono_type (type);
1646 /* Check that the field belongs to the class */
1647 for (k = klass; k; k = k->parent) {
1648 if (k == handle->parent) {
1649 found = TRUE;
1650 break;
1654 if (!found)
1655 /* The managed code will throw the exception */
1656 return NULL;
1659 return mono_field_get_object (mono_domain_get (), klass, handle);
1662 ICALL_EXPORT MonoArray*
1663 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1665 MonoError error;
1666 MonoType *type = mono_field_get_type_checked (field->field, &error);
1667 if (!mono_error_ok (&error))
1668 mono_error_raise_exception (&error);
1670 return type_array_from_modifiers (field->field->parent->image, type, optional);
1673 ICALL_EXPORT int
1674 vell_icall_get_method_attributes (MonoMethod *method)
1676 return method->flags;
1679 ICALL_EXPORT void
1680 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1682 MonoError error;
1683 MonoDomain *domain = mono_domain_get ();
1684 MonoMethodSignature* sig;
1685 MONO_ARCH_SAVE_REGS;
1687 sig = mono_method_signature_checked (method, &error);
1688 if (!mono_error_ok (&error))
1689 mono_error_raise_exception (&error);
1692 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1693 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1694 info->attrs = method->flags;
1695 info->implattrs = method->iflags;
1696 if (sig->call_convention == MONO_CALL_DEFAULT)
1697 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1698 else {
1699 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1700 info->callconv = 2;
1701 else
1702 info->callconv = 1;
1704 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1707 ICALL_EXPORT MonoArray*
1708 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1710 MonoDomain *domain = mono_domain_get ();
1712 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1715 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1716 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1718 MonoDomain *domain = mono_domain_get ();
1719 MonoReflectionMarshalAsAttribute* res = NULL;
1720 MonoMarshalSpec **mspecs;
1721 int i;
1723 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1724 mono_method_get_marshal_info (method, mspecs);
1726 if (mspecs [0])
1727 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1729 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1730 if (mspecs [i])
1731 mono_metadata_free_marshal_spec (mspecs [i]);
1732 g_free (mspecs);
1734 return res;
1737 ICALL_EXPORT gint32
1738 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1740 MonoClass *parent = field->field->parent;
1741 if (!parent->size_inited)
1742 mono_class_init (parent);
1744 return field->field->offset - sizeof (MonoObject);
1747 ICALL_EXPORT MonoReflectionType*
1748 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1750 MonoClass *parent;
1751 MONO_ARCH_SAVE_REGS;
1753 parent = declaring? field->field->parent: field->klass;
1755 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1758 ICALL_EXPORT MonoObject *
1759 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1761 MonoClass *fklass = field->klass;
1762 MonoClassField *cf = field->field;
1763 MonoDomain *domain = mono_object_domain (field);
1765 if (fklass->image->assembly->ref_only)
1766 mono_raise_exception (mono_get_exception_invalid_operation (
1767 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1769 if (mono_security_core_clr_enabled ())
1770 mono_security_core_clr_ensure_reflection_access_field (cf);
1772 return mono_field_get_value_object (domain, cf, obj);
1775 ICALL_EXPORT void
1776 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1778 MonoError error;
1779 MonoClassField *cf = field->field;
1780 MonoType *type;
1781 gchar *v;
1783 MONO_ARCH_SAVE_REGS;
1785 if (field->klass->image->assembly->ref_only)
1786 mono_raise_exception (mono_get_exception_invalid_operation (
1787 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1789 if (mono_security_core_clr_enabled ())
1790 mono_security_core_clr_ensure_reflection_access_field (cf);
1792 type = mono_field_get_type_checked (cf, &error);
1793 if (!mono_error_ok (&error))
1794 mono_error_raise_exception (&error);
1796 v = (gchar *) value;
1797 if (!type->byref) {
1798 switch (type->type) {
1799 case MONO_TYPE_U1:
1800 case MONO_TYPE_I1:
1801 case MONO_TYPE_BOOLEAN:
1802 case MONO_TYPE_U2:
1803 case MONO_TYPE_I2:
1804 case MONO_TYPE_CHAR:
1805 case MONO_TYPE_U:
1806 case MONO_TYPE_I:
1807 case MONO_TYPE_U4:
1808 case MONO_TYPE_I4:
1809 case MONO_TYPE_R4:
1810 case MONO_TYPE_U8:
1811 case MONO_TYPE_I8:
1812 case MONO_TYPE_R8:
1813 case MONO_TYPE_VALUETYPE:
1814 case MONO_TYPE_PTR:
1815 if (v != NULL)
1816 v += sizeof (MonoObject);
1817 break;
1818 case MONO_TYPE_STRING:
1819 case MONO_TYPE_OBJECT:
1820 case MONO_TYPE_CLASS:
1821 case MONO_TYPE_ARRAY:
1822 case MONO_TYPE_SZARRAY:
1823 /* Do nothing */
1824 break;
1825 case MONO_TYPE_GENERICINST: {
1826 MonoGenericClass *gclass = type->data.generic_class;
1827 g_assert (!gclass->context.class_inst->is_open);
1829 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1830 MonoClass *nklass = mono_class_from_mono_type (type);
1831 MonoObject *nullable;
1834 * Convert the boxed vtype into a Nullable structure.
1835 * This is complicated by the fact that Nullables have
1836 * a variable structure.
1838 nullable = mono_object_new (mono_domain_get (), nklass);
1840 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1842 v = mono_object_unbox (nullable);
1844 else
1845 if (gclass->container_class->valuetype && (v != NULL))
1846 v += sizeof (MonoObject);
1847 break;
1849 default:
1850 g_error ("type 0x%x not handled in "
1851 "ves_icall_FieldInfo_SetValueInternal", type->type);
1852 return;
1856 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1857 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1858 if (!vtable->initialized)
1859 mono_runtime_class_init (vtable);
1860 mono_field_static_set_value (vtable, cf, v);
1861 } else {
1862 mono_field_set_value (obj, cf, v);
1866 ICALL_EXPORT MonoObject *
1867 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1869 MonoObject *o = NULL;
1870 MonoClassField *field = this->field;
1871 MonoClass *klass;
1872 MonoDomain *domain = mono_object_domain (this);
1873 gchar *v;
1874 MonoTypeEnum def_type;
1875 const char *def_value;
1876 MonoType *t;
1877 MonoError error;
1879 MONO_ARCH_SAVE_REGS;
1881 mono_class_init (field->parent);
1883 t = mono_field_get_type_checked (field, &error);
1884 if (!mono_error_ok (&error))
1885 mono_error_raise_exception (&error);
1887 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1888 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1890 if (field->parent->image->dynamic) {
1891 /* FIXME: */
1892 g_assert_not_reached ();
1895 def_value = mono_class_get_field_default_value (field, &def_type);
1896 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1897 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1899 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1900 switch (def_type) {
1901 case MONO_TYPE_U1:
1902 case MONO_TYPE_I1:
1903 case MONO_TYPE_BOOLEAN:
1904 case MONO_TYPE_U2:
1905 case MONO_TYPE_I2:
1906 case MONO_TYPE_CHAR:
1907 case MONO_TYPE_U:
1908 case MONO_TYPE_I:
1909 case MONO_TYPE_U4:
1910 case MONO_TYPE_I4:
1911 case MONO_TYPE_R4:
1912 case MONO_TYPE_U8:
1913 case MONO_TYPE_I8:
1914 case MONO_TYPE_R8: {
1915 MonoType *t;
1917 /* boxed value type */
1918 t = g_new0 (MonoType, 1);
1919 t->type = def_type;
1920 klass = mono_class_from_mono_type (t);
1921 g_free (t);
1922 o = mono_object_new (domain, klass);
1923 v = ((gchar *) o) + sizeof (MonoObject);
1924 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1925 break;
1927 case MONO_TYPE_STRING:
1928 case MONO_TYPE_CLASS:
1929 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1930 break;
1931 default:
1932 g_assert_not_reached ();
1935 return o;
1938 ICALL_EXPORT MonoReflectionType*
1939 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1941 MonoError error;
1942 MonoClassField *field = ref_field->field;
1943 MonoType *type = mono_field_get_type_checked (field, &error);
1944 if (!mono_error_ok (&error))
1945 mono_error_raise_exception (&error);
1946 return mono_type_get_object (mono_object_domain (ref_field), type);
1949 ICALL_EXPORT MonoReflectionType*
1950 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1952 MonoMethod *method = rmethod->method.method;
1954 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1957 /* From MonoProperty.cs */
1958 typedef enum {
1959 PInfo_Attributes = 1,
1960 PInfo_GetMethod = 1 << 1,
1961 PInfo_SetMethod = 1 << 2,
1962 PInfo_ReflectedType = 1 << 3,
1963 PInfo_DeclaringType = 1 << 4,
1964 PInfo_Name = 1 << 5
1965 } PInfo;
1967 ICALL_EXPORT void
1968 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1970 MonoDomain *domain = mono_object_domain (property);
1972 MONO_ARCH_SAVE_REGS;
1974 if ((req_info & PInfo_ReflectedType) != 0)
1975 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1976 if ((req_info & PInfo_DeclaringType) != 0)
1977 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1979 if ((req_info & PInfo_Name) != 0)
1980 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1982 if ((req_info & PInfo_Attributes) != 0)
1983 info->attrs = property->property->attrs;
1985 if ((req_info & PInfo_GetMethod) != 0)
1986 MONO_STRUCT_SETREF (info, get, property->property->get ?
1987 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1989 if ((req_info & PInfo_SetMethod) != 0)
1990 MONO_STRUCT_SETREF (info, set, property->property->set ?
1991 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1993 * There may be other methods defined for properties, though, it seems they are not exposed
1994 * in the reflection API
1998 ICALL_EXPORT void
1999 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2001 MonoDomain *domain = mono_object_domain (event);
2003 MONO_ARCH_SAVE_REGS;
2005 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2006 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2008 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2009 info->attrs = event->event->attrs;
2010 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2011 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2012 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2014 #ifndef MONO_SMALL_CONFIG
2015 if (event->event->other) {
2016 int i, n = 0;
2017 while (event->event->other [n])
2018 n++;
2019 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2021 for (i = 0; i < n; i++)
2022 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2024 #endif
2027 static void
2028 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2030 int i;
2031 MonoClass *ic;
2033 mono_class_setup_interfaces (klass, error);
2034 if (!mono_error_ok (error))
2035 return;
2037 for (i = 0; i < klass->interface_count; i++) {
2038 ic = klass->interfaces [i];
2039 g_hash_table_insert (ifaces, ic, ic);
2041 collect_interfaces (ic, ifaces, error);
2042 if (!mono_error_ok (error))
2043 return;
2047 typedef struct {
2048 MonoArray *iface_array;
2049 MonoGenericContext *context;
2050 MonoError *error;
2051 MonoDomain *domain;
2052 int next_idx;
2053 } FillIfaceArrayData;
2055 static void
2056 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2058 FillIfaceArrayData *data = user_data;
2059 MonoClass *ic = key;
2060 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2062 if (!mono_error_ok (data->error))
2063 return;
2065 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2066 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2067 if (!mono_error_ok (data->error))
2068 return;
2071 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2073 if (inflated)
2074 mono_metadata_free_type (inflated);
2077 ICALL_EXPORT MonoArray*
2078 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2080 MonoError error;
2081 MonoClass *class = mono_class_from_mono_type (type->type);
2082 MonoClass *parent;
2083 FillIfaceArrayData data = { 0 };
2084 int len;
2086 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2088 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2089 data.context = mono_class_get_context (class);
2090 class = class->generic_class->container_class;
2093 for (parent = class; parent; parent = parent->parent) {
2094 mono_class_setup_interfaces (parent, &error);
2095 if (!mono_error_ok (&error))
2096 goto fail;
2097 collect_interfaces (parent, iface_hash, &error);
2098 if (!mono_error_ok (&error))
2099 goto fail;
2102 data.error = &error;
2103 data.domain = mono_object_domain (type);
2105 len = g_hash_table_size (iface_hash);
2106 if (len == 0) {
2107 g_hash_table_destroy (iface_hash);
2108 if (!data.domain->empty_types)
2109 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2110 return data.domain->empty_types;
2113 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2114 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2115 if (!mono_error_ok (&error))
2116 goto fail;
2118 g_hash_table_destroy (iface_hash);
2119 return data.iface_array;
2121 fail:
2122 g_hash_table_destroy (iface_hash);
2123 mono_error_raise_exception (&error);
2124 return NULL;
2127 ICALL_EXPORT void
2128 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2130 gboolean variance_used;
2131 MonoClass *class = mono_class_from_mono_type (type->type);
2132 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2133 MonoReflectionMethod *member;
2134 MonoMethod* method;
2135 gpointer iter;
2136 int i = 0, len, ioffset;
2137 MonoDomain *domain;
2139 MONO_ARCH_SAVE_REGS;
2140 mono_class_init_or_throw (class);
2141 mono_class_init_or_throw (iclass);
2143 mono_class_setup_vtable (class);
2145 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2146 if (ioffset == -1)
2147 return;
2149 len = mono_class_num_methods (iclass);
2150 domain = mono_object_domain (type);
2151 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2152 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2153 iter = NULL;
2154 while ((method = mono_class_get_methods (iclass, &iter))) {
2155 member = mono_method_get_object (domain, method, iclass);
2156 mono_array_setref (*methods, i, member);
2157 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2158 mono_array_setref (*targets, i, member);
2160 i ++;
2164 ICALL_EXPORT void
2165 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2167 MonoClass *klass = mono_class_from_mono_type (type->type);
2168 mono_class_init_or_throw (klass);
2170 if (klass->image->dynamic) {
2171 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2172 *packing = tb->packing_size;
2173 *size = tb->class_size;
2174 } else {
2175 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2179 ICALL_EXPORT MonoReflectionType*
2180 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2182 MonoClass *class;
2184 MONO_ARCH_SAVE_REGS;
2186 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2187 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2189 class = mono_class_from_mono_type (type->type);
2190 mono_class_init_or_throw (class);
2192 // GetElementType should only return a type for:
2193 // Array Pointer PassedByRef
2194 if (type->type->byref)
2195 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2196 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2197 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2198 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2199 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2200 else
2201 return NULL;
2204 ICALL_EXPORT MonoReflectionType*
2205 ves_icall_get_type_parent (MonoReflectionType *type)
2207 MonoClass *class = mono_class_from_mono_type (type->type);
2208 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2211 ICALL_EXPORT MonoBoolean
2212 ves_icall_type_ispointer (MonoReflectionType *type)
2214 MONO_ARCH_SAVE_REGS;
2216 return type->type->type == MONO_TYPE_PTR;
2219 ICALL_EXPORT MonoBoolean
2220 ves_icall_type_isprimitive (MonoReflectionType *type)
2222 MONO_ARCH_SAVE_REGS;
2224 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2227 ICALL_EXPORT MonoBoolean
2228 ves_icall_type_isbyref (MonoReflectionType *type)
2230 MONO_ARCH_SAVE_REGS;
2232 return type->type->byref;
2235 ICALL_EXPORT MonoBoolean
2236 ves_icall_type_iscomobject (MonoReflectionType *type)
2238 MonoClass *klass = mono_class_from_mono_type (type->type);
2239 mono_class_init_or_throw (klass);
2241 return mono_class_is_com_object (klass);
2244 ICALL_EXPORT MonoReflectionModule*
2245 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2247 MonoClass *class = mono_class_from_mono_type (type->type);
2248 return mono_module_get_object (mono_object_domain (type), class->image);
2251 ICALL_EXPORT MonoReflectionAssembly*
2252 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2254 MonoDomain *domain = mono_domain_get ();
2255 MonoClass *class = mono_class_from_mono_type (type->type);
2256 return mono_assembly_get_object (domain, class->image->assembly);
2259 ICALL_EXPORT MonoReflectionType*
2260 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2262 MonoDomain *domain = mono_domain_get ();
2263 MonoClass *class;
2265 MONO_ARCH_SAVE_REGS;
2267 if (type->type->byref)
2268 return NULL;
2269 if (type->type->type == MONO_TYPE_VAR)
2270 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2271 else if (type->type->type == MONO_TYPE_MVAR)
2272 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2273 else
2274 class = mono_class_from_mono_type (type->type)->nested_in;
2276 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2279 ICALL_EXPORT MonoString*
2280 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2282 MonoDomain *domain = mono_domain_get ();
2283 MonoClass *class = mono_class_from_mono_type (type->type);
2285 if (type->type->byref) {
2286 char *n = g_strdup_printf ("%s&", class->name);
2287 MonoString *res = mono_string_new (domain, n);
2289 g_free (n);
2291 return res;
2292 } else {
2293 return mono_string_new (domain, class->name);
2297 ICALL_EXPORT MonoString*
2298 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2300 MonoDomain *domain = mono_domain_get ();
2301 MonoClass *class = mono_class_from_mono_type (type->type);
2303 while (class->nested_in)
2304 class = class->nested_in;
2306 if (class->name_space [0] == '\0')
2307 return NULL;
2308 else
2309 return mono_string_new (domain, class->name_space);
2312 ICALL_EXPORT gint32
2313 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2315 MonoClass *class;
2317 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2318 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2320 class = mono_class_from_mono_type (type->type);
2322 return class->rank;
2325 ICALL_EXPORT MonoArray*
2326 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2328 MonoArray *res;
2329 MonoClass *klass, *pklass;
2330 MonoDomain *domain = mono_object_domain (type);
2331 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2332 int i;
2333 MONO_ARCH_SAVE_REGS;
2335 klass = mono_class_from_mono_type (type->type);
2337 if (klass->generic_container) {
2338 MonoGenericContainer *container = klass->generic_container;
2339 res = mono_array_new_specific (array_vtable, container->type_argc);
2340 for (i = 0; i < container->type_argc; ++i) {
2341 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2342 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2344 } else if (klass->generic_class) {
2345 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2346 res = mono_array_new_specific (array_vtable, inst->type_argc);
2347 for (i = 0; i < inst->type_argc; ++i)
2348 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2349 } else {
2350 res = mono_array_new_specific (array_vtable, 0);
2352 return res;
2355 ICALL_EXPORT gboolean
2356 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2358 MonoClass *klass;
2359 MONO_ARCH_SAVE_REGS;
2361 if (!IS_MONOTYPE (type))
2362 return FALSE;
2364 if (type->type->byref)
2365 return FALSE;
2367 klass = mono_class_from_mono_type (type->type);
2368 return klass->generic_container != NULL;
2371 ICALL_EXPORT MonoReflectionType*
2372 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2374 MonoClass *klass;
2375 MONO_ARCH_SAVE_REGS;
2377 if (type->type->byref)
2378 return NULL;
2380 klass = mono_class_from_mono_type (type->type);
2382 if (klass->generic_container) {
2383 return type; /* check this one */
2385 if (klass->generic_class) {
2386 MonoClass *generic_class = klass->generic_class->container_class;
2387 gpointer tb;
2389 tb = mono_class_get_ref_info (generic_class);
2391 if (generic_class->wastypebuilder && tb)
2392 return tb;
2393 else
2394 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2396 return NULL;
2399 ICALL_EXPORT MonoReflectionType*
2400 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2402 MonoClass *class;
2403 MonoType *geninst, **types;
2404 int i, count;
2406 g_assert (IS_MONOTYPE (type));
2407 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2409 count = mono_array_length (type_array);
2410 types = g_new0 (MonoType *, count);
2412 for (i = 0; i < count; i++) {
2413 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2414 types [i] = t->type;
2417 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2418 g_free (types);
2419 if (!geninst)
2420 return NULL;
2422 class = mono_class_from_mono_type (geninst);
2424 /*we might inflate to the GTD*/
2425 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2426 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2428 return mono_type_get_object (mono_object_domain (type), geninst);
2431 ICALL_EXPORT gboolean
2432 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2434 MonoClass *klass;
2435 MONO_ARCH_SAVE_REGS;
2437 if (type->type->byref)
2438 return FALSE;
2440 klass = mono_class_from_mono_type (type->type);
2442 return klass->generic_class != NULL;
2445 ICALL_EXPORT gboolean
2446 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2448 MonoClass *klass;
2449 MONO_ARCH_SAVE_REGS;
2451 if (!IS_MONOTYPE (type))
2452 return FALSE;
2454 if (type->type->byref)
2455 return FALSE;
2457 klass = mono_class_from_mono_type (type->type);
2458 return klass->generic_class != NULL || klass->generic_container != NULL;
2461 ICALL_EXPORT gint32
2462 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2464 MONO_ARCH_SAVE_REGS;
2466 if (!IS_MONOTYPE (type))
2467 return -1;
2469 if (is_generic_parameter (type->type))
2470 return mono_type_get_generic_param_num (type->type);
2471 return -1;
2474 ICALL_EXPORT GenericParameterAttributes
2475 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2477 MONO_ARCH_SAVE_REGS;
2479 g_assert (IS_MONOTYPE (type));
2480 g_assert (is_generic_parameter (type->type));
2481 return mono_generic_param_info (type->type->data.generic_param)->flags;
2484 ICALL_EXPORT MonoArray *
2485 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2487 MonoGenericParamInfo *param_info;
2488 MonoDomain *domain;
2489 MonoClass **ptr;
2490 MonoArray *res;
2491 int i, count;
2493 MONO_ARCH_SAVE_REGS;
2495 g_assert (IS_MONOTYPE (type));
2497 domain = mono_object_domain (type);
2498 param_info = mono_generic_param_info (type->type->data.generic_param);
2499 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2502 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2503 for (i = 0; i < count; i++)
2504 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2507 return res;
2510 ICALL_EXPORT MonoBoolean
2511 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2513 MONO_ARCH_SAVE_REGS;
2514 return is_generic_parameter (type->type);
2517 ICALL_EXPORT MonoBoolean
2518 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2520 MONO_ARCH_SAVE_REGS;
2521 return is_generic_parameter (tb->type.type);
2524 ICALL_EXPORT void
2525 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2526 MonoReflectionType *t)
2528 enumtype->type = t->type;
2531 ICALL_EXPORT MonoReflectionMethod*
2532 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2533 MonoReflectionMethod* generic)
2535 MonoDomain *domain;
2536 MonoClass *klass;
2537 MonoMethod *method;
2538 gpointer iter;
2540 MONO_ARCH_SAVE_REGS;
2542 domain = ((MonoObject *)type)->vtable->domain;
2544 klass = mono_class_from_mono_type (type->type);
2545 mono_class_init_or_throw (klass);
2547 iter = NULL;
2548 while ((method = mono_class_get_methods (klass, &iter))) {
2549 if (method->token == generic->method->token)
2550 return mono_method_get_object (domain, method, klass);
2553 return NULL;
2558 ICALL_EXPORT MonoReflectionMethod *
2559 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2561 MonoMethod *method;
2562 MonoType *type = ref_type->type;
2564 MONO_ARCH_SAVE_REGS;
2566 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2567 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2568 if (type->type == MONO_TYPE_VAR)
2569 return NULL;
2571 method = mono_type_get_generic_param_owner (type)->owner.method;
2572 g_assert (method);
2573 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2576 ICALL_EXPORT MonoReflectionDllImportAttribute*
2577 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2579 static MonoClass *DllImportAttributeClass = NULL;
2580 MonoDomain *domain = mono_domain_get ();
2581 MonoReflectionDllImportAttribute *attr;
2582 MonoImage *image = method->klass->image;
2583 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2584 MonoTableInfo *tables = image->tables;
2585 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2586 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2587 guint32 im_cols [MONO_IMPLMAP_SIZE];
2588 guint32 scope_token;
2589 const char *import = NULL;
2590 const char *scope = NULL;
2591 guint32 flags;
2593 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2594 return NULL;
2596 if (!DllImportAttributeClass) {
2597 DllImportAttributeClass =
2598 mono_class_from_name (mono_defaults.corlib,
2599 "System.Runtime.InteropServices", "DllImportAttribute");
2600 g_assert (DllImportAttributeClass);
2603 if (method->klass->image->dynamic) {
2604 MonoReflectionMethodAux *method_aux =
2605 g_hash_table_lookup (
2606 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2607 if (method_aux) {
2608 import = method_aux->dllentry;
2609 scope = method_aux->dll;
2612 if (!import || !scope) {
2613 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2614 return NULL;
2617 else {
2618 if (piinfo->implmap_idx) {
2619 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2621 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2622 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2623 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2624 scope = mono_metadata_string_heap (image, scope_token);
2627 flags = piinfo->piflags;
2629 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2631 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2632 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2633 attr->call_conv = (flags & 0x700) >> 8;
2634 attr->charset = ((flags & 0x6) >> 1) + 1;
2635 if (attr->charset == 1)
2636 attr->charset = 2;
2637 attr->exact_spelling = (flags & 0x1) != 0;
2638 attr->set_last_error = (flags & 0x40) != 0;
2639 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2640 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2641 attr->preserve_sig = FALSE;
2643 return attr;
2646 ICALL_EXPORT MonoReflectionMethod *
2647 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2649 MonoMethodInflated *imethod;
2650 MonoMethod *result;
2652 MONO_ARCH_SAVE_REGS;
2654 if (method->method->is_generic)
2655 return method;
2657 if (!method->method->is_inflated)
2658 return NULL;
2660 imethod = (MonoMethodInflated *) method->method;
2662 result = imethod->declaring;
2663 /* Not a generic method. */
2664 if (!result->is_generic)
2665 return NULL;
2667 if (method->method->klass->image->dynamic) {
2668 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2669 MonoReflectionMethod *res;
2672 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2673 * the dynamic case as well ?
2675 mono_image_lock ((MonoImage*)image);
2676 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2677 mono_image_unlock ((MonoImage*)image);
2679 if (res)
2680 return res;
2683 if (imethod->context.class_inst) {
2684 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2685 /*Generic methods gets the context of the GTD.*/
2686 if (mono_class_get_context (klass))
2687 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2690 return mono_method_get_object (mono_object_domain (method), result, NULL);
2693 ICALL_EXPORT gboolean
2694 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2696 MONO_ARCH_SAVE_REGS;
2698 return mono_method_signature (method->method)->generic_param_count != 0;
2701 ICALL_EXPORT gboolean
2702 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2704 MONO_ARCH_SAVE_REGS;
2706 return method->method->is_generic;
2709 ICALL_EXPORT MonoArray*
2710 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2712 MonoArray *res;
2713 MonoDomain *domain;
2714 int count, i;
2715 MONO_ARCH_SAVE_REGS;
2717 domain = mono_object_domain (method);
2719 if (method->method->is_inflated) {
2720 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2722 if (inst) {
2723 count = inst->type_argc;
2724 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2726 for (i = 0; i < count; i++)
2727 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2729 return res;
2733 count = mono_method_signature (method->method)->generic_param_count;
2734 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2736 for (i = 0; i < count; i++) {
2737 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2738 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2739 MonoClass *pklass = mono_class_from_generic_parameter (
2740 param, method->method->klass->image, TRUE);
2741 mono_array_setref (res, i,
2742 mono_type_get_object (domain, &pklass->byval_arg));
2745 return res;
2748 ICALL_EXPORT MonoObject *
2749 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2752 * Invoke from reflection is supposed to always be a virtual call (the API
2753 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2754 * greater flexibility.
2756 MonoMethod *m = method->method;
2757 MonoMethodSignature *sig = mono_method_signature (m);
2758 MonoImage *image;
2759 int pcount;
2760 void *obj = this;
2762 MONO_ARCH_SAVE_REGS;
2764 *exc = NULL;
2766 if (mono_security_core_clr_enabled ())
2767 mono_security_core_clr_ensure_reflection_access_method (m);
2769 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2770 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2771 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2772 return NULL;
2775 if (this) {
2776 if (!mono_object_isinst (this, m->klass)) {
2777 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2778 char *target_name = mono_type_get_full_name (m->klass);
2779 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2780 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2781 g_free (msg);
2782 g_free (target_name);
2783 g_free (this_name);
2784 return NULL;
2786 m = mono_object_get_virtual_method (this, m);
2787 /* must pass the pointer to the value for valuetype methods */
2788 if (m->klass->valuetype)
2789 obj = mono_object_unbox (this);
2790 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2791 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2792 return NULL;
2796 if (sig->ret->byref) {
2797 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
2798 return NULL;
2801 pcount = params? mono_array_length (params): 0;
2802 if (pcount != sig->param_count) {
2803 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2804 return NULL;
2807 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2808 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2809 return NULL;
2812 image = m->klass->image;
2813 if (image->assembly->ref_only) {
2814 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2815 return NULL;
2818 if (image->dynamic && !((MonoDynamicImage*)image)->run) {
2819 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2820 return NULL;
2823 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2824 int i;
2825 uintptr_t *lengths;
2826 intptr_t *lower_bounds;
2827 pcount = mono_array_length (params);
2828 lengths = alloca (sizeof (uintptr_t) * pcount);
2829 /* Note: the synthetized array .ctors have int32 as argument type */
2830 for (i = 0; i < pcount; ++i)
2831 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2833 if (m->klass->rank == pcount) {
2834 /* Only lengths provided. */
2835 lower_bounds = NULL;
2836 } else {
2837 g_assert (pcount == (m->klass->rank * 2));
2838 /* lower bounds are first. */
2839 lower_bounds = (intptr_t*)lengths;
2840 lengths += m->klass->rank;
2843 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2845 return mono_runtime_invoke_array (m, obj, params, NULL);
2848 #ifndef DISABLE_REMOTING
2849 ICALL_EXPORT MonoObject *
2850 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2852 MonoDomain *domain = mono_object_domain (method);
2853 MonoMethod *m = method->method;
2854 MonoMethodSignature *sig = mono_method_signature (m);
2855 MonoArray *out_args;
2856 MonoObject *result;
2857 int i, j, outarg_count = 0;
2859 MONO_ARCH_SAVE_REGS;
2861 if (m->klass == mono_defaults.object_class) {
2863 if (!strcmp (m->name, "FieldGetter")) {
2864 MonoClass *k = this->vtable->klass;
2865 MonoString *name;
2866 char *str;
2868 /* If this is a proxy, then it must be a CBO */
2869 if (k == mono_defaults.transparent_proxy_class) {
2870 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2871 this = tp->rp->unwrapped_server;
2872 g_assert (this);
2873 k = this->vtable->klass;
2876 name = mono_array_get (params, MonoString *, 1);
2877 str = mono_string_to_utf8 (name);
2879 do {
2880 MonoClassField* field = mono_class_get_field_from_name (k, str);
2881 if (field) {
2882 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2883 if (field_klass->valuetype)
2884 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2885 else
2886 result = *((gpointer *)((char *)this + field->offset));
2888 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2889 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2890 mono_array_setref (out_args, 0, result);
2891 g_free (str);
2892 return NULL;
2894 k = k->parent;
2895 } while (k);
2897 g_free (str);
2898 g_assert_not_reached ();
2900 } else if (!strcmp (m->name, "FieldSetter")) {
2901 MonoClass *k = this->vtable->klass;
2902 MonoString *name;
2903 guint32 size;
2904 gint32 align;
2905 char *str;
2907 /* If this is a proxy, then it must be a CBO */
2908 if (k == mono_defaults.transparent_proxy_class) {
2909 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2910 this = tp->rp->unwrapped_server;
2911 g_assert (this);
2912 k = this->vtable->klass;
2915 name = mono_array_get (params, MonoString *, 1);
2916 str = mono_string_to_utf8 (name);
2918 do {
2919 MonoClassField* field = mono_class_get_field_from_name (k, str);
2920 if (field) {
2921 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2922 MonoObject *val = mono_array_get (params, gpointer, 2);
2924 if (field_klass->valuetype) {
2925 size = mono_type_size (field->type, &align);
2926 g_assert (size == mono_class_value_size (field_klass, NULL));
2927 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2928 } else {
2929 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2932 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2933 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2935 g_free (str);
2936 return NULL;
2939 k = k->parent;
2940 } while (k);
2942 g_free (str);
2943 g_assert_not_reached ();
2948 for (i = 0; i < mono_array_length (params); i++) {
2949 if (sig->params [i]->byref)
2950 outarg_count++;
2953 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2955 /* handle constructors only for objects already allocated */
2956 if (!strcmp (method->method->name, ".ctor"))
2957 g_assert (this);
2959 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2960 g_assert (!method->method->klass->valuetype);
2961 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2963 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2964 if (sig->params [i]->byref) {
2965 gpointer arg;
2966 arg = mono_array_get (params, gpointer, i);
2967 mono_array_setref (out_args, j, arg);
2968 j++;
2972 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2974 return result;
2976 #endif
2978 static guint64
2979 read_enum_value (char *mem, int type)
2981 switch (type) {
2982 case MONO_TYPE_U1:
2983 return *(guint8*)mem;
2984 case MONO_TYPE_I1:
2985 return *(gint8*)mem;
2986 case MONO_TYPE_U2:
2987 return *(guint16*)mem;
2988 case MONO_TYPE_I2:
2989 return *(gint16*)mem;
2990 case MONO_TYPE_U4:
2991 return *(guint32*)mem;
2992 case MONO_TYPE_I4:
2993 return *(gint32*)mem;
2994 case MONO_TYPE_U8:
2995 return *(guint64*)mem;
2996 case MONO_TYPE_I8:
2997 return *(gint64*)mem;
2998 default:
2999 g_assert_not_reached ();
3001 return 0;
3004 static void
3005 write_enum_value (char *mem, int type, guint64 value)
3007 switch (type) {
3008 case MONO_TYPE_U1:
3009 case MONO_TYPE_I1: {
3010 guint8 *p = (guint8*)mem;
3011 *p = value;
3012 break;
3014 case MONO_TYPE_U2:
3015 case MONO_TYPE_I2: {
3016 guint16 *p = (void*)mem;
3017 *p = value;
3018 break;
3020 case MONO_TYPE_U4:
3021 case MONO_TYPE_I4: {
3022 guint32 *p = (void*)mem;
3023 *p = value;
3024 break;
3026 case MONO_TYPE_U8:
3027 case MONO_TYPE_I8: {
3028 guint64 *p = (void*)mem;
3029 *p = value;
3030 break;
3032 default:
3033 g_assert_not_reached ();
3035 return;
3038 ICALL_EXPORT MonoObject *
3039 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3041 MonoDomain *domain;
3042 MonoClass *enumc, *objc;
3043 MonoObject *res;
3044 MonoType *etype;
3045 guint64 val;
3047 MONO_ARCH_SAVE_REGS;
3049 MONO_CHECK_ARG_NULL (enumType);
3050 MONO_CHECK_ARG_NULL (value);
3052 domain = mono_object_domain (enumType);
3053 enumc = mono_class_from_mono_type (enumType->type);
3055 mono_class_init_or_throw (enumc);
3057 objc = value->vtable->klass;
3059 if (!enumc->enumtype)
3060 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3061 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3062 mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
3064 etype = mono_class_enum_basetype (enumc);
3065 if (!etype)
3066 /* MS throws this for typebuilders */
3067 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3069 res = mono_object_new (domain, enumc);
3070 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3071 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3073 return res;
3076 ICALL_EXPORT MonoObject *
3077 ves_icall_System_Enum_get_value (MonoObject *this)
3079 MonoObject *res;
3080 MonoClass *enumc;
3081 gpointer dst;
3082 gpointer src;
3083 int size;
3085 MONO_ARCH_SAVE_REGS;
3087 if (!this)
3088 return NULL;
3090 g_assert (this->vtable->klass->enumtype);
3092 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3093 res = mono_object_new (mono_object_domain (this), enumc);
3094 dst = (char *)res + sizeof (MonoObject);
3095 src = (char *)this + sizeof (MonoObject);
3096 size = mono_class_value_size (enumc, NULL);
3098 memcpy (dst, src, size);
3100 return res;
3103 ICALL_EXPORT MonoReflectionType *
3104 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3106 MonoType *etype;
3107 MonoClass *klass;
3109 MONO_ARCH_SAVE_REGS;
3111 klass = mono_class_from_mono_type (type->type);
3112 mono_class_init_or_throw (klass);
3114 etype = mono_class_enum_basetype (klass);
3115 if (!etype)
3116 /* MS throws this for typebuilders */
3117 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3119 return mono_type_get_object (mono_object_domain (type), etype);
3122 ICALL_EXPORT int
3123 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3125 gpointer tdata = (char *)this + sizeof (MonoObject);
3126 gpointer odata = (char *)other + sizeof (MonoObject);
3127 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3128 g_assert (basetype);
3130 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3131 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3132 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3133 if (me == other) \
3134 return 0; \
3135 return me > other ? 1 : -1; \
3136 } while (0)
3138 switch (basetype->type) {
3139 case MONO_TYPE_U1:
3140 COMPARE_ENUM_VALUES (guint8);
3141 case MONO_TYPE_I1:
3142 COMPARE_ENUM_VALUES (gint8);
3143 case MONO_TYPE_CHAR:
3144 case MONO_TYPE_U2:
3145 COMPARE_ENUM_VALUES (guint16);
3146 case MONO_TYPE_I2:
3147 COMPARE_ENUM_VALUES (gint16);
3148 case MONO_TYPE_U4:
3149 COMPARE_ENUM_VALUES (guint32);
3150 case MONO_TYPE_I4:
3151 COMPARE_ENUM_VALUES (gint32);
3152 case MONO_TYPE_U8:
3153 COMPARE_ENUM_VALUES (guint64);
3154 case MONO_TYPE_I8:
3155 COMPARE_ENUM_VALUES (gint64);
3156 default:
3157 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3159 #undef COMPARE_ENUM_VALUES
3160 return 0;
3163 ICALL_EXPORT int
3164 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3166 gpointer data = (char *)this + sizeof (MonoObject);
3167 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3168 g_assert (basetype);
3170 switch (basetype->type) {
3171 case MONO_TYPE_I1:
3172 return *((gint8*)data);
3173 case MONO_TYPE_U1:
3174 return *((guint8*)data);
3175 case MONO_TYPE_CHAR:
3176 case MONO_TYPE_U2:
3177 return *((guint16*)data);
3179 case MONO_TYPE_I2:
3180 return *((gint16*)data);
3181 case MONO_TYPE_U4:
3182 return *((guint32*)data);
3183 case MONO_TYPE_I4:
3184 return *((gint32*)data);
3185 case MONO_TYPE_U8:
3186 case MONO_TYPE_I8: {
3187 gint64 value = *((gint64*)data);
3188 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3190 default:
3191 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3193 return 0;
3196 ICALL_EXPORT void
3197 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3199 MonoDomain *domain = mono_object_domain (type);
3200 MonoClass *enumc = mono_class_from_mono_type (type->type);
3201 guint j = 0, nvalues, crow;
3202 gpointer iter;
3203 MonoClassField *field;
3205 MONO_ARCH_SAVE_REGS;
3207 mono_class_init_or_throw (enumc);
3209 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3210 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3211 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3212 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3214 crow = -1;
3215 iter = NULL;
3216 while ((field = mono_class_get_fields (enumc, &iter))) {
3217 const char *p;
3218 int len;
3219 MonoTypeEnum def_type;
3221 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3222 continue;
3223 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3224 continue;
3225 if (mono_field_is_deleted (field))
3226 continue;
3227 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3229 p = mono_class_get_field_default_value (field, &def_type);
3230 len = mono_metadata_decode_blob_size (p, &p);
3231 switch (mono_class_enum_basetype (enumc)->type) {
3232 case MONO_TYPE_U1:
3233 case MONO_TYPE_I1:
3234 mono_array_set (info->values, gchar, j, *p);
3235 break;
3236 case MONO_TYPE_CHAR:
3237 case MONO_TYPE_U2:
3238 case MONO_TYPE_I2:
3239 mono_array_set (info->values, gint16, j, read16 (p));
3240 break;
3241 case MONO_TYPE_U4:
3242 case MONO_TYPE_I4:
3243 mono_array_set (info->values, gint32, j, read32 (p));
3244 break;
3245 case MONO_TYPE_U8:
3246 case MONO_TYPE_I8:
3247 mono_array_set (info->values, gint64, j, read64 (p));
3248 break;
3249 default:
3250 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3252 ++j;
3256 enum {
3257 BFLAGS_IgnoreCase = 1,
3258 BFLAGS_DeclaredOnly = 2,
3259 BFLAGS_Instance = 4,
3260 BFLAGS_Static = 8,
3261 BFLAGS_Public = 0x10,
3262 BFLAGS_NonPublic = 0x20,
3263 BFLAGS_FlattenHierarchy = 0x40,
3264 BFLAGS_InvokeMethod = 0x100,
3265 BFLAGS_CreateInstance = 0x200,
3266 BFLAGS_GetField = 0x400,
3267 BFLAGS_SetField = 0x800,
3268 BFLAGS_GetProperty = 0x1000,
3269 BFLAGS_SetProperty = 0x2000,
3270 BFLAGS_ExactBinding = 0x10000,
3271 BFLAGS_SuppressChangeType = 0x20000,
3272 BFLAGS_OptionalParamBinding = 0x40000
3275 ICALL_EXPORT MonoReflectionField *
3276 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3278 MonoDomain *domain;
3279 MonoClass *startklass, *klass;
3280 int match;
3281 MonoClassField *field;
3282 gpointer iter;
3283 char *utf8_name;
3284 int (*compare_func) (const char *s1, const char *s2) = NULL;
3285 domain = ((MonoObject *)type)->vtable->domain;
3286 klass = startklass = mono_class_from_mono_type (type->type);
3288 if (!name)
3289 mono_raise_exception (mono_get_exception_argument_null ("name"));
3290 if (type->type->byref)
3291 return NULL;
3293 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3295 handle_parent:
3296 if (klass->exception_type != MONO_EXCEPTION_NONE)
3297 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3299 iter = NULL;
3300 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3301 guint32 flags = mono_field_get_flags (field);
3302 match = 0;
3304 if (mono_field_is_deleted_with_flags (field, flags))
3305 continue;
3306 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3307 if (bflags & BFLAGS_Public)
3308 match++;
3309 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3310 if (bflags & BFLAGS_NonPublic) {
3311 match++;
3314 if (!match)
3315 continue;
3316 match = 0;
3317 if (flags & FIELD_ATTRIBUTE_STATIC) {
3318 if (bflags & BFLAGS_Static)
3319 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3320 match++;
3321 } else {
3322 if (bflags & BFLAGS_Instance)
3323 match++;
3326 if (!match)
3327 continue;
3329 utf8_name = mono_string_to_utf8 (name);
3331 if (compare_func (mono_field_get_name (field), utf8_name)) {
3332 g_free (utf8_name);
3333 continue;
3335 g_free (utf8_name);
3337 return mono_field_get_object (domain, klass, field);
3339 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3340 goto handle_parent;
3342 return NULL;
3345 ICALL_EXPORT MonoArray*
3346 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3348 MonoDomain *domain;
3349 MonoClass *startklass, *klass, *refklass;
3350 MonoArray *res;
3351 MonoObject *member;
3352 int i, match;
3353 gpointer iter;
3354 MonoClassField *field;
3355 MonoPtrArray tmp_array;
3357 MONO_ARCH_SAVE_REGS;
3359 domain = ((MonoObject *)type)->vtable->domain;
3360 if (type->type->byref)
3361 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3362 klass = startklass = mono_class_from_mono_type (type->type);
3363 refklass = mono_class_from_mono_type (reftype->type);
3365 mono_ptr_array_init (tmp_array, 2);
3367 handle_parent:
3368 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3369 mono_ptr_array_destroy (tmp_array);
3370 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3373 iter = NULL;
3374 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3375 guint32 flags = mono_field_get_flags (field);
3376 match = 0;
3377 if (mono_field_is_deleted_with_flags (field, flags))
3378 continue;
3379 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3380 if (bflags & BFLAGS_Public)
3381 match++;
3382 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3383 if (bflags & BFLAGS_NonPublic) {
3384 match++;
3387 if (!match)
3388 continue;
3389 match = 0;
3390 if (flags & FIELD_ATTRIBUTE_STATIC) {
3391 if (bflags & BFLAGS_Static)
3392 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3393 match++;
3394 } else {
3395 if (bflags & BFLAGS_Instance)
3396 match++;
3399 if (!match)
3400 continue;
3401 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3402 mono_ptr_array_append (tmp_array, member);
3404 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3405 goto handle_parent;
3407 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3409 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3410 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3412 mono_ptr_array_destroy (tmp_array);
3414 return res;
3417 static gboolean
3418 method_nonpublic (MonoMethod* method, gboolean start_klass)
3420 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3421 case METHOD_ATTRIBUTE_ASSEM:
3422 return (start_klass || mono_defaults.generic_ilist_class);
3423 case METHOD_ATTRIBUTE_PRIVATE:
3424 return start_klass;
3425 case METHOD_ATTRIBUTE_PUBLIC:
3426 return FALSE;
3427 default:
3428 return TRUE;
3432 GPtrArray*
3433 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3435 GPtrArray *array;
3436 MonoClass *startklass;
3437 MonoMethod *method;
3438 gpointer iter;
3439 int len, match, nslots;
3440 /*FIXME, use MonoBitSet*/
3441 guint32 method_slots_default [8];
3442 guint32 *method_slots = NULL;
3443 int (*compare_func) (const char *s1, const char *s2) = NULL;
3445 array = g_ptr_array_new ();
3446 startklass = klass;
3447 *ex = NULL;
3449 len = 0;
3450 if (name != NULL)
3451 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3453 /* An optimization for calls made from Delegate:CreateDelegate () */
3454 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3455 method = mono_get_delegate_invoke (klass);
3456 if (mono_loader_get_last_error ())
3457 goto loader_error;
3459 g_ptr_array_add (array, method);
3460 return array;
3463 mono_class_setup_vtable (klass);
3464 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3465 goto loader_error;
3467 if (is_generic_parameter (&klass->byval_arg))
3468 nslots = mono_class_get_vtable_size (klass->parent);
3469 else
3470 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3471 if (nslots >= sizeof (method_slots_default) * 8) {
3472 method_slots = g_new0 (guint32, nslots / 32 + 1);
3473 } else {
3474 method_slots = method_slots_default;
3475 memset (method_slots, 0, sizeof (method_slots_default));
3477 handle_parent:
3478 mono_class_setup_vtable (klass);
3479 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3480 goto loader_error;
3482 iter = NULL;
3483 while ((method = mono_class_get_methods (klass, &iter))) {
3484 match = 0;
3485 if (method->slot != -1) {
3486 g_assert (method->slot < nslots);
3487 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3488 continue;
3489 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3490 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3493 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3494 continue;
3495 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3496 if (bflags & BFLAGS_Public)
3497 match++;
3498 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3499 match++;
3501 if (!match)
3502 continue;
3503 match = 0;
3504 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3505 if (bflags & BFLAGS_Static)
3506 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3507 match++;
3508 } else {
3509 if (bflags & BFLAGS_Instance)
3510 match++;
3513 if (!match)
3514 continue;
3516 if (name != NULL) {
3517 if (compare_func (name, method->name))
3518 continue;
3521 match = 0;
3522 g_ptr_array_add (array, method);
3524 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3525 goto handle_parent;
3526 if (method_slots != method_slots_default)
3527 g_free (method_slots);
3529 return array;
3531 loader_error:
3532 if (method_slots != method_slots_default)
3533 g_free (method_slots);
3534 g_ptr_array_free (array, TRUE);
3536 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3537 *ex = mono_class_get_exception_for_failure (klass);
3538 } else {
3539 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3540 mono_loader_clear_error ();
3542 return NULL;
3545 ICALL_EXPORT MonoArray*
3546 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3548 static MonoClass *MethodInfo_array;
3549 MonoDomain *domain;
3550 MonoArray *res;
3551 MonoVTable *array_vtable;
3552 MonoException *ex = NULL;
3553 const char *mname = NULL;
3554 GPtrArray *method_array;
3555 MonoClass *klass, *refklass;
3556 int i;
3558 if (!MethodInfo_array) {
3559 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3560 mono_memory_barrier ();
3561 MethodInfo_array = klass;
3564 klass = mono_class_from_mono_type (type->type);
3565 refklass = mono_class_from_mono_type (reftype->type);
3566 domain = ((MonoObject *)type)->vtable->domain;
3567 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3568 if (type->type->byref)
3569 return mono_array_new_specific (array_vtable, 0);
3571 if (name)
3572 mname = mono_string_to_utf8 (name);
3574 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3575 g_free ((char*)mname);
3576 if (ex)
3577 mono_raise_exception (ex);
3579 res = mono_array_new_specific (array_vtable, method_array->len);
3582 for (i = 0; i < method_array->len; ++i) {
3583 MonoMethod *method = g_ptr_array_index (method_array, i);
3584 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3587 g_ptr_array_free (method_array, TRUE);
3588 return res;
3591 ICALL_EXPORT MonoArray*
3592 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3594 MonoDomain *domain;
3595 static MonoClass *System_Reflection_ConstructorInfo;
3596 MonoClass *startklass, *klass, *refklass;
3597 MonoArray *res;
3598 MonoMethod *method;
3599 MonoObject *member;
3600 int i, match;
3601 gpointer iter = NULL;
3602 MonoPtrArray tmp_array;
3604 MONO_ARCH_SAVE_REGS;
3606 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3608 domain = ((MonoObject *)type)->vtable->domain;
3609 if (type->type->byref)
3610 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3611 klass = startklass = mono_class_from_mono_type (type->type);
3612 refklass = mono_class_from_mono_type (reftype->type);
3614 if (!System_Reflection_ConstructorInfo)
3615 System_Reflection_ConstructorInfo = mono_class_from_name (
3616 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3618 iter = NULL;
3619 while ((method = mono_class_get_methods (klass, &iter))) {
3620 match = 0;
3621 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3622 continue;
3623 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3624 if (bflags & BFLAGS_Public)
3625 match++;
3626 } else {
3627 if (bflags & BFLAGS_NonPublic)
3628 match++;
3630 if (!match)
3631 continue;
3632 match = 0;
3633 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3634 if (bflags & BFLAGS_Static)
3635 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3636 match++;
3637 } else {
3638 if (bflags & BFLAGS_Instance)
3639 match++;
3642 if (!match)
3643 continue;
3644 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3646 mono_ptr_array_append (tmp_array, member);
3649 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3651 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3652 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3654 mono_ptr_array_destroy (tmp_array);
3656 return res;
3659 static guint
3660 property_hash (gconstpointer data)
3662 MonoProperty *prop = (MonoProperty*)data;
3664 return g_str_hash (prop->name);
3667 static gboolean
3668 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3670 // Properties are hide-by-name-and-signature
3671 if (!g_str_equal (prop1->name, prop2->name))
3672 return FALSE;
3674 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3675 return FALSE;
3676 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3677 return FALSE;
3678 return TRUE;
3681 static gboolean
3682 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3684 if (!accessor)
3685 return FALSE;
3687 return method_nonpublic (accessor, start_klass);
3690 ICALL_EXPORT MonoArray*
3691 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3693 MonoException *ex;
3694 MonoDomain *domain;
3695 static MonoClass *System_Reflection_PropertyInfo;
3696 MonoClass *startklass, *klass;
3697 MonoArray *res;
3698 MonoMethod *method;
3699 MonoProperty *prop;
3700 int i, match;
3701 guint32 flags;
3702 gchar *propname = NULL;
3703 int (*compare_func) (const char *s1, const char *s2) = NULL;
3704 gpointer iter;
3705 GHashTable *properties = NULL;
3706 MonoPtrArray tmp_array;
3708 MONO_ARCH_SAVE_REGS;
3710 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3712 if (!System_Reflection_PropertyInfo)
3713 System_Reflection_PropertyInfo = mono_class_from_name (
3714 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3716 domain = ((MonoObject *)type)->vtable->domain;
3717 if (type->type->byref)
3718 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3719 klass = startklass = mono_class_from_mono_type (type->type);
3721 if (name != NULL) {
3722 propname = mono_string_to_utf8 (name);
3723 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3726 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3727 handle_parent:
3728 mono_class_setup_vtable (klass);
3729 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3730 goto loader_error;
3732 iter = NULL;
3733 while ((prop = mono_class_get_properties (klass, &iter))) {
3734 match = 0;
3735 method = prop->get;
3736 if (!method)
3737 method = prop->set;
3738 if (method)
3739 flags = method->flags;
3740 else
3741 flags = 0;
3742 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3743 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3744 if (bflags & BFLAGS_Public)
3745 match++;
3746 } else if (bflags & BFLAGS_NonPublic) {
3747 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3748 property_accessor_nonpublic(prop->set, startklass == klass)) {
3749 match++;
3752 if (!match)
3753 continue;
3754 match = 0;
3755 if (flags & METHOD_ATTRIBUTE_STATIC) {
3756 if (bflags & BFLAGS_Static)
3757 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3758 match++;
3759 } else {
3760 if (bflags & BFLAGS_Instance)
3761 match++;
3764 if (!match)
3765 continue;
3766 match = 0;
3768 if (name != NULL) {
3769 if (compare_func (propname, prop->name))
3770 continue;
3773 if (g_hash_table_lookup (properties, prop))
3774 continue;
3776 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3778 g_hash_table_insert (properties, prop, prop);
3780 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3781 goto handle_parent;
3783 g_hash_table_destroy (properties);
3784 g_free (propname);
3786 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3787 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3788 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3790 mono_ptr_array_destroy (tmp_array);
3792 return res;
3794 loader_error:
3795 if (properties)
3796 g_hash_table_destroy (properties);
3797 if (name)
3798 g_free (propname);
3799 mono_ptr_array_destroy (tmp_array);
3801 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3802 ex = mono_class_get_exception_for_failure (klass);
3803 } else {
3804 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3805 mono_loader_clear_error ();
3807 mono_raise_exception (ex);
3808 return NULL;
3811 ICALL_EXPORT MonoReflectionEvent *
3812 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3814 MonoDomain *domain;
3815 MonoClass *klass, *startklass;
3816 gpointer iter;
3817 MonoEvent *event;
3818 MonoMethod *method;
3819 gchar *event_name;
3820 int (*compare_func) (const char *s1, const char *s2);
3822 MONO_ARCH_SAVE_REGS;
3824 event_name = mono_string_to_utf8 (name);
3825 if (type->type->byref)
3826 return NULL;
3827 klass = startklass = mono_class_from_mono_type (type->type);
3828 domain = mono_object_domain (type);
3830 mono_class_init_or_throw (klass);
3832 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3833 handle_parent:
3834 if (klass->exception_type != MONO_EXCEPTION_NONE)
3835 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3837 iter = NULL;
3838 while ((event = mono_class_get_events (klass, &iter))) {
3839 if (compare_func (event->name, event_name))
3840 continue;
3842 method = event->add;
3843 if (!method)
3844 method = event->remove;
3845 if (!method)
3846 method = event->raise;
3847 if (method) {
3848 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3849 if (!(bflags & BFLAGS_Public))
3850 continue;
3851 } else {
3852 if (!(bflags & BFLAGS_NonPublic))
3853 continue;
3854 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3855 continue;
3858 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3859 if (!(bflags & BFLAGS_Static))
3860 continue;
3861 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3862 continue;
3863 } else {
3864 if (!(bflags & BFLAGS_Instance))
3865 continue;
3867 } else
3868 if (!(bflags & BFLAGS_NonPublic))
3869 continue;
3871 g_free (event_name);
3872 return mono_event_get_object (domain, startklass, event);
3875 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3876 goto handle_parent;
3878 g_free (event_name);
3879 return NULL;
3882 static guint
3883 event_hash (gconstpointer data)
3885 MonoEvent *event = (MonoEvent*)data;
3887 return g_str_hash (event->name);
3890 static gboolean
3891 event_equal (MonoEvent *event1, MonoEvent *event2)
3893 // Events are hide-by-name
3894 return g_str_equal (event1->name, event2->name);
3897 ICALL_EXPORT MonoArray*
3898 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3900 MonoException *ex;
3901 MonoDomain *domain;
3902 static MonoClass *System_Reflection_EventInfo;
3903 MonoClass *startklass, *klass;
3904 MonoArray *res;
3905 MonoMethod *method;
3906 MonoEvent *event;
3907 int i, match;
3908 gpointer iter;
3909 GHashTable *events = NULL;
3910 MonoPtrArray tmp_array;
3912 MONO_ARCH_SAVE_REGS;
3914 mono_ptr_array_init (tmp_array, 4);
3916 if (!System_Reflection_EventInfo)
3917 System_Reflection_EventInfo = mono_class_from_name (
3918 mono_defaults.corlib, "System.Reflection", "EventInfo");
3920 domain = mono_object_domain (type);
3921 if (type->type->byref)
3922 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3923 klass = startklass = mono_class_from_mono_type (type->type);
3925 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3926 handle_parent:
3927 mono_class_setup_vtable (klass);
3928 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3929 goto loader_error;
3931 iter = NULL;
3932 while ((event = mono_class_get_events (klass, &iter))) {
3933 match = 0;
3934 method = event->add;
3935 if (!method)
3936 method = event->remove;
3937 if (!method)
3938 method = event->raise;
3939 if (method) {
3940 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3941 if (bflags & BFLAGS_Public)
3942 match++;
3943 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3944 if (bflags & BFLAGS_NonPublic)
3945 match++;
3948 else
3949 if (bflags & BFLAGS_NonPublic)
3950 match ++;
3951 if (!match)
3952 continue;
3953 match = 0;
3954 if (method) {
3955 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3956 if (bflags & BFLAGS_Static)
3957 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3958 match++;
3959 } else {
3960 if (bflags & BFLAGS_Instance)
3961 match++;
3964 else
3965 if (bflags & BFLAGS_Instance)
3966 match ++;
3967 if (!match)
3968 continue;
3970 if (g_hash_table_lookup (events, event))
3971 continue;
3973 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3975 g_hash_table_insert (events, event, event);
3977 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3978 goto handle_parent;
3980 g_hash_table_destroy (events);
3982 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3984 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3985 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3987 mono_ptr_array_destroy (tmp_array);
3989 return res;
3991 loader_error:
3992 mono_ptr_array_destroy (tmp_array);
3993 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3994 ex = mono_class_get_exception_for_failure (klass);
3995 } else {
3996 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3997 mono_loader_clear_error ();
3999 mono_raise_exception (ex);
4000 return NULL;
4003 ICALL_EXPORT MonoReflectionType *
4004 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4006 MonoDomain *domain;
4007 MonoClass *klass;
4008 MonoClass *nested;
4009 char *str;
4010 gpointer iter;
4012 MONO_ARCH_SAVE_REGS;
4014 if (name == NULL)
4015 mono_raise_exception (mono_get_exception_argument_null ("name"));
4017 domain = ((MonoObject *)type)->vtable->domain;
4018 if (type->type->byref)
4019 return NULL;
4020 klass = mono_class_from_mono_type (type->type);
4022 str = mono_string_to_utf8 (name);
4024 handle_parent:
4025 if (klass->exception_type != MONO_EXCEPTION_NONE)
4026 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4029 * If a nested type is generic, return its generic type definition.
4030 * Note that this means that the return value is essentially a
4031 * nested type of the generic type definition of @klass.
4033 * A note in MSDN claims that a generic type definition can have
4034 * nested types that aren't generic. In any case, the container of that
4035 * nested type would be the generic type definition.
4037 if (klass->generic_class)
4038 klass = klass->generic_class->container_class;
4040 iter = NULL;
4041 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4042 int match = 0;
4043 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4044 if (bflags & BFLAGS_Public)
4045 match++;
4046 } else {
4047 if (bflags & BFLAGS_NonPublic)
4048 match++;
4050 if (!match)
4051 continue;
4052 if (strcmp (nested->name, str) == 0){
4053 g_free (str);
4054 return mono_type_get_object (domain, &nested->byval_arg);
4057 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4058 goto handle_parent;
4059 g_free (str);
4060 return NULL;
4063 ICALL_EXPORT MonoArray*
4064 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4066 MonoDomain *domain;
4067 MonoClass *klass;
4068 MonoArray *res;
4069 MonoObject *member;
4070 int i, match;
4071 MonoClass *nested;
4072 gpointer iter;
4073 MonoPtrArray tmp_array;
4075 MONO_ARCH_SAVE_REGS;
4077 domain = ((MonoObject *)type)->vtable->domain;
4078 if (type->type->byref)
4079 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4080 klass = mono_class_from_mono_type (type->type);
4083 * If a nested type is generic, return its generic type definition.
4084 * Note that this means that the return value is essentially the set
4085 * of nested types of the generic type definition of @klass.
4087 * A note in MSDN claims that a generic type definition can have
4088 * nested types that aren't generic. In any case, the container of that
4089 * nested type would be the generic type definition.
4091 if (klass->generic_class)
4092 klass = klass->generic_class->container_class;
4094 mono_ptr_array_init (tmp_array, 1);
4095 iter = NULL;
4096 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4097 match = 0;
4098 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4099 if (bflags & BFLAGS_Public)
4100 match++;
4101 } else {
4102 if (bflags & BFLAGS_NonPublic)
4103 match++;
4105 if (!match)
4106 continue;
4107 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4108 mono_ptr_array_append (tmp_array, member);
4111 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4113 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4114 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4116 mono_ptr_array_destroy (tmp_array);
4118 return res;
4121 ICALL_EXPORT MonoReflectionType*
4122 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4124 gchar *str;
4125 MonoType *type = NULL;
4126 MonoTypeNameParse info;
4127 gboolean type_resolve;
4129 MONO_ARCH_SAVE_REGS;
4131 /* On MS.NET, this does not fire a TypeResolve event */
4132 type_resolve = TRUE;
4133 str = mono_string_to_utf8 (name);
4134 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4135 if (!mono_reflection_parse_type (str, &info)) {
4136 g_free (str);
4137 mono_reflection_free_type_info (&info);
4138 if (throwOnError) /* uhm: this is a parse error, though... */
4139 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4140 /*g_print ("failed parse\n");*/
4141 return NULL;
4144 if (info.assembly.name) {
4145 g_free (str);
4146 mono_reflection_free_type_info (&info);
4147 if (throwOnError) {
4148 /* 1.0 and 2.0 throw different exceptions */
4149 if (mono_defaults.generic_ilist_class)
4150 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4151 else
4152 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4154 return NULL;
4157 if (module != NULL) {
4158 if (module->image)
4159 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4160 else
4161 type = NULL;
4163 else
4164 if (assembly->assembly->dynamic) {
4165 /* Enumerate all modules */
4166 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4167 int i;
4169 type = NULL;
4170 if (abuilder->modules) {
4171 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4172 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4173 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4174 if (type)
4175 break;
4179 if (!type && abuilder->loaded_modules) {
4180 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4181 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4182 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4183 if (type)
4184 break;
4188 else
4189 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4190 g_free (str);
4191 mono_reflection_free_type_info (&info);
4192 if (!type) {
4193 MonoException *e = NULL;
4195 if (throwOnError)
4196 e = mono_get_exception_type_load (name, NULL);
4198 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4199 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4201 mono_loader_clear_error ();
4203 if (e != NULL)
4204 mono_raise_exception (e);
4206 return NULL;
4207 } else if (mono_loader_get_last_error ()) {
4208 if (throwOnError)
4209 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4210 mono_loader_clear_error ();
4213 if (type->type == MONO_TYPE_CLASS) {
4214 MonoClass *klass = mono_type_get_class (type);
4216 if (mono_security_enabled () && !klass->exception_type)
4217 /* Some security problems are detected during generic vtable construction */
4218 mono_class_setup_vtable (klass);
4220 /* need to report exceptions ? */
4221 if (throwOnError && klass->exception_type) {
4222 /* report SecurityException (or others) that occured when loading the assembly */
4223 MonoException *exc = mono_class_get_exception_for_failure (klass);
4224 mono_loader_clear_error ();
4225 mono_raise_exception (exc);
4226 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4227 return NULL;
4231 /* g_print ("got it\n"); */
4232 return mono_type_get_object (mono_object_domain (assembly), type);
4235 static gboolean
4236 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4238 gchar *content;
4239 gchar *shadow_ini_file;
4240 gsize len;
4242 /* Check for shadow-copied assembly */
4243 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4244 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4245 content = NULL;
4246 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4247 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4248 if (content) {
4249 g_free (content);
4250 content = NULL;
4253 g_free (shadow_ini_file);
4254 if (content != NULL) {
4255 if (*filename)
4256 g_free (*filename);
4257 *filename = content;
4258 return TRUE;
4261 return FALSE;
4264 ICALL_EXPORT MonoString *
4265 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4267 MonoDomain *domain = mono_object_domain (assembly);
4268 MonoAssembly *mass = assembly->assembly;
4269 MonoString *res = NULL;
4270 gchar *uri;
4271 gchar *absolute;
4272 gchar *dirname;
4274 MONO_ARCH_SAVE_REGS;
4276 if (g_path_is_absolute (mass->image->name)) {
4277 absolute = g_strdup (mass->image->name);
4278 dirname = g_path_get_dirname (absolute);
4279 } else {
4280 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4281 dirname = g_strdup (mass->basedir);
4284 replace_shadow_path (domain, dirname, &absolute);
4285 g_free (dirname);
4286 #if HOST_WIN32
4288 gint i;
4289 for (i = strlen (absolute) - 1; i >= 0; i--)
4290 if (absolute [i] == '\\')
4291 absolute [i] = '/';
4293 #endif
4294 if (escaped) {
4295 uri = g_filename_to_uri (absolute, NULL, NULL);
4296 } else {
4297 const char *prepend = "file://";
4298 #if HOST_WIN32
4299 if (*absolute == '/' && *(absolute + 1) == '/') {
4300 prepend = "file:";
4301 } else {
4302 prepend = "file:///";
4304 #endif
4305 uri = g_strconcat (prepend, absolute, NULL);
4308 if (uri) {
4309 res = mono_string_new (domain, uri);
4310 g_free (uri);
4312 g_free (absolute);
4313 return res;
4316 ICALL_EXPORT MonoBoolean
4317 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4319 MonoAssembly *mass = assembly->assembly;
4321 MONO_ARCH_SAVE_REGS;
4323 return mass->in_gac;
4326 ICALL_EXPORT MonoReflectionAssembly*
4327 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4329 gchar *name;
4330 MonoAssembly *res;
4331 MonoImageOpenStatus status;
4333 MONO_ARCH_SAVE_REGS;
4335 name = mono_string_to_utf8 (mname);
4336 res = mono_assembly_load_with_partial_name (name, &status);
4338 g_free (name);
4340 if (res == NULL)
4341 return NULL;
4342 return mono_assembly_get_object (mono_domain_get (), res);
4345 ICALL_EXPORT MonoString *
4346 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4348 MonoDomain *domain = mono_object_domain (assembly);
4349 MonoString *res;
4351 MONO_ARCH_SAVE_REGS;
4353 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4355 return res;
4358 ICALL_EXPORT MonoBoolean
4359 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4361 MONO_ARCH_SAVE_REGS;
4363 return assembly->assembly->ref_only;
4366 ICALL_EXPORT MonoString *
4367 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4369 MonoDomain *domain = mono_object_domain (assembly);
4371 MONO_ARCH_SAVE_REGS;
4373 return mono_string_new (domain, assembly->assembly->image->version);
4376 ICALL_EXPORT MonoReflectionMethod*
4377 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4379 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4381 MONO_ARCH_SAVE_REGS;
4383 if (!token)
4384 return NULL;
4385 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4388 ICALL_EXPORT MonoReflectionModule*
4389 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4391 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4394 ICALL_EXPORT MonoArray*
4395 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4397 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4398 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4399 int i;
4400 const char *val;
4402 MONO_ARCH_SAVE_REGS;
4404 for (i = 0; i < table->rows; ++i) {
4405 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4406 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4408 return result;
4411 static MonoObject*
4412 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4414 static MonoClass *System_Version = NULL;
4415 static MonoMethod *create_version = NULL;
4416 MonoObject *result;
4417 gpointer args [4];
4419 if (!System_Version) {
4420 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4421 g_assert (System_Version);
4424 if (!create_version) {
4425 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4426 create_version = mono_method_desc_search_in_class (desc, System_Version);
4427 g_assert (create_version);
4428 mono_method_desc_free (desc);
4431 args [0] = &major;
4432 args [1] = &minor;
4433 args [2] = &build;
4434 args [3] = &revision;
4435 result = mono_object_new (domain, System_Version);
4436 mono_runtime_invoke (create_version, result, args, NULL);
4438 return result;
4441 ICALL_EXPORT MonoArray*
4442 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4444 static MonoClass *System_Reflection_AssemblyName;
4445 MonoArray *result;
4446 MonoDomain *domain = mono_object_domain (assembly);
4447 int i, count = 0;
4448 static MonoMethod *create_culture = NULL;
4449 MonoImage *image = assembly->assembly->image;
4450 MonoTableInfo *t;
4452 MONO_ARCH_SAVE_REGS;
4454 if (!System_Reflection_AssemblyName)
4455 System_Reflection_AssemblyName = mono_class_from_name (
4456 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4458 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4459 count = t->rows;
4461 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4463 if (count > 0 && !create_culture) {
4464 MonoMethodDesc *desc = mono_method_desc_new (
4465 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4466 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4467 g_assert (create_culture);
4468 mono_method_desc_free (desc);
4471 for (i = 0; i < count; i++) {
4472 MonoReflectionAssemblyName *aname;
4473 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4475 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4477 aname = (MonoReflectionAssemblyName *) mono_object_new (
4478 domain, System_Reflection_AssemblyName);
4480 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4482 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4483 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4484 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4485 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4486 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4487 aname->versioncompat = 1; /* SameMachine (default) */
4488 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4489 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4491 if (create_culture) {
4492 gpointer args [2];
4493 MonoBoolean assembly_ref = 1;
4494 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4495 args [1] = &assembly_ref;
4496 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4499 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4500 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4501 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4503 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4504 /* public key token isn't copied - the class library will
4505 automatically generate it from the public key if required */
4506 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4507 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4508 } else {
4509 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4510 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4512 } else {
4513 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4516 /* note: this function doesn't return the codebase on purpose (i.e. it can
4517 be used under partial trust as path information isn't present). */
4519 mono_array_setref (result, i, aname);
4521 return result;
4524 /* move this in some file in mono/util/ */
4525 static char *
4526 g_concat_dir_and_file (const char *dir, const char *file)
4528 g_return_val_if_fail (dir != NULL, NULL);
4529 g_return_val_if_fail (file != NULL, NULL);
4532 * If the directory name doesn't have a / on the end, we need
4533 * to add one so we get a proper path to the file
4535 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4536 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4537 else
4538 return g_strconcat (dir, file, NULL);
4541 ICALL_EXPORT void *
4542 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4544 char *n = mono_string_to_utf8 (name);
4545 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4546 guint32 i;
4547 guint32 cols [MONO_MANIFEST_SIZE];
4548 guint32 impl, file_idx;
4549 const char *val;
4550 MonoImage *module;
4552 MONO_ARCH_SAVE_REGS;
4554 for (i = 0; i < table->rows; ++i) {
4555 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4556 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4557 if (strcmp (val, n) == 0)
4558 break;
4560 g_free (n);
4561 if (i == table->rows)
4562 return NULL;
4563 /* FIXME */
4564 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4565 if (impl) {
4567 * this code should only be called after obtaining the
4568 * ResourceInfo and handling the other cases.
4570 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4571 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4573 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4574 if (!module)
4575 return NULL;
4577 else
4578 module = assembly->assembly->image;
4580 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4582 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4585 ICALL_EXPORT gboolean
4586 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4588 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4589 int i;
4590 guint32 cols [MONO_MANIFEST_SIZE];
4591 guint32 file_cols [MONO_FILE_SIZE];
4592 const char *val;
4593 char *n;
4595 MONO_ARCH_SAVE_REGS;
4597 n = mono_string_to_utf8 (name);
4598 for (i = 0; i < table->rows; ++i) {
4599 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4600 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4601 if (strcmp (val, n) == 0)
4602 break;
4604 g_free (n);
4605 if (i == table->rows)
4606 return FALSE;
4608 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4609 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4611 else {
4612 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4613 case MONO_IMPLEMENTATION_FILE:
4614 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4615 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4616 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4617 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4618 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4619 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4620 info->location = 0;
4621 else
4622 info->location = RESOURCE_LOCATION_EMBEDDED;
4623 break;
4625 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4626 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4627 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4628 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4629 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4630 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4631 g_free (msg);
4632 mono_raise_exception (ex);
4634 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4636 /* Obtain info recursively */
4637 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4638 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4639 break;
4641 case MONO_IMPLEMENTATION_EXP_TYPE:
4642 g_assert_not_reached ();
4643 break;
4647 return TRUE;
4650 ICALL_EXPORT MonoObject*
4651 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4653 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4654 MonoArray *result = NULL;
4655 int i, count;
4656 const char *val;
4657 char *n;
4659 MONO_ARCH_SAVE_REGS;
4661 /* check hash if needed */
4662 if (name) {
4663 n = mono_string_to_utf8 (name);
4664 for (i = 0; i < table->rows; ++i) {
4665 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4666 if (strcmp (val, n) == 0) {
4667 MonoString *fn;
4668 g_free (n);
4669 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4670 fn = mono_string_new (mono_object_domain (assembly), n);
4671 g_free (n);
4672 return (MonoObject*)fn;
4675 g_free (n);
4676 return NULL;
4679 count = 0;
4680 for (i = 0; i < table->rows; ++i) {
4681 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4682 count ++;
4685 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4687 count = 0;
4688 for (i = 0; i < table->rows; ++i) {
4689 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4690 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4691 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4692 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4693 g_free (n);
4694 count ++;
4697 return (MonoObject*)result;
4700 ICALL_EXPORT MonoArray*
4701 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4703 MonoDomain *domain = mono_domain_get();
4704 MonoArray *res;
4705 MonoClass *klass;
4706 int i, j, file_count = 0;
4707 MonoImage **modules;
4708 guint32 module_count, real_module_count;
4709 MonoTableInfo *table;
4710 guint32 cols [MONO_FILE_SIZE];
4711 MonoImage *image = assembly->assembly->image;
4713 g_assert (image != NULL);
4714 g_assert (!assembly->assembly->dynamic);
4716 table = &image->tables [MONO_TABLE_FILE];
4717 file_count = table->rows;
4719 modules = image->modules;
4720 module_count = image->module_count;
4722 real_module_count = 0;
4723 for (i = 0; i < module_count; ++i)
4724 if (modules [i])
4725 real_module_count ++;
4727 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4728 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4730 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4731 j = 1;
4732 for (i = 0; i < module_count; ++i)
4733 if (modules [i]) {
4734 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4735 ++j;
4738 for (i = 0; i < file_count; ++i, ++j) {
4739 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4740 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4741 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4742 else {
4743 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4744 if (!m) {
4745 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4746 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4748 mono_array_setref (res, j, mono_module_get_object (domain, m));
4752 return res;
4755 ICALL_EXPORT MonoReflectionMethod*
4756 ves_icall_GetCurrentMethod (void)
4758 MonoMethod *m = mono_method_get_last_managed ();
4760 while (m->is_inflated)
4761 m = ((MonoMethodInflated*)m)->declaring;
4763 return mono_method_get_object (mono_domain_get (), m, NULL);
4767 static MonoMethod*
4768 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4770 int offset = -1, i;
4771 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4772 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4773 //method is inflated, we should inflate it on the other class
4774 MonoGenericContext ctx;
4775 ctx.method_inst = inflated->context.method_inst;
4776 ctx.class_inst = inflated->context.class_inst;
4777 if (klass->generic_class)
4778 ctx.class_inst = klass->generic_class->context.class_inst;
4779 else if (klass->generic_container)
4780 ctx.class_inst = klass->generic_container->context.class_inst;
4781 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4784 mono_class_setup_methods (method->klass);
4785 if (method->klass->exception_type)
4786 return NULL;
4787 for (i = 0; i < method->klass->method.count; ++i) {
4788 if (method->klass->methods [i] == method) {
4789 offset = i;
4790 break;
4793 mono_class_setup_methods (klass);
4794 if (klass->exception_type)
4795 return NULL;
4796 g_assert (offset >= 0 && offset < klass->method.count);
4797 return klass->methods [offset];
4800 ICALL_EXPORT MonoReflectionMethod*
4801 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4803 MonoClass *klass;
4804 if (type) {
4805 klass = mono_class_from_mono_type (type);
4806 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4807 return NULL;
4808 if (method->klass != klass) {
4809 method = mono_method_get_equivalent_method (method, klass);
4810 if (!method)
4811 return NULL;
4813 } else
4814 klass = method->klass;
4815 return mono_method_get_object (mono_domain_get (), method, klass);
4818 ICALL_EXPORT MonoReflectionMethod*
4819 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4821 return mono_method_get_object (mono_domain_get (), method, NULL);
4824 ICALL_EXPORT MonoReflectionMethodBody*
4825 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4827 return mono_method_body_get_object (mono_domain_get (), method);
4830 ICALL_EXPORT MonoReflectionAssembly*
4831 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4833 MonoMethod *dest = NULL;
4835 MONO_ARCH_SAVE_REGS;
4837 mono_stack_walk_no_il (get_executing, &dest);
4838 g_assert (dest);
4839 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4843 ICALL_EXPORT MonoReflectionAssembly*
4844 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4846 MonoDomain* domain = mono_domain_get ();
4848 MONO_ARCH_SAVE_REGS;
4850 if (!domain->entry_assembly)
4851 return NULL;
4853 return mono_assembly_get_object (domain, domain->entry_assembly);
4856 ICALL_EXPORT MonoReflectionAssembly*
4857 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4859 MonoMethod *m;
4860 MonoMethod *dest;
4862 MONO_ARCH_SAVE_REGS;
4864 dest = NULL;
4865 mono_stack_walk_no_il (get_executing, &dest);
4866 m = dest;
4867 mono_stack_walk_no_il (get_caller, &dest);
4868 if (!dest)
4869 dest = m;
4870 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4873 ICALL_EXPORT MonoString *
4874 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4875 gboolean assembly_qualified)
4877 MonoDomain *domain = mono_object_domain (object);
4878 MonoTypeNameFormat format;
4879 MonoString *res;
4880 gchar *name;
4882 if (full_name)
4883 format = assembly_qualified ?
4884 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4885 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4886 else
4887 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4889 name = mono_type_get_name_full (object->type, format);
4890 if (!name)
4891 return NULL;
4893 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4894 g_free (name);
4895 return NULL;
4898 res = mono_string_new (domain, name);
4899 g_free (name);
4901 return res;
4904 ICALL_EXPORT int
4905 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4907 MonoClass *klass = mono_class_from_mono_type (this->type);
4908 mono_class_init_or_throw (klass);
4909 return mono_security_core_clr_class_level (klass);
4912 static void
4913 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4915 static MonoMethod *create_culture = NULL;
4916 gpointer args [2];
4917 guint32 pkey_len;
4918 const char *pkey_ptr;
4919 gchar *codebase;
4920 MonoBoolean assembly_ref = 0;
4922 MONO_ARCH_SAVE_REGS;
4924 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4925 aname->major = name->major;
4926 aname->minor = name->minor;
4927 aname->build = name->build;
4928 aname->flags = name->flags;
4929 aname->revision = name->revision;
4930 aname->hashalg = name->hash_alg;
4931 aname->versioncompat = 1; /* SameMachine (default) */
4932 aname->processor_architecture = name->arch;
4934 if (by_default_version)
4935 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4937 codebase = NULL;
4938 if (absolute != NULL && *absolute != '\0') {
4939 const gchar *prepend = "file://";
4940 gchar *result;
4942 codebase = g_strdup (absolute);
4944 #if HOST_WIN32
4946 gint i;
4947 for (i = strlen (codebase) - 1; i >= 0; i--)
4948 if (codebase [i] == '\\')
4949 codebase [i] = '/';
4951 if (*codebase == '/' && *(codebase + 1) == '/') {
4952 prepend = "file:";
4953 } else {
4954 prepend = "file:///";
4957 #endif
4958 result = g_strconcat (prepend, codebase, NULL);
4959 g_free (codebase);
4960 codebase = result;
4963 if (codebase) {
4964 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4965 g_free (codebase);
4968 if (!create_culture) {
4969 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4970 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4971 g_assert (create_culture);
4972 mono_method_desc_free (desc);
4975 if (name->culture) {
4976 args [0] = mono_string_new (domain, name->culture);
4977 args [1] = &assembly_ref;
4978 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4981 if (name->public_key) {
4982 pkey_ptr = (char*)name->public_key;
4983 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4985 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4986 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4987 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4988 } else if (default_publickey) {
4989 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4990 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4993 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4994 if (name->public_key_token [0]) {
4995 int i, j;
4996 char *p;
4998 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4999 p = mono_array_addr (aname->keyToken, char, 0);
5001 for (i = 0, j = 0; i < 8; i++) {
5002 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5003 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5004 p++;
5006 } else if (default_token) {
5007 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5011 ICALL_EXPORT MonoString *
5012 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5014 MonoDomain *domain = mono_object_domain (assembly);
5015 MonoAssembly *mass = assembly->assembly;
5016 MonoString *res;
5017 gchar *name;
5019 name = mono_stringify_assembly_name (&mass->aname);
5020 res = mono_string_new (domain, name);
5021 g_free (name);
5023 return res;
5026 ICALL_EXPORT void
5027 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5029 gchar *absolute;
5030 MonoAssembly *mass = assembly->assembly;
5032 MONO_ARCH_SAVE_REGS;
5034 if (g_path_is_absolute (mass->image->name)) {
5035 fill_reflection_assembly_name (mono_object_domain (assembly),
5036 aname, &mass->aname, mass->image->name, TRUE,
5037 TRUE, TRUE);
5038 return;
5040 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5042 fill_reflection_assembly_name (mono_object_domain (assembly),
5043 aname, &mass->aname, absolute, TRUE, TRUE,
5044 TRUE);
5046 g_free (absolute);
5049 ICALL_EXPORT void
5050 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5052 char *filename;
5053 MonoImageOpenStatus status = MONO_IMAGE_OK;
5054 gboolean res;
5055 MonoImage *image;
5056 MonoAssemblyName name;
5057 char *dirname
5059 MONO_ARCH_SAVE_REGS;
5061 filename = mono_string_to_utf8 (fname);
5063 dirname = g_path_get_dirname (filename);
5064 replace_shadow_path (mono_domain_get (), dirname, &filename);
5065 g_free (dirname);
5067 image = mono_image_open (filename, &status);
5069 if (!image){
5070 MonoException *exc;
5072 g_free (filename);
5073 if (status == MONO_IMAGE_IMAGE_INVALID)
5074 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5075 else
5076 exc = mono_get_exception_file_not_found2 (NULL, fname);
5077 mono_raise_exception (exc);
5080 res = mono_assembly_fill_assembly_name (image, &name);
5081 if (!res) {
5082 mono_image_close (image);
5083 g_free (filename);
5084 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5087 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5088 TRUE, FALSE, TRUE);
5090 g_free (filename);
5091 mono_image_close (image);
5094 ICALL_EXPORT MonoBoolean
5095 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5096 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5098 MonoBoolean result = FALSE;
5099 MonoDeclSecurityEntry entry;
5101 /* SecurityAction.RequestMinimum */
5102 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5103 *minimum = entry.blob;
5104 *minLength = entry.size;
5105 result = TRUE;
5107 /* SecurityAction.RequestOptional */
5108 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5109 *optional = entry.blob;
5110 *optLength = entry.size;
5111 result = TRUE;
5113 /* SecurityAction.RequestRefuse */
5114 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5115 *refused = entry.blob;
5116 *refLength = entry.size;
5117 result = TRUE;
5120 return result;
5123 static MonoArray*
5124 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5126 MonoArray *res;
5127 MonoClass *klass;
5128 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5129 int i, count;
5130 guint32 attrs, visibility;
5132 /* we start the count from 1 because we skip the special type <Module> */
5133 if (exportedOnly) {
5134 count = 0;
5135 for (i = 1; i < tdef->rows; ++i) {
5136 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5137 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5138 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5139 count++;
5141 } else {
5142 count = tdef->rows - 1;
5144 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5145 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5146 count = 0;
5147 for (i = 1; i < tdef->rows; ++i) {
5148 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5149 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5150 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5151 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5152 if (klass) {
5153 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5154 } else {
5155 MonoLoaderError *error;
5156 MonoException *ex;
5158 error = mono_loader_get_last_error ();
5159 g_assert (error != NULL);
5161 ex = mono_loader_error_prepare_exception (error);
5162 mono_array_setref (*exceptions, count, ex);
5164 if (mono_loader_get_last_error ())
5165 mono_loader_clear_error ();
5166 count++;
5170 return res;
5173 ICALL_EXPORT MonoArray*
5174 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5176 MonoArray *res = NULL;
5177 MonoArray *exceptions = NULL;
5178 MonoImage *image = NULL;
5179 MonoTableInfo *table = NULL;
5180 MonoDomain *domain;
5181 GList *list = NULL;
5182 int i, len, ex_count;
5184 MONO_ARCH_SAVE_REGS;
5186 domain = mono_object_domain (assembly);
5188 g_assert (!assembly->assembly->dynamic);
5189 image = assembly->assembly->image;
5190 table = &image->tables [MONO_TABLE_FILE];
5191 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5193 /* Append data from all modules in the assembly */
5194 for (i = 0; i < table->rows; ++i) {
5195 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5196 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5197 if (loaded_image) {
5198 MonoArray *ex2;
5199 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5200 /* Append the new types to the end of the array */
5201 if (mono_array_length (res2) > 0) {
5202 guint32 len1, len2;
5203 MonoArray *res3, *ex3;
5205 len1 = mono_array_length (res);
5206 len2 = mono_array_length (res2);
5208 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5209 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5210 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5211 res = res3;
5213 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5214 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5215 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5216 exceptions = ex3;
5222 /* the ReflectionTypeLoadException must have all the types (Types property),
5223 * NULL replacing types which throws an exception. The LoaderException must
5224 * contain all exceptions for NULL items.
5227 len = mono_array_length (res);
5229 ex_count = 0;
5230 for (i = 0; i < len; i++) {
5231 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5232 MonoClass *klass;
5234 if (t) {
5235 klass = mono_type_get_class (t->type);
5236 if ((klass != NULL) && klass->exception_type) {
5237 /* keep the class in the list */
5238 list = g_list_append (list, klass);
5239 /* and replace Type with NULL */
5240 mono_array_setref (res, i, NULL);
5242 } else {
5243 ex_count ++;
5247 if (list || ex_count) {
5248 GList *tmp = NULL;
5249 MonoException *exc = NULL;
5250 MonoArray *exl = NULL;
5251 int j, length = g_list_length (list) + ex_count;
5253 mono_loader_clear_error ();
5255 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5256 /* Types for which mono_class_get () succeeded */
5257 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5258 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5259 mono_array_setref (exl, i, exc);
5261 /* Types for which it don't */
5262 for (j = 0; j < mono_array_length (exceptions); ++j) {
5263 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5264 if (exc) {
5265 g_assert (i < length);
5266 mono_array_setref (exl, i, exc);
5267 i ++;
5270 g_list_free (list);
5271 list = NULL;
5273 exc = mono_get_exception_reflection_type_load (res, exl);
5274 mono_loader_clear_error ();
5275 mono_raise_exception (exc);
5278 return res;
5281 ICALL_EXPORT gboolean
5282 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5284 MonoAssemblyName aname;
5285 MonoDomain *domain = mono_object_domain (name);
5286 char *val;
5287 gboolean is_version_defined;
5288 gboolean is_token_defined;
5290 aname.public_key = NULL;
5291 val = mono_string_to_utf8 (assname);
5292 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5293 g_free ((guint8*) aname.public_key);
5294 g_free (val);
5295 return FALSE;
5298 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5299 FALSE, is_token_defined);
5301 mono_assembly_name_free (&aname);
5302 g_free ((guint8*) aname.public_key);
5303 g_free (val);
5305 return TRUE;
5308 ICALL_EXPORT MonoReflectionType*
5309 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5311 MonoDomain *domain = mono_object_domain (module);
5312 MonoClass *klass;
5314 MONO_ARCH_SAVE_REGS;
5316 g_assert (module->image);
5318 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5319 /* These images do not have a global type */
5320 return NULL;
5322 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5323 return mono_type_get_object (domain, &klass->byval_arg);
5326 ICALL_EXPORT void
5327 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5329 /*if (module->image)
5330 mono_image_close (module->image);*/
5333 ICALL_EXPORT MonoString*
5334 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5336 MonoDomain *domain = mono_object_domain (module);
5338 MONO_ARCH_SAVE_REGS;
5340 g_assert (module->image);
5341 return mono_string_new (domain, module->image->guid);
5344 ICALL_EXPORT gpointer
5345 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5347 #ifdef HOST_WIN32
5348 if (module->image && module->image->is_module_handle)
5349 return module->image->raw_data;
5350 #endif
5352 return (gpointer) (-1);
5355 ICALL_EXPORT void
5356 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5358 if (image->dynamic) {
5359 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5360 *pe_kind = dyn->pe_kind;
5361 *machine = dyn->machine;
5363 else {
5364 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5365 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5369 ICALL_EXPORT gint32
5370 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5372 return (image->md_version_major << 16) | (image->md_version_minor);
5375 ICALL_EXPORT MonoArray*
5376 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5378 MonoArray *exceptions;
5379 int i;
5381 MONO_ARCH_SAVE_REGS;
5383 if (!module->image)
5384 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5385 else {
5386 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5387 for (i = 0; i < mono_array_length (exceptions); ++i) {
5388 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5389 if (ex)
5390 mono_raise_exception (ex);
5392 return res;
5396 static gboolean
5397 mono_memberref_is_method (MonoImage *image, guint32 token)
5399 if (!image->dynamic) {
5400 guint32 cols [MONO_MEMBERREF_SIZE];
5401 const char *sig;
5402 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5403 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5404 mono_metadata_decode_blob_size (sig, &sig);
5405 return (*sig != 0x6);
5406 } else {
5407 MonoClass *handle_class;
5409 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5410 return FALSE;
5412 return mono_defaults.methodhandle_class == handle_class;
5416 static void
5417 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5419 if (type_args)
5420 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5421 mono_array_addr (type_args, MonoType*, 0));
5422 else
5423 context->class_inst = NULL;
5424 if (method_args)
5425 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5426 mono_array_addr (method_args, MonoType*, 0));
5427 else
5428 context->method_inst = NULL;
5431 ICALL_EXPORT MonoType*
5432 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5434 MonoClass *klass;
5435 int table = mono_metadata_token_table (token);
5436 int index = mono_metadata_token_index (token);
5437 MonoGenericContext context;
5439 *error = ResolveTokenError_Other;
5441 /* Validate token */
5442 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5443 (table != MONO_TABLE_TYPESPEC)) {
5444 *error = ResolveTokenError_BadTable;
5445 return NULL;
5448 if (image->dynamic) {
5449 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5450 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5451 return klass ? &klass->byval_arg : NULL;
5454 init_generic_context_from_args (&context, type_args, method_args);
5455 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5456 return klass ? &klass->byval_arg : NULL;
5459 if ((index <= 0) || (index > image->tables [table].rows)) {
5460 *error = ResolveTokenError_OutOfRange;
5461 return NULL;
5464 init_generic_context_from_args (&context, type_args, method_args);
5465 klass = mono_class_get_full (image, token, &context);
5467 if (mono_loader_get_last_error ())
5468 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5470 if (klass)
5471 return &klass->byval_arg;
5472 else
5473 return NULL;
5476 ICALL_EXPORT MonoMethod*
5477 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5479 int table = mono_metadata_token_table (token);
5480 int index = mono_metadata_token_index (token);
5481 MonoGenericContext context;
5482 MonoMethod *method;
5484 *error = ResolveTokenError_Other;
5486 /* Validate token */
5487 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5488 (table != MONO_TABLE_MEMBERREF)) {
5489 *error = ResolveTokenError_BadTable;
5490 return NULL;
5493 if (image->dynamic) {
5494 if (table == MONO_TABLE_METHOD)
5495 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5497 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5498 *error = ResolveTokenError_BadTable;
5499 return NULL;
5502 init_generic_context_from_args (&context, type_args, method_args);
5503 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5506 if ((index <= 0) || (index > image->tables [table].rows)) {
5507 *error = ResolveTokenError_OutOfRange;
5508 return NULL;
5510 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5511 *error = ResolveTokenError_BadTable;
5512 return NULL;
5515 init_generic_context_from_args (&context, type_args, method_args);
5516 method = mono_get_method_full (image, token, NULL, &context);
5518 if (mono_loader_get_last_error ())
5519 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5521 return method;
5524 ICALL_EXPORT MonoString*
5525 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5527 int index = mono_metadata_token_index (token);
5529 *error = ResolveTokenError_Other;
5531 /* Validate token */
5532 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5533 *error = ResolveTokenError_BadTable;
5534 return NULL;
5537 if (image->dynamic)
5538 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5540 if ((index <= 0) || (index >= image->heap_us.size)) {
5541 *error = ResolveTokenError_OutOfRange;
5542 return NULL;
5545 /* FIXME: What to do if the index points into the middle of a string ? */
5547 return mono_ldstr (mono_domain_get (), image, index);
5550 ICALL_EXPORT MonoClassField*
5551 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5553 MonoClass *klass;
5554 int table = mono_metadata_token_table (token);
5555 int index = mono_metadata_token_index (token);
5556 MonoGenericContext context;
5557 MonoClassField *field;
5559 *error = ResolveTokenError_Other;
5561 /* Validate token */
5562 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5563 *error = ResolveTokenError_BadTable;
5564 return NULL;
5567 if (image->dynamic) {
5568 if (table == MONO_TABLE_FIELD)
5569 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5571 if (mono_memberref_is_method (image, token)) {
5572 *error = ResolveTokenError_BadTable;
5573 return NULL;
5576 init_generic_context_from_args (&context, type_args, method_args);
5577 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5580 if ((index <= 0) || (index > image->tables [table].rows)) {
5581 *error = ResolveTokenError_OutOfRange;
5582 return NULL;
5584 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5585 *error = ResolveTokenError_BadTable;
5586 return NULL;
5589 init_generic_context_from_args (&context, type_args, method_args);
5590 field = mono_field_from_token (image, token, &klass, &context);
5592 if (mono_loader_get_last_error ())
5593 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5595 return field;
5599 ICALL_EXPORT MonoObject*
5600 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5602 int table = mono_metadata_token_table (token);
5604 *error = ResolveTokenError_Other;
5606 switch (table) {
5607 case MONO_TABLE_TYPEDEF:
5608 case MONO_TABLE_TYPEREF:
5609 case MONO_TABLE_TYPESPEC: {
5610 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5611 if (t)
5612 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5613 else
5614 return NULL;
5616 case MONO_TABLE_METHOD:
5617 case MONO_TABLE_METHODSPEC: {
5618 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5619 if (m)
5620 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5621 else
5622 return NULL;
5624 case MONO_TABLE_FIELD: {
5625 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5626 if (f)
5627 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5628 else
5629 return NULL;
5631 case MONO_TABLE_MEMBERREF:
5632 if (mono_memberref_is_method (image, token)) {
5633 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5634 if (m)
5635 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5636 else
5637 return NULL;
5639 else {
5640 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5641 if (f)
5642 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5643 else
5644 return NULL;
5646 break;
5648 default:
5649 *error = ResolveTokenError_BadTable;
5652 return NULL;
5655 ICALL_EXPORT MonoArray*
5656 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5658 int table = mono_metadata_token_table (token);
5659 int idx = mono_metadata_token_index (token);
5660 MonoTableInfo *tables = image->tables;
5661 guint32 sig, len;
5662 const char *ptr;
5663 MonoArray *res;
5665 *error = ResolveTokenError_OutOfRange;
5667 /* FIXME: Support other tables ? */
5668 if (table != MONO_TABLE_STANDALONESIG)
5669 return NULL;
5671 if (image->dynamic)
5672 return NULL;
5674 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5675 return NULL;
5677 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5679 ptr = mono_metadata_blob_heap (image, sig);
5680 len = mono_metadata_decode_blob_size (ptr, &ptr);
5682 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5683 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5684 return res;
5687 ICALL_EXPORT MonoReflectionType*
5688 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5690 MonoClass *klass;
5691 int isbyref = 0, rank;
5692 char *str = mono_string_to_utf8 (smodifiers);
5693 char *p;
5695 MONO_ARCH_SAVE_REGS;
5697 klass = mono_class_from_mono_type (tb->type.type);
5698 p = str;
5699 /* logic taken from mono_reflection_parse_type(): keep in sync */
5700 while (*p) {
5701 switch (*p) {
5702 case '&':
5703 if (isbyref) { /* only one level allowed by the spec */
5704 g_free (str);
5705 return NULL;
5707 isbyref = 1;
5708 p++;
5709 g_free (str);
5710 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5711 break;
5712 case '*':
5713 klass = mono_ptr_class_get (&klass->byval_arg);
5714 mono_class_init (klass);
5715 p++;
5716 break;
5717 case '[':
5718 rank = 1;
5719 p++;
5720 while (*p) {
5721 if (*p == ']')
5722 break;
5723 if (*p == ',')
5724 rank++;
5725 else if (*p != '*') { /* '*' means unknown lower bound */
5726 g_free (str);
5727 return NULL;
5729 ++p;
5731 if (*p != ']') {
5732 g_free (str);
5733 return NULL;
5735 p++;
5736 klass = mono_array_class_get (klass, rank);
5737 mono_class_init (klass);
5738 break;
5739 default:
5740 break;
5743 g_free (str);
5744 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5747 ICALL_EXPORT MonoBoolean
5748 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5750 MonoType *type;
5751 MonoBoolean res;
5753 MONO_ARCH_SAVE_REGS;
5755 type = t->type;
5756 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5758 return res;
5761 static void
5762 check_for_invalid_type (MonoClass *klass)
5764 char *name;
5765 MonoString *str;
5766 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5767 return;
5769 name = mono_type_get_full_name (klass);
5770 str = mono_string_new (mono_domain_get (), name);
5771 g_free (name);
5772 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5775 ICALL_EXPORT MonoReflectionType *
5776 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5778 MonoClass *klass, *aklass;
5780 MONO_ARCH_SAVE_REGS;
5782 klass = mono_class_from_mono_type (type->type);
5783 check_for_invalid_type (klass);
5785 if (rank == 0) //single dimentional array
5786 aklass = mono_array_class_get (klass, 1);
5787 else
5788 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5790 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5793 ICALL_EXPORT MonoReflectionType *
5794 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5796 MonoClass *klass;
5798 MONO_ARCH_SAVE_REGS;
5800 klass = mono_class_from_mono_type (type->type);
5801 mono_class_init_or_throw (klass);
5802 check_for_invalid_type (klass);
5804 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5807 ICALL_EXPORT MonoReflectionType *
5808 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5810 MonoClass *klass, *pklass;
5812 klass = mono_class_from_mono_type (type->type);
5813 mono_class_init_or_throw (klass);
5814 check_for_invalid_type (klass);
5816 pklass = mono_ptr_class_get (type->type);
5818 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5821 ICALL_EXPORT MonoObject *
5822 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5823 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5825 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5826 MonoObject *delegate;
5827 gpointer func;
5828 MonoMethod *method = info->method;
5830 MONO_ARCH_SAVE_REGS;
5832 mono_class_init_or_throw (delegate_class);
5834 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5836 if (mono_security_core_clr_enabled ()) {
5837 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5838 return NULL;
5841 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5843 if (method->dynamic) {
5844 /* Creating a trampoline would leak memory */
5845 func = mono_compile_method (method);
5846 } else {
5847 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5848 method = mono_object_get_virtual_method (target, method);
5849 func = mono_create_ftnptr (mono_domain_get (),
5850 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5853 mono_delegate_ctor_with_method (delegate, target, func, method);
5855 return delegate;
5858 ICALL_EXPORT void
5859 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5861 /* Reset the invoke impl to the default one */
5862 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5866 * Magic number to convert a time which is relative to
5867 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5869 #define EPOCH_ADJUST ((guint64)62135596800LL)
5872 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5874 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5876 #ifdef HOST_WIN32
5877 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5878 static void
5879 convert_to_absolute_date(SYSTEMTIME *date)
5881 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5882 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5883 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5884 /* from the calendar FAQ */
5885 int a = (14 - date->wMonth) / 12;
5886 int y = date->wYear - a;
5887 int m = date->wMonth + 12 * a - 2;
5888 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5890 /* d is now the day of the week for the first of the month (0 == Sunday) */
5892 int day_of_week = date->wDayOfWeek;
5894 /* set day_in_month to the first day in the month which falls on day_of_week */
5895 int day_in_month = 1 + (day_of_week - d);
5896 if (day_in_month <= 0)
5897 day_in_month += 7;
5899 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5900 date->wDay = day_in_month + (date->wDay - 1) * 7;
5901 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5902 date->wDay -= 7;
5904 #endif
5906 #ifndef HOST_WIN32
5908 * Return's the offset from GMT of a local time.
5910 * tm is a local time
5911 * t is the same local time as seconds.
5913 static int
5914 gmt_offset(struct tm *tm, time_t t)
5916 #if defined (HAVE_TM_GMTOFF)
5917 return tm->tm_gmtoff;
5918 #else
5919 struct tm g;
5920 time_t t2;
5921 g = *gmtime(&t);
5922 g.tm_isdst = tm->tm_isdst;
5923 t2 = mktime(&g);
5924 return (int)difftime(t, t2);
5925 #endif
5927 #endif
5929 * This is heavily based on zdump.c from glibc 2.2.
5931 * * data[0]: start of daylight saving time (in DateTime ticks).
5932 * * data[1]: end of daylight saving time (in DateTime ticks).
5933 * * data[2]: utcoffset (in TimeSpan ticks).
5934 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5935 * * name[0]: name of this timezone when not daylight saving.
5936 * * name[1]: name of this timezone when daylight saving.
5938 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5939 * the class library allows years between 1 and 9999.
5941 * Returns true on success and zero on failure.
5943 ICALL_EXPORT guint32
5944 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5946 #ifndef HOST_WIN32
5947 MonoDomain *domain = mono_domain_get ();
5948 struct tm start, tt;
5949 time_t t;
5951 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5952 int day, transitioned;
5953 char tzone [64];
5955 gmtoff_st = gmtoff_ds = transitioned = 0;
5957 MONO_ARCH_SAVE_REGS;
5959 MONO_CHECK_ARG_NULL (data);
5960 MONO_CHECK_ARG_NULL (names);
5962 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5963 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5966 * no info is better than crashing: we'll need our own tz data
5967 * to make this work properly, anyway. The range is probably
5968 * reduced to 1970 .. 2037 because that is what mktime is
5969 * guaranteed to support (we get into an infinite loop
5970 * otherwise).
5973 memset (&start, 0, sizeof (start));
5975 start.tm_mday = 1;
5976 start.tm_year = year-1900;
5978 t = mktime (&start);
5980 if ((year < 1970) || (year > 2037) || (t == -1)) {
5981 t = time (NULL);
5982 tt = *localtime (&t);
5983 strftime (tzone, sizeof (tzone), "%Z", &tt);
5984 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5985 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5986 return 1;
5989 gmtoff = gmt_offset (&start, t);
5991 /* For each day of the year, calculate the tm_gmtoff. */
5992 for (day = 0; day < 365 && transitioned < 2; day++) {
5994 t += 3600*24;
5995 tt = *localtime (&t);
5997 gmtoff_after = gmt_offset(&tt, t);
5999 /* Daylight saving starts or ends here. */
6000 if (gmtoff_after != gmtoff) {
6001 struct tm tt1;
6002 time_t t1;
6004 /* Try to find the exact hour when daylight saving starts/ends. */
6005 t1 = t;
6006 do {
6007 t1 -= 3600;
6008 tt1 = *localtime (&t1);
6009 } while (gmt_offset (&tt1, t1) != gmtoff);
6011 /* Try to find the exact minute when daylight saving starts/ends. */
6012 do {
6013 t1 += 60;
6014 tt1 = *localtime (&t1);
6015 } while (gmt_offset (&tt1, t1) == gmtoff);
6016 t1+=gmtoff;
6017 strftime (tzone, sizeof (tzone), "%Z", &tt);
6019 /* Write data, if we're already in daylight saving, we're done. */
6020 if (tt.tm_isdst) {
6021 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6022 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6023 if (gmtoff_ds == 0) {
6024 gmtoff_st = gmtoff;
6025 gmtoff_ds = gmtoff_after;
6027 transitioned++;
6028 } else {
6029 time_t te;
6030 te = mktime (&tt);
6032 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6033 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6034 if (gmtoff_ds == 0) {
6035 gmtoff_st = gmtoff_after;
6036 gmtoff_ds = gmtoff;
6038 transitioned++;
6041 /* This is only set once when we enter daylight saving. */
6042 if (tt1.tm_isdst) {
6043 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6044 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6046 gmtoff = gmt_offset (&tt, t);
6050 if (transitioned < 2) {
6051 strftime (tzone, sizeof (tzone), "%Z", &tt);
6052 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6053 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6054 mono_array_set ((*data), gint64, 0, 0);
6055 mono_array_set ((*data), gint64, 1, 0);
6056 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6057 mono_array_set ((*data), gint64, 3, 0);
6060 return 1;
6061 #else
6062 MonoDomain *domain = mono_domain_get ();
6063 TIME_ZONE_INFORMATION tz_info;
6064 FILETIME ft;
6065 int i;
6066 int err, tz_id;
6068 tz_id = GetTimeZoneInformation (&tz_info);
6069 if (tz_id == TIME_ZONE_ID_INVALID)
6070 return 0;
6072 MONO_CHECK_ARG_NULL (data);
6073 MONO_CHECK_ARG_NULL (names);
6075 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6076 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6078 for (i = 0; i < 32; ++i)
6079 if (!tz_info.DaylightName [i])
6080 break;
6081 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6082 for (i = 0; i < 32; ++i)
6083 if (!tz_info.StandardName [i])
6084 break;
6085 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6087 if ((year <= 1601) || (year > 30827)) {
6089 * According to MSDN, the MS time functions can't handle dates outside
6090 * this interval.
6092 return 1;
6095 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6096 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6097 tz_info.StandardDate.wYear = year;
6098 convert_to_absolute_date(&tz_info.StandardDate);
6099 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6100 //g_assert(err);
6101 if (err == 0)
6102 return 0;
6104 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6105 tz_info.DaylightDate.wYear = year;
6106 convert_to_absolute_date(&tz_info.DaylightDate);
6107 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6108 //g_assert(err);
6109 if (err == 0)
6110 return 0;
6112 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6114 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6115 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6117 return 1;
6118 #endif
6121 /* System.Buffer */
6123 static inline gint32
6124 mono_array_get_byte_length (MonoArray *array)
6126 MonoClass *klass;
6127 int length;
6128 int i;
6130 klass = array->obj.vtable->klass;
6132 if (array->bounds == NULL)
6133 length = array->max_length;
6134 else {
6135 length = 1;
6136 for (i = 0; i < klass->rank; ++ i)
6137 length *= array->bounds [i].length;
6140 switch (klass->element_class->byval_arg.type) {
6141 case MONO_TYPE_I1:
6142 case MONO_TYPE_U1:
6143 case MONO_TYPE_BOOLEAN:
6144 return length;
6145 case MONO_TYPE_I2:
6146 case MONO_TYPE_U2:
6147 case MONO_TYPE_CHAR:
6148 return length << 1;
6149 case MONO_TYPE_I4:
6150 case MONO_TYPE_U4:
6151 case MONO_TYPE_R4:
6152 return length << 2;
6153 case MONO_TYPE_I:
6154 case MONO_TYPE_U:
6155 return length * sizeof (gpointer);
6156 case MONO_TYPE_I8:
6157 case MONO_TYPE_U8:
6158 case MONO_TYPE_R8:
6159 return length << 3;
6160 default:
6161 return -1;
6165 ICALL_EXPORT gint32
6166 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6168 MONO_ARCH_SAVE_REGS;
6170 return mono_array_get_byte_length (array);
6173 ICALL_EXPORT gint8
6174 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6176 MONO_ARCH_SAVE_REGS;
6178 return mono_array_get (array, gint8, idx);
6181 ICALL_EXPORT void
6182 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6184 MONO_ARCH_SAVE_REGS;
6186 mono_array_set (array, gint8, idx, value);
6189 ICALL_EXPORT MonoBoolean
6190 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6192 guint8 *src_buf, *dest_buf;
6194 MONO_ARCH_SAVE_REGS;
6196 /* This is called directly from the class libraries without going through the managed wrapper */
6197 MONO_CHECK_ARG_NULL (src);
6198 MONO_CHECK_ARG_NULL (dest);
6200 /* watch out for integer overflow */
6201 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6202 return FALSE;
6204 src_buf = (guint8 *)src->vector + src_offset;
6205 dest_buf = (guint8 *)dest->vector + dest_offset;
6207 if (src != dest)
6208 memcpy (dest_buf, src_buf, count);
6209 else
6210 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6212 return TRUE;
6215 #ifndef DISABLE_REMOTING
6216 ICALL_EXPORT MonoObject *
6217 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6219 MonoDomain *domain = mono_object_domain (this);
6220 MonoObject *res;
6221 MonoRealProxy *rp = ((MonoRealProxy *)this);
6222 MonoTransparentProxy *tp;
6223 MonoType *type;
6224 MonoClass *klass;
6226 MONO_ARCH_SAVE_REGS;
6228 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6229 tp = (MonoTransparentProxy*) res;
6231 MONO_OBJECT_SETREF (tp, rp, rp);
6232 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6233 klass = mono_class_from_mono_type (type);
6235 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6236 tp->remote_class = mono_remote_class (domain, class_name, klass);
6238 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6239 return res;
6242 ICALL_EXPORT MonoReflectionType *
6243 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6245 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6247 #endif
6249 /* System.Environment */
6251 MonoString*
6252 ves_icall_System_Environment_get_UserName (void)
6254 MONO_ARCH_SAVE_REGS;
6256 /* using glib is more portable */
6257 return mono_string_new (mono_domain_get (), g_get_user_name ());
6261 ICALL_EXPORT MonoString *
6262 ves_icall_System_Environment_get_MachineName (void)
6264 #if defined (HOST_WIN32)
6265 gunichar2 *buf;
6266 guint32 len;
6267 MonoString *result;
6269 len = MAX_COMPUTERNAME_LENGTH + 1;
6270 buf = g_new (gunichar2, len);
6272 result = NULL;
6273 if (GetComputerName (buf, (PDWORD) &len))
6274 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6276 g_free (buf);
6277 return result;
6278 #elif !defined(DISABLE_SOCKETS)
6279 gchar buf [256];
6280 MonoString *result;
6282 if (gethostname (buf, sizeof (buf)) == 0)
6283 result = mono_string_new (mono_domain_get (), buf);
6284 else
6285 result = NULL;
6287 return result;
6288 #else
6289 return mono_string_new (mono_domain_get (), "mono");
6290 #endif
6293 ICALL_EXPORT int
6294 ves_icall_System_Environment_get_Platform (void)
6296 #if defined (TARGET_WIN32)
6297 /* Win32NT */
6298 return 2;
6299 #elif defined(__MACH__)
6300 /* OSX */
6302 // Notice that the value is hidden from user code, and only exposed
6303 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6304 // define and making assumptions based on Unix/128/4 values before there
6305 // was a MacOS define. Lots of code would assume that not-Unix meant
6306 // Windows, but in this case, it would be OSX.
6308 return 6;
6309 #else
6310 /* Unix */
6311 return 4;
6312 #endif
6315 ICALL_EXPORT MonoString *
6316 ves_icall_System_Environment_get_NewLine (void)
6318 MONO_ARCH_SAVE_REGS;
6320 #if defined (HOST_WIN32)
6321 return mono_string_new (mono_domain_get (), "\r\n");
6322 #else
6323 return mono_string_new (mono_domain_get (), "\n");
6324 #endif
6327 ICALL_EXPORT MonoString *
6328 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6330 const gchar *value;
6331 gchar *utf8_name;
6333 MONO_ARCH_SAVE_REGS;
6335 if (name == NULL)
6336 return NULL;
6338 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6339 value = g_getenv (utf8_name);
6341 g_free (utf8_name);
6343 if (value == 0)
6344 return NULL;
6346 return mono_string_new (mono_domain_get (), value);
6350 * There is no standard way to get at environ.
6352 #ifndef _MSC_VER
6353 #ifndef __MINGW32_VERSION
6354 #if defined(__APPLE__) && !defined (__arm__)
6355 /* Apple defines this in crt_externs.h but doesn't provide that header for
6356 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6357 * in fact exist on all implementations (so far)
6359 gchar ***_NSGetEnviron(void);
6360 #define environ (*_NSGetEnviron())
6361 #else
6362 extern
6363 char **environ;
6364 #endif
6365 #endif
6366 #endif
6368 ICALL_EXPORT MonoArray *
6369 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6371 #ifdef HOST_WIN32
6372 MonoArray *names;
6373 MonoDomain *domain;
6374 MonoString *str;
6375 WCHAR* env_strings;
6376 WCHAR* env_string;
6377 WCHAR* equal_str;
6378 int n = 0;
6380 env_strings = GetEnvironmentStrings();
6382 if (env_strings) {
6383 env_string = env_strings;
6384 while (*env_string != '\0') {
6385 /* weird case that MS seems to skip */
6386 if (*env_string != '=')
6387 n++;
6388 while (*env_string != '\0')
6389 env_string++;
6390 env_string++;
6394 domain = mono_domain_get ();
6395 names = mono_array_new (domain, mono_defaults.string_class, n);
6397 if (env_strings) {
6398 n = 0;
6399 env_string = env_strings;
6400 while (*env_string != '\0') {
6401 /* weird case that MS seems to skip */
6402 if (*env_string != '=') {
6403 equal_str = wcschr(env_string, '=');
6404 g_assert(equal_str);
6405 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6406 mono_array_setref (names, n, str);
6407 n++;
6409 while (*env_string != '\0')
6410 env_string++;
6411 env_string++;
6414 FreeEnvironmentStrings (env_strings);
6417 return names;
6419 #else
6420 MonoArray *names;
6421 MonoDomain *domain;
6422 MonoString *str;
6423 gchar **e, **parts;
6424 int n;
6426 MONO_ARCH_SAVE_REGS;
6428 n = 0;
6429 for (e = environ; *e != 0; ++ e)
6430 ++ n;
6432 domain = mono_domain_get ();
6433 names = mono_array_new (domain, mono_defaults.string_class, n);
6435 n = 0;
6436 for (e = environ; *e != 0; ++ e) {
6437 parts = g_strsplit (*e, "=", 2);
6438 if (*parts != 0) {
6439 str = mono_string_new (domain, *parts);
6440 mono_array_setref (names, n, str);
6443 g_strfreev (parts);
6445 ++ n;
6448 return names;
6449 #endif
6453 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6455 #if !GLIB_CHECK_VERSION(2,4,0)
6456 #define g_setenv(a,b,c) setenv(a,b,c)
6457 #define g_unsetenv(a) unsetenv(a)
6458 #endif
6460 ICALL_EXPORT void
6461 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6463 MonoError error;
6464 #ifdef HOST_WIN32
6466 gunichar2 *utf16_name, *utf16_value;
6467 #else
6468 gchar *utf8_name, *utf8_value;
6469 #endif
6471 MONO_ARCH_SAVE_REGS;
6473 #ifdef HOST_WIN32
6474 utf16_name = mono_string_to_utf16 (name);
6475 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6476 SetEnvironmentVariable (utf16_name, NULL);
6477 g_free (utf16_name);
6478 return;
6481 utf16_value = mono_string_to_utf16 (value);
6483 SetEnvironmentVariable (utf16_name, utf16_value);
6485 g_free (utf16_name);
6486 g_free (utf16_value);
6487 #else
6488 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6490 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6491 g_unsetenv (utf8_name);
6492 g_free (utf8_name);
6493 return;
6496 utf8_value = mono_string_to_utf8_checked (value, &error);
6497 if (!mono_error_ok (&error)) {
6498 g_free (utf8_name);
6499 mono_error_raise_exception (&error);
6501 g_setenv (utf8_name, utf8_value, TRUE);
6503 g_free (utf8_name);
6504 g_free (utf8_value);
6505 #endif
6508 ICALL_EXPORT void
6509 ves_icall_System_Environment_Exit (int result)
6511 MONO_ARCH_SAVE_REGS;
6513 mono_environment_exitcode_set (result);
6515 /* FIXME: There are some cleanup hangs that should be worked out, but
6516 * if the program is going to exit, everything will be cleaned up when
6517 * NaCl exits anyway.
6519 #ifndef __native_client__
6520 if (!mono_runtime_try_shutdown ())
6521 mono_thread_exit ();
6523 /* Suspend all managed threads since the runtime is going away */
6524 mono_thread_suspend_all_other_threads ();
6526 mono_runtime_quit ();
6527 #endif
6529 /* we may need to do some cleanup here... */
6530 exit (result);
6533 ICALL_EXPORT MonoString*
6534 ves_icall_System_Environment_GetGacPath (void)
6536 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6539 ICALL_EXPORT MonoString*
6540 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6542 #if defined (HOST_WIN32)
6543 #ifndef CSIDL_FLAG_CREATE
6544 #define CSIDL_FLAG_CREATE 0x8000
6545 #endif
6547 WCHAR path [MAX_PATH];
6548 /* Create directory if no existing */
6549 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6550 int len = 0;
6551 while (path [len])
6552 ++ len;
6553 return mono_string_new_utf16 (mono_domain_get (), path, len);
6555 #else
6556 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6557 #endif
6558 return mono_string_new (mono_domain_get (), "");
6561 ICALL_EXPORT MonoArray *
6562 ves_icall_System_Environment_GetLogicalDrives (void)
6564 gunichar2 buf [256], *ptr, *dname;
6565 gunichar2 *u16;
6566 guint initial_size = 127, size = 128;
6567 gint ndrives;
6568 MonoArray *result;
6569 MonoString *drivestr;
6570 MonoDomain *domain = mono_domain_get ();
6571 gint len;
6573 MONO_ARCH_SAVE_REGS;
6575 buf [0] = '\0';
6576 ptr = buf;
6578 while (size > initial_size) {
6579 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6580 if (size > initial_size) {
6581 if (ptr != buf)
6582 g_free (ptr);
6583 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6584 initial_size = size;
6585 size++;
6589 /* Count strings */
6590 dname = ptr;
6591 ndrives = 0;
6592 do {
6593 while (*dname++);
6594 ndrives++;
6595 } while (*dname);
6597 dname = ptr;
6598 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6599 ndrives = 0;
6600 do {
6601 len = 0;
6602 u16 = dname;
6603 while (*u16) { u16++; len ++; }
6604 drivestr = mono_string_new_utf16 (domain, dname, len);
6605 mono_array_setref (result, ndrives++, drivestr);
6606 while (*dname++);
6607 } while (*dname);
6609 if (ptr != buf)
6610 g_free (ptr);
6612 return result;
6615 ICALL_EXPORT MonoString *
6616 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6618 gunichar2 volume_name [MAX_PATH + 1];
6620 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6621 return NULL;
6622 return mono_string_from_utf16 (volume_name);
6625 ICALL_EXPORT MonoString *
6626 ves_icall_System_Environment_InternalGetHome (void)
6628 MONO_ARCH_SAVE_REGS;
6630 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6633 static const char *encodings [] = {
6634 (char *) 1,
6635 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6636 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6637 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6638 (char *) 2,
6639 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6640 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6641 "x_unicode_2_0_utf_7",
6642 (char *) 3,
6643 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6644 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6645 (char *) 4,
6646 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6647 "iso_10646_ucs2",
6648 (char *) 5,
6649 "unicodefffe", "utf_16be",
6650 (char *) 6,
6651 "iso_8859_1",
6652 (char *) 0
6656 * Returns the internal codepage, if the value of "int_code_page" is
6657 * 1 at entry, and we can not compute a suitable code page number,
6658 * returns the code page as a string
6660 ICALL_EXPORT MonoString*
6661 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6663 const char *cset;
6664 const char *p;
6665 char *c;
6666 char *codepage = NULL;
6667 int code;
6668 int want_name = *int_code_page;
6669 int i;
6671 *int_code_page = -1;
6672 MONO_ARCH_SAVE_REGS;
6674 g_get_charset (&cset);
6675 c = codepage = strdup (cset);
6676 for (c = codepage; *c; c++){
6677 if (isascii (*c) && isalpha (*c))
6678 *c = tolower (*c);
6679 if (*c == '-')
6680 *c = '_';
6682 /* g_print ("charset: %s\n", cset); */
6684 /* handle some common aliases */
6685 p = encodings [0];
6686 code = 0;
6687 for (i = 0; p != 0; ){
6688 if ((gssize) p < 7){
6689 code = (gssize) p;
6690 p = encodings [++i];
6691 continue;
6693 if (strcmp (p, codepage) == 0){
6694 *int_code_page = code;
6695 break;
6697 p = encodings [++i];
6700 if (strstr (codepage, "utf_8") != NULL)
6701 *int_code_page |= 0x10000000;
6702 free (codepage);
6704 if (want_name && *int_code_page == -1)
6705 return mono_string_new (mono_domain_get (), cset);
6706 else
6707 return NULL;
6710 ICALL_EXPORT MonoBoolean
6711 ves_icall_System_Environment_get_HasShutdownStarted (void)
6713 if (mono_runtime_is_shutting_down ())
6714 return TRUE;
6716 if (mono_domain_is_unloading (mono_domain_get ()))
6717 return TRUE;
6719 return FALSE;
6722 ICALL_EXPORT void
6723 ves_icall_System_Environment_BroadcastSettingChange (void)
6725 #ifdef HOST_WIN32
6726 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6727 #endif
6730 ICALL_EXPORT void
6731 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6732 MonoReflectionMethod *method,
6733 MonoArray *out_args)
6735 MONO_ARCH_SAVE_REGS;
6737 mono_message_init (mono_object_domain (this), this, method, out_args);
6740 #ifndef DISABLE_REMOTING
6741 ICALL_EXPORT MonoBoolean
6742 ves_icall_IsTransparentProxy (MonoObject *proxy)
6744 MONO_ARCH_SAVE_REGS;
6746 if (!proxy)
6747 return 0;
6749 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6750 return 1;
6752 return 0;
6755 ICALL_EXPORT MonoReflectionMethod *
6756 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6757 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6759 MonoClass *klass;
6760 MonoMethod *method;
6761 MonoMethod **vtable;
6762 MonoMethod *res = NULL;
6764 MONO_CHECK_ARG_NULL (rtype);
6765 MONO_CHECK_ARG_NULL (rmethod);
6767 method = rmethod->method;
6768 klass = mono_class_from_mono_type (rtype->type);
6769 mono_class_init_or_throw (klass);
6771 if (MONO_CLASS_IS_INTERFACE (klass))
6772 return NULL;
6774 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6775 return NULL;
6777 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6778 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6779 return rmethod;
6780 else
6781 return NULL;
6784 mono_class_setup_vtable (klass);
6785 vtable = klass->vtable;
6787 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6788 gboolean variance_used = FALSE;
6789 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6790 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6791 if (offs >= 0)
6792 res = vtable [offs + method->slot];
6793 } else {
6794 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6795 return NULL;
6797 if (method->slot != -1)
6798 res = vtable [method->slot];
6801 if (!res)
6802 return NULL;
6804 return mono_method_get_object (mono_domain_get (), res, NULL);
6807 ICALL_EXPORT void
6808 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6810 MonoClass *klass;
6811 MonoVTable* vtable;
6813 MONO_ARCH_SAVE_REGS;
6815 klass = mono_class_from_mono_type (type->type);
6816 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6818 mono_vtable_set_is_remote (vtable, enable);
6821 #else /* DISABLE_REMOTING */
6823 ICALL_EXPORT void
6824 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6826 g_assert_not_reached ();
6829 #endif
6831 ICALL_EXPORT MonoObject *
6832 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6834 MonoClass *klass;
6835 MonoDomain *domain;
6837 MONO_ARCH_SAVE_REGS;
6839 domain = mono_object_domain (type);
6840 klass = mono_class_from_mono_type (type->type);
6841 mono_class_init_or_throw (klass);
6843 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6844 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6846 if (klass->rank >= 1) {
6847 g_assert (klass->rank == 1);
6848 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6849 } else {
6850 /* Bypass remoting object creation check */
6851 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6855 ICALL_EXPORT MonoString *
6856 ves_icall_System_IO_get_temp_path (void)
6858 MONO_ARCH_SAVE_REGS;
6860 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6863 #ifndef PLATFORM_NO_DRIVEINFO
6864 ICALL_EXPORT MonoBoolean
6865 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6866 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6867 gint32 *error)
6869 gboolean result;
6870 ULARGE_INTEGER wapi_free_bytes_avail;
6871 ULARGE_INTEGER wapi_total_number_of_bytes;
6872 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6874 MONO_ARCH_SAVE_REGS;
6876 *error = ERROR_SUCCESS;
6877 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6878 &wapi_total_number_of_free_bytes);
6880 if (result) {
6881 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6882 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6883 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6884 } else {
6885 *free_bytes_avail = 0;
6886 *total_number_of_bytes = 0;
6887 *total_number_of_free_bytes = 0;
6888 *error = GetLastError ();
6891 return result;
6894 ICALL_EXPORT guint32
6895 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6897 MONO_ARCH_SAVE_REGS;
6899 return GetDriveType (mono_string_chars (root_path_name));
6901 #endif
6903 ICALL_EXPORT gpointer
6904 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6906 MONO_ARCH_SAVE_REGS;
6908 return mono_compile_method (method);
6911 ICALL_EXPORT MonoString *
6912 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6914 MonoString *mcpath;
6915 gchar *path;
6917 MONO_ARCH_SAVE_REGS;
6919 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6921 #if defined (HOST_WIN32)
6922 /* Avoid mixing '/' and '\\' */
6924 gint i;
6925 for (i = strlen (path) - 1; i >= 0; i--)
6926 if (path [i] == '/')
6927 path [i] = '\\';
6929 #endif
6930 mcpath = mono_string_new (mono_domain_get (), path);
6931 g_free (path);
6933 return mcpath;
6936 static MonoString *
6937 get_bundled_app_config (void)
6939 const gchar *app_config;
6940 MonoDomain *domain;
6941 MonoString *file;
6942 gchar *config_file_name, *config_file_path;
6943 gsize len;
6944 gchar *module;
6946 MONO_ARCH_SAVE_REGS;
6948 domain = mono_domain_get ();
6949 file = domain->setup->configuration_file;
6950 if (!file)
6951 return NULL;
6953 // Retrieve config file and remove the extension
6954 config_file_name = mono_string_to_utf8 (file);
6955 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6956 if (!config_file_path)
6957 config_file_path = config_file_name;
6958 len = strlen (config_file_path) - strlen (".config");
6959 module = g_malloc0 (len + 1);
6960 memcpy (module, config_file_path, len);
6961 // Get the config file from the module name
6962 app_config = mono_config_string_for_assembly_file (module);
6963 // Clean-up
6964 g_free (module);
6965 if (config_file_name != config_file_path)
6966 g_free (config_file_name);
6967 g_free (config_file_path);
6969 if (!app_config)
6970 return NULL;
6972 return mono_string_new (mono_domain_get (), app_config);
6975 static MonoString *
6976 get_bundled_machine_config (void)
6978 const gchar *machine_config;
6980 MONO_ARCH_SAVE_REGS;
6982 machine_config = mono_get_machine_config ();
6984 if (!machine_config)
6985 return NULL;
6987 return mono_string_new (mono_domain_get (), machine_config);
6990 ICALL_EXPORT MonoString *
6991 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6993 MonoString *ipath;
6994 gchar *path;
6996 MONO_ARCH_SAVE_REGS;
6998 path = g_path_get_dirname (mono_get_config_dir ());
7000 #if defined (HOST_WIN32)
7001 /* Avoid mixing '/' and '\\' */
7003 gint i;
7004 for (i = strlen (path) - 1; i >= 0; i--)
7005 if (path [i] == '/')
7006 path [i] = '\\';
7008 #endif
7009 ipath = mono_string_new (mono_domain_get (), path);
7010 g_free (path);
7012 return ipath;
7015 ICALL_EXPORT gboolean
7016 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7018 MonoPEResourceDataEntry *entry;
7019 MonoImage *image;
7021 MONO_ARCH_SAVE_REGS;
7023 if (!assembly || !result || !size)
7024 return FALSE;
7026 *result = NULL;
7027 *size = 0;
7028 image = assembly->assembly->image;
7029 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7030 if (!entry)
7031 return FALSE;
7033 *result = mono_image_rva_map (image, entry->rde_data_offset);
7034 if (!(*result)) {
7035 g_free (entry);
7036 return FALSE;
7038 *size = entry->rde_size;
7039 g_free (entry);
7040 return TRUE;
7043 ICALL_EXPORT MonoBoolean
7044 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7046 return mono_is_debugger_attached ();
7049 ICALL_EXPORT MonoBoolean
7050 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7052 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7053 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7054 else
7055 return FALSE;
7058 ICALL_EXPORT void
7059 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7061 if (mono_get_runtime_callbacks ()->debug_log)
7062 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7065 ICALL_EXPORT void
7066 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7068 #if defined (HOST_WIN32)
7069 OutputDebugString (mono_string_chars (message));
7070 #else
7071 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7072 #endif
7075 /* Only used for value types */
7076 ICALL_EXPORT MonoObject *
7077 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7079 MonoClass *klass;
7080 MonoDomain *domain;
7082 MONO_ARCH_SAVE_REGS;
7084 domain = mono_object_domain (type);
7085 klass = mono_class_from_mono_type (type->type);
7086 mono_class_init_or_throw (klass);
7088 if (mono_class_is_nullable (klass))
7089 /* No arguments -> null */
7090 return NULL;
7092 return mono_object_new (domain, klass);
7095 ICALL_EXPORT MonoReflectionMethod *
7096 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7098 MonoClass *klass, *parent;
7099 MonoMethod *method = m->method;
7100 MonoMethod *result = NULL;
7101 int slot;
7103 MONO_ARCH_SAVE_REGS;
7105 if (method->klass == NULL)
7106 return m;
7108 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7109 MONO_CLASS_IS_INTERFACE (method->klass) ||
7110 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7111 return m;
7113 slot = mono_method_get_vtable_slot (method);
7114 if (slot == -1)
7115 return m;
7117 klass = method->klass;
7118 if (klass->generic_class)
7119 klass = klass->generic_class->container_class;
7121 if (definition) {
7122 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7123 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7124 mono_class_setup_vtable (parent);
7125 if (parent->vtable_size <= slot)
7126 break;
7127 klass = parent;
7129 } else {
7130 klass = klass->parent;
7131 if (!klass)
7132 return m;
7135 if (klass == method->klass)
7136 return m;
7138 /*This is possible if definition == FALSE.
7139 * Do it here to be really sure we don't read invalid memory.
7141 if (slot >= klass->vtable_size)
7142 return m;
7144 mono_class_setup_vtable (klass);
7146 result = klass->vtable [slot];
7147 if (result == NULL) {
7148 /* It is an abstract method */
7149 gpointer iter = NULL;
7150 while ((result = mono_class_get_methods (klass, &iter)))
7151 if (result->slot == slot)
7152 break;
7155 if (result == NULL)
7156 return m;
7158 return mono_method_get_object (mono_domain_get (), result, NULL);
7161 ICALL_EXPORT MonoString*
7162 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7164 MonoMethod *method = m->method;
7166 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7167 return m->name;
7170 ICALL_EXPORT void
7171 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7173 MONO_ARCH_SAVE_REGS;
7175 iter->sig = *(MonoMethodSignature**)argsp;
7177 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7178 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7180 iter->next_arg = 0;
7181 /* FIXME: it's not documented what start is exactly... */
7182 if (start) {
7183 iter->args = start;
7184 } else {
7185 iter->args = argsp + sizeof (gpointer);
7187 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7189 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7192 ICALL_EXPORT MonoTypedRef
7193 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7195 guint32 i, arg_size;
7196 gint32 align;
7197 MonoTypedRef res;
7198 MONO_ARCH_SAVE_REGS;
7200 i = iter->sig->sentinelpos + iter->next_arg;
7202 g_assert (i < iter->sig->param_count);
7204 res.type = iter->sig->params [i];
7205 res.klass = mono_class_from_mono_type (res.type);
7206 arg_size = mono_type_stack_size (res.type, &align);
7207 #if defined(__arm__) || defined(__mips__)
7208 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7209 #endif
7210 res.value = iter->args;
7211 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7212 /* Values are stored as 8 byte register sized objects, but 'value'
7213 * is dereferenced as a pointer in other routines.
7215 res.value = (char*)res.value + 4;
7216 #endif
7217 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7218 if (arg_size <= sizeof (gpointer)) {
7219 int dummy;
7220 int padding = arg_size - mono_type_size (res.type, &dummy);
7221 res.value = (guint8*)res.value + padding;
7223 #endif
7224 iter->args = (char*)iter->args + arg_size;
7225 iter->next_arg++;
7227 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7229 return res;
7232 ICALL_EXPORT MonoTypedRef
7233 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7235 guint32 i, arg_size;
7236 gint32 align;
7237 MonoTypedRef res;
7238 MONO_ARCH_SAVE_REGS;
7240 i = iter->sig->sentinelpos + iter->next_arg;
7242 g_assert (i < iter->sig->param_count);
7244 while (i < iter->sig->param_count) {
7245 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7246 continue;
7247 res.type = iter->sig->params [i];
7248 res.klass = mono_class_from_mono_type (res.type);
7249 /* FIXME: endianess issue... */
7250 arg_size = mono_type_stack_size (res.type, &align);
7251 #if defined(__arm__) || defined(__mips__)
7252 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7253 #endif
7254 res.value = iter->args;
7255 iter->args = (char*)iter->args + arg_size;
7256 iter->next_arg++;
7257 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7258 return res;
7260 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7262 res.type = NULL;
7263 res.value = NULL;
7264 res.klass = NULL;
7265 return res;
7268 ICALL_EXPORT MonoType*
7269 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7271 gint i;
7272 MONO_ARCH_SAVE_REGS;
7274 i = iter->sig->sentinelpos + iter->next_arg;
7276 g_assert (i < iter->sig->param_count);
7278 return iter->sig->params [i];
7281 ICALL_EXPORT MonoObject*
7282 mono_TypedReference_ToObject (MonoTypedRef tref)
7284 MONO_ARCH_SAVE_REGS;
7286 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7287 MonoObject** objp = tref.value;
7288 return *objp;
7291 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7294 ICALL_EXPORT MonoObject*
7295 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7297 MONO_ARCH_SAVE_REGS;
7299 if (MONO_TYPE_IS_REFERENCE (type)) {
7300 MonoObject** objp = value;
7301 return *objp;
7304 return mono_value_box (mono_domain_get (), klass, value);
7307 static void
7308 prelink_method (MonoMethod *method)
7310 const char *exc_class, *exc_arg;
7311 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7312 return;
7313 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7314 if (exc_class) {
7315 mono_raise_exception(
7316 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7318 /* create the wrapper, too? */
7321 ICALL_EXPORT void
7322 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7324 MONO_ARCH_SAVE_REGS;
7325 prelink_method (method->method);
7328 ICALL_EXPORT void
7329 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7331 MonoClass *klass = mono_class_from_mono_type (type->type);
7332 MonoMethod* m;
7333 gpointer iter = NULL;
7334 MONO_ARCH_SAVE_REGS;
7336 mono_class_init_or_throw (klass);
7338 while ((m = mono_class_get_methods (klass, &iter)))
7339 prelink_method (m);
7342 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7343 ICALL_EXPORT void
7344 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7345 gint32 const **exponents,
7346 gunichar2 const **digitLowerTable,
7347 gunichar2 const **digitUpperTable,
7348 gint64 const **tenPowersList,
7349 gint32 const **decHexDigits)
7351 *mantissas = Formatter_MantissaBitsTable;
7352 *exponents = Formatter_TensExponentTable;
7353 *digitLowerTable = Formatter_DigitLowerTable;
7354 *digitUpperTable = Formatter_DigitUpperTable;
7355 *tenPowersList = Formatter_TenPowersList;
7356 *decHexDigits = Formatter_DecHexDigits;
7359 ICALL_EXPORT void
7360 get_category_data (int version,
7361 guint8 const **category_data,
7362 guint16 const **category_astral_index)
7364 *category_astral_index = NULL;
7366 #ifndef DISABLE_NET_4_0
7367 if (version == 4) {
7368 *category_data = CategoryData_v4;
7369 #ifndef DISABLE_ASTRAL
7370 *category_astral_index = CategoryData_v4_astral_index;
7371 #endif
7372 return;
7374 #endif
7376 *category_data = CategoryData_v2;
7377 #ifndef DISABLE_ASTRAL
7378 *category_astral_index = CategoryData_v2_astral_index;
7379 #endif
7382 /* These parameters are "readonly" in corlib/System/Char.cs */
7383 ICALL_EXPORT void
7384 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7385 guint8 const **category_data,
7386 guint16 const **category_astral_index,
7387 guint8 const **numeric_data,
7388 gdouble const **numeric_data_values,
7389 guint16 const **to_lower_data_low,
7390 guint16 const **to_lower_data_high,
7391 guint16 const **to_upper_data_low,
7392 guint16 const **to_upper_data_high)
7394 get_category_data (category_data_version, category_data, category_astral_index);
7395 *numeric_data = NumericData;
7396 *numeric_data_values = NumericDataValues;
7397 *to_lower_data_low = ToLowerDataLow;
7398 *to_lower_data_high = ToLowerDataHigh;
7399 *to_upper_data_low = ToUpperDataLow;
7400 *to_upper_data_high = ToUpperDataHigh;
7403 ICALL_EXPORT gint32
7404 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7406 return method->method->token;
7410 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7411 * and avoid useless allocations.
7413 static MonoArray*
7414 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7416 MonoArray *res;
7417 int i, count = 0;
7418 for (i = 0; i < type->num_mods; ++i) {
7419 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7420 count++;
7422 if (!count)
7423 return NULL;
7424 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7425 count = 0;
7426 for (i = 0; i < type->num_mods; ++i) {
7427 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7428 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7429 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7430 count++;
7433 return res;
7436 ICALL_EXPORT MonoArray*
7437 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7439 MonoType *type = param->ClassImpl->type;
7440 MonoClass *member_class = mono_object_class (param->MemberImpl);
7441 MonoMethod *method = NULL;
7442 MonoImage *image;
7443 int pos;
7444 MonoMethodSignature *sig;
7446 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7447 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7448 method = rmethod->method;
7449 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7450 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7451 if (!(method = prop->property->get))
7452 method = prop->property->set;
7453 g_assert (method);
7454 } else {
7455 char *type_name = mono_type_get_full_name (member_class);
7456 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7457 MonoException *ex = mono_get_exception_not_supported (msg);
7458 g_free (type_name);
7459 g_free (msg);
7460 mono_raise_exception (ex);
7463 image = method->klass->image;
7464 pos = param->PositionImpl;
7465 sig = mono_method_signature (method);
7466 if (pos == -1)
7467 type = sig->ret;
7468 else
7469 type = sig->params [pos];
7471 return type_array_from_modifiers (image, type, optional);
7474 static MonoType*
7475 get_property_type (MonoProperty *prop)
7477 MonoMethodSignature *sig;
7478 if (prop->get) {
7479 sig = mono_method_signature (prop->get);
7480 return sig->ret;
7481 } else if (prop->set) {
7482 sig = mono_method_signature (prop->set);
7483 return sig->params [sig->param_count - 1];
7485 return NULL;
7488 ICALL_EXPORT MonoArray*
7489 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7491 MonoType *type = get_property_type (property->property);
7492 MonoImage *image = property->klass->image;
7494 if (!type)
7495 return NULL;
7496 return type_array_from_modifiers (image, type, optional);
7500 *Construct a MonoType suited to be used to decode a constant blob object.
7502 * @type is the target type which will be constructed
7503 * @blob_type is the blob type, for example, that comes from the constant table
7504 * @real_type is the expected constructed type.
7506 static void
7507 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7509 type->type = blob_type;
7510 type->data.klass = NULL;
7511 if (blob_type == MONO_TYPE_CLASS)
7512 type->data.klass = mono_defaults.object_class;
7513 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7514 /* For enums, we need to use the base type */
7515 type->type = MONO_TYPE_VALUETYPE;
7516 type->data.klass = mono_class_from_mono_type (real_type);
7517 } else
7518 type->data.klass = mono_class_from_mono_type (real_type);
7521 ICALL_EXPORT MonoObject*
7522 property_info_get_default_value (MonoReflectionProperty *property)
7524 MonoType blob_type;
7525 MonoProperty *prop = property->property;
7526 MonoType *type = get_property_type (prop);
7527 MonoDomain *domain = mono_object_domain (property);
7528 MonoTypeEnum def_type;
7529 const char *def_value;
7530 MonoObject *o;
7532 mono_class_init (prop->parent);
7534 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7535 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7537 def_value = mono_class_get_property_default_value (prop, &def_type);
7539 mono_type_from_blob_type (&blob_type, def_type, type);
7540 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7542 return o;
7545 ICALL_EXPORT MonoBoolean
7546 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7548 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7549 MonoCustomAttrInfo *cinfo;
7550 gboolean found;
7552 mono_class_init_or_throw (attr_class);
7554 cinfo = mono_reflection_get_custom_attrs_info (obj);
7555 if (!cinfo)
7556 return FALSE;
7557 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7558 if (!cinfo->cached)
7559 mono_custom_attrs_free (cinfo);
7560 return found;
7563 ICALL_EXPORT MonoArray*
7564 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7566 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7567 MonoArray *res;
7568 MonoError error;
7570 if (attr_class)
7571 mono_class_init_or_throw (attr_class);
7573 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7574 if (!mono_error_ok (&error))
7575 mono_error_raise_exception (&error);
7576 if (mono_loader_get_last_error ()) {
7577 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7578 g_assert_not_reached ();
7579 /* Not reached */
7580 return NULL;
7581 } else {
7582 return res;
7586 ICALL_EXPORT MonoString*
7587 ves_icall_Mono_Runtime_GetDisplayName (void)
7589 char *info;
7590 MonoString *display_name;
7592 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7593 display_name = mono_string_new (mono_domain_get (), info);
7594 g_free (info);
7595 return display_name;
7598 ICALL_EXPORT MonoString*
7599 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7601 MonoString *message;
7602 guint32 ret;
7603 gunichar2 buf[256];
7605 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7606 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7607 buf, 255, NULL);
7608 if (ret == 0) {
7609 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7610 } else {
7611 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7614 return message;
7617 const static guchar
7618 dbase64 [] = {
7619 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7620 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7621 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7622 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7623 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7624 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7625 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7626 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7629 static MonoArray *
7630 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7632 gint ignored;
7633 gint i;
7634 gunichar2 c;
7635 gunichar2 last, prev_last, prev2_last;
7636 gint olength;
7637 MonoArray *result;
7638 guchar *res_ptr;
7639 gint a [4], b [4];
7640 MonoException *exc;
7642 int havePadding = 0;
7643 ignored = 0;
7644 last = prev_last = 0, prev2_last = 0;
7645 for (i = 0; i < ilength; i++) {
7646 c = start [i];
7647 if (c >= sizeof (dbase64)) {
7648 exc = mono_exception_from_name_msg (mono_get_corlib (),
7649 "System", "FormatException",
7650 "Invalid character found.");
7651 mono_raise_exception (exc);
7652 } else if (isspace (c)) {
7653 ignored++;
7654 } else if (havePadding && c != '=') {
7655 exc = mono_exception_from_name_msg (mono_get_corlib (),
7656 "System", "FormatException",
7657 "Invalid character found.");
7658 mono_raise_exception (exc);
7659 } else {
7660 if (c == '=') havePadding = 1;
7661 prev2_last = prev_last;
7662 prev_last = last;
7663 last = c;
7667 olength = ilength - ignored;
7669 if (allowWhitespaceOnly && olength == 0) {
7670 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7673 if ((olength & 3) != 0 || olength <= 0) {
7674 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7675 "FormatException", "Invalid length.");
7676 mono_raise_exception (exc);
7679 if (prev2_last == '=') {
7680 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7681 mono_raise_exception (exc);
7684 olength = (olength * 3) / 4;
7685 if (last == '=')
7686 olength--;
7688 if (prev_last == '=')
7689 olength--;
7691 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7692 res_ptr = mono_array_addr (result, guchar, 0);
7693 for (i = 0; i < ilength; ) {
7694 int k;
7696 for (k = 0; k < 4 && i < ilength;) {
7697 c = start [i++];
7698 if (isspace (c))
7699 continue;
7701 a [k] = (guchar) c;
7702 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7703 exc = mono_exception_from_name_msg (mono_get_corlib (),
7704 "System", "FormatException",
7705 "Invalid character found.");
7706 mono_raise_exception (exc);
7708 k++;
7711 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7712 if (a [2] != '=')
7713 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7714 if (a [3] != '=')
7715 *res_ptr++ = (b [2] << 6) | b [3];
7717 while (i < ilength && isspace (start [i]))
7718 i++;
7721 return result;
7724 ICALL_EXPORT MonoArray *
7725 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7727 MONO_ARCH_SAVE_REGS;
7729 return base64_to_byte_array (mono_string_chars (str),
7730 mono_string_length (str), allowWhitespaceOnly);
7733 ICALL_EXPORT MonoArray *
7734 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7736 MONO_ARCH_SAVE_REGS;
7738 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7739 length, FALSE);
7742 #ifndef DISABLE_ICALL_TABLES
7744 #define ICALL_TYPE(id,name,first)
7745 #define ICALL(id,name,func) Icall_ ## id,
7747 enum {
7748 #include "metadata/icall-def.h"
7749 Icall_last
7752 #undef ICALL_TYPE
7753 #undef ICALL
7754 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7755 #define ICALL(id,name,func)
7756 enum {
7757 #include "metadata/icall-def.h"
7758 Icall_type_num
7761 #undef ICALL_TYPE
7762 #undef ICALL
7763 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7764 #define ICALL(id,name,func)
7765 typedef struct {
7766 guint16 first_icall;
7767 } IcallTypeDesc;
7769 static const IcallTypeDesc
7770 icall_type_descs [] = {
7771 #include "metadata/icall-def.h"
7772 {Icall_last}
7775 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7777 #undef ICALL_TYPE
7778 #define ICALL_TYPE(id,name,first)
7779 #undef ICALL
7781 #ifdef HAVE_ARRAY_ELEM_INIT
7782 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7783 #define MSGSTRFIELD1(line) str##line
7785 static const struct msgstrtn_t {
7786 #define ICALL(id,name,func)
7787 #undef ICALL_TYPE
7788 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7789 #include "metadata/icall-def.h"
7790 #undef ICALL_TYPE
7791 } icall_type_names_str = {
7792 #define ICALL_TYPE(id,name,first) (name),
7793 #include "metadata/icall-def.h"
7794 #undef ICALL_TYPE
7796 static const guint16 icall_type_names_idx [] = {
7797 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7798 #include "metadata/icall-def.h"
7799 #undef ICALL_TYPE
7801 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7803 static const struct msgstr_t {
7804 #undef ICALL
7805 #define ICALL_TYPE(id,name,first)
7806 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7807 #include "metadata/icall-def.h"
7808 #undef ICALL
7809 } icall_names_str = {
7810 #define ICALL(id,name,func) (name),
7811 #include "metadata/icall-def.h"
7812 #undef ICALL
7814 static const guint16 icall_names_idx [] = {
7815 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7816 #include "metadata/icall-def.h"
7817 #undef ICALL
7819 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7821 #else
7823 #undef ICALL_TYPE
7824 #undef ICALL
7825 #define ICALL_TYPE(id,name,first) name,
7826 #define ICALL(id,name,func)
7827 static const char* const
7828 icall_type_names [] = {
7829 #include "metadata/icall-def.h"
7830 NULL
7833 #define icall_type_name_get(id) (icall_type_names [(id)])
7835 #undef ICALL_TYPE
7836 #undef ICALL
7837 #define ICALL_TYPE(id,name,first)
7838 #define ICALL(id,name,func) name,
7839 static const char* const
7840 icall_names [] = {
7841 #include "metadata/icall-def.h"
7842 NULL
7844 #define icall_name_get(id) icall_names [(id)]
7846 #endif /* !HAVE_ARRAY_ELEM_INIT */
7848 #undef ICALL_TYPE
7849 #undef ICALL
7850 #define ICALL_TYPE(id,name,first)
7851 #define ICALL(id,name,func) func,
7852 static const gconstpointer
7853 icall_functions [] = {
7854 #include "metadata/icall-def.h"
7855 NULL
7858 #ifdef ENABLE_ICALL_SYMBOL_MAP
7859 #undef ICALL_TYPE
7860 #undef ICALL
7861 #define ICALL_TYPE(id,name,first)
7862 #define ICALL(id,name,func) #func,
7863 static const gconstpointer
7864 icall_symbols [] = {
7865 #include "metadata/icall-def.h"
7866 NULL
7868 #endif
7870 #endif /* DISABLE_ICALL_TABLES */
7872 static mono_mutex_t icall_mutex;
7873 static GHashTable *icall_hash = NULL;
7874 static GHashTable *jit_icall_hash_name = NULL;
7875 static GHashTable *jit_icall_hash_addr = NULL;
7877 void
7878 mono_icall_init (void)
7880 #ifndef DISABLE_ICALL_TABLES
7881 int i = 0;
7883 /* check that tables are sorted: disable in release */
7884 if (TRUE) {
7885 int j;
7886 const char *prev_class = NULL;
7887 const char *prev_method;
7889 for (i = 0; i < Icall_type_num; ++i) {
7890 const IcallTypeDesc *desc;
7891 int num_icalls;
7892 prev_method = NULL;
7893 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7894 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7895 prev_class = icall_type_name_get (i);
7896 desc = &icall_type_descs [i];
7897 num_icalls = icall_desc_num_icalls (desc);
7898 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7899 for (j = 0; j < num_icalls; ++j) {
7900 const char *methodn = icall_name_get (desc->first_icall + j);
7901 if (prev_method && strcmp (prev_method, methodn) >= 0)
7902 g_print ("method %s should come before method %s\n", methodn, prev_method);
7903 prev_method = methodn;
7907 #endif
7909 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7910 mono_mutex_init (&icall_mutex);
7913 static void
7914 mono_icall_lock (void)
7916 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7919 static void
7920 mono_icall_unlock (void)
7922 mono_locks_mutex_release (&icall_mutex, IcallLock);
7925 void
7926 mono_icall_cleanup (void)
7928 g_hash_table_destroy (icall_hash);
7929 g_hash_table_destroy (jit_icall_hash_name);
7930 g_hash_table_destroy (jit_icall_hash_addr);
7931 mono_mutex_destroy (&icall_mutex);
7934 void
7935 mono_add_internal_call (const char *name, gconstpointer method)
7937 mono_icall_lock ();
7939 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7941 mono_icall_unlock ();
7944 #ifndef DISABLE_ICALL_TABLES
7946 #ifdef HAVE_ARRAY_ELEM_INIT
7947 static int
7948 compare_method_imap (const void *key, const void *elem)
7950 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7951 return strcmp (key, method_name);
7954 static gpointer
7955 find_method_icall (const IcallTypeDesc *imap, const char *name)
7957 const guint16 *nameslot = mono_binary_search (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7958 if (!nameslot)
7959 return NULL;
7960 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7963 static int
7964 compare_class_imap (const void *key, const void *elem)
7966 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7967 return strcmp (key, class_name);
7970 static const IcallTypeDesc*
7971 find_class_icalls (const char *name)
7973 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7974 if (!nameslot)
7975 return NULL;
7976 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7979 #else /* HAVE_ARRAY_ELEM_INIT */
7981 static int
7982 compare_method_imap (const void *key, const void *elem)
7984 const char** method_name = (const char**)elem;
7985 return strcmp (key, *method_name);
7988 static gpointer
7989 find_method_icall (const IcallTypeDesc *imap, const char *name)
7991 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7992 if (!nameslot)
7993 return NULL;
7994 return (gpointer)icall_functions [(nameslot - icall_names)];
7997 static int
7998 compare_class_imap (const void *key, const void *elem)
8000 const char** class_name = (const char**)elem;
8001 return strcmp (key, *class_name);
8004 static const IcallTypeDesc*
8005 find_class_icalls (const char *name)
8007 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8008 if (!nameslot)
8009 return NULL;
8010 return &icall_type_descs [nameslot - icall_type_names];
8013 #endif /* HAVE_ARRAY_ELEM_INIT */
8015 #endif /* DISABLE_ICALL_TABLES */
8018 * we should probably export this as an helper (handle nested types).
8019 * Returns the number of chars written in buf.
8021 static int
8022 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8024 int nspacelen, cnamelen;
8025 nspacelen = strlen (klass->name_space);
8026 cnamelen = strlen (klass->name);
8027 if (nspacelen + cnamelen + 2 > bufsize)
8028 return 0;
8029 if (nspacelen) {
8030 memcpy (buf, klass->name_space, nspacelen);
8031 buf [nspacelen ++] = '.';
8033 memcpy (buf + nspacelen, klass->name, cnamelen);
8034 buf [nspacelen + cnamelen] = 0;
8035 return nspacelen + cnamelen;
8038 #ifdef DISABLE_ICALL_TABLES
8039 static void
8040 no_icall_table (void)
8042 g_assert_not_reached ();
8044 #endif
8046 gpointer
8047 mono_lookup_internal_call (MonoMethod *method)
8049 char *sigstart;
8050 char *tmpsig;
8051 char mname [2048];
8052 int typelen = 0, mlen, siglen;
8053 gpointer res;
8054 #ifndef DISABLE_ICALL_TABLES
8055 const IcallTypeDesc *imap = NULL;
8056 #endif
8058 g_assert (method != NULL);
8060 if (method->is_inflated)
8061 method = ((MonoMethodInflated *) method)->declaring;
8063 if (method->klass->nested_in) {
8064 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8065 if (!pos)
8066 return NULL;
8068 mname [pos++] = '/';
8069 mname [pos] = 0;
8071 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8072 if (!typelen)
8073 return NULL;
8075 typelen += pos;
8076 } else {
8077 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8078 if (!typelen)
8079 return NULL;
8082 #ifndef DISABLE_ICALL_TABLES
8083 imap = find_class_icalls (mname);
8084 #endif
8086 mname [typelen] = ':';
8087 mname [typelen + 1] = ':';
8089 mlen = strlen (method->name);
8090 memcpy (mname + typelen + 2, method->name, mlen);
8091 sigstart = mname + typelen + 2 + mlen;
8092 *sigstart = 0;
8094 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8095 siglen = strlen (tmpsig);
8096 if (typelen + mlen + siglen + 6 > sizeof (mname))
8097 return NULL;
8098 sigstart [0] = '(';
8099 memcpy (sigstart + 1, tmpsig, siglen);
8100 sigstart [siglen + 1] = ')';
8101 sigstart [siglen + 2] = 0;
8102 g_free (tmpsig);
8104 mono_icall_lock ();
8106 res = g_hash_table_lookup (icall_hash, mname);
8107 if (res) {
8108 mono_icall_unlock ();;
8109 return res;
8111 /* try without signature */
8112 *sigstart = 0;
8113 res = g_hash_table_lookup (icall_hash, mname);
8114 if (res) {
8115 mono_icall_unlock ();
8116 return res;
8119 #ifdef DISABLE_ICALL_TABLES
8120 mono_icall_unlock ();
8121 /* Fail only when the result is actually used */
8122 /* mono_marshal_get_native_wrapper () depends on this */
8123 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8124 return ves_icall_System_String_ctor_RedirectToCreateString;
8125 else
8126 return no_icall_table;
8127 #else
8128 /* it wasn't found in the static call tables */
8129 if (!imap) {
8130 mono_icall_unlock ();
8131 return NULL;
8133 res = find_method_icall (imap, sigstart - mlen);
8134 if (res) {
8135 mono_icall_unlock ();
8136 return res;
8138 /* try _with_ signature */
8139 *sigstart = '(';
8140 res = find_method_icall (imap, sigstart - mlen);
8141 if (res) {
8142 mono_icall_unlock ();
8143 return res;
8146 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8147 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8148 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8149 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8150 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");
8151 g_print ("If you see other errors or faults after this message they are probably related\n");
8152 g_print ("and you need to fix your mono install first.\n");
8154 mono_icall_unlock ();
8156 return NULL;
8157 #endif
8160 #ifdef ENABLE_ICALL_SYMBOL_MAP
8161 static int
8162 func_cmp (gconstpointer key, gconstpointer p)
8164 return (gsize)key - (gsize)*(gsize*)p;
8166 #endif
8169 * mono_lookup_icall_symbol:
8171 * Given the icall METHOD, returns its C symbol.
8173 const char*
8174 mono_lookup_icall_symbol (MonoMethod *m)
8176 #ifdef DISABLE_ICALL_TABLES
8177 g_assert_not_reached ();
8178 return NULL;
8179 #else
8180 #ifdef ENABLE_ICALL_SYMBOL_MAP
8181 gpointer func;
8182 int i;
8183 gpointer slot;
8184 static gconstpointer *functions_sorted;
8185 static const char**symbols_sorted;
8186 static gboolean inited;
8188 if (!inited) {
8189 gboolean changed;
8191 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8192 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8193 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8194 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8195 /* Bubble sort the two arrays */
8196 changed = TRUE;
8197 while (changed) {
8198 changed = FALSE;
8199 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8200 if (functions_sorted [i] > functions_sorted [i + 1]) {
8201 gconstpointer tmp;
8203 tmp = functions_sorted [i];
8204 functions_sorted [i] = functions_sorted [i + 1];
8205 functions_sorted [i + 1] = tmp;
8206 tmp = symbols_sorted [i];
8207 symbols_sorted [i] = symbols_sorted [i + 1];
8208 symbols_sorted [i + 1] = tmp;
8209 changed = TRUE;
8215 func = mono_lookup_internal_call (m);
8216 if (!func)
8217 return NULL;
8218 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8219 if (!slot)
8220 return NULL;
8221 g_assert (slot);
8222 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8223 #else
8224 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8225 g_assert_not_reached ();
8226 return 0;
8227 #endif
8228 #endif
8231 static MonoType*
8232 type_from_typename (char *typename)
8234 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8236 if (!strcmp (typename, "int"))
8237 klass = mono_defaults.int_class;
8238 else if (!strcmp (typename, "ptr"))
8239 klass = mono_defaults.int_class;
8240 else if (!strcmp (typename, "void"))
8241 klass = mono_defaults.void_class;
8242 else if (!strcmp (typename, "int32"))
8243 klass = mono_defaults.int32_class;
8244 else if (!strcmp (typename, "uint32"))
8245 klass = mono_defaults.uint32_class;
8246 else if (!strcmp (typename, "int8"))
8247 klass = mono_defaults.sbyte_class;
8248 else if (!strcmp (typename, "uint8"))
8249 klass = mono_defaults.byte_class;
8250 else if (!strcmp (typename, "int16"))
8251 klass = mono_defaults.int16_class;
8252 else if (!strcmp (typename, "uint16"))
8253 klass = mono_defaults.uint16_class;
8254 else if (!strcmp (typename, "long"))
8255 klass = mono_defaults.int64_class;
8256 else if (!strcmp (typename, "ulong"))
8257 klass = mono_defaults.uint64_class;
8258 else if (!strcmp (typename, "float"))
8259 klass = mono_defaults.single_class;
8260 else if (!strcmp (typename, "double"))
8261 klass = mono_defaults.double_class;
8262 else if (!strcmp (typename, "object"))
8263 klass = mono_defaults.object_class;
8264 else if (!strcmp (typename, "obj"))
8265 klass = mono_defaults.object_class;
8266 else if (!strcmp (typename, "string"))
8267 klass = mono_defaults.string_class;
8268 else if (!strcmp (typename, "bool"))
8269 klass = mono_defaults.boolean_class;
8270 else if (!strcmp (typename, "boolean"))
8271 klass = mono_defaults.boolean_class;
8272 else {
8273 g_error ("%s", typename);
8274 g_assert_not_reached ();
8276 return &klass->byval_arg;
8280 * LOCKING: Take the corlib image lock.
8282 MonoMethodSignature*
8283 mono_create_icall_signature (const char *sigstr)
8285 gchar **parts;
8286 int i, len;
8287 gchar **tmp;
8288 MonoMethodSignature *res, *res2;
8289 MonoImage *corlib = mono_defaults.corlib;
8291 mono_image_lock (corlib);
8292 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8293 mono_image_unlock (corlib);
8295 if (res)
8296 return res;
8298 parts = g_strsplit (sigstr, " ", 256);
8300 tmp = parts;
8301 len = 0;
8302 while (*tmp) {
8303 len ++;
8304 tmp ++;
8307 res = mono_metadata_signature_alloc (corlib, len - 1);
8308 res->pinvoke = 1;
8310 #ifdef HOST_WIN32
8312 * Under windows, the default pinvoke calling convention is STDCALL but
8313 * we need CDECL.
8315 res->call_convention = MONO_CALL_C;
8316 #endif
8318 res->ret = type_from_typename (parts [0]);
8319 for (i = 1; i < len; ++i) {
8320 res->params [i - 1] = type_from_typename (parts [i]);
8323 g_strfreev (parts);
8325 mono_image_lock (corlib);
8326 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8327 if (res2)
8328 res = res2; /*Value is allocated in the image pool*/
8329 else
8330 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8331 mono_image_unlock (corlib);
8333 return res;
8336 MonoJitICallInfo *
8337 mono_find_jit_icall_by_name (const char *name)
8339 MonoJitICallInfo *info;
8340 g_assert (jit_icall_hash_name);
8342 mono_icall_lock ();
8343 info = g_hash_table_lookup (jit_icall_hash_name, name);
8344 mono_icall_unlock ();
8345 return info;
8348 MonoJitICallInfo *
8349 mono_find_jit_icall_by_addr (gconstpointer addr)
8351 MonoJitICallInfo *info;
8352 g_assert (jit_icall_hash_addr);
8354 mono_icall_lock ();
8355 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8356 mono_icall_unlock ();
8358 return info;
8362 * mono_get_jit_icall_info:
8364 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8365 * caller should access it while holding the icall lock.
8367 GHashTable*
8368 mono_get_jit_icall_info (void)
8370 return jit_icall_hash_name;
8374 * mono_lookup_jit_icall_symbol:
8376 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8378 const char*
8379 mono_lookup_jit_icall_symbol (const char *name)
8381 MonoJitICallInfo *info;
8382 const char *res = NULL;
8384 mono_icall_lock ();
8385 info = g_hash_table_lookup (jit_icall_hash_name, name);
8386 if (info)
8387 res = info->c_symbol;
8388 mono_icall_unlock ();
8389 return res;
8392 void
8393 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8395 mono_icall_lock ();
8396 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8397 mono_icall_unlock ();
8400 MonoJitICallInfo *
8401 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8403 MonoJitICallInfo *info;
8405 g_assert (func);
8406 g_assert (name);
8408 mono_icall_lock ();
8410 if (!jit_icall_hash_name) {
8411 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8412 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8415 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8416 g_warning ("jit icall already defined \"%s\"\n", name);
8417 g_assert_not_reached ();
8420 info = g_new0 (MonoJitICallInfo, 1);
8422 info->name = name;
8423 info->func = func;
8424 info->sig = sig;
8425 info->c_symbol = c_symbol;
8427 if (is_save) {
8428 info->wrapper = func;
8429 } else {
8430 info->wrapper = NULL;
8433 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8434 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8436 mono_icall_unlock ();
8437 return info;
8440 MonoJitICallInfo *
8441 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8443 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);