2010-03-12 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / icall.c
blobd1f2bb0806f481647c130c7795941c23bc48031d
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)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 #include <config.h>
14 #include <glib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <ctype.h>
18 #ifdef HAVE_ALLOCA_H
19 #include <alloca.h>
20 #endif
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #if defined (HOST_WIN32)
28 #include <stdlib.h>
29 #endif
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/io-layer/io-layer.h>
71 #include <mono/utils/strtod.h>
72 #include <mono/utils/monobitset.h>
73 #include <mono/utils/mono-time.h>
74 #include <mono/utils/mono-proclib.h>
75 #include <mono/utils/mono-string.h>
76 #include <mono/utils/mono-error-internals.h>
77 #include <mono/utils/mono-mmap.h>
79 #if defined (HOST_WIN32)
80 #include <windows.h>
81 #include <shlobj.h>
82 #endif
83 #include "decimal.h"
85 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
87 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
89 static MonoArray*
90 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
92 /* This is an implementation of a growable pointer array that avoids doing memory allocations for small sizes.
93 * It works by allocating an initial small array on stack and only going to malloc'd memory if needed.
95 typedef struct {
96 void **data;
97 int size;
98 int capacity;
99 } MonoPtrArray;
101 #define MONO_PTR_ARRAY_MAX_ON_STACK (16)
103 #define mono_ptr_array_init(ARRAY, INITIAL_SIZE) do {\
104 (ARRAY).size = 0; \
105 (ARRAY).capacity = MAX (INITIAL_SIZE, MONO_PTR_ARRAY_MAX_ON_STACK); \
106 (ARRAY).data = INITIAL_SIZE > MONO_PTR_ARRAY_MAX_ON_STACK ? mono_gc_alloc_fixed (sizeof (void*) * INITIAL_SIZE, NULL) : g_newa (void*, MONO_PTR_ARRAY_MAX_ON_STACK); \
107 } while (0)
109 #define mono_ptr_array_destroy(ARRAY) do {\
110 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
111 mono_gc_free_fixed ((ARRAY).data); \
112 } while (0)
114 #define mono_ptr_array_append(ARRAY, VALUE) do { \
115 if ((ARRAY).size >= (ARRAY).capacity) {\
116 void *__tmp = mono_gc_alloc_fixed (sizeof (void*) * (ARRAY).capacity * 2, NULL); \
117 memcpy (__tmp, (ARRAY).data, (ARRAY).capacity * sizeof (void*)); \
118 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
119 mono_gc_free_fixed ((ARRAY).data); \
120 (ARRAY).data = __tmp; \
121 (ARRAY).capacity *= 2;\
123 ((ARRAY).data [(ARRAY).size++] = VALUE); \
124 } while (0)
126 #define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \
127 ((ARRAY).data [(IDX)] = VALUE); \
128 } while (0)
130 #define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)])
132 #define mono_ptr_array_size(ARRAY) ((ARRAY).size)
135 static inline MonoBoolean
136 is_generic_parameter (MonoType *type)
138 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
142 * We expect a pointer to a char, not a string
144 static gboolean
145 mono_double_ParseImpl (char *ptr, double *result)
147 gchar *endptr = NULL;
148 *result = 0.0;
150 MONO_ARCH_SAVE_REGS;
152 #ifdef __arm__
153 if (*ptr)
154 *result = strtod (ptr, &endptr);
155 #else
156 if (*ptr){
157 #ifdef _EGLIB_MAJOR
158 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
159 EnterCriticalSection (&mono_strtod_mutex);
160 *result = mono_strtod (ptr, &endptr);
161 LeaveCriticalSection (&mono_strtod_mutex);
162 #else
163 *result = mono_strtod (ptr, &endptr);
164 #endif
166 #endif
168 if (!*ptr || (endptr && *endptr))
169 return FALSE;
171 return TRUE;
174 static MonoObject *
175 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
177 MonoClass *ac;
178 MonoArray *ao;
179 gint32 esize;
180 gpointer *ea;
182 MONO_ARCH_SAVE_REGS;
184 ao = (MonoArray *)this;
185 ac = (MonoClass *)ao->obj.vtable->klass;
187 esize = mono_array_element_size (ac);
188 ea = (gpointer*)((char*)ao->vector + (pos * esize));
190 if (ac->element_class->valuetype)
191 return mono_value_box (this->vtable->domain, ac->element_class, ea);
192 else
193 return *ea;
196 static MonoObject *
197 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
199 MonoClass *ac, *ic;
200 MonoArray *ao, *io;
201 gint32 i, pos, *ind;
203 MONO_ARCH_SAVE_REGS;
205 MONO_CHECK_ARG_NULL (idxs);
207 io = (MonoArray *)idxs;
208 ic = (MonoClass *)io->obj.vtable->klass;
210 ao = (MonoArray *)this;
211 ac = (MonoClass *)ao->obj.vtable->klass;
213 g_assert (ic->rank == 1);
214 if (io->bounds != NULL || io->max_length != ac->rank)
215 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
217 ind = (gint32 *)io->vector;
219 if (ao->bounds == NULL) {
220 if (*ind < 0 || *ind >= ao->max_length)
221 mono_raise_exception (mono_get_exception_index_out_of_range ());
223 return ves_icall_System_Array_GetValueImpl (this, *ind);
226 for (i = 0; i < ac->rank; i++)
227 if ((ind [i] < ao->bounds [i].lower_bound) ||
228 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
229 mono_raise_exception (mono_get_exception_index_out_of_range ());
231 pos = ind [0] - ao->bounds [0].lower_bound;
232 for (i = 1; i < ac->rank; i++)
233 pos = pos*ao->bounds [i].length + ind [i] -
234 ao->bounds [i].lower_bound;
236 return ves_icall_System_Array_GetValueImpl (this, pos);
239 static void
240 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
242 MonoClass *ac, *vc, *ec;
243 gint32 esize, vsize;
244 gpointer *ea, *va;
245 int et, vt;
247 guint64 u64 = 0;
248 gint64 i64 = 0;
249 gdouble r64 = 0;
251 MONO_ARCH_SAVE_REGS;
253 if (value)
254 vc = value->vtable->klass;
255 else
256 vc = NULL;
258 ac = this->obj.vtable->klass;
259 ec = ac->element_class;
261 esize = mono_array_element_size (ac);
262 ea = (gpointer*)((char*)this->vector + (pos * esize));
263 va = (gpointer*)((char*)value + sizeof (MonoObject));
265 if (mono_class_is_nullable (ec)) {
266 mono_nullable_init ((guint8*)ea, value, ec);
267 return;
270 if (!value) {
271 memset (ea, 0, esize);
272 return;
275 #define NO_WIDENING_CONVERSION G_STMT_START{\
276 mono_raise_exception (mono_get_exception_argument ( \
277 "value", "not a widening conversion")); \
278 }G_STMT_END
280 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
281 if (esize < vsize + (extra)) \
282 mono_raise_exception (mono_get_exception_argument ( \
283 "value", "not a widening conversion")); \
284 }G_STMT_END
286 #define INVALID_CAST G_STMT_START{\
287 mono_raise_exception (mono_get_exception_invalid_cast ()); \
288 }G_STMT_END
290 /* Check element (destination) type. */
291 switch (ec->byval_arg.type) {
292 case MONO_TYPE_STRING:
293 switch (vc->byval_arg.type) {
294 case MONO_TYPE_STRING:
295 break;
296 default:
297 INVALID_CAST;
299 break;
300 case MONO_TYPE_BOOLEAN:
301 switch (vc->byval_arg.type) {
302 case MONO_TYPE_BOOLEAN:
303 break;
304 case MONO_TYPE_CHAR:
305 case MONO_TYPE_U1:
306 case MONO_TYPE_U2:
307 case MONO_TYPE_U4:
308 case MONO_TYPE_U8:
309 case MONO_TYPE_I1:
310 case MONO_TYPE_I2:
311 case MONO_TYPE_I4:
312 case MONO_TYPE_I8:
313 case MONO_TYPE_R4:
314 case MONO_TYPE_R8:
315 NO_WIDENING_CONVERSION;
316 default:
317 INVALID_CAST;
319 break;
322 if (!ec->valuetype) {
323 if (!mono_object_isinst (value, ec))
324 INVALID_CAST;
325 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
326 return;
329 if (mono_object_isinst (value, ec)) {
330 if (ec->has_references)
331 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
332 else
333 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
334 return;
337 if (!vc->valuetype)
338 INVALID_CAST;
340 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
342 et = ec->byval_arg.type;
343 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
344 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
346 vt = vc->byval_arg.type;
347 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
348 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
350 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
351 switch (vt) { \
352 case MONO_TYPE_U1: \
353 case MONO_TYPE_U2: \
354 case MONO_TYPE_U4: \
355 case MONO_TYPE_U8: \
356 case MONO_TYPE_CHAR: \
357 CHECK_WIDENING_CONVERSION(0); \
358 *(etype *) ea = (etype) u64; \
359 return; \
360 /* You can't assign a signed value to an unsigned array. */ \
361 case MONO_TYPE_I1: \
362 case MONO_TYPE_I2: \
363 case MONO_TYPE_I4: \
364 case MONO_TYPE_I8: \
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_SIGNED(etype) G_STMT_START{\
373 switch (vt) { \
374 case MONO_TYPE_I1: \
375 case MONO_TYPE_I2: \
376 case MONO_TYPE_I4: \
377 case MONO_TYPE_I8: \
378 CHECK_WIDENING_CONVERSION(0); \
379 *(etype *) ea = (etype) i64; \
380 return; \
381 /* You can assign an unsigned value to a signed array if the array's */ \
382 /* element size is larger than the value size. */ \
383 case MONO_TYPE_U1: \
384 case MONO_TYPE_U2: \
385 case MONO_TYPE_U4: \
386 case MONO_TYPE_U8: \
387 case MONO_TYPE_CHAR: \
388 CHECK_WIDENING_CONVERSION(1); \
389 *(etype *) ea = (etype) u64; \
390 return; \
391 /* You can't assign a floating point number to an integer array. */ \
392 case MONO_TYPE_R4: \
393 case MONO_TYPE_R8: \
394 NO_WIDENING_CONVERSION; \
396 }G_STMT_END
398 #define ASSIGN_REAL(etype) G_STMT_START{\
399 switch (vt) { \
400 case MONO_TYPE_R4: \
401 case MONO_TYPE_R8: \
402 CHECK_WIDENING_CONVERSION(0); \
403 *(etype *) ea = (etype) r64; \
404 return; \
405 /* All integer values fit into a floating point array, so we don't */ \
406 /* need to CHECK_WIDENING_CONVERSION here. */ \
407 case MONO_TYPE_I1: \
408 case MONO_TYPE_I2: \
409 case MONO_TYPE_I4: \
410 case MONO_TYPE_I8: \
411 *(etype *) ea = (etype) i64; \
412 return; \
413 case MONO_TYPE_U1: \
414 case MONO_TYPE_U2: \
415 case MONO_TYPE_U4: \
416 case MONO_TYPE_U8: \
417 case MONO_TYPE_CHAR: \
418 *(etype *) ea = (etype) u64; \
419 return; \
421 }G_STMT_END
423 switch (vt) {
424 case MONO_TYPE_U1:
425 u64 = *(guint8 *) va;
426 break;
427 case MONO_TYPE_U2:
428 u64 = *(guint16 *) va;
429 break;
430 case MONO_TYPE_U4:
431 u64 = *(guint32 *) va;
432 break;
433 case MONO_TYPE_U8:
434 u64 = *(guint64 *) va;
435 break;
436 case MONO_TYPE_I1:
437 i64 = *(gint8 *) va;
438 break;
439 case MONO_TYPE_I2:
440 i64 = *(gint16 *) va;
441 break;
442 case MONO_TYPE_I4:
443 i64 = *(gint32 *) va;
444 break;
445 case MONO_TYPE_I8:
446 i64 = *(gint64 *) va;
447 break;
448 case MONO_TYPE_R4:
449 r64 = *(gfloat *) va;
450 break;
451 case MONO_TYPE_R8:
452 r64 = *(gdouble *) va;
453 break;
454 case MONO_TYPE_CHAR:
455 u64 = *(guint16 *) va;
456 break;
457 case MONO_TYPE_BOOLEAN:
458 /* Boolean is only compatible with itself. */
459 switch (et) {
460 case MONO_TYPE_CHAR:
461 case MONO_TYPE_U1:
462 case MONO_TYPE_U2:
463 case MONO_TYPE_U4:
464 case MONO_TYPE_U8:
465 case MONO_TYPE_I1:
466 case MONO_TYPE_I2:
467 case MONO_TYPE_I4:
468 case MONO_TYPE_I8:
469 case MONO_TYPE_R4:
470 case MONO_TYPE_R8:
471 NO_WIDENING_CONVERSION;
472 default:
473 INVALID_CAST;
475 break;
478 /* If we can't do a direct copy, let's try a widening conversion. */
479 switch (et) {
480 case MONO_TYPE_CHAR:
481 ASSIGN_UNSIGNED (guint16);
482 case MONO_TYPE_U1:
483 ASSIGN_UNSIGNED (guint8);
484 case MONO_TYPE_U2:
485 ASSIGN_UNSIGNED (guint16);
486 case MONO_TYPE_U4:
487 ASSIGN_UNSIGNED (guint32);
488 case MONO_TYPE_U8:
489 ASSIGN_UNSIGNED (guint64);
490 case MONO_TYPE_I1:
491 ASSIGN_SIGNED (gint8);
492 case MONO_TYPE_I2:
493 ASSIGN_SIGNED (gint16);
494 case MONO_TYPE_I4:
495 ASSIGN_SIGNED (gint32);
496 case MONO_TYPE_I8:
497 ASSIGN_SIGNED (gint64);
498 case MONO_TYPE_R4:
499 ASSIGN_REAL (gfloat);
500 case MONO_TYPE_R8:
501 ASSIGN_REAL (gdouble);
504 INVALID_CAST;
505 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
506 return;
508 #undef INVALID_CAST
509 #undef NO_WIDENING_CONVERSION
510 #undef CHECK_WIDENING_CONVERSION
511 #undef ASSIGN_UNSIGNED
512 #undef ASSIGN_SIGNED
513 #undef ASSIGN_REAL
516 static void
517 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
518 MonoArray *idxs)
520 MonoClass *ac, *ic;
521 gint32 i, pos, *ind;
523 MONO_ARCH_SAVE_REGS;
525 MONO_CHECK_ARG_NULL (idxs);
527 ic = idxs->obj.vtable->klass;
528 ac = this->obj.vtable->klass;
530 g_assert (ic->rank == 1);
531 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
532 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
534 ind = (gint32 *)idxs->vector;
536 if (this->bounds == NULL) {
537 if (*ind < 0 || *ind >= this->max_length)
538 mono_raise_exception (mono_get_exception_index_out_of_range ());
540 ves_icall_System_Array_SetValueImpl (this, value, *ind);
541 return;
544 for (i = 0; i < ac->rank; i++)
545 if ((ind [i] < this->bounds [i].lower_bound) ||
546 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
547 mono_raise_exception (mono_get_exception_index_out_of_range ());
549 pos = ind [0] - this->bounds [0].lower_bound;
550 for (i = 1; i < ac->rank; i++)
551 pos = pos * this->bounds [i].length + ind [i] -
552 this->bounds [i].lower_bound;
554 ves_icall_System_Array_SetValueImpl (this, value, pos);
557 static MonoArray *
558 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
560 MonoClass *aklass;
561 MonoArray *array;
562 mono_array_size_t *sizes, i;
563 gboolean bounded = FALSE;
565 MONO_ARCH_SAVE_REGS;
567 MONO_CHECK_ARG_NULL (type);
568 MONO_CHECK_ARG_NULL (lengths);
570 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
571 if (bounds)
572 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
574 for (i = 0; i < mono_array_length (lengths); i++)
575 if (mono_array_get (lengths, gint32, i) < 0)
576 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
578 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
579 /* vectors are not the same as one dimensional arrays with no-zero bounds */
580 bounded = TRUE;
581 else
582 bounded = FALSE;
584 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
586 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
587 for (i = 0; i < aklass->rank; ++i) {
588 sizes [i] = mono_array_get (lengths, guint32, i);
589 if (bounds)
590 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
591 else
592 sizes [i + aklass->rank] = 0;
595 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
597 return array;
600 static MonoArray *
601 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
603 MonoClass *aklass;
604 MonoArray *array;
605 mono_array_size_t *sizes, i;
606 gboolean bounded = FALSE;
608 MONO_ARCH_SAVE_REGS;
610 MONO_CHECK_ARG_NULL (type);
611 MONO_CHECK_ARG_NULL (lengths);
613 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
614 if (bounds)
615 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
617 for (i = 0; i < mono_array_length (lengths); i++)
618 if ((mono_array_get (lengths, gint64, i) < 0) ||
619 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
620 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
622 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
623 /* vectors are not the same as one dimensional arrays with no-zero bounds */
624 bounded = TRUE;
625 else
626 bounded = FALSE;
628 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
630 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
631 for (i = 0; i < aklass->rank; ++i) {
632 sizes [i] = mono_array_get (lengths, guint64, i);
633 if (bounds)
634 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
635 else
636 sizes [i + aklass->rank] = 0;
639 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
641 return array;
644 static gint32
645 ves_icall_System_Array_GetRank (MonoObject *this)
647 MONO_ARCH_SAVE_REGS;
649 return this->vtable->klass->rank;
652 static gint32
653 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
655 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
656 mono_array_size_t length;
658 MONO_ARCH_SAVE_REGS;
660 if ((dimension < 0) || (dimension >= rank))
661 mono_raise_exception (mono_get_exception_index_out_of_range ());
663 if (this->bounds == NULL)
664 length = this->max_length;
665 else
666 length = this->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32)
670 mono_raise_exception (mono_get_exception_overflow ());
671 #endif
672 return length;
675 static gint64
676 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
678 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
680 MONO_ARCH_SAVE_REGS;
682 if ((dimension < 0) || (dimension >= rank))
683 mono_raise_exception (mono_get_exception_index_out_of_range ());
685 if (this->bounds == NULL)
686 return this->max_length;
688 return this->bounds [dimension].length;
691 static gint32
692 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
694 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
696 MONO_ARCH_SAVE_REGS;
698 if ((dimension < 0) || (dimension >= rank))
699 mono_raise_exception (mono_get_exception_index_out_of_range ());
701 if (this->bounds == NULL)
702 return 0;
704 return this->bounds [dimension].lower_bound;
707 static void
708 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
710 int sz = mono_array_element_size (mono_object_class (arr));
711 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
714 static gboolean
715 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
717 int element_size;
718 void * dest_addr;
719 void * source_addr;
720 MonoClass *src_class;
721 MonoClass *dest_class;
722 int i;
724 MONO_ARCH_SAVE_REGS;
726 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
727 return FALSE;
729 if (source->bounds || dest->bounds)
730 return FALSE;
732 /* there's no integer overflow since mono_array_length returns an unsigned integer */
733 if ((dest_idx + length > mono_array_length (dest)) ||
734 (source_idx + length > mono_array_length (source)))
735 return FALSE;
737 src_class = source->obj.vtable->klass->element_class;
738 dest_class = dest->obj.vtable->klass->element_class;
741 * Handle common cases.
744 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
745 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
746 int has_refs = dest_class->has_references;
747 for (i = source_idx; i < source_idx + length; ++i) {
748 MonoObject *elem = mono_array_get (source, MonoObject*, i);
749 if (elem && !mono_object_isinst (elem, dest_class))
750 return FALSE;
753 element_size = mono_array_element_size (dest->obj.vtable->klass);
754 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
755 for (i = 0; i < length; ++i) {
756 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
757 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
758 if (!elem)
759 continue;
760 if (has_refs)
761 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
762 else
763 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
765 return TRUE;
768 /* Check if we're copying a char[] <==> (u)short[] */
769 if (src_class != dest_class) {
770 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
771 return FALSE;
773 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
775 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
776 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
777 for (i = source_idx; i < source_idx + length; ++i) {
778 MonoObject *elem = mono_array_get (source, MonoObject*, i);
779 if (elem && !mono_object_isinst (elem, dest_class))
780 return FALSE;
782 else
783 return FALSE;
786 if (dest_class->valuetype) {
787 element_size = mono_array_element_size (source->obj.vtable->klass);
788 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
789 if (dest_class->has_references) {
790 mono_value_copy_array (dest, dest_idx, source_addr, length);
791 } else {
792 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
793 memmove (dest_addr, source_addr, element_size * length);
795 } else {
796 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
799 return TRUE;
802 static void
803 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
805 MonoClass *ac;
806 MonoArray *ao;
807 gint32 esize;
808 gpointer *ea;
810 MONO_ARCH_SAVE_REGS;
812 ao = (MonoArray *)this;
813 ac = (MonoClass *)ao->obj.vtable->klass;
815 esize = mono_array_element_size (ac);
816 ea = (gpointer*)((char*)ao->vector + (pos * esize));
818 memcpy (value, ea, esize);
821 static void
822 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
824 MonoClass *ac, *ec;
825 MonoArray *ao;
826 gint32 esize;
827 gpointer *ea;
829 MONO_ARCH_SAVE_REGS;
831 ao = (MonoArray *)this;
832 ac = (MonoClass *)ao->obj.vtable->klass;
833 ec = ac->element_class;
835 esize = mono_array_element_size (ac);
836 ea = (gpointer*)((char*)ao->vector + (pos * esize));
838 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
839 g_assert (esize == sizeof (gpointer));
840 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
841 } else {
842 g_assert (ec->inited);
843 g_assert (esize == mono_class_value_size (ec, NULL));
844 if (ec->has_references)
845 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
846 else
847 memcpy (ea, value, esize);
851 static void
852 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
854 MonoClass *klass = array->obj.vtable->klass;
855 guint32 size = mono_array_element_size (klass);
856 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
857 int align;
858 const char *field_data;
860 if (MONO_TYPE_IS_REFERENCE (type) ||
861 (type->type == MONO_TYPE_VALUETYPE &&
862 (!mono_type_get_class (type) ||
863 mono_type_get_class (type)->has_references))) {
864 MonoException *exc = mono_get_exception_argument("array",
865 "Cannot initialize array containing references");
866 mono_raise_exception (exc);
869 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
870 MonoException *exc = mono_get_exception_argument("field_handle",
871 "Field doesn't have an RVA");
872 mono_raise_exception (exc);
875 size *= array->max_length;
876 field_data = mono_field_get_data (field_handle);
878 if (size > mono_type_size (field_handle->type, &align)) {
879 MonoException *exc = mono_get_exception_argument("field_handle",
880 "Field not large enough to fill array");
881 mono_raise_exception (exc);
884 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
885 #define SWAP(n) {\
886 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
887 guint ## n *src = (guint ## n *) field_data; \
888 guint ## n *end = (guint ## n *)((char*)src + size); \
890 for (; src < end; data++, src++) { \
891 *data = read ## n (src); \
895 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
897 switch (type->type) {
898 case MONO_TYPE_CHAR:
899 case MONO_TYPE_I2:
900 case MONO_TYPE_U2:
901 SWAP (16);
902 break;
903 case MONO_TYPE_I4:
904 case MONO_TYPE_U4:
905 case MONO_TYPE_R4:
906 SWAP (32);
907 break;
908 case MONO_TYPE_I8:
909 case MONO_TYPE_U8:
910 case MONO_TYPE_R8:
911 SWAP (64);
912 break;
913 default:
914 memcpy (mono_array_addr (array, char, 0), field_data, size);
915 break;
917 #else
918 memcpy (mono_array_addr (array, char, 0), field_data, size);
919 #ifdef ARM_FPU_FPA
920 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
921 gint i;
922 double tmp;
923 double *data = (double*)mono_array_addr (array, double, 0);
925 for (i = 0; i < size; i++, data++) {
926 readr8 (data, &tmp);
927 *data = tmp;
930 #endif
931 #endif
934 static gint
935 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
937 MONO_ARCH_SAVE_REGS;
939 return offsetof (MonoString, chars);
942 static MonoObject *
943 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
945 MONO_ARCH_SAVE_REGS;
947 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
948 return obj;
949 else
950 return mono_object_clone (obj);
953 static void
954 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
956 MonoClass *klass;
957 MonoVTable *vtable;
959 MONO_CHECK_ARG_NULL (handle);
961 klass = mono_class_from_mono_type (handle);
962 MONO_CHECK_ARG (handle, klass);
964 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
966 /* This will call the type constructor */
967 mono_runtime_class_init (vtable);
970 static void
971 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
973 MONO_ARCH_SAVE_REGS;
975 mono_image_check_for_module_cctor (image);
976 if (image->has_module_cctor) {
977 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
978 /*It's fine to raise the exception here*/
979 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
983 static MonoBoolean
984 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
986 guint8 *stack_addr;
987 guint8 *current;
988 size_t stack_size;
989 /* later make this configurable and per-arch */
990 int min_size = 4096 * 4 * sizeof (void*);
991 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
992 /* if we have no info we are optimistic and assume there is enough room */
993 if (!stack_addr)
994 return TRUE;
995 current = (guint8 *)&stack_addr;
996 if (current > stack_addr) {
997 if ((current - stack_addr) < min_size)
998 return FALSE;
999 } else {
1000 if (current - (stack_addr - stack_size) < min_size)
1001 return FALSE;
1003 return TRUE;
1006 static MonoObject *
1007 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
1009 MONO_ARCH_SAVE_REGS;
1011 return mono_object_clone (this);
1014 static gint32
1015 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
1017 MonoClass *klass;
1018 MonoObject **values = NULL;
1019 MonoObject *o;
1020 int count = 0;
1021 gint32 result = 0;
1022 MonoClassField* field;
1023 gpointer iter;
1025 MONO_ARCH_SAVE_REGS;
1027 klass = mono_object_class (this);
1029 if (mono_class_num_fields (klass) == 0)
1030 return mono_object_hash (this);
1033 * Compute the starting value of the hashcode for fields of primitive
1034 * types, and return the remaining fields in an array to the managed side.
1035 * This way, we can avoid costly reflection operations in managed code.
1037 iter = NULL;
1038 while ((field = mono_class_get_fields (klass, &iter))) {
1039 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1040 continue;
1041 if (mono_field_is_deleted (field))
1042 continue;
1043 /* FIXME: Add more types */
1044 switch (field->type->type) {
1045 case MONO_TYPE_I4:
1046 result ^= *(gint32*)((guint8*)this + field->offset);
1047 break;
1048 case MONO_TYPE_STRING: {
1049 MonoString *s;
1050 s = *(MonoString**)((guint8*)this + field->offset);
1051 if (s != NULL)
1052 result ^= mono_string_hash (s);
1053 break;
1055 default:
1056 if (!values)
1057 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1058 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1059 values [count++] = o;
1063 if (values) {
1064 int i;
1065 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1066 for (i = 0; i < count; ++i)
1067 mono_array_setref (*fields, i, values [i]);
1068 } else {
1069 *fields = NULL;
1071 return result;
1074 static MonoBoolean
1075 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1077 MonoClass *klass;
1078 MonoObject **values = NULL;
1079 MonoObject *o;
1080 MonoClassField* field;
1081 gpointer iter;
1082 int count = 0;
1084 MONO_ARCH_SAVE_REGS;
1086 MONO_CHECK_ARG_NULL (that);
1088 if (this->vtable != that->vtable)
1089 return FALSE;
1091 klass = mono_object_class (this);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1100 * managed code.
1102 *fields = NULL;
1103 iter = NULL;
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1106 continue;
1107 if (mono_field_is_deleted (field))
1108 continue;
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1111 case MONO_TYPE_U1:
1112 case MONO_TYPE_I1:
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1115 return FALSE;
1116 break;
1117 case MONO_TYPE_U2:
1118 case MONO_TYPE_I2:
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1121 return FALSE;
1122 break;
1123 case MONO_TYPE_U4:
1124 case MONO_TYPE_I4:
1125 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1126 return FALSE;
1127 break;
1128 case MONO_TYPE_U8:
1129 case MONO_TYPE_I8:
1130 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1131 return FALSE;
1132 break;
1133 case MONO_TYPE_R4:
1134 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1135 return FALSE;
1136 break;
1137 case MONO_TYPE_R8:
1138 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1139 return FALSE;
1140 break;
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1148 if (s1 == s2)
1149 break;
1150 if ((s1 == NULL) || (s2 == NULL))
1151 return FALSE;
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1154 if (s1len != s2len)
1155 return FALSE;
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1158 return FALSE;
1159 break;
1161 default:
1162 if (!values)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1165 values [count++] = o;
1166 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1167 values [count++] = o;
1170 if (klass->enumtype)
1171 /* enums only have one non-static field */
1172 break;
1175 if (values) {
1176 int i;
1177 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1178 for (i = 0; i < count; ++i)
1179 mono_array_setref (*fields, i, values [i]);
1180 return FALSE;
1181 } else {
1182 return TRUE;
1186 static MonoReflectionType *
1187 ves_icall_System_Object_GetType (MonoObject *obj)
1189 MONO_ARCH_SAVE_REGS;
1191 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1192 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1193 else
1194 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1197 static void
1198 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1200 MONO_ARCH_SAVE_REGS;
1202 mtype->type = &obj->vtable->klass->byval_arg;
1203 g_assert (mtype->type->type);
1206 static gint32
1207 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1209 MONO_ARCH_SAVE_REGS;
1211 MONO_CHECK_ARG_NULL (obj);
1213 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1216 static gint32
1217 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1218 MonoReflectionMethod *method,
1219 MonoArray *opt_param_types)
1221 MONO_ARCH_SAVE_REGS;
1223 MONO_CHECK_ARG_NULL (method);
1225 return mono_image_create_method_token (
1226 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1229 static void
1230 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1232 MONO_ARCH_SAVE_REGS;
1234 mono_image_create_pefile (mb, file);
1237 static void
1238 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1240 MONO_ARCH_SAVE_REGS;
1242 mono_image_build_metadata (mb);
1245 static void
1246 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1248 MONO_ARCH_SAVE_REGS;
1250 mono_image_register_token (mb->dynamic_image, token, obj);
1253 static gboolean
1254 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1256 MonoMethod **dest = data;
1258 /* skip unmanaged frames */
1259 if (!managed)
1260 return FALSE;
1262 if (m == *dest) {
1263 *dest = NULL;
1264 return FALSE;
1266 if (!(*dest)) {
1267 *dest = m;
1268 return TRUE;
1270 return FALSE;
1273 static gboolean
1274 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1276 MonoMethod **dest = data;
1278 /* skip unmanaged frames */
1279 if (!managed)
1280 return FALSE;
1282 if (!(*dest)) {
1283 if (!strcmp (m->klass->name_space, "System.Reflection"))
1284 return FALSE;
1285 *dest = m;
1286 return TRUE;
1288 return FALSE;
1291 static gboolean
1292 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1294 MonoMethod **dest = data;
1296 /* skip unmanaged frames */
1297 if (!managed)
1298 return FALSE;
1300 if (m->wrapper_type != MONO_WRAPPER_NONE)
1301 return FALSE;
1303 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1304 return FALSE;
1306 if (m == *dest) {
1307 *dest = NULL;
1308 return FALSE;
1310 if (!(*dest)) {
1311 *dest = m;
1312 return TRUE;
1314 return FALSE;
1317 static MonoReflectionType *
1318 type_from_name (const char *str, MonoBoolean ignoreCase)
1320 MonoType *type = NULL;
1321 MonoAssembly *assembly = NULL;
1322 MonoTypeNameParse info;
1323 char *temp_str = g_strdup (str);
1324 gboolean type_resolve = FALSE;
1326 MONO_ARCH_SAVE_REGS;
1328 /* mono_reflection_parse_type() mangles the string */
1329 if (!mono_reflection_parse_type (temp_str, &info)) {
1330 mono_reflection_free_type_info (&info);
1331 g_free (temp_str);
1332 return NULL;
1335 if (info.assembly.name) {
1336 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1337 } else {
1338 MonoMethod *m = mono_method_get_last_managed ();
1339 MonoMethod *dest = m;
1341 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1342 if (!dest)
1343 dest = m;
1346 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1347 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1348 * to crash. This only seems to happen in some strange remoting
1349 * scenarios and I was unable to figure out what's happening there.
1350 * Dec 10, 2005 - Martin.
1353 if (dest) {
1354 assembly = dest->klass->image->assembly;
1355 type_resolve = TRUE;
1356 } else {
1357 g_warning (G_STRLOC);
1361 if (assembly) {
1362 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1363 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1366 if (!info.assembly.name && !type) /* try mscorlib */
1367 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1369 if (assembly && !type && type_resolve) {
1370 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1371 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1374 mono_reflection_free_type_info (&info);
1375 g_free (temp_str);
1377 if (!type)
1378 return NULL;
1380 return mono_type_get_object (mono_domain_get (), type);
1383 #ifdef UNUSED
1384 MonoReflectionType *
1385 mono_type_get (const char *str)
1387 char *copy = g_strdup (str);
1388 MonoReflectionType *type = type_from_name (copy, FALSE);
1390 g_free (copy);
1391 return type;
1393 #endif
1395 static MonoReflectionType*
1396 ves_icall_type_from_name (MonoString *name,
1397 MonoBoolean throwOnError,
1398 MonoBoolean ignoreCase)
1400 char *str = mono_string_to_utf8 (name);
1401 MonoReflectionType *type;
1403 type = type_from_name (str, ignoreCase);
1404 g_free (str);
1405 if (type == NULL){
1406 MonoException *e = NULL;
1408 if (throwOnError)
1409 e = mono_get_exception_type_load (name, NULL);
1411 mono_loader_clear_error ();
1412 if (e != NULL)
1413 mono_raise_exception (e);
1416 return type;
1420 static MonoReflectionType*
1421 ves_icall_type_from_handle (MonoType *handle)
1423 MonoDomain *domain = mono_domain_get ();
1424 MonoClass *klass = mono_class_from_mono_type (handle);
1426 MONO_ARCH_SAVE_REGS;
1428 mono_class_init (klass);
1429 return mono_type_get_object (domain, handle);
1432 static MonoBoolean
1433 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1435 MONO_ARCH_SAVE_REGS;
1437 if (c && type->type && c->type)
1438 return mono_metadata_type_equal (type->type, c->type);
1439 else
1440 return (type == c) ? TRUE : FALSE;
1443 /* System.TypeCode */
1444 typedef enum {
1445 TYPECODE_EMPTY,
1446 TYPECODE_OBJECT,
1447 TYPECODE_DBNULL,
1448 TYPECODE_BOOLEAN,
1449 TYPECODE_CHAR,
1450 TYPECODE_SBYTE,
1451 TYPECODE_BYTE,
1452 TYPECODE_INT16,
1453 TYPECODE_UINT16,
1454 TYPECODE_INT32,
1455 TYPECODE_UINT32,
1456 TYPECODE_INT64,
1457 TYPECODE_UINT64,
1458 TYPECODE_SINGLE,
1459 TYPECODE_DOUBLE,
1460 TYPECODE_DECIMAL,
1461 TYPECODE_DATETIME,
1462 TYPECODE_STRING = 18
1463 } TypeCode;
1465 static guint32
1466 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1468 int t = type->type->type;
1470 MONO_ARCH_SAVE_REGS;
1472 if (type->type->byref)
1473 return TYPECODE_OBJECT;
1475 handle_enum:
1476 switch (t) {
1477 case MONO_TYPE_VOID:
1478 return TYPECODE_OBJECT;
1479 case MONO_TYPE_BOOLEAN:
1480 return TYPECODE_BOOLEAN;
1481 case MONO_TYPE_U1:
1482 return TYPECODE_BYTE;
1483 case MONO_TYPE_I1:
1484 return TYPECODE_SBYTE;
1485 case MONO_TYPE_U2:
1486 return TYPECODE_UINT16;
1487 case MONO_TYPE_I2:
1488 return TYPECODE_INT16;
1489 case MONO_TYPE_CHAR:
1490 return TYPECODE_CHAR;
1491 case MONO_TYPE_PTR:
1492 case MONO_TYPE_U:
1493 case MONO_TYPE_I:
1494 return TYPECODE_OBJECT;
1495 case MONO_TYPE_U4:
1496 return TYPECODE_UINT32;
1497 case MONO_TYPE_I4:
1498 return TYPECODE_INT32;
1499 case MONO_TYPE_U8:
1500 return TYPECODE_UINT64;
1501 case MONO_TYPE_I8:
1502 return TYPECODE_INT64;
1503 case MONO_TYPE_R4:
1504 return TYPECODE_SINGLE;
1505 case MONO_TYPE_R8:
1506 return TYPECODE_DOUBLE;
1507 case MONO_TYPE_VALUETYPE:
1508 if (type->type->data.klass->enumtype) {
1509 t = mono_class_enum_basetype (type->type->data.klass)->type;
1510 goto handle_enum;
1511 } else {
1512 MonoClass *k = type->type->data.klass;
1513 if (strcmp (k->name_space, "System") == 0) {
1514 if (strcmp (k->name, "Decimal") == 0)
1515 return TYPECODE_DECIMAL;
1516 else if (strcmp (k->name, "DateTime") == 0)
1517 return TYPECODE_DATETIME;
1520 return TYPECODE_OBJECT;
1521 case MONO_TYPE_STRING:
1522 return TYPECODE_STRING;
1523 case MONO_TYPE_SZARRAY:
1524 case MONO_TYPE_ARRAY:
1525 case MONO_TYPE_OBJECT:
1526 case MONO_TYPE_VAR:
1527 case MONO_TYPE_MVAR:
1528 case MONO_TYPE_TYPEDBYREF:
1529 return TYPECODE_OBJECT;
1530 case MONO_TYPE_CLASS:
1532 MonoClass *k = type->type->data.klass;
1533 if (strcmp (k->name_space, "System") == 0) {
1534 if (strcmp (k->name, "DBNull") == 0)
1535 return TYPECODE_DBNULL;
1538 return TYPECODE_OBJECT;
1539 case MONO_TYPE_GENERICINST:
1540 return TYPECODE_OBJECT;
1541 default:
1542 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1544 return 0;
1547 static guint32
1548 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1550 MonoDomain *domain;
1551 MonoClass *klass;
1552 MonoClass *klassc;
1554 MONO_ARCH_SAVE_REGS;
1556 g_assert (type != NULL);
1558 domain = ((MonoObject *)type)->vtable->domain;
1560 if (!c) /* FIXME: dont know what do do here */
1561 return 0;
1563 klass = mono_class_from_mono_type (type->type);
1564 klassc = mono_class_from_mono_type (c->type);
1566 if (type->type->byref)
1567 return klassc == mono_defaults.object_class;
1569 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1572 static guint32
1573 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1575 MonoDomain *domain;
1576 MonoClass *klass;
1577 MonoClass *klassc;
1579 MONO_ARCH_SAVE_REGS;
1581 g_assert (type != NULL);
1583 domain = ((MonoObject *)type)->vtable->domain;
1585 klass = mono_class_from_mono_type (type->type);
1586 klassc = mono_class_from_mono_type (c->type);
1588 if (type->type->byref && !c->type->byref)
1589 return FALSE;
1591 return mono_class_is_assignable_from (klass, klassc);
1594 static guint32
1595 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1597 MonoClass *klass = mono_class_from_mono_type (type->type);
1598 return mono_object_isinst (obj, klass) != NULL;
1601 static guint32
1602 ves_icall_get_attributes (MonoReflectionType *type)
1604 MonoClass *klass = mono_class_from_mono_type (type->type);
1606 MONO_ARCH_SAVE_REGS;
1608 return klass->flags;
1611 static MonoReflectionMarshal*
1612 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1614 MonoClass *klass = field->field->parent;
1615 MonoMarshalType *info;
1616 int i;
1618 if (klass->generic_container ||
1619 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1620 return NULL;
1622 info = mono_marshal_load_type_info (klass);
1624 for (i = 0; i < info->num_fields; ++i) {
1625 if (info->fields [i].field == field->field) {
1626 if (!info->fields [i].mspec)
1627 return NULL;
1628 else
1629 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1633 return NULL;
1636 static MonoReflectionField*
1637 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1639 gboolean found = FALSE;
1640 MonoClass *klass;
1641 MonoClass *k;
1643 g_assert (handle);
1645 if (!type) {
1646 klass = handle->parent;
1647 } else {
1648 klass = mono_class_from_mono_type (type);
1650 /* Check that the field belongs to the class */
1651 for (k = klass; k; k = k->parent) {
1652 if (k == handle->parent) {
1653 found = TRUE;
1654 break;
1658 if (!found)
1659 /* The managed code will throw the exception */
1660 return NULL;
1663 return mono_field_get_object (mono_domain_get (), klass, handle);
1666 static MonoArray*
1667 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1669 MonoType *type = field->field->type;
1671 return type_array_from_modifiers (field->field->parent->image, type, optional);
1674 static void
1675 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1677 MonoDomain *domain = mono_domain_get ();
1678 MonoMethodSignature* sig;
1679 MONO_ARCH_SAVE_REGS;
1681 sig = mono_method_signature (method);
1682 if (!sig) {
1683 g_assert (mono_loader_get_last_error ());
1684 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1687 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1688 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1689 info->attrs = method->flags;
1690 info->implattrs = method->iflags;
1691 if (sig->call_convention == MONO_CALL_DEFAULT)
1692 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1693 else {
1694 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1695 info->callconv = 2;
1696 else
1697 info->callconv = 1;
1699 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1702 static MonoArray*
1703 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1705 MonoDomain *domain = mono_domain_get ();
1707 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1710 static MonoReflectionMarshal*
1711 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1713 MonoDomain *domain = mono_domain_get ();
1714 MonoReflectionMarshal* res = NULL;
1715 MonoMarshalSpec **mspecs;
1716 int i;
1718 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1719 mono_method_get_marshal_info (method, mspecs);
1721 if (mspecs [0])
1722 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1724 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1725 if (mspecs [i])
1726 mono_metadata_free_marshal_spec (mspecs [i]);
1727 g_free (mspecs);
1729 return res;
1732 static gint32
1733 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1735 return field->field->offset - sizeof (MonoObject);
1738 static MonoReflectionType*
1739 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1741 MonoClass *parent;
1742 MONO_ARCH_SAVE_REGS;
1744 parent = declaring? field->field->parent: field->klass;
1746 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1749 static MonoObject *
1750 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1752 MonoObject *o;
1753 MonoClassField *cf = field->field;
1754 MonoClass *klass;
1755 MonoVTable *vtable;
1756 MonoType *t;
1757 MonoDomain *domain = mono_object_domain (field);
1758 gchar *v;
1759 gboolean is_static = FALSE;
1760 gboolean is_ref = FALSE;
1762 MONO_ARCH_SAVE_REGS;
1764 if (field->klass->image->assembly->ref_only)
1765 mono_raise_exception (mono_get_exception_invalid_operation (
1766 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1768 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1769 mono_security_core_clr_ensure_reflection_access_field (cf);
1771 mono_class_init (field->klass);
1773 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1774 is_static = TRUE;
1776 if (obj && !is_static) {
1777 /* Check that the field belongs to the object */
1778 gboolean found = FALSE;
1779 MonoClass *k;
1781 for (k = obj->vtable->klass; k; k = k->parent) {
1782 if (k == cf->parent) {
1783 found = TRUE;
1784 break;
1788 if (!found) {
1789 char *msg = g_strdup_printf ("Field '%s' defined on type '%s' is not a field on the target object which is of type '%s'.", mono_field_get_name (cf), cf->parent->name, obj->vtable->klass->name);
1790 MonoException *ex = mono_get_exception_argument (NULL, msg);
1791 g_free (msg);
1792 mono_raise_exception (ex);
1796 t = mono_type_get_underlying_type (cf->type);
1797 switch (t->type) {
1798 case MONO_TYPE_STRING:
1799 case MONO_TYPE_OBJECT:
1800 case MONO_TYPE_CLASS:
1801 case MONO_TYPE_ARRAY:
1802 case MONO_TYPE_SZARRAY:
1803 is_ref = TRUE;
1804 break;
1805 case MONO_TYPE_U1:
1806 case MONO_TYPE_I1:
1807 case MONO_TYPE_BOOLEAN:
1808 case MONO_TYPE_U2:
1809 case MONO_TYPE_I2:
1810 case MONO_TYPE_CHAR:
1811 case MONO_TYPE_U:
1812 case MONO_TYPE_I:
1813 case MONO_TYPE_U4:
1814 case MONO_TYPE_I4:
1815 case MONO_TYPE_R4:
1816 case MONO_TYPE_U8:
1817 case MONO_TYPE_I8:
1818 case MONO_TYPE_R8:
1819 case MONO_TYPE_VALUETYPE:
1820 is_ref = t->byref;
1821 break;
1822 case MONO_TYPE_GENERICINST:
1823 if (mono_type_generic_inst_is_valuetype (t)) {
1824 is_ref = t->byref;
1825 } else {
1826 is_ref = TRUE;
1828 break;
1829 default:
1830 g_error ("type 0x%x not handled in "
1831 "ves_icall_Monofield_GetValue", t->type);
1832 return NULL;
1835 vtable = NULL;
1836 if (is_static) {
1837 vtable = mono_class_vtable_full (domain, cf->parent, TRUE);
1838 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1839 mono_runtime_class_init (vtable);
1842 if (is_ref) {
1843 if (is_static) {
1844 mono_field_static_get_value (vtable, cf, &o);
1845 } else {
1846 mono_field_get_value (obj, cf, &o);
1848 return o;
1851 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1852 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1853 guint8 *buf;
1855 /* Convert the Nullable structure into a boxed vtype */
1856 if (is_static)
1857 buf = (guint8*)vtable->data + cf->offset;
1858 else
1859 buf = (guint8*)obj + cf->offset;
1861 return mono_nullable_box (buf, nklass);
1864 /* boxed value type */
1865 klass = mono_class_from_mono_type (cf->type);
1866 o = mono_object_new (domain, klass);
1867 v = ((gchar *) o) + sizeof (MonoObject);
1868 if (is_static) {
1869 mono_field_static_get_value (vtable, cf, v);
1870 } else {
1871 mono_field_get_value (obj, cf, v);
1874 return o;
1877 static void
1878 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1880 MonoClassField *cf = field->field;
1881 gchar *v;
1883 MONO_ARCH_SAVE_REGS;
1885 if (field->klass->image->assembly->ref_only)
1886 mono_raise_exception (mono_get_exception_invalid_operation (
1887 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1889 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1890 mono_security_core_clr_ensure_reflection_access_field (cf);
1892 v = (gchar *) value;
1893 if (!cf->type->byref) {
1894 switch (cf->type->type) {
1895 case MONO_TYPE_U1:
1896 case MONO_TYPE_I1:
1897 case MONO_TYPE_BOOLEAN:
1898 case MONO_TYPE_U2:
1899 case MONO_TYPE_I2:
1900 case MONO_TYPE_CHAR:
1901 case MONO_TYPE_U:
1902 case MONO_TYPE_I:
1903 case MONO_TYPE_U4:
1904 case MONO_TYPE_I4:
1905 case MONO_TYPE_R4:
1906 case MONO_TYPE_U8:
1907 case MONO_TYPE_I8:
1908 case MONO_TYPE_R8:
1909 case MONO_TYPE_VALUETYPE:
1910 if (v != NULL)
1911 v += sizeof (MonoObject);
1912 break;
1913 case MONO_TYPE_STRING:
1914 case MONO_TYPE_OBJECT:
1915 case MONO_TYPE_CLASS:
1916 case MONO_TYPE_ARRAY:
1917 case MONO_TYPE_SZARRAY:
1918 /* Do nothing */
1919 break;
1920 case MONO_TYPE_GENERICINST: {
1921 MonoGenericClass *gclass = cf->type->data.generic_class;
1922 g_assert (!gclass->context.class_inst->is_open);
1924 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1925 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1926 MonoObject *nullable;
1929 * Convert the boxed vtype into a Nullable structure.
1930 * This is complicated by the fact that Nullables have
1931 * a variable structure.
1933 nullable = mono_object_new (mono_domain_get (), nklass);
1935 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1937 v = mono_object_unbox (nullable);
1939 else
1940 if (gclass->container_class->valuetype && (v != NULL))
1941 v += sizeof (MonoObject);
1942 break;
1944 default:
1945 g_error ("type 0x%x not handled in "
1946 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1947 return;
1951 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1952 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1953 if (!vtable->initialized)
1954 mono_runtime_class_init (vtable);
1955 mono_field_static_set_value (vtable, cf, v);
1956 } else {
1957 mono_field_set_value (obj, cf, v);
1961 static MonoObject *
1962 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1964 MonoObject *o = NULL;
1965 MonoClassField *field = this->field;
1966 MonoClass *klass;
1967 MonoDomain *domain = mono_object_domain (this);
1968 gchar *v;
1969 MonoTypeEnum def_type;
1970 const char *def_value;
1972 MONO_ARCH_SAVE_REGS;
1974 mono_class_init (field->parent);
1976 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1977 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1979 if (field->parent->image->dynamic) {
1980 /* FIXME: */
1981 g_assert_not_reached ();
1984 def_value = mono_class_get_field_default_value (field, &def_type);
1986 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1987 switch (def_type) {
1988 case MONO_TYPE_U1:
1989 case MONO_TYPE_I1:
1990 case MONO_TYPE_BOOLEAN:
1991 case MONO_TYPE_U2:
1992 case MONO_TYPE_I2:
1993 case MONO_TYPE_CHAR:
1994 case MONO_TYPE_U:
1995 case MONO_TYPE_I:
1996 case MONO_TYPE_U4:
1997 case MONO_TYPE_I4:
1998 case MONO_TYPE_R4:
1999 case MONO_TYPE_U8:
2000 case MONO_TYPE_I8:
2001 case MONO_TYPE_R8: {
2002 MonoType *t;
2004 /* boxed value type */
2005 t = g_new0 (MonoType, 1);
2006 t->type = def_type;
2007 klass = mono_class_from_mono_type (t);
2008 g_free (t);
2009 o = mono_object_new (domain, klass);
2010 v = ((gchar *) o) + sizeof (MonoObject);
2011 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2012 break;
2014 case MONO_TYPE_STRING:
2015 case MONO_TYPE_CLASS:
2016 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2017 break;
2018 default:
2019 g_assert_not_reached ();
2022 return o;
2025 static MonoReflectionType*
2026 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
2028 MonoMethod *method = rmethod->method.method;
2030 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
2033 /* From MonoProperty.cs */
2034 typedef enum {
2035 PInfo_Attributes = 1,
2036 PInfo_GetMethod = 1 << 1,
2037 PInfo_SetMethod = 1 << 2,
2038 PInfo_ReflectedType = 1 << 3,
2039 PInfo_DeclaringType = 1 << 4,
2040 PInfo_Name = 1 << 5
2041 } PInfo;
2043 static void
2044 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2046 MonoDomain *domain = mono_object_domain (property);
2048 MONO_ARCH_SAVE_REGS;
2050 if ((req_info & PInfo_ReflectedType) != 0)
2051 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2052 else if ((req_info & PInfo_DeclaringType) != 0)
2053 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
2055 if ((req_info & PInfo_Name) != 0)
2056 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2058 if ((req_info & PInfo_Attributes) != 0)
2059 info->attrs = property->property->attrs;
2061 if ((req_info & PInfo_GetMethod) != 0)
2062 MONO_STRUCT_SETREF (info, get, property->property->get ?
2063 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2065 if ((req_info & PInfo_SetMethod) != 0)
2066 MONO_STRUCT_SETREF (info, set, property->property->set ?
2067 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2069 * There may be other methods defined for properties, though, it seems they are not exposed
2070 * in the reflection API
2074 static void
2075 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2077 MonoDomain *domain = mono_object_domain (event);
2079 MONO_ARCH_SAVE_REGS;
2081 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2082 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2084 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2085 info->attrs = event->event->attrs;
2086 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2087 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2088 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2090 #ifndef MONO_SMALL_CONFIG
2091 if (event->event->other) {
2092 int i, n = 0;
2093 while (event->event->other [n])
2094 n++;
2095 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2097 for (i = 0; i < n; i++)
2098 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2100 #endif
2103 static MonoArray*
2104 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2106 MonoError error;
2107 MonoDomain *domain = mono_object_domain (type);
2108 MonoArray *intf;
2109 GPtrArray *ifaces = NULL;
2110 int i;
2111 MonoClass *class = mono_class_from_mono_type (type->type);
2112 MonoClass *parent;
2113 MonoBitSet *slots;
2114 MonoGenericContext *context = NULL;
2116 MONO_ARCH_SAVE_REGS;
2118 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2119 context = mono_class_get_context (class);
2120 class = class->generic_class->container_class;
2123 mono_class_setup_vtable (class);
2125 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2127 for (parent = class; parent; parent = parent->parent) {
2128 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent, &error);
2129 if (!mono_error_ok (&error)) {
2130 mono_bitset_free (slots);
2131 mono_error_raise_exception (&error);
2132 return NULL;
2133 } else if (tmp_ifaces) {
2134 for (i = 0; i < tmp_ifaces->len; ++i) {
2135 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2137 if (mono_bitset_test (slots, ic->interface_id))
2138 continue;
2140 mono_bitset_set (slots, ic->interface_id);
2141 if (ifaces == NULL)
2142 ifaces = g_ptr_array_new ();
2143 g_ptr_array_add (ifaces, ic);
2145 g_ptr_array_free (tmp_ifaces, TRUE);
2148 mono_bitset_free (slots);
2150 if (!ifaces)
2151 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2153 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2154 for (i = 0; i < ifaces->len; ++i) {
2155 MonoClass *ic = g_ptr_array_index (ifaces, i);
2156 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2157 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2158 inflated = ret = mono_class_inflate_generic_type (ret, context);
2160 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2161 if (inflated)
2162 mono_metadata_free_type (inflated);
2164 g_ptr_array_free (ifaces, TRUE);
2166 return intf;
2169 static void
2170 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2172 gboolean variance_used;
2173 MonoClass *class = mono_class_from_mono_type (type->type);
2174 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2175 MonoReflectionMethod *member;
2176 MonoMethod* method;
2177 gpointer iter;
2178 int i = 0, len, ioffset;
2179 MonoDomain *domain;
2181 MONO_ARCH_SAVE_REGS;
2183 mono_class_setup_vtable (class);
2185 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2186 if (ioffset == -1)
2187 return;
2189 len = mono_class_num_methods (iclass);
2190 domain = mono_object_domain (type);
2191 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2192 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2193 iter = NULL;
2194 while ((method = mono_class_get_methods (iclass, &iter))) {
2195 member = mono_method_get_object (domain, method, iclass);
2196 mono_array_setref (*methods, i, member);
2197 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2198 mono_array_setref (*targets, i, member);
2200 i ++;
2204 static void
2205 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2207 MonoClass *klass = mono_class_from_mono_type (type->type);
2209 if (klass->image->dynamic) {
2210 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2211 *packing = tb->packing_size;
2212 *size = tb->class_size;
2213 } else {
2214 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2218 static MonoReflectionType*
2219 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2221 MonoClass *class;
2223 MONO_ARCH_SAVE_REGS;
2225 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2226 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2228 class = mono_class_from_mono_type (type->type);
2230 // GetElementType should only return a type for:
2231 // Array Pointer PassedByRef
2232 if (type->type->byref)
2233 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2234 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2235 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2236 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2237 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2238 else
2239 return NULL;
2242 static MonoReflectionType*
2243 ves_icall_get_type_parent (MonoReflectionType *type)
2245 MonoClass *class = mono_class_from_mono_type (type->type);
2247 MONO_ARCH_SAVE_REGS;
2249 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2252 static MonoBoolean
2253 ves_icall_type_ispointer (MonoReflectionType *type)
2255 MONO_ARCH_SAVE_REGS;
2257 return type->type->type == MONO_TYPE_PTR;
2260 static MonoBoolean
2261 ves_icall_type_isprimitive (MonoReflectionType *type)
2263 MONO_ARCH_SAVE_REGS;
2265 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)));
2268 static MonoBoolean
2269 ves_icall_type_isbyref (MonoReflectionType *type)
2271 MONO_ARCH_SAVE_REGS;
2273 return type->type->byref;
2276 static MonoBoolean
2277 ves_icall_type_iscomobject (MonoReflectionType *type)
2279 MonoClass *klass = mono_class_from_mono_type (type->type);
2280 MONO_ARCH_SAVE_REGS;
2282 return (klass && klass->is_com_object);
2285 static MonoReflectionModule*
2286 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2288 MonoClass *class = mono_class_from_mono_type (type->type);
2290 MONO_ARCH_SAVE_REGS;
2292 return mono_module_get_object (mono_object_domain (type), class->image);
2295 static MonoReflectionAssembly*
2296 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2298 MonoDomain *domain = mono_domain_get ();
2299 MonoClass *class = mono_class_from_mono_type (type->type);
2301 MONO_ARCH_SAVE_REGS;
2303 return mono_assembly_get_object (domain, class->image->assembly);
2306 static MonoReflectionType*
2307 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2309 MonoDomain *domain = mono_domain_get ();
2310 MonoClass *class;
2312 MONO_ARCH_SAVE_REGS;
2314 if (type->type->byref)
2315 return NULL;
2316 if (type->type->type == MONO_TYPE_VAR)
2317 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2318 else if (type->type->type == MONO_TYPE_MVAR)
2319 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2320 else
2321 class = mono_class_from_mono_type (type->type)->nested_in;
2323 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2326 static MonoReflectionType*
2327 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2329 MonoDomain *domain = mono_domain_get ();
2330 MonoClass *class = mono_class_from_mono_type (type->type);
2332 MONO_ARCH_SAVE_REGS;
2334 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2335 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2336 else if (class->element_class)
2337 return mono_type_get_object (domain, &class->element_class->byval_arg);
2338 else
2339 return NULL;
2342 static MonoString*
2343 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2345 MonoDomain *domain = mono_domain_get ();
2346 MonoClass *class = mono_class_from_mono_type (type->type);
2348 MONO_ARCH_SAVE_REGS;
2350 if (type->type->byref) {
2351 char *n = g_strdup_printf ("%s&", class->name);
2352 MonoString *res = mono_string_new (domain, n);
2354 g_free (n);
2356 return res;
2357 } else {
2358 return mono_string_new (domain, class->name);
2362 static MonoString*
2363 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2365 MonoDomain *domain = mono_domain_get ();
2366 MonoClass *class = mono_class_from_mono_type (type->type);
2368 MONO_ARCH_SAVE_REGS;
2370 while (class->nested_in)
2371 class = class->nested_in;
2373 if (class->name_space [0] == '\0')
2374 return NULL;
2375 else
2376 return mono_string_new (domain, class->name_space);
2379 static gint32
2380 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2382 MonoClass *class;
2384 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2385 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2387 class = mono_class_from_mono_type (type->type);
2388 return class->rank;
2391 static MonoArray*
2392 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2394 MonoArray *res;
2395 MonoClass *klass, *pklass;
2396 MonoDomain *domain = mono_object_domain (type);
2397 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2398 int i;
2399 MONO_ARCH_SAVE_REGS;
2401 klass = mono_class_from_mono_type (type->type);
2403 if (klass->generic_container) {
2404 MonoGenericContainer *container = klass->generic_container;
2405 res = mono_array_new_specific (array_vtable, container->type_argc);
2406 for (i = 0; i < container->type_argc; ++i) {
2407 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2408 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2410 } else if (klass->generic_class) {
2411 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2412 res = mono_array_new_specific (array_vtable, inst->type_argc);
2413 for (i = 0; i < inst->type_argc; ++i)
2414 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2415 } else {
2416 res = mono_array_new_specific (array_vtable, 0);
2418 return res;
2421 static gboolean
2422 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2424 MonoClass *klass;
2425 MONO_ARCH_SAVE_REGS;
2427 if (!IS_MONOTYPE (type))
2428 return FALSE;
2430 if (type->type->byref)
2431 return FALSE;
2433 klass = mono_class_from_mono_type (type->type);
2435 return klass->generic_container != NULL;
2438 static MonoReflectionType*
2439 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2441 MonoClass *klass;
2442 MONO_ARCH_SAVE_REGS;
2444 if (type->type->byref)
2445 return NULL;
2447 klass = mono_class_from_mono_type (type->type);
2448 if (klass->generic_container) {
2449 return type; /* check this one */
2451 if (klass->generic_class) {
2452 MonoClass *generic_class = klass->generic_class->container_class;
2453 gpointer tb;
2455 tb = mono_class_get_ref_info (generic_class);
2457 if (generic_class->wastypebuilder && tb)
2458 return tb;
2459 else
2460 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2462 return NULL;
2465 static MonoReflectionType*
2466 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2468 MonoType *geninst, **types;
2469 int i, count;
2471 MONO_ARCH_SAVE_REGS;
2473 count = mono_array_length (type_array);
2474 types = g_new0 (MonoType *, count);
2476 for (i = 0; i < count; i++) {
2477 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2478 types [i] = t->type;
2481 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2482 g_free (types);
2483 if (!geninst)
2484 return NULL;
2486 return mono_type_get_object (mono_object_domain (type), geninst);
2489 static gboolean
2490 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2492 MonoClass *klass;
2493 MONO_ARCH_SAVE_REGS;
2495 if (type->type->byref)
2496 return FALSE;
2498 klass = mono_class_from_mono_type (type->type);
2499 return klass->generic_class != NULL;
2502 static gboolean
2503 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2505 MonoClass *klass;
2506 MONO_ARCH_SAVE_REGS;
2508 if (!IS_MONOTYPE (type))
2509 return FALSE;
2511 if (type->type->byref)
2512 return FALSE;
2514 klass = mono_class_from_mono_type (type->type);
2515 return klass->generic_class != NULL || klass->generic_container != NULL;
2518 static gint32
2519 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2521 MONO_ARCH_SAVE_REGS;
2523 if (!IS_MONOTYPE (type))
2524 return -1;
2526 if (is_generic_parameter (type->type))
2527 return mono_type_get_generic_param_num (type->type);
2528 return -1;
2531 static GenericParameterAttributes
2532 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2534 MONO_ARCH_SAVE_REGS;
2536 g_assert (IS_MONOTYPE (type));
2537 g_assert (is_generic_parameter (type->type));
2538 return mono_generic_param_info (type->type->data.generic_param)->flags;
2541 static MonoArray *
2542 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2544 MonoGenericParamInfo *param_info;
2545 MonoDomain *domain;
2546 MonoClass **ptr;
2547 MonoArray *res;
2548 int i, count;
2550 MONO_ARCH_SAVE_REGS;
2552 g_assert (IS_MONOTYPE (type));
2554 domain = mono_object_domain (type);
2555 param_info = mono_generic_param_info (type->type->data.generic_param);
2556 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2559 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2560 for (i = 0; i < count; i++)
2561 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2564 return res;
2567 static MonoBoolean
2568 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2570 MONO_ARCH_SAVE_REGS;
2571 return is_generic_parameter (type->type);
2574 static MonoBoolean
2575 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2577 MONO_ARCH_SAVE_REGS;
2578 return is_generic_parameter (tb->type.type);
2581 static void
2582 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2583 MonoReflectionType *t)
2585 enumtype->type = t->type;
2588 static MonoReflectionMethod*
2589 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2590 MonoReflectionMethod* generic)
2592 MonoDomain *domain;
2593 MonoClass *klass;
2594 MonoMethod *method;
2595 gpointer iter;
2597 MONO_ARCH_SAVE_REGS;
2599 domain = ((MonoObject *)type)->vtable->domain;
2601 klass = mono_class_from_mono_type (type->type);
2603 iter = NULL;
2604 while ((method = mono_class_get_methods (klass, &iter))) {
2605 if (method->token == generic->method->token)
2606 return mono_method_get_object (domain, method, klass);
2609 return NULL;
2614 static MonoReflectionMethod *
2615 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2617 MonoMethod *method;
2618 MonoType *type = ref_type->type;
2620 MONO_ARCH_SAVE_REGS;
2622 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2623 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2624 if (type->type == MONO_TYPE_VAR)
2625 return NULL;
2627 method = mono_type_get_generic_param_owner (type)->owner.method;
2628 g_assert (method);
2629 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2632 static MonoReflectionDllImportAttribute*
2633 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2635 static MonoClass *DllImportAttributeClass = NULL;
2636 MonoDomain *domain = mono_domain_get ();
2637 MonoReflectionDllImportAttribute *attr;
2638 MonoImage *image = method->klass->image;
2639 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2640 MonoTableInfo *tables = image->tables;
2641 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2642 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2643 guint32 im_cols [MONO_IMPLMAP_SIZE];
2644 guint32 scope_token;
2645 const char *import = NULL;
2646 const char *scope = NULL;
2647 guint32 flags;
2649 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2650 return NULL;
2652 if (!DllImportAttributeClass) {
2653 DllImportAttributeClass =
2654 mono_class_from_name (mono_defaults.corlib,
2655 "System.Runtime.InteropServices", "DllImportAttribute");
2656 g_assert (DllImportAttributeClass);
2659 if (method->klass->image->dynamic) {
2660 MonoReflectionMethodAux *method_aux =
2661 g_hash_table_lookup (
2662 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2663 if (method_aux) {
2664 import = method_aux->dllentry;
2665 scope = method_aux->dll;
2668 if (!import || !scope) {
2669 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2670 return NULL;
2673 else {
2674 if (piinfo->implmap_idx) {
2675 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2677 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2678 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2679 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2680 scope = mono_metadata_string_heap (image, scope_token);
2683 flags = piinfo->piflags;
2685 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2687 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2688 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2689 attr->call_conv = (flags & 0x700) >> 8;
2690 attr->charset = ((flags & 0x6) >> 1) + 1;
2691 if (attr->charset == 1)
2692 attr->charset = 2;
2693 attr->exact_spelling = (flags & 0x1) != 0;
2694 attr->set_last_error = (flags & 0x40) != 0;
2695 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2696 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2697 attr->preserve_sig = FALSE;
2699 return attr;
2702 static MonoReflectionMethod *
2703 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2705 MonoMethodInflated *imethod;
2706 MonoMethod *result;
2708 MONO_ARCH_SAVE_REGS;
2710 if (method->method->is_generic)
2711 return method;
2713 if (!method->method->is_inflated)
2714 return NULL;
2716 imethod = (MonoMethodInflated *) method->method;
2718 result = imethod->declaring;
2719 /* Not a generic method. */
2720 if (!result->is_generic)
2721 return NULL;
2723 if (method->method->klass->image->dynamic) {
2724 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2725 MonoReflectionMethod *res;
2728 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2729 * the dynamic case as well ?
2731 mono_loader_lock ();
2732 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2733 mono_loader_unlock ();
2735 if (res)
2736 return res;
2739 if (imethod->context.class_inst) {
2740 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2741 /*Generic methods gets the context of the GTD.*/
2742 if (mono_class_get_context (klass))
2743 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2746 return mono_method_get_object (mono_object_domain (method), result, NULL);
2749 static gboolean
2750 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2752 MONO_ARCH_SAVE_REGS;
2754 return mono_method_signature (method->method)->generic_param_count != 0;
2757 static gboolean
2758 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2760 MONO_ARCH_SAVE_REGS;
2762 return method->method->is_generic;
2765 static MonoArray*
2766 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2768 MonoArray *res;
2769 MonoDomain *domain;
2770 int count, i;
2771 MONO_ARCH_SAVE_REGS;
2773 domain = mono_object_domain (method);
2775 if (method->method->is_inflated) {
2776 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2778 if (inst) {
2779 count = inst->type_argc;
2780 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2782 for (i = 0; i < count; i++)
2783 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2785 return res;
2789 count = mono_method_signature (method->method)->generic_param_count;
2790 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2792 for (i = 0; i < count; i++) {
2793 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2794 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2795 MonoClass *pklass = mono_class_from_generic_parameter (
2796 param, method->method->klass->image, TRUE);
2797 mono_array_setref (res, i,
2798 mono_type_get_object (domain, &pklass->byval_arg));
2801 return res;
2804 static MonoObject *
2805 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2808 * Invoke from reflection is supposed to always be a virtual call (the API
2809 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2810 * greater flexibility.
2812 MonoMethod *m = method->method;
2813 int pcount;
2814 void *obj = this;
2816 MONO_ARCH_SAVE_REGS;
2818 *exc = NULL;
2820 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2821 mono_security_core_clr_ensure_reflection_access_method (m);
2823 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2824 if (this) {
2825 if (!mono_object_isinst (this, m->klass)) {
2826 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2827 return NULL;
2829 m = mono_object_get_virtual_method (this, m);
2830 /* must pass the pointer to the value for valuetype methods */
2831 if (m->klass->valuetype)
2832 obj = mono_object_unbox (this);
2833 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2834 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2835 return NULL;
2839 pcount = params? mono_array_length (params): 0;
2840 if (pcount != mono_method_signature (m)->param_count) {
2841 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2842 return NULL;
2845 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2846 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."));
2847 return NULL;
2850 if (m->klass->image->assembly->ref_only) {
2851 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."));
2852 return NULL;
2855 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2856 int i;
2857 mono_array_size_t *lengths;
2858 mono_array_size_t *lower_bounds;
2859 pcount = mono_array_length (params);
2860 lengths = alloca (sizeof (mono_array_size_t) * pcount);
2861 for (i = 0; i < pcount; ++i)
2862 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2864 if (m->klass->rank == pcount) {
2865 /* Only lengths provided. */
2866 lower_bounds = NULL;
2867 } else {
2868 g_assert (pcount == (m->klass->rank * 2));
2869 /* lower bounds are first. */
2870 lower_bounds = lengths;
2871 lengths += m->klass->rank;
2874 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2876 return mono_runtime_invoke_array (m, obj, params, NULL);
2879 static MonoObject *
2880 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2882 MonoDomain *domain = mono_object_domain (method);
2883 MonoMethod *m = method->method;
2884 MonoMethodSignature *sig = mono_method_signature (m);
2885 MonoArray *out_args;
2886 MonoObject *result;
2887 int i, j, outarg_count = 0;
2889 MONO_ARCH_SAVE_REGS;
2891 if (m->klass == mono_defaults.object_class) {
2893 if (!strcmp (m->name, "FieldGetter")) {
2894 MonoClass *k = this->vtable->klass;
2895 MonoString *name;
2896 char *str;
2898 /* If this is a proxy, then it must be a CBO */
2899 if (k == mono_defaults.transparent_proxy_class) {
2900 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2901 this = tp->rp->unwrapped_server;
2902 g_assert (this);
2903 k = this->vtable->klass;
2906 name = mono_array_get (params, MonoString *, 1);
2907 str = mono_string_to_utf8 (name);
2909 do {
2910 MonoClassField* field = mono_class_get_field_from_name (k, str);
2911 if (field) {
2912 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2913 if (field_klass->valuetype)
2914 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2915 else
2916 result = *((gpointer *)((char *)this + field->offset));
2918 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2919 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2920 mono_array_setref (out_args, 0, result);
2921 g_free (str);
2922 return NULL;
2924 k = k->parent;
2925 } while (k);
2927 g_free (str);
2928 g_assert_not_reached ();
2930 } else if (!strcmp (m->name, "FieldSetter")) {
2931 MonoClass *k = this->vtable->klass;
2932 MonoString *name;
2933 guint32 size;
2934 gint32 align;
2935 char *str;
2937 /* If this is a proxy, then it must be a CBO */
2938 if (k == mono_defaults.transparent_proxy_class) {
2939 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2940 this = tp->rp->unwrapped_server;
2941 g_assert (this);
2942 k = this->vtable->klass;
2945 name = mono_array_get (params, MonoString *, 1);
2946 str = mono_string_to_utf8 (name);
2948 do {
2949 MonoClassField* field = mono_class_get_field_from_name (k, str);
2950 if (field) {
2951 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2952 MonoObject *val = mono_array_get (params, gpointer, 2);
2954 if (field_klass->valuetype) {
2955 size = mono_type_size (field->type, &align);
2956 g_assert (size == mono_class_value_size (field_klass, NULL));
2957 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2958 } else {
2959 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2962 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2963 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2965 g_free (str);
2966 return NULL;
2969 k = k->parent;
2970 } while (k);
2972 g_free (str);
2973 g_assert_not_reached ();
2978 for (i = 0; i < mono_array_length (params); i++) {
2979 if (sig->params [i]->byref)
2980 outarg_count++;
2983 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2985 /* handle constructors only for objects already allocated */
2986 if (!strcmp (method->method->name, ".ctor"))
2987 g_assert (this);
2989 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2990 g_assert (!method->method->klass->valuetype);
2991 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2993 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2994 if (sig->params [i]->byref) {
2995 gpointer arg;
2996 arg = mono_array_get (params, gpointer, i);
2997 mono_array_setref (out_args, j, arg);
2998 j++;
3002 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3004 return result;
3007 static guint64
3008 read_enum_value (char *mem, int type)
3010 switch (type) {
3011 case MONO_TYPE_U1:
3012 return *(guint8*)mem;
3013 case MONO_TYPE_I1:
3014 return *(gint8*)mem;
3015 case MONO_TYPE_U2:
3016 return *(guint16*)mem;
3017 case MONO_TYPE_I2:
3018 return *(gint16*)mem;
3019 case MONO_TYPE_U4:
3020 return *(guint32*)mem;
3021 case MONO_TYPE_I4:
3022 return *(gint32*)mem;
3023 case MONO_TYPE_U8:
3024 return *(guint64*)mem;
3025 case MONO_TYPE_I8:
3026 return *(gint64*)mem;
3027 default:
3028 g_assert_not_reached ();
3030 return 0;
3033 static void
3034 write_enum_value (char *mem, int type, guint64 value)
3036 switch (type) {
3037 case MONO_TYPE_U1:
3038 case MONO_TYPE_I1: {
3039 guint8 *p = (guint8*)mem;
3040 *p = value;
3041 break;
3043 case MONO_TYPE_U2:
3044 case MONO_TYPE_I2: {
3045 guint16 *p = (void*)mem;
3046 *p = value;
3047 break;
3049 case MONO_TYPE_U4:
3050 case MONO_TYPE_I4: {
3051 guint32 *p = (void*)mem;
3052 *p = value;
3053 break;
3055 case MONO_TYPE_U8:
3056 case MONO_TYPE_I8: {
3057 guint64 *p = (void*)mem;
3058 *p = value;
3059 break;
3061 default:
3062 g_assert_not_reached ();
3064 return;
3067 static MonoObject *
3068 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3070 MonoDomain *domain;
3071 MonoClass *enumc, *objc;
3072 MonoObject *res;
3073 guint64 val;
3075 MONO_ARCH_SAVE_REGS;
3077 MONO_CHECK_ARG_NULL (enumType);
3078 MONO_CHECK_ARG_NULL (value);
3080 domain = mono_object_domain (enumType);
3081 enumc = mono_class_from_mono_type (enumType->type);
3082 objc = value->vtable->klass;
3084 if (!enumc->enumtype)
3085 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3086 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3087 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."));
3089 res = mono_object_new (domain, enumc);
3090 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3091 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3093 return res;
3096 static MonoObject *
3097 ves_icall_System_Enum_get_value (MonoObject *this)
3099 MonoObject *res;
3100 MonoClass *enumc;
3101 gpointer dst;
3102 gpointer src;
3103 int size;
3105 MONO_ARCH_SAVE_REGS;
3107 if (!this)
3108 return NULL;
3110 g_assert (this->vtable->klass->enumtype);
3112 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3113 res = mono_object_new (mono_object_domain (this), enumc);
3114 dst = (char *)res + sizeof (MonoObject);
3115 src = (char *)this + sizeof (MonoObject);
3116 size = mono_class_value_size (enumc, NULL);
3118 memcpy (dst, src, size);
3120 return res;
3123 static MonoReflectionType *
3124 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3126 MONO_ARCH_SAVE_REGS;
3128 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3131 static int
3132 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3134 gpointer tdata = (char *)this + sizeof (MonoObject);
3135 gpointer odata = (char *)other + sizeof (MonoObject);
3136 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3137 g_assert (basetype);
3139 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3140 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3141 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3142 if (me == other) \
3143 return 0; \
3144 return me > other ? 1 : -1; \
3145 } while (0)
3147 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3148 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3149 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3150 if (me == other) \
3151 return 0; \
3152 return me - other; \
3153 } while (0)
3155 switch (basetype->type) {
3156 case MONO_TYPE_U1:
3157 COMPARE_ENUM_VALUES (guint8);
3158 case MONO_TYPE_I1:
3159 COMPARE_ENUM_VALUES (gint8);
3160 case MONO_TYPE_CHAR:
3161 case MONO_TYPE_U2:
3162 COMPARE_ENUM_VALUES_RANGE (guint16);
3163 case MONO_TYPE_I2:
3164 COMPARE_ENUM_VALUES (gint16);
3165 case MONO_TYPE_U4:
3166 COMPARE_ENUM_VALUES (guint32);
3167 case MONO_TYPE_I4:
3168 COMPARE_ENUM_VALUES (gint32);
3169 case MONO_TYPE_U8:
3170 COMPARE_ENUM_VALUES (guint64);
3171 case MONO_TYPE_I8:
3172 COMPARE_ENUM_VALUES (gint64);
3173 default:
3174 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3176 #undef COMPARE_ENUM_VALUES_RANGE
3177 #undef COMPARE_ENUM_VALUES
3178 return 0;
3181 static int
3182 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3184 gpointer data = (char *)this + sizeof (MonoObject);
3185 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3186 g_assert (basetype);
3188 switch (basetype->type) {
3189 case MONO_TYPE_I1:
3190 return *((gint8*)data);
3191 case MONO_TYPE_U1:
3192 return *((guint8*)data);
3193 case MONO_TYPE_CHAR:
3194 case MONO_TYPE_U2:
3195 return *((guint16*)data);
3197 case MONO_TYPE_I2:
3198 return *((gint16*)data);
3199 case MONO_TYPE_U4:
3200 return *((guint32*)data);
3201 case MONO_TYPE_I4:
3202 return *((gint32*)data);
3203 case MONO_TYPE_U8:
3204 case MONO_TYPE_I8: {
3205 gint64 value = *((gint64*)data);
3206 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3208 default:
3209 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3211 return 0;
3214 static void
3215 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3217 MonoDomain *domain = mono_object_domain (type);
3218 MonoClass *enumc = mono_class_from_mono_type (type->type);
3219 guint j = 0, nvalues, crow;
3220 gpointer iter;
3221 MonoClassField *field;
3223 MONO_ARCH_SAVE_REGS;
3225 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3226 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3227 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3228 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3230 crow = -1;
3231 iter = NULL;
3232 while ((field = mono_class_get_fields (enumc, &iter))) {
3233 const char *p;
3234 int len;
3235 MonoTypeEnum def_type;
3237 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3238 continue;
3239 if (mono_field_is_deleted (field))
3240 continue;
3241 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3243 p = mono_class_get_field_default_value (field, &def_type);
3244 len = mono_metadata_decode_blob_size (p, &p);
3245 switch (mono_class_enum_basetype (enumc)->type) {
3246 case MONO_TYPE_U1:
3247 case MONO_TYPE_I1:
3248 mono_array_set (info->values, gchar, j, *p);
3249 break;
3250 case MONO_TYPE_CHAR:
3251 case MONO_TYPE_U2:
3252 case MONO_TYPE_I2:
3253 mono_array_set (info->values, gint16, j, read16 (p));
3254 break;
3255 case MONO_TYPE_U4:
3256 case MONO_TYPE_I4:
3257 mono_array_set (info->values, gint32, j, read32 (p));
3258 break;
3259 case MONO_TYPE_U8:
3260 case MONO_TYPE_I8:
3261 mono_array_set (info->values, gint64, j, read64 (p));
3262 break;
3263 default:
3264 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3266 ++j;
3270 enum {
3271 BFLAGS_IgnoreCase = 1,
3272 BFLAGS_DeclaredOnly = 2,
3273 BFLAGS_Instance = 4,
3274 BFLAGS_Static = 8,
3275 BFLAGS_Public = 0x10,
3276 BFLAGS_NonPublic = 0x20,
3277 BFLAGS_FlattenHierarchy = 0x40,
3278 BFLAGS_InvokeMethod = 0x100,
3279 BFLAGS_CreateInstance = 0x200,
3280 BFLAGS_GetField = 0x400,
3281 BFLAGS_SetField = 0x800,
3282 BFLAGS_GetProperty = 0x1000,
3283 BFLAGS_SetProperty = 0x2000,
3284 BFLAGS_ExactBinding = 0x10000,
3285 BFLAGS_SuppressChangeType = 0x20000,
3286 BFLAGS_OptionalParamBinding = 0x40000
3289 static MonoReflectionField *
3290 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3292 MonoDomain *domain;
3293 MonoClass *startklass, *klass;
3294 int match;
3295 MonoClassField *field;
3296 gpointer iter;
3297 char *utf8_name;
3298 int (*compare_func) (const char *s1, const char *s2) = NULL;
3299 domain = ((MonoObject *)type)->vtable->domain;
3300 klass = startklass = mono_class_from_mono_type (type->type);
3302 MONO_ARCH_SAVE_REGS;
3304 if (!name)
3305 mono_raise_exception (mono_get_exception_argument_null ("name"));
3306 if (type->type->byref)
3307 return NULL;
3309 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3311 handle_parent:
3312 if (klass->exception_type != MONO_EXCEPTION_NONE)
3313 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3315 iter = NULL;
3316 while ((field = mono_class_get_fields (klass, &iter))) {
3317 match = 0;
3319 if (field->type == NULL)
3320 continue;
3321 if (mono_field_is_deleted (field))
3322 continue;
3323 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3324 if (bflags & BFLAGS_Public)
3325 match++;
3326 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3327 if (bflags & BFLAGS_NonPublic) {
3328 match++;
3331 if (!match)
3332 continue;
3333 match = 0;
3334 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3335 if (bflags & BFLAGS_Static)
3336 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3337 match++;
3338 } else {
3339 if (bflags & BFLAGS_Instance)
3340 match++;
3343 if (!match)
3344 continue;
3346 utf8_name = mono_string_to_utf8 (name);
3348 if (compare_func (mono_field_get_name (field), utf8_name)) {
3349 g_free (utf8_name);
3350 continue;
3352 g_free (utf8_name);
3354 return mono_field_get_object (domain, klass, field);
3356 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3357 goto handle_parent;
3359 return NULL;
3362 static MonoArray*
3363 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3365 MonoDomain *domain;
3366 MonoClass *startklass, *klass, *refklass;
3367 MonoArray *res;
3368 MonoObject *member;
3369 int i, match;
3370 gpointer iter;
3371 MonoClassField *field;
3372 MonoPtrArray tmp_array;
3374 MONO_ARCH_SAVE_REGS;
3376 domain = ((MonoObject *)type)->vtable->domain;
3377 if (type->type->byref)
3378 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3379 klass = startklass = mono_class_from_mono_type (type->type);
3380 refklass = mono_class_from_mono_type (reftype->type);
3382 mono_ptr_array_init (tmp_array, 2);
3384 handle_parent:
3385 if (klass->exception_type != MONO_EXCEPTION_NONE)
3386 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3388 iter = NULL;
3389 while ((field = mono_class_get_fields (klass, &iter))) {
3390 match = 0;
3391 if (mono_field_is_deleted (field))
3392 continue;
3393 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3394 if (bflags & BFLAGS_Public)
3395 match++;
3396 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3397 if (bflags & BFLAGS_NonPublic) {
3398 match++;
3401 if (!match)
3402 continue;
3403 match = 0;
3404 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3405 if (bflags & BFLAGS_Static)
3406 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3407 match++;
3408 } else {
3409 if (bflags & BFLAGS_Instance)
3410 match++;
3413 if (!match)
3414 continue;
3415 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3416 mono_ptr_array_append (tmp_array, member);
3418 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3419 goto handle_parent;
3421 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3423 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3424 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3426 mono_ptr_array_destroy (tmp_array);
3428 return res;
3431 static gboolean
3432 method_nonpublic (MonoMethod* method, gboolean start_klass)
3434 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3435 case METHOD_ATTRIBUTE_ASSEM:
3436 return (start_klass || mono_defaults.generic_ilist_class);
3437 case METHOD_ATTRIBUTE_PRIVATE:
3438 return start_klass;
3439 case METHOD_ATTRIBUTE_PUBLIC:
3440 return FALSE;
3441 default:
3442 return TRUE;
3446 static MonoArray*
3447 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3449 static MonoClass *MethodInfo_array;
3450 MonoDomain *domain;
3451 MonoClass *startklass, *klass, *refklass;
3452 MonoArray *res;
3453 MonoMethod *method;
3454 gpointer iter;
3455 MonoObject *member;
3456 int i, len, match, nslots;
3457 /*FIXME, use MonoBitSet*/
3458 guint32 method_slots_default [8];
3459 guint32 *method_slots = NULL;
3460 gchar *mname = NULL;
3461 int (*compare_func) (const char *s1, const char *s2) = NULL;
3462 MonoVTable *array_vtable;
3463 MonoException *ex;
3464 MonoPtrArray tmp_array;
3466 MONO_ARCH_SAVE_REGS;
3468 mono_ptr_array_init (tmp_array, 4);
3470 if (!MethodInfo_array) {
3471 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3472 mono_memory_barrier ();
3473 MethodInfo_array = klass;
3476 domain = ((MonoObject *)type)->vtable->domain;
3477 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3478 if (type->type->byref)
3479 return mono_array_new_specific (array_vtable, 0);
3480 klass = startklass = mono_class_from_mono_type (type->type);
3481 refklass = mono_class_from_mono_type (reftype->type);
3482 len = 0;
3483 if (name != NULL) {
3484 mname = mono_string_to_utf8 (name);
3485 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3488 /* An optimization for calls made from Delegate:CreateDelegate () */
3489 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3490 method = mono_get_delegate_invoke (klass);
3491 if (mono_loader_get_last_error ())
3492 goto loader_error;
3494 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3496 res = mono_array_new_specific (array_vtable, 1);
3497 mono_array_setref (res, 0, member);
3498 g_free (mname);
3499 return res;
3502 mono_class_setup_vtable (klass);
3503 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3504 goto loader_error;
3506 if (is_generic_parameter (type->type))
3507 nslots = mono_class_get_vtable_size (klass->parent);
3508 else
3509 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3510 if (nslots >= sizeof (method_slots_default) * 8) {
3511 method_slots = g_new0 (guint32, nslots / 32 + 1);
3512 } else {
3513 method_slots = method_slots_default;
3514 memset (method_slots, 0, sizeof (method_slots_default));
3516 handle_parent:
3517 mono_class_setup_vtable (klass);
3518 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3519 goto loader_error;
3521 iter = NULL;
3522 while ((method = mono_class_get_methods (klass, &iter))) {
3523 match = 0;
3524 if (method->slot != -1) {
3525 g_assert (method->slot < nslots);
3526 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3527 continue;
3528 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3529 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3532 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3533 continue;
3534 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3535 if (bflags & BFLAGS_Public)
3536 match++;
3537 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3538 match++;
3540 if (!match)
3541 continue;
3542 match = 0;
3543 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3544 if (bflags & BFLAGS_Static)
3545 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3546 match++;
3547 } else {
3548 if (bflags & BFLAGS_Instance)
3549 match++;
3552 if (!match)
3553 continue;
3555 if (name != NULL) {
3556 if (compare_func (mname, method->name))
3557 continue;
3560 match = 0;
3562 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3564 mono_ptr_array_append (tmp_array, member);
3566 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3567 goto handle_parent;
3569 g_free (mname);
3570 if (method_slots != method_slots_default)
3571 g_free (method_slots);
3573 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3575 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3576 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3578 mono_ptr_array_destroy (tmp_array);
3579 return res;
3581 loader_error:
3582 g_free (mname);
3583 if (method_slots != method_slots_default)
3584 g_free (method_slots);
3585 mono_ptr_array_destroy (tmp_array);
3586 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3587 ex = mono_class_get_exception_for_failure (klass);
3588 } else {
3589 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3590 mono_loader_clear_error ();
3592 mono_raise_exception (ex);
3593 return NULL;
3596 static MonoArray*
3597 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3599 MonoDomain *domain;
3600 static MonoClass *System_Reflection_ConstructorInfo;
3601 MonoClass *startklass, *klass, *refklass;
3602 MonoArray *res;
3603 MonoMethod *method;
3604 MonoObject *member;
3605 int i, match;
3606 gpointer iter = NULL;
3607 MonoPtrArray tmp_array;
3609 MONO_ARCH_SAVE_REGS;
3611 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3613 domain = ((MonoObject *)type)->vtable->domain;
3614 if (type->type->byref)
3615 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3616 klass = startklass = mono_class_from_mono_type (type->type);
3617 refklass = mono_class_from_mono_type (reftype->type);
3619 if (klass->exception_type != MONO_EXCEPTION_NONE)
3620 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3622 if (!System_Reflection_ConstructorInfo)
3623 System_Reflection_ConstructorInfo = mono_class_from_name (
3624 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3626 iter = NULL;
3627 while ((method = mono_class_get_methods (klass, &iter))) {
3628 match = 0;
3629 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3630 continue;
3631 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3632 if (bflags & BFLAGS_Public)
3633 match++;
3634 } else {
3635 if (bflags & BFLAGS_NonPublic)
3636 match++;
3638 if (!match)
3639 continue;
3640 match = 0;
3641 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3642 if (bflags & BFLAGS_Static)
3643 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3644 match++;
3645 } else {
3646 if (bflags & BFLAGS_Instance)
3647 match++;
3650 if (!match)
3651 continue;
3652 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3654 mono_ptr_array_append (tmp_array, member);
3657 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3659 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3660 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3662 mono_ptr_array_destroy (tmp_array);
3664 return res;
3667 static guint
3668 property_hash (gconstpointer data)
3670 MonoProperty *prop = (MonoProperty*)data;
3672 return g_str_hash (prop->name);
3675 static gboolean
3676 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3678 // Properties are hide-by-name-and-signature
3679 if (!g_str_equal (prop1->name, prop2->name))
3680 return FALSE;
3682 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3683 return FALSE;
3684 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3685 return FALSE;
3686 return TRUE;
3689 static gboolean
3690 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3692 if (!accessor)
3693 return FALSE;
3695 return method_nonpublic (accessor, start_klass);
3698 static MonoArray*
3699 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3701 MonoDomain *domain;
3702 static MonoClass *System_Reflection_PropertyInfo;
3703 MonoClass *startklass, *klass;
3704 MonoArray *res;
3705 MonoMethod *method;
3706 MonoProperty *prop;
3707 int i, match;
3708 guint32 flags;
3709 gchar *propname = NULL;
3710 int (*compare_func) (const char *s1, const char *s2) = NULL;
3711 gpointer iter;
3712 GHashTable *properties;
3713 MonoPtrArray tmp_array;
3715 MONO_ARCH_SAVE_REGS;
3717 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3719 if (!System_Reflection_PropertyInfo)
3720 System_Reflection_PropertyInfo = mono_class_from_name (
3721 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3723 domain = ((MonoObject *)type)->vtable->domain;
3724 if (type->type->byref)
3725 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3726 klass = startklass = mono_class_from_mono_type (type->type);
3727 if (name != NULL) {
3728 propname = mono_string_to_utf8 (name);
3729 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3732 mono_class_setup_vtable (klass);
3734 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3735 handle_parent:
3736 mono_class_setup_vtable (klass);
3737 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3738 g_hash_table_destroy (properties);
3739 if (name != NULL)
3740 g_free (propname);
3741 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3744 iter = NULL;
3745 while ((prop = mono_class_get_properties (klass, &iter))) {
3746 match = 0;
3747 method = prop->get;
3748 if (!method)
3749 method = prop->set;
3750 if (method)
3751 flags = method->flags;
3752 else
3753 flags = 0;
3754 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3755 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3756 if (bflags & BFLAGS_Public)
3757 match++;
3758 } else if (bflags & BFLAGS_NonPublic) {
3759 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3760 property_accessor_nonpublic(prop->set, startklass == klass)) {
3761 match++;
3764 if (!match)
3765 continue;
3766 match = 0;
3767 if (flags & METHOD_ATTRIBUTE_STATIC) {
3768 if (bflags & BFLAGS_Static)
3769 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3770 match++;
3771 } else {
3772 if (bflags & BFLAGS_Instance)
3773 match++;
3776 if (!match)
3777 continue;
3778 match = 0;
3780 if (name != NULL) {
3781 if (compare_func (propname, prop->name))
3782 continue;
3785 if (g_hash_table_lookup (properties, prop))
3786 continue;
3788 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3790 g_hash_table_insert (properties, prop, prop);
3792 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3793 goto handle_parent;
3795 g_hash_table_destroy (properties);
3796 g_free (propname);
3798 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3799 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3800 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3802 mono_ptr_array_destroy (tmp_array);
3804 return res;
3807 static MonoReflectionEvent *
3808 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3810 MonoDomain *domain;
3811 MonoClass *klass, *startklass;
3812 gpointer iter;
3813 MonoEvent *event;
3814 MonoMethod *method;
3815 gchar *event_name;
3817 MONO_ARCH_SAVE_REGS;
3819 event_name = mono_string_to_utf8 (name);
3820 if (type->type->byref)
3821 return NULL;
3822 klass = startklass = mono_class_from_mono_type (type->type);
3823 domain = mono_object_domain (type);
3825 handle_parent:
3826 if (klass->exception_type != MONO_EXCEPTION_NONE)
3827 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3829 iter = NULL;
3830 while ((event = mono_class_get_events (klass, &iter))) {
3831 if (strcmp (event->name, event_name))
3832 continue;
3834 method = event->add;
3835 if (!method)
3836 method = event->remove;
3837 if (!method)
3838 method = event->raise;
3839 if (method) {
3840 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3841 if (!(bflags & BFLAGS_Public))
3842 continue;
3843 } else {
3844 if (!(bflags & BFLAGS_NonPublic))
3845 continue;
3846 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3847 continue;
3850 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3851 if (!(bflags & BFLAGS_Static))
3852 continue;
3853 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3854 continue;
3855 } else {
3856 if (!(bflags & BFLAGS_Instance))
3857 continue;
3859 } else
3860 if (!(bflags & BFLAGS_NonPublic))
3861 continue;
3863 g_free (event_name);
3864 return mono_event_get_object (domain, startklass, event);
3867 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3868 goto handle_parent;
3870 g_free (event_name);
3871 return NULL;
3874 static MonoArray*
3875 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3877 MonoDomain *domain;
3878 static MonoClass *System_Reflection_EventInfo;
3879 MonoClass *startklass, *klass;
3880 MonoArray *res;
3881 MonoMethod *method;
3882 MonoEvent *event;
3883 int i, match;
3884 gpointer iter;
3886 MonoPtrArray tmp_array;
3888 MONO_ARCH_SAVE_REGS;
3890 mono_ptr_array_init (tmp_array, 4);
3892 if (!System_Reflection_EventInfo)
3893 System_Reflection_EventInfo = mono_class_from_name (
3894 mono_defaults.corlib, "System.Reflection", "EventInfo");
3896 domain = mono_object_domain (type);
3897 if (type->type->byref)
3898 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3899 klass = startklass = mono_class_from_mono_type (type->type);
3901 handle_parent:
3902 if (klass->exception_type != MONO_EXCEPTION_NONE)
3903 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3905 iter = NULL;
3906 while ((event = mono_class_get_events (klass, &iter))) {
3907 match = 0;
3908 method = event->add;
3909 if (!method)
3910 method = event->remove;
3911 if (!method)
3912 method = event->raise;
3913 if (method) {
3914 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3915 if (bflags & BFLAGS_Public)
3916 match++;
3917 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3918 if (bflags & BFLAGS_NonPublic)
3919 match++;
3922 else
3923 if (bflags & BFLAGS_NonPublic)
3924 match ++;
3925 if (!match)
3926 continue;
3927 match = 0;
3928 if (method) {
3929 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3930 if (bflags & BFLAGS_Static)
3931 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3932 match++;
3933 } else {
3934 if (bflags & BFLAGS_Instance)
3935 match++;
3938 else
3939 if (bflags & BFLAGS_Instance)
3940 match ++;
3941 if (!match)
3942 continue;
3943 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3945 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3946 goto handle_parent;
3948 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3950 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3951 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3953 mono_ptr_array_destroy (tmp_array);
3955 return res;
3958 static MonoReflectionType *
3959 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3961 MonoDomain *domain;
3962 MonoClass *klass;
3963 MonoClass *nested;
3964 char *str;
3965 gpointer iter;
3967 MONO_ARCH_SAVE_REGS;
3969 if (name == NULL)
3970 mono_raise_exception (mono_get_exception_argument_null ("name"));
3972 domain = ((MonoObject *)type)->vtable->domain;
3973 if (type->type->byref)
3974 return NULL;
3975 klass = mono_class_from_mono_type (type->type);
3976 str = mono_string_to_utf8 (name);
3978 handle_parent:
3979 if (klass->exception_type != MONO_EXCEPTION_NONE)
3980 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3983 * If a nested type is generic, return its generic type definition.
3984 * Note that this means that the return value is essentially a
3985 * nested type of the generic type definition of @klass.
3987 * A note in MSDN claims that a generic type definition can have
3988 * nested types that aren't generic. In any case, the container of that
3989 * nested type would be the generic type definition.
3991 if (klass->generic_class)
3992 klass = klass->generic_class->container_class;
3994 iter = NULL;
3995 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3996 int match = 0;
3997 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3998 if (bflags & BFLAGS_Public)
3999 match++;
4000 } else {
4001 if (bflags & BFLAGS_NonPublic)
4002 match++;
4004 if (!match)
4005 continue;
4006 if (strcmp (nested->name, str) == 0){
4007 g_free (str);
4008 return mono_type_get_object (domain, &nested->byval_arg);
4011 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4012 goto handle_parent;
4013 g_free (str);
4014 return NULL;
4017 static MonoArray*
4018 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4020 MonoDomain *domain;
4021 MonoClass *klass;
4022 MonoArray *res;
4023 MonoObject *member;
4024 int i, match;
4025 MonoClass *nested;
4026 gpointer iter;
4027 MonoPtrArray tmp_array;
4029 MONO_ARCH_SAVE_REGS;
4031 domain = ((MonoObject *)type)->vtable->domain;
4032 if (type->type->byref)
4033 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4034 klass = mono_class_from_mono_type (type->type);
4035 if (klass->exception_type != MONO_EXCEPTION_NONE)
4036 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4039 * If a nested type is generic, return its generic type definition.
4040 * Note that this means that the return value is essentially the set
4041 * of nested types of the generic type definition of @klass.
4043 * A note in MSDN claims that a generic type definition can have
4044 * nested types that aren't generic. In any case, the container of that
4045 * nested type would be the generic type definition.
4047 if (klass->generic_class)
4048 klass = klass->generic_class->container_class;
4050 mono_ptr_array_init (tmp_array, 1);
4051 iter = NULL;
4052 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4053 match = 0;
4054 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4055 if (bflags & BFLAGS_Public)
4056 match++;
4057 } else {
4058 if (bflags & BFLAGS_NonPublic)
4059 match++;
4061 if (!match)
4062 continue;
4063 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4064 mono_ptr_array_append (tmp_array, member);
4067 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4069 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4070 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4072 mono_ptr_array_destroy (tmp_array);
4074 return res;
4077 static MonoReflectionType*
4078 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4080 gchar *str;
4081 MonoType *type = NULL;
4082 MonoTypeNameParse info;
4083 gboolean type_resolve;
4085 MONO_ARCH_SAVE_REGS;
4087 /* On MS.NET, this does not fire a TypeResolve event */
4088 type_resolve = TRUE;
4089 str = mono_string_to_utf8 (name);
4090 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4091 if (!mono_reflection_parse_type (str, &info)) {
4092 g_free (str);
4093 mono_reflection_free_type_info (&info);
4094 if (throwOnError) /* uhm: this is a parse error, though... */
4095 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4096 /*g_print ("failed parse\n");*/
4097 return NULL;
4100 if (info.assembly.name) {
4101 g_free (str);
4102 mono_reflection_free_type_info (&info);
4103 if (throwOnError) {
4104 /* 1.0 and 2.0 throw different exceptions */
4105 if (mono_defaults.generic_ilist_class)
4106 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4107 else
4108 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4110 return NULL;
4113 if (module != NULL) {
4114 if (module->image)
4115 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4116 else
4117 type = NULL;
4119 else
4120 if (assembly->assembly->dynamic) {
4121 /* Enumerate all modules */
4122 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4123 int i;
4125 type = NULL;
4126 if (abuilder->modules) {
4127 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4128 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4129 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4130 if (type)
4131 break;
4135 if (!type && abuilder->loaded_modules) {
4136 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4137 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4138 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4139 if (type)
4140 break;
4144 else
4145 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4146 g_free (str);
4147 mono_reflection_free_type_info (&info);
4148 if (!type) {
4149 MonoException *e = NULL;
4151 if (throwOnError)
4152 e = mono_get_exception_type_load (name, NULL);
4154 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4155 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4157 mono_loader_clear_error ();
4159 if (e != NULL)
4160 mono_raise_exception (e);
4162 return NULL;
4165 if (type->type == MONO_TYPE_CLASS) {
4166 MonoClass *klass = mono_type_get_class (type);
4168 if (mono_is_security_manager_active () && !klass->exception_type)
4169 /* Some security problems are detected during generic vtable construction */
4170 mono_class_setup_vtable (klass);
4171 /* need to report exceptions ? */
4172 if (throwOnError && klass->exception_type) {
4173 /* report SecurityException (or others) that occured when loading the assembly */
4174 MonoException *exc = mono_class_get_exception_for_failure (klass);
4175 mono_loader_clear_error ();
4176 mono_raise_exception (exc);
4177 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4178 return NULL;
4182 /* g_print ("got it\n"); */
4183 return mono_type_get_object (mono_object_domain (assembly), type);
4186 static gboolean
4187 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4189 gchar *content;
4190 gchar *shadow_ini_file;
4191 gsize len;
4193 /* Check for shadow-copied assembly */
4194 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4195 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4196 content = NULL;
4197 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4198 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4199 if (content) {
4200 g_free (content);
4201 content = NULL;
4204 g_free (shadow_ini_file);
4205 if (content != NULL) {
4206 if (*filename)
4207 g_free (*filename);
4208 *filename = content;
4209 return TRUE;
4212 return FALSE;
4215 static MonoString *
4216 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4218 MonoDomain *domain = mono_object_domain (assembly);
4219 MonoAssembly *mass = assembly->assembly;
4220 MonoString *res = NULL;
4221 gchar *uri;
4222 gchar *absolute;
4223 gchar *dirname;
4225 MONO_ARCH_SAVE_REGS;
4227 if (g_path_is_absolute (mass->image->name)) {
4228 absolute = g_strdup (mass->image->name);
4229 dirname = g_path_get_dirname (absolute);
4230 } else {
4231 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4232 dirname = g_strdup (mass->basedir);
4235 replace_shadow_path (domain, dirname, &absolute);
4236 g_free (dirname);
4237 #if HOST_WIN32
4239 gint i;
4240 for (i = strlen (absolute) - 1; i >= 0; i--)
4241 if (absolute [i] == '\\')
4242 absolute [i] = '/';
4244 #endif
4245 if (escaped) {
4246 uri = g_filename_to_uri (absolute, NULL, NULL);
4247 } else {
4248 const char *prepend = "file://";
4249 #if HOST_WIN32
4250 if (*absolute == '/' && *(absolute + 1) == '/') {
4251 prepend = "file:";
4252 } else {
4253 prepend = "file:///";
4255 #endif
4256 uri = g_strconcat (prepend, absolute, NULL);
4259 if (uri) {
4260 res = mono_string_new (domain, uri);
4261 g_free (uri);
4263 g_free (absolute);
4264 return res;
4267 static MonoBoolean
4268 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4270 MonoAssembly *mass = assembly->assembly;
4272 MONO_ARCH_SAVE_REGS;
4274 return mass->in_gac;
4277 static MonoReflectionAssembly*
4278 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4280 gchar *name;
4281 MonoAssembly *res;
4282 MonoImageOpenStatus status;
4284 MONO_ARCH_SAVE_REGS;
4286 name = mono_string_to_utf8 (mname);
4287 res = mono_assembly_load_with_partial_name (name, &status);
4289 g_free (name);
4291 if (res == NULL)
4292 return NULL;
4293 return mono_assembly_get_object (mono_domain_get (), res);
4296 static MonoString *
4297 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4299 MonoDomain *domain = mono_object_domain (assembly);
4300 MonoString *res;
4302 MONO_ARCH_SAVE_REGS;
4304 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4306 return res;
4309 static MonoBoolean
4310 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4312 MONO_ARCH_SAVE_REGS;
4314 return assembly->assembly->ref_only;
4317 static MonoString *
4318 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4320 MonoDomain *domain = mono_object_domain (assembly);
4322 MONO_ARCH_SAVE_REGS;
4324 return mono_string_new (domain, assembly->assembly->image->version);
4327 static MonoReflectionMethod*
4328 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4330 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4332 MONO_ARCH_SAVE_REGS;
4334 if (!token)
4335 return NULL;
4336 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4339 static MonoReflectionModule*
4340 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4342 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4345 static MonoArray*
4346 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4348 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4349 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4350 int i;
4351 const char *val;
4353 MONO_ARCH_SAVE_REGS;
4355 for (i = 0; i < table->rows; ++i) {
4356 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4357 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4359 return result;
4362 static MonoObject*
4363 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4365 static MonoClass *System_Version = NULL;
4366 static MonoMethod *create_version = NULL;
4367 MonoObject *result;
4368 gpointer args [4];
4370 if (!System_Version) {
4371 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4372 g_assert (System_Version);
4375 if (!create_version) {
4376 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4377 create_version = mono_method_desc_search_in_class (desc, System_Version);
4378 g_assert (create_version);
4379 mono_method_desc_free (desc);
4382 args [0] = &major;
4383 args [1] = &minor;
4384 args [2] = &build;
4385 args [3] = &revision;
4386 result = mono_object_new (domain, System_Version);
4387 mono_runtime_invoke (create_version, result, args, NULL);
4389 return result;
4392 static MonoArray*
4393 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4395 static MonoClass *System_Reflection_AssemblyName;
4396 MonoArray *result;
4397 MonoDomain *domain = mono_object_domain (assembly);
4398 int i, count = 0;
4399 static MonoMethod *create_culture = NULL;
4400 MonoImage *image = assembly->assembly->image;
4401 MonoTableInfo *t;
4403 MONO_ARCH_SAVE_REGS;
4405 if (!System_Reflection_AssemblyName)
4406 System_Reflection_AssemblyName = mono_class_from_name (
4407 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4409 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4410 count = t->rows;
4412 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4414 if (count > 0 && !create_culture) {
4415 MonoMethodDesc *desc = mono_method_desc_new (
4416 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4417 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4418 g_assert (create_culture);
4419 mono_method_desc_free (desc);
4422 for (i = 0; i < count; i++) {
4423 MonoReflectionAssemblyName *aname;
4424 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4426 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4428 aname = (MonoReflectionAssemblyName *) mono_object_new (
4429 domain, System_Reflection_AssemblyName);
4431 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4433 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4434 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4435 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4436 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4437 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4438 aname->versioncompat = 1; /* SameMachine (default) */
4439 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4440 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4442 if (create_culture) {
4443 gpointer args [2];
4444 MonoBoolean assembly_ref = 1;
4445 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4446 args [1] = &assembly_ref;
4447 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4450 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4451 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4452 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4454 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4455 /* public key token isn't copied - the class library will
4456 automatically generate it from the public key if required */
4457 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4458 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4459 } else {
4460 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4461 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4463 } else {
4464 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4467 /* note: this function doesn't return the codebase on purpose (i.e. it can
4468 be used under partial trust as path information isn't present). */
4470 mono_array_setref (result, i, aname);
4472 return result;
4475 typedef struct {
4476 MonoArray *res;
4477 int idx;
4478 } NameSpaceInfo;
4480 static void
4481 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4483 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4485 mono_array_setref (info->res, info->idx, name);
4486 info->idx++;
4489 static MonoArray*
4490 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4492 MonoImage *img = assembly->assembly->image;
4493 MonoArray *res;
4494 NameSpaceInfo info;
4495 int len;
4497 MONO_ARCH_SAVE_REGS;
4499 mono_image_lock (img);
4500 mono_image_init_name_cache (img);
4502 RETRY_LEN:
4503 len = g_hash_table_size (img->name_cache);
4504 mono_image_unlock (img);
4506 /*we can't create objects holding the image lock */
4507 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4509 mono_image_lock (img);
4510 /*len might have changed, create a new array*/
4511 if (len != g_hash_table_size (img->name_cache))
4512 goto RETRY_LEN;
4514 info.res = res;
4515 info.idx = 0;
4516 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4517 mono_image_unlock (img);
4519 return res;
4522 /* move this in some file in mono/util/ */
4523 static char *
4524 g_concat_dir_and_file (const char *dir, const char *file)
4526 g_return_val_if_fail (dir != NULL, NULL);
4527 g_return_val_if_fail (file != NULL, NULL);
4530 * If the directory name doesn't have a / on the end, we need
4531 * to add one so we get a proper path to the file
4533 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4534 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4535 else
4536 return g_strconcat (dir, file, NULL);
4539 static void *
4540 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4542 char *n = mono_string_to_utf8 (name);
4543 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4544 guint32 i;
4545 guint32 cols [MONO_MANIFEST_SIZE];
4546 guint32 impl, file_idx;
4547 const char *val;
4548 MonoImage *module;
4550 MONO_ARCH_SAVE_REGS;
4552 for (i = 0; i < table->rows; ++i) {
4553 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4554 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4555 if (strcmp (val, n) == 0)
4556 break;
4558 g_free (n);
4559 if (i == table->rows)
4560 return NULL;
4561 /* FIXME */
4562 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4563 if (impl) {
4565 * this code should only be called after obtaining the
4566 * ResourceInfo and handling the other cases.
4568 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4569 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4571 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4572 if (!module)
4573 return NULL;
4575 else
4576 module = assembly->assembly->image;
4578 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4580 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4583 static gboolean
4584 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4586 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4587 int i;
4588 guint32 cols [MONO_MANIFEST_SIZE];
4589 guint32 file_cols [MONO_FILE_SIZE];
4590 const char *val;
4591 char *n;
4593 MONO_ARCH_SAVE_REGS;
4595 n = mono_string_to_utf8 (name);
4596 for (i = 0; i < table->rows; ++i) {
4597 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4598 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4599 if (strcmp (val, n) == 0)
4600 break;
4602 g_free (n);
4603 if (i == table->rows)
4604 return FALSE;
4606 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4607 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4609 else {
4610 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4611 case MONO_IMPLEMENTATION_FILE:
4612 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4613 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4614 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4615 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4616 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4617 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4618 info->location = 0;
4619 else
4620 info->location = RESOURCE_LOCATION_EMBEDDED;
4621 break;
4623 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4624 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4625 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4626 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4627 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4628 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4629 g_free (msg);
4630 mono_raise_exception (ex);
4632 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4634 /* Obtain info recursively */
4635 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4636 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4637 break;
4639 case MONO_IMPLEMENTATION_EXP_TYPE:
4640 g_assert_not_reached ();
4641 break;
4645 return TRUE;
4648 static MonoObject*
4649 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4651 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4652 MonoArray *result = NULL;
4653 int i, count;
4654 const char *val;
4655 char *n;
4657 MONO_ARCH_SAVE_REGS;
4659 /* check hash if needed */
4660 if (name) {
4661 n = mono_string_to_utf8 (name);
4662 for (i = 0; i < table->rows; ++i) {
4663 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4664 if (strcmp (val, n) == 0) {
4665 MonoString *fn;
4666 g_free (n);
4667 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4668 fn = mono_string_new (mono_object_domain (assembly), n);
4669 g_free (n);
4670 return (MonoObject*)fn;
4673 g_free (n);
4674 return NULL;
4677 count = 0;
4678 for (i = 0; i < table->rows; ++i) {
4679 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4680 count ++;
4683 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4685 count = 0;
4686 for (i = 0; i < table->rows; ++i) {
4687 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4688 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4689 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4690 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4691 g_free (n);
4692 count ++;
4695 return (MonoObject*)result;
4698 static MonoArray*
4699 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4701 MonoDomain *domain = mono_domain_get();
4702 MonoArray *res;
4703 MonoClass *klass;
4704 int i, j, file_count = 0;
4705 MonoImage **modules;
4706 guint32 module_count, real_module_count;
4707 MonoTableInfo *table;
4708 guint32 cols [MONO_FILE_SIZE];
4709 MonoImage *image = assembly->assembly->image;
4711 g_assert (image != NULL);
4712 g_assert (!assembly->assembly->dynamic);
4714 table = &image->tables [MONO_TABLE_FILE];
4715 file_count = table->rows;
4717 modules = image->modules;
4718 module_count = image->module_count;
4720 real_module_count = 0;
4721 for (i = 0; i < module_count; ++i)
4722 if (modules [i])
4723 real_module_count ++;
4725 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4726 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4728 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4729 j = 1;
4730 for (i = 0; i < module_count; ++i)
4731 if (modules [i]) {
4732 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4733 ++j;
4736 for (i = 0; i < file_count; ++i, ++j) {
4737 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4738 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4739 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4740 else {
4741 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4742 if (!m) {
4743 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4744 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4746 mono_array_setref (res, j, mono_module_get_object (domain, m));
4750 return res;
4753 static MonoReflectionMethod*
4754 ves_icall_GetCurrentMethod (void)
4756 MonoMethod *m = mono_method_get_last_managed ();
4758 while (m->is_inflated)
4759 m = ((MonoMethodInflated*)m)->declaring;
4761 return mono_method_get_object (mono_domain_get (), m, NULL);
4765 static MonoMethod*
4766 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4768 int offset = -1, i;
4769 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4770 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4771 //method is inflated, we should inflate it on the other class
4772 MonoGenericContext ctx;
4773 ctx.method_inst = inflated->context.method_inst;
4774 ctx.class_inst = inflated->context.class_inst;
4775 if (klass->generic_class)
4776 ctx.class_inst = klass->generic_class->context.class_inst;
4777 else if (klass->generic_container)
4778 ctx.class_inst = klass->generic_container->context.class_inst;
4779 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4782 mono_class_setup_methods (method->klass);
4783 if (method->klass->exception_type)
4784 return NULL;
4785 for (i = 0; i < method->klass->method.count; ++i) {
4786 if (method->klass->methods [i] == method) {
4787 offset = i;
4788 break;
4791 mono_class_setup_methods (klass);
4792 if (klass->exception_type)
4793 return NULL;
4794 g_assert (offset >= 0 && offset < klass->method.count);
4795 return klass->methods [offset];
4798 static MonoReflectionMethod*
4799 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4801 MonoClass *klass;
4802 if (type) {
4803 klass = mono_class_from_mono_type (type);
4804 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4805 return NULL;
4806 if (method->klass != klass) {
4807 method = mono_method_get_equivalent_method (method, klass);
4808 if (!method)
4809 return NULL;
4811 } else
4812 klass = method->klass;
4813 return mono_method_get_object (mono_domain_get (), method, klass);
4816 static MonoReflectionMethod*
4817 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4819 return mono_method_get_object (mono_domain_get (), method, NULL);
4822 static MonoReflectionMethodBody*
4823 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4825 return mono_method_body_get_object (mono_domain_get (), method);
4828 static MonoReflectionAssembly*
4829 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4831 MonoMethod *dest = NULL;
4833 MONO_ARCH_SAVE_REGS;
4835 mono_stack_walk_no_il (get_executing, &dest);
4836 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4840 static MonoReflectionAssembly*
4841 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4843 MonoDomain* domain = mono_domain_get ();
4845 MONO_ARCH_SAVE_REGS;
4847 if (!domain->entry_assembly)
4848 return NULL;
4850 return mono_assembly_get_object (domain, domain->entry_assembly);
4853 static MonoReflectionAssembly*
4854 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4856 MonoMethod *m;
4857 MonoMethod *dest;
4859 MONO_ARCH_SAVE_REGS;
4861 dest = NULL;
4862 mono_stack_walk_no_il (get_executing, &dest);
4863 m = dest;
4864 mono_stack_walk_no_il (get_caller, &dest);
4865 if (!dest)
4866 dest = m;
4867 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4870 static MonoString *
4871 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4872 gboolean assembly_qualified)
4874 MonoDomain *domain = mono_object_domain (object);
4875 MonoTypeNameFormat format;
4876 MonoString *res;
4877 gchar *name;
4879 MONO_ARCH_SAVE_REGS;
4880 if (full_name)
4881 format = assembly_qualified ?
4882 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4883 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4884 else
4885 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4887 name = mono_type_get_name_full (object->type, format);
4888 if (!name)
4889 return NULL;
4891 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4892 g_free (name);
4893 return NULL;
4896 res = mono_string_new (domain, name);
4897 g_free (name);
4899 return res;
4902 static int
4903 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4905 MonoClass *klass = mono_class_from_mono_type (this->type);
4906 return mono_security_core_clr_class_level (klass);
4909 static void
4910 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4912 static MonoMethod *create_culture = NULL;
4913 gpointer args [2];
4914 guint32 pkey_len;
4915 const char *pkey_ptr;
4916 gchar *codebase;
4917 MonoBoolean assembly_ref = 0;
4919 MONO_ARCH_SAVE_REGS;
4921 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4922 aname->major = name->major;
4923 aname->minor = name->minor;
4924 aname->build = name->build;
4925 aname->flags = name->flags;
4926 aname->revision = name->revision;
4927 aname->hashalg = name->hash_alg;
4928 aname->versioncompat = 1; /* SameMachine (default) */
4930 if (by_default_version)
4931 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4933 codebase = NULL;
4934 if (absolute != NULL && *absolute != '\0') {
4935 const gchar *prepend = "file://";
4936 gchar *result;
4938 codebase = g_strdup (absolute);
4940 #if HOST_WIN32
4942 gint i;
4943 for (i = strlen (codebase) - 1; i >= 0; i--)
4944 if (codebase [i] == '\\')
4945 codebase [i] = '/';
4947 if (*codebase == '/' && *(codebase + 1) == '/') {
4948 prepend = "file:";
4949 } else {
4950 prepend = "file:///";
4953 #endif
4954 result = g_strconcat (prepend, codebase, NULL);
4955 g_free (codebase);
4956 codebase = result;
4959 if (codebase) {
4960 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4961 g_free (codebase);
4964 if (!create_culture) {
4965 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4966 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4967 g_assert (create_culture);
4968 mono_method_desc_free (desc);
4971 if (name->culture) {
4972 args [0] = mono_string_new (domain, name->culture);
4973 args [1] = &assembly_ref;
4974 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4977 if (name->public_key) {
4978 pkey_ptr = (char*)name->public_key;
4979 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4981 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4982 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4983 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4984 } else if (default_publickey) {
4985 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4986 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4989 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4990 if (name->public_key_token [0]) {
4991 int i, j;
4992 char *p;
4994 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4995 p = mono_array_addr (aname->keyToken, char, 0);
4997 for (i = 0, j = 0; i < 8; i++) {
4998 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4999 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5000 p++;
5002 } else if (default_token) {
5003 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5007 static MonoString *
5008 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5010 MonoDomain *domain = mono_object_domain (assembly);
5011 MonoAssembly *mass = assembly->assembly;
5012 MonoString *res;
5013 gchar *name;
5015 name = g_strdup_printf (
5016 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5017 mass->aname.name,
5018 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5019 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5020 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5021 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5023 res = mono_string_new (domain, name);
5024 g_free (name);
5026 return res;
5029 static void
5030 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5032 gchar *absolute;
5033 MonoAssembly *mass = assembly->assembly;
5035 MONO_ARCH_SAVE_REGS;
5037 if (g_path_is_absolute (mass->image->name)) {
5038 fill_reflection_assembly_name (mono_object_domain (assembly),
5039 aname, &mass->aname, mass->image->name, TRUE,
5040 TRUE, TRUE);
5041 return;
5043 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5045 fill_reflection_assembly_name (mono_object_domain (assembly),
5046 aname, &mass->aname, absolute, TRUE, TRUE,
5047 TRUE);
5049 g_free (absolute);
5052 static void
5053 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5055 char *filename;
5056 MonoImageOpenStatus status = MONO_IMAGE_OK;
5057 gboolean res;
5058 MonoImage *image;
5059 MonoAssemblyName name;
5060 char *dirname
5062 MONO_ARCH_SAVE_REGS;
5064 filename = mono_string_to_utf8 (fname);
5066 dirname = g_path_get_dirname (filename);
5067 replace_shadow_path (mono_domain_get (), dirname, &filename);
5068 g_free (dirname);
5070 image = mono_image_open (filename, &status);
5072 if (!image){
5073 MonoException *exc;
5075 g_free (filename);
5076 if (status == MONO_IMAGE_IMAGE_INVALID)
5077 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5078 else
5079 exc = mono_get_exception_file_not_found2 (NULL, fname);
5080 mono_raise_exception (exc);
5083 res = mono_assembly_fill_assembly_name (image, &name);
5084 if (!res) {
5085 mono_image_close (image);
5086 g_free (filename);
5087 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5090 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5091 TRUE, FALSE, TRUE);
5093 g_free (filename);
5094 mono_image_close (image);
5097 static MonoBoolean
5098 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5099 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5101 MonoBoolean result = FALSE;
5102 MonoDeclSecurityEntry entry;
5104 /* SecurityAction.RequestMinimum */
5105 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5106 *minimum = entry.blob;
5107 *minLength = entry.size;
5108 result = TRUE;
5110 /* SecurityAction.RequestOptional */
5111 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5112 *optional = entry.blob;
5113 *optLength = entry.size;
5114 result = TRUE;
5116 /* SecurityAction.RequestRefuse */
5117 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5118 *refused = entry.blob;
5119 *refLength = entry.size;
5120 result = TRUE;
5123 return result;
5126 static MonoArray*
5127 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5129 MonoArray *res;
5130 MonoClass *klass;
5131 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5132 int i, count;
5133 guint32 attrs, visibility;
5135 /* we start the count from 1 because we skip the special type <Module> */
5136 if (exportedOnly) {
5137 count = 0;
5138 for (i = 1; i < tdef->rows; ++i) {
5139 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5140 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5141 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5142 count++;
5144 } else {
5145 count = tdef->rows - 1;
5147 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5148 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5149 count = 0;
5150 for (i = 1; i < tdef->rows; ++i) {
5151 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5152 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5153 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5154 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5155 if (klass) {
5156 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5157 } else {
5158 MonoLoaderError *error;
5159 MonoException *ex;
5161 error = mono_loader_get_last_error ();
5162 g_assert (error != NULL);
5164 ex = mono_loader_error_prepare_exception (error);
5165 mono_array_setref (*exceptions, count, ex);
5167 if (mono_loader_get_last_error ())
5168 mono_loader_clear_error ();
5169 count++;
5173 return res;
5176 static MonoArray*
5177 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5179 MonoArray *res = NULL;
5180 MonoArray *exceptions = NULL;
5181 MonoImage *image = NULL;
5182 MonoTableInfo *table = NULL;
5183 MonoDomain *domain;
5184 GList *list = NULL;
5185 int i, len, ex_count;
5187 MONO_ARCH_SAVE_REGS;
5189 domain = mono_object_domain (assembly);
5191 g_assert (!assembly->assembly->dynamic);
5192 image = assembly->assembly->image;
5193 table = &image->tables [MONO_TABLE_FILE];
5194 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5196 /* Append data from all modules in the assembly */
5197 for (i = 0; i < table->rows; ++i) {
5198 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5199 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5200 if (loaded_image) {
5201 MonoArray *ex2;
5202 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5203 /* Append the new types to the end of the array */
5204 if (mono_array_length (res2) > 0) {
5205 guint32 len1, len2;
5206 MonoArray *res3, *ex3;
5208 len1 = mono_array_length (res);
5209 len2 = mono_array_length (res2);
5211 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5212 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5213 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5214 res = res3;
5216 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5217 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5218 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5219 exceptions = ex3;
5225 /* the ReflectionTypeLoadException must have all the types (Types property),
5226 * NULL replacing types which throws an exception. The LoaderException must
5227 * contain all exceptions for NULL items.
5230 len = mono_array_length (res);
5232 ex_count = 0;
5233 for (i = 0; i < len; i++) {
5234 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5235 MonoClass *klass;
5237 if (t) {
5238 klass = mono_type_get_class (t->type);
5239 if ((klass != NULL) && klass->exception_type) {
5240 /* keep the class in the list */
5241 list = g_list_append (list, klass);
5242 /* and replace Type with NULL */
5243 mono_array_setref (res, i, NULL);
5245 } else {
5246 ex_count ++;
5250 if (list || ex_count) {
5251 GList *tmp = NULL;
5252 MonoException *exc = NULL;
5253 MonoArray *exl = NULL;
5254 int j, length = g_list_length (list) + ex_count;
5256 mono_loader_clear_error ();
5258 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5259 /* Types for which mono_class_get () succeeded */
5260 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5261 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5262 mono_array_setref (exl, i, exc);
5264 /* Types for which it don't */
5265 for (j = 0; j < mono_array_length (exceptions); ++j) {
5266 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5267 if (exc) {
5268 g_assert (i < length);
5269 mono_array_setref (exl, i, exc);
5270 i ++;
5273 g_list_free (list);
5274 list = NULL;
5276 exc = mono_get_exception_reflection_type_load (res, exl);
5277 mono_loader_clear_error ();
5278 mono_raise_exception (exc);
5281 return res;
5284 static gboolean
5285 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5287 MonoAssemblyName aname;
5288 MonoDomain *domain = mono_object_domain (name);
5289 char *val;
5290 gboolean is_version_defined;
5291 gboolean is_token_defined;
5293 aname.public_key = NULL;
5294 val = mono_string_to_utf8 (assname);
5295 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5296 g_free ((guint8*) aname.public_key);
5297 g_free (val);
5298 return FALSE;
5301 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5302 FALSE, is_token_defined);
5304 mono_assembly_name_free (&aname);
5305 g_free ((guint8*) aname.public_key);
5306 g_free (val);
5308 return TRUE;
5311 static MonoReflectionType*
5312 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5314 MonoDomain *domain = mono_object_domain (module);
5315 MonoClass *klass;
5317 MONO_ARCH_SAVE_REGS;
5319 g_assert (module->image);
5321 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5322 /* These images do not have a global type */
5323 return NULL;
5325 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5326 return mono_type_get_object (domain, &klass->byval_arg);
5329 static void
5330 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5332 /*if (module->image)
5333 mono_image_close (module->image);*/
5336 static MonoString*
5337 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5339 MonoDomain *domain = mono_object_domain (module);
5341 MONO_ARCH_SAVE_REGS;
5343 g_assert (module->image);
5344 return mono_string_new (domain, module->image->guid);
5347 static gpointer
5348 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5350 #ifdef HOST_WIN32
5351 if (module->image && module->image->is_module_handle)
5352 return module->image->raw_data;
5353 #endif
5355 return (gpointer) (-1);
5358 static void
5359 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5361 if (image->dynamic) {
5362 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5363 *pe_kind = dyn->pe_kind;
5364 *machine = dyn->machine;
5366 else {
5367 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5368 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5372 static gint32
5373 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5375 return (image->md_version_major << 16) | (image->md_version_minor);
5378 static MonoArray*
5379 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5381 MonoArray *exceptions;
5382 int i;
5384 MONO_ARCH_SAVE_REGS;
5386 if (!module->image)
5387 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5388 else {
5389 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5390 for (i = 0; i < mono_array_length (exceptions); ++i) {
5391 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5392 if (ex)
5393 mono_raise_exception (ex);
5395 return res;
5399 static gboolean
5400 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5402 guint32 cols [MONO_MEMBERREF_SIZE];
5403 const char *sig;
5404 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5405 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5406 mono_metadata_decode_blob_size (sig, &sig);
5407 return (*sig != 0x6);
5410 static void
5411 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5413 if (type_args)
5414 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5415 mono_array_addr (type_args, MonoType*, 0));
5416 else
5417 context->class_inst = NULL;
5418 if (method_args)
5419 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5420 mono_array_addr (method_args, MonoType*, 0));
5421 else
5422 context->method_inst = NULL;
5425 static MonoType*
5426 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5428 MonoClass *klass;
5429 int table = mono_metadata_token_table (token);
5430 int index = mono_metadata_token_index (token);
5431 MonoGenericContext context;
5433 *error = ResolveTokenError_Other;
5435 /* Validate token */
5436 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5437 (table != MONO_TABLE_TYPESPEC)) {
5438 *error = ResolveTokenError_BadTable;
5439 return NULL;
5442 if (image->dynamic) {
5443 if (type_args || method_args)
5444 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5445 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5446 if (!klass)
5447 return NULL;
5448 return &klass->byval_arg;
5451 if ((index <= 0) || (index > image->tables [table].rows)) {
5452 *error = ResolveTokenError_OutOfRange;
5453 return NULL;
5456 init_generic_context_from_args (&context, type_args, method_args);
5457 klass = mono_class_get_full (image, token, &context);
5459 if (mono_loader_get_last_error ())
5460 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5462 if (klass)
5463 return &klass->byval_arg;
5464 else
5465 return NULL;
5468 static MonoMethod*
5469 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5471 int table = mono_metadata_token_table (token);
5472 int index = mono_metadata_token_index (token);
5473 MonoGenericContext context;
5474 MonoMethod *method;
5476 *error = ResolveTokenError_Other;
5478 /* Validate token */
5479 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5480 (table != MONO_TABLE_MEMBERREF)) {
5481 *error = ResolveTokenError_BadTable;
5482 return NULL;
5485 if (image->dynamic) {
5486 if (type_args || method_args)
5487 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5488 /* FIXME: validate memberref token type */
5489 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5492 if ((index <= 0) || (index > image->tables [table].rows)) {
5493 *error = ResolveTokenError_OutOfRange;
5494 return NULL;
5496 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5497 *error = ResolveTokenError_BadTable;
5498 return NULL;
5501 init_generic_context_from_args (&context, type_args, method_args);
5502 method = mono_get_method_full (image, token, NULL, &context);
5504 if (mono_loader_get_last_error ())
5505 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5507 return method;
5510 static MonoString*
5511 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5513 int index = mono_metadata_token_index (token);
5515 *error = ResolveTokenError_Other;
5517 /* Validate token */
5518 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5519 *error = ResolveTokenError_BadTable;
5520 return NULL;
5523 if (image->dynamic)
5524 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5526 if ((index <= 0) || (index >= image->heap_us.size)) {
5527 *error = ResolveTokenError_OutOfRange;
5528 return NULL;
5531 /* FIXME: What to do if the index points into the middle of a string ? */
5533 return mono_ldstr (mono_domain_get (), image, index);
5536 static MonoClassField*
5537 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5539 MonoClass *klass;
5540 int table = mono_metadata_token_table (token);
5541 int index = mono_metadata_token_index (token);
5542 MonoGenericContext context;
5543 MonoClassField *field;
5545 *error = ResolveTokenError_Other;
5547 /* Validate token */
5548 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5549 *error = ResolveTokenError_BadTable;
5550 return NULL;
5553 if (image->dynamic) {
5554 if (type_args || method_args)
5555 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5556 /* FIXME: validate memberref token type */
5557 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5560 if ((index <= 0) || (index > image->tables [table].rows)) {
5561 *error = ResolveTokenError_OutOfRange;
5562 return NULL;
5564 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5565 *error = ResolveTokenError_BadTable;
5566 return NULL;
5569 init_generic_context_from_args (&context, type_args, method_args);
5570 field = mono_field_from_token (image, token, &klass, &context);
5572 if (mono_loader_get_last_error ())
5573 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5575 return field;
5579 static MonoObject*
5580 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5582 int table = mono_metadata_token_table (token);
5584 *error = ResolveTokenError_Other;
5586 switch (table) {
5587 case MONO_TABLE_TYPEDEF:
5588 case MONO_TABLE_TYPEREF:
5589 case MONO_TABLE_TYPESPEC: {
5590 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5591 if (t)
5592 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5593 else
5594 return NULL;
5596 case MONO_TABLE_METHOD:
5597 case MONO_TABLE_METHODSPEC: {
5598 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5599 if (m)
5600 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5601 else
5602 return NULL;
5604 case MONO_TABLE_FIELD: {
5605 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5606 if (f)
5607 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5608 else
5609 return NULL;
5611 case MONO_TABLE_MEMBERREF:
5612 if (mono_metadata_memberref_is_method (image, token)) {
5613 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5614 if (m)
5615 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5616 else
5617 return NULL;
5619 else {
5620 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5621 if (f)
5622 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5623 else
5624 return NULL;
5626 break;
5628 default:
5629 *error = ResolveTokenError_BadTable;
5632 return NULL;
5635 static MonoArray*
5636 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5638 int table = mono_metadata_token_table (token);
5639 int idx = mono_metadata_token_index (token);
5640 MonoTableInfo *tables = image->tables;
5641 guint32 sig, len;
5642 const char *ptr;
5643 MonoArray *res;
5645 *error = ResolveTokenError_OutOfRange;
5647 /* FIXME: Support other tables ? */
5648 if (table != MONO_TABLE_STANDALONESIG)
5649 return NULL;
5651 if (image->dynamic)
5652 return NULL;
5654 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5655 return NULL;
5657 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5659 ptr = mono_metadata_blob_heap (image, sig);
5660 len = mono_metadata_decode_blob_size (ptr, &ptr);
5662 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5663 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5664 return res;
5667 static MonoReflectionType*
5668 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5670 MonoClass *klass;
5671 int isbyref = 0, rank;
5672 char *str = mono_string_to_utf8 (smodifiers);
5673 char *p;
5675 MONO_ARCH_SAVE_REGS;
5677 klass = mono_class_from_mono_type (tb->type.type);
5678 p = str;
5679 /* logic taken from mono_reflection_parse_type(): keep in sync */
5680 while (*p) {
5681 switch (*p) {
5682 case '&':
5683 if (isbyref) { /* only one level allowed by the spec */
5684 g_free (str);
5685 return NULL;
5687 isbyref = 1;
5688 p++;
5689 g_free (str);
5690 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5691 break;
5692 case '*':
5693 klass = mono_ptr_class_get (&klass->byval_arg);
5694 mono_class_init (klass);
5695 p++;
5696 break;
5697 case '[':
5698 rank = 1;
5699 p++;
5700 while (*p) {
5701 if (*p == ']')
5702 break;
5703 if (*p == ',')
5704 rank++;
5705 else if (*p != '*') { /* '*' means unknown lower bound */
5706 g_free (str);
5707 return NULL;
5709 ++p;
5711 if (*p != ']') {
5712 g_free (str);
5713 return NULL;
5715 p++;
5716 klass = mono_array_class_get (klass, rank);
5717 mono_class_init (klass);
5718 break;
5719 default:
5720 break;
5723 g_free (str);
5724 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5727 static MonoBoolean
5728 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5730 MonoType *type;
5731 MonoBoolean res;
5733 MONO_ARCH_SAVE_REGS;
5735 type = t->type;
5736 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5738 return res;
5741 static MonoReflectionType *
5742 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5744 MonoClass *klass, *aklass;
5746 MONO_ARCH_SAVE_REGS;
5748 klass = mono_class_from_mono_type (type->type);
5749 if (rank == 0) //single dimentional array
5750 aklass = mono_array_class_get (klass, 1);
5751 else
5752 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5754 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5757 static MonoReflectionType *
5758 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5760 MonoClass *klass;
5762 MONO_ARCH_SAVE_REGS;
5764 klass = mono_class_from_mono_type (type->type);
5766 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5769 static MonoReflectionType *
5770 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5772 MonoClass *pklass;
5774 MONO_ARCH_SAVE_REGS;
5776 pklass = mono_ptr_class_get (type->type);
5778 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5781 static MonoObject *
5782 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5783 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5785 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5786 MonoObject *delegate;
5787 gpointer func;
5788 MonoMethod *method = info->method;
5790 MONO_ARCH_SAVE_REGS;
5792 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5794 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5795 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5796 return NULL;
5799 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5801 if (method->dynamic) {
5802 /* Creating a trampoline would leak memory */
5803 func = mono_compile_method (method);
5804 } else {
5805 func = mono_create_ftnptr (mono_domain_get (),
5806 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5809 mono_delegate_ctor_with_method (delegate, target, func, method);
5811 return delegate;
5814 static void
5815 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5817 /* Reset the invoke impl to the default one */
5818 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5822 * Magic number to convert a time which is relative to
5823 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5825 #define EPOCH_ADJUST ((guint64)62135596800LL)
5828 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5830 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5832 #ifdef HOST_WIN32
5833 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5834 static void
5835 convert_to_absolute_date(SYSTEMTIME *date)
5837 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5838 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5839 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5840 /* from the calendar FAQ */
5841 int a = (14 - date->wMonth) / 12;
5842 int y = date->wYear - a;
5843 int m = date->wMonth + 12 * a - 2;
5844 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5846 /* d is now the day of the week for the first of the month (0 == Sunday) */
5848 int day_of_week = date->wDayOfWeek;
5850 /* set day_in_month to the first day in the month which falls on day_of_week */
5851 int day_in_month = 1 + (day_of_week - d);
5852 if (day_in_month <= 0)
5853 day_in_month += 7;
5855 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5856 date->wDay = day_in_month + (date->wDay - 1) * 7;
5857 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5858 date->wDay -= 7;
5860 #endif
5862 #ifndef HOST_WIN32
5864 * Return's the offset from GMT of a local time.
5866 * tm is a local time
5867 * t is the same local time as seconds.
5869 static int
5870 gmt_offset(struct tm *tm, time_t t)
5872 #if defined (HAVE_TM_GMTOFF)
5873 return tm->tm_gmtoff;
5874 #else
5875 struct tm g;
5876 time_t t2;
5877 g = *gmtime(&t);
5878 g.tm_isdst = tm->tm_isdst;
5879 t2 = mktime(&g);
5880 return (int)difftime(t, t2);
5881 #endif
5883 #endif
5885 * This is heavily based on zdump.c from glibc 2.2.
5887 * * data[0]: start of daylight saving time (in DateTime ticks).
5888 * * data[1]: end of daylight saving time (in DateTime ticks).
5889 * * data[2]: utcoffset (in TimeSpan ticks).
5890 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5891 * * name[0]: name of this timezone when not daylight saving.
5892 * * name[1]: name of this timezone when daylight saving.
5894 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5895 * the class library allows years between 1 and 9999.
5897 * Returns true on success and zero on failure.
5899 static guint32
5900 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5902 #ifndef HOST_WIN32
5903 MonoDomain *domain = mono_domain_get ();
5904 struct tm start, tt;
5905 time_t t;
5907 long int gmtoff;
5908 int is_daylight = 0, day;
5909 char tzone [64];
5911 MONO_ARCH_SAVE_REGS;
5913 MONO_CHECK_ARG_NULL (data);
5914 MONO_CHECK_ARG_NULL (names);
5916 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5917 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5920 * no info is better than crashing: we'll need our own tz data
5921 * to make this work properly, anyway. The range is probably
5922 * reduced to 1970 .. 2037 because that is what mktime is
5923 * guaranteed to support (we get into an infinite loop
5924 * otherwise).
5927 memset (&start, 0, sizeof (start));
5929 start.tm_mday = 1;
5930 start.tm_year = year-1900;
5932 t = mktime (&start);
5934 if ((year < 1970) || (year > 2037) || (t == -1)) {
5935 t = time (NULL);
5936 tt = *localtime (&t);
5937 strftime (tzone, sizeof (tzone), "%Z", &tt);
5938 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5939 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5940 return 1;
5943 gmtoff = gmt_offset (&start, t);
5945 /* For each day of the year, calculate the tm_gmtoff. */
5946 for (day = 0; day < 365; day++) {
5948 t += 3600*24;
5949 tt = *localtime (&t);
5951 /* Daylight saving starts or ends here. */
5952 if (gmt_offset (&tt, t) != gmtoff) {
5953 struct tm tt1;
5954 time_t t1;
5956 /* Try to find the exact hour when daylight saving starts/ends. */
5957 t1 = t;
5958 do {
5959 t1 -= 3600;
5960 tt1 = *localtime (&t1);
5961 } while (gmt_offset (&tt1, t1) != gmtoff);
5963 /* Try to find the exact minute when daylight saving starts/ends. */
5964 do {
5965 t1 += 60;
5966 tt1 = *localtime (&t1);
5967 } while (gmt_offset (&tt1, t1) == gmtoff);
5968 t1+=gmtoff;
5969 strftime (tzone, sizeof (tzone), "%Z", &tt);
5971 /* Write data, if we're already in daylight saving, we're done. */
5972 if (is_daylight) {
5973 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5974 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5975 return 1;
5976 } else {
5977 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5978 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5979 is_daylight = 1;
5982 /* This is only set once when we enter daylight saving. */
5983 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5984 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5986 gmtoff = gmt_offset (&tt, t);
5990 if (!is_daylight) {
5991 strftime (tzone, sizeof (tzone), "%Z", &tt);
5992 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5993 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5994 mono_array_set ((*data), gint64, 0, 0);
5995 mono_array_set ((*data), gint64, 1, 0);
5996 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5997 mono_array_set ((*data), gint64, 3, 0);
6000 return 1;
6001 #else
6002 MonoDomain *domain = mono_domain_get ();
6003 TIME_ZONE_INFORMATION tz_info;
6004 FILETIME ft;
6005 int i;
6006 int err, tz_id;
6008 tz_id = GetTimeZoneInformation (&tz_info);
6009 if (tz_id == TIME_ZONE_ID_INVALID)
6010 return 0;
6012 MONO_CHECK_ARG_NULL (data);
6013 MONO_CHECK_ARG_NULL (names);
6015 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6016 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6018 for (i = 0; i < 32; ++i)
6019 if (!tz_info.DaylightName [i])
6020 break;
6021 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6022 for (i = 0; i < 32; ++i)
6023 if (!tz_info.StandardName [i])
6024 break;
6025 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6027 if ((year <= 1601) || (year > 30827)) {
6029 * According to MSDN, the MS time functions can't handle dates outside
6030 * this interval.
6032 return 1;
6035 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6036 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6037 tz_info.StandardDate.wYear = year;
6038 convert_to_absolute_date(&tz_info.StandardDate);
6039 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6040 //g_assert(err);
6041 if (err == 0)
6042 return 0;
6044 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6045 tz_info.DaylightDate.wYear = year;
6046 convert_to_absolute_date(&tz_info.DaylightDate);
6047 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6048 //g_assert(err);
6049 if (err == 0)
6050 return 0;
6052 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6054 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6055 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6057 return 1;
6058 #endif
6061 static gpointer
6062 ves_icall_System_Object_obj_address (MonoObject *this)
6064 MONO_ARCH_SAVE_REGS;
6066 return this;
6069 /* System.Buffer */
6071 static inline gint32
6072 mono_array_get_byte_length (MonoArray *array)
6074 MonoClass *klass;
6075 int length;
6076 int i;
6078 klass = array->obj.vtable->klass;
6080 if (array->bounds == NULL)
6081 length = array->max_length;
6082 else {
6083 length = 1;
6084 for (i = 0; i < klass->rank; ++ i)
6085 length *= array->bounds [i].length;
6088 switch (klass->element_class->byval_arg.type) {
6089 case MONO_TYPE_I1:
6090 case MONO_TYPE_U1:
6091 case MONO_TYPE_BOOLEAN:
6092 return length;
6093 case MONO_TYPE_I2:
6094 case MONO_TYPE_U2:
6095 case MONO_TYPE_CHAR:
6096 return length << 1;
6097 case MONO_TYPE_I4:
6098 case MONO_TYPE_U4:
6099 case MONO_TYPE_R4:
6100 return length << 2;
6101 case MONO_TYPE_I:
6102 case MONO_TYPE_U:
6103 return length * sizeof (gpointer);
6104 case MONO_TYPE_I8:
6105 case MONO_TYPE_U8:
6106 case MONO_TYPE_R8:
6107 return length << 3;
6108 default:
6109 return -1;
6113 static gint32
6114 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6116 MONO_ARCH_SAVE_REGS;
6118 return mono_array_get_byte_length (array);
6121 static gint8
6122 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6124 MONO_ARCH_SAVE_REGS;
6126 return mono_array_get (array, gint8, idx);
6129 static void
6130 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6132 MONO_ARCH_SAVE_REGS;
6134 mono_array_set (array, gint8, idx, value);
6137 static MonoBoolean
6138 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6140 guint8 *src_buf, *dest_buf;
6142 MONO_ARCH_SAVE_REGS;
6144 /* watch out for integer overflow */
6145 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6146 return FALSE;
6148 src_buf = (guint8 *)src->vector + src_offset;
6149 dest_buf = (guint8 *)dest->vector + dest_offset;
6151 if (src != dest)
6152 memcpy (dest_buf, src_buf, count);
6153 else
6154 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6156 return TRUE;
6159 static MonoObject *
6160 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6162 MonoDomain *domain = mono_object_domain (this);
6163 MonoObject *res;
6164 MonoRealProxy *rp = ((MonoRealProxy *)this);
6165 MonoTransparentProxy *tp;
6166 MonoType *type;
6167 MonoClass *klass;
6169 MONO_ARCH_SAVE_REGS;
6171 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6172 tp = (MonoTransparentProxy*) res;
6174 MONO_OBJECT_SETREF (tp, rp, rp);
6175 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6176 klass = mono_class_from_mono_type (type);
6178 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6179 tp->remote_class = mono_remote_class (domain, class_name, klass);
6181 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6182 return res;
6185 static MonoReflectionType *
6186 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6188 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6191 /* System.Environment */
6193 MonoString*
6194 ves_icall_System_Environment_get_UserName (void)
6196 MONO_ARCH_SAVE_REGS;
6198 /* using glib is more portable */
6199 return mono_string_new (mono_domain_get (), g_get_user_name ());
6203 static MonoString *
6204 ves_icall_System_Environment_get_MachineName (void)
6206 #if defined (HOST_WIN32)
6207 gunichar2 *buf;
6208 guint32 len;
6209 MonoString *result;
6211 len = MAX_COMPUTERNAME_LENGTH + 1;
6212 buf = g_new (gunichar2, len);
6214 result = NULL;
6215 if (GetComputerName (buf, (PDWORD) &len))
6216 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6218 g_free (buf);
6219 return result;
6220 #elif !defined(DISABLE_SOCKETS)
6221 gchar buf [256];
6222 MonoString *result;
6224 if (gethostname (buf, sizeof (buf)) == 0)
6225 result = mono_string_new (mono_domain_get (), buf);
6226 else
6227 result = NULL;
6229 return result;
6230 #else
6231 return mono_string_new (mono_domain_get (), "mono");
6232 #endif
6235 static int
6236 ves_icall_System_Environment_get_Platform (void)
6238 #if defined (TARGET_WIN32)
6239 /* Win32NT */
6240 return 2;
6241 #elif defined(__MACH__)
6242 /* OSX */
6244 // For compatibility with our client code, this will be 4 for a while.
6245 // We will eventually move to 6 to match .NET, but it requires all client
6246 // code to be updated and the documentation everywhere to be updated
6247 // first.
6249 return 4;
6250 #else
6251 /* Unix */
6252 return 4;
6253 #endif
6256 static MonoString *
6257 ves_icall_System_Environment_get_NewLine (void)
6259 MONO_ARCH_SAVE_REGS;
6261 #if defined (HOST_WIN32)
6262 return mono_string_new (mono_domain_get (), "\r\n");
6263 #else
6264 return mono_string_new (mono_domain_get (), "\n");
6265 #endif
6268 static MonoString *
6269 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6271 const gchar *value;
6272 gchar *utf8_name;
6274 MONO_ARCH_SAVE_REGS;
6276 if (name == NULL)
6277 return NULL;
6279 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6280 value = g_getenv (utf8_name);
6282 g_free (utf8_name);
6284 if (value == 0)
6285 return NULL;
6287 return mono_string_new (mono_domain_get (), value);
6291 * There is no standard way to get at environ.
6293 #ifndef _MSC_VER
6294 #ifndef __MINGW32_VERSION
6295 #ifdef __APPLE__
6296 /* Apple defines this in crt_externs.h but doesn't provide that header for
6297 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6298 * in fact exist on all implementations (so far)
6300 gchar ***_NSGetEnviron(void);
6301 #define environ (*_NSGetEnviron())
6302 #else
6303 extern
6304 char **environ;
6305 #endif
6306 #endif
6307 #endif
6309 static MonoArray *
6310 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6312 #ifdef HOST_WIN32
6313 MonoArray *names;
6314 MonoDomain *domain;
6315 MonoString *str;
6316 WCHAR* env_strings;
6317 WCHAR* env_string;
6318 WCHAR* equal_str;
6319 int n = 0;
6321 env_strings = GetEnvironmentStrings();
6323 if (env_strings) {
6324 env_string = env_strings;
6325 while (*env_string != '\0') {
6326 /* weird case that MS seems to skip */
6327 if (*env_string != '=')
6328 n++;
6329 while (*env_string != '\0')
6330 env_string++;
6331 env_string++;
6335 domain = mono_domain_get ();
6336 names = mono_array_new (domain, mono_defaults.string_class, n);
6338 if (env_strings) {
6339 n = 0;
6340 env_string = env_strings;
6341 while (*env_string != '\0') {
6342 /* weird case that MS seems to skip */
6343 if (*env_string != '=') {
6344 equal_str = wcschr(env_string, '=');
6345 g_assert(equal_str);
6346 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6347 mono_array_setref (names, n, str);
6348 n++;
6350 while (*env_string != '\0')
6351 env_string++;
6352 env_string++;
6355 FreeEnvironmentStrings (env_strings);
6358 return names;
6360 #else
6361 MonoArray *names;
6362 MonoDomain *domain;
6363 MonoString *str;
6364 gchar **e, **parts;
6365 int n;
6367 MONO_ARCH_SAVE_REGS;
6369 n = 0;
6370 for (e = environ; *e != 0; ++ e)
6371 ++ n;
6373 domain = mono_domain_get ();
6374 names = mono_array_new (domain, mono_defaults.string_class, n);
6376 n = 0;
6377 for (e = environ; *e != 0; ++ e) {
6378 parts = g_strsplit (*e, "=", 2);
6379 if (*parts != 0) {
6380 str = mono_string_new (domain, *parts);
6381 mono_array_setref (names, n, str);
6384 g_strfreev (parts);
6386 ++ n;
6389 return names;
6390 #endif
6394 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6396 #if !GLIB_CHECK_VERSION(2,4,0)
6397 #define g_setenv(a,b,c) setenv(a,b,c)
6398 #define g_unsetenv(a) unsetenv(a)
6399 #endif
6401 static void
6402 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6404 MonoError error;
6405 #ifdef HOST_WIN32
6407 gunichar2 *utf16_name, *utf16_value;
6408 #else
6409 gchar *utf8_name, *utf8_value;
6410 #endif
6412 MONO_ARCH_SAVE_REGS;
6414 #ifdef HOST_WIN32
6415 utf16_name = mono_string_to_utf16 (name);
6416 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6417 SetEnvironmentVariable (utf16_name, NULL);
6418 g_free (utf16_name);
6419 return;
6422 utf16_value = mono_string_to_utf16 (value);
6424 SetEnvironmentVariable (utf16_name, utf16_value);
6426 g_free (utf16_name);
6427 g_free (utf16_value);
6428 #else
6429 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6431 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6432 g_unsetenv (utf8_name);
6433 g_free (utf8_name);
6434 return;
6437 utf8_value = mono_string_to_utf8_checked (value, &error);
6438 if (!mono_error_ok (&error)) {
6439 g_free (utf8_name);
6440 mono_error_raise_exception (&error);
6442 g_setenv (utf8_name, utf8_value, TRUE);
6444 g_free (utf8_name);
6445 g_free (utf8_value);
6446 #endif
6449 static void
6450 ves_icall_System_Environment_Exit (int result)
6452 MONO_ARCH_SAVE_REGS;
6454 mono_threads_set_shutting_down ();
6456 mono_runtime_set_shutting_down ();
6458 /* Suspend all managed threads since the runtime is going away */
6459 mono_thread_suspend_all_other_threads ();
6461 mono_runtime_quit ();
6463 /* we may need to do some cleanup here... */
6464 exit (result);
6467 static MonoString*
6468 ves_icall_System_Environment_GetGacPath (void)
6470 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6473 static MonoString*
6474 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6476 #if defined (HOST_WIN32)
6477 #ifndef CSIDL_FLAG_CREATE
6478 #define CSIDL_FLAG_CREATE 0x8000
6479 #endif
6481 WCHAR path [MAX_PATH];
6482 /* Create directory if no existing */
6483 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6484 int len = 0;
6485 while (path [len])
6486 ++ len;
6487 return mono_string_new_utf16 (mono_domain_get (), path, len);
6489 #else
6490 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6491 #endif
6492 return mono_string_new (mono_domain_get (), "");
6495 static MonoArray *
6496 ves_icall_System_Environment_GetLogicalDrives (void)
6498 gunichar2 buf [128], *ptr, *dname;
6499 gunichar2 *u16;
6500 guint initial_size = 127, size = 128;
6501 gint ndrives;
6502 MonoArray *result;
6503 MonoString *drivestr;
6504 MonoDomain *domain = mono_domain_get ();
6505 gint len;
6507 MONO_ARCH_SAVE_REGS;
6509 buf [0] = '\0';
6510 ptr = buf;
6512 while (size > initial_size) {
6513 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6514 if (size > initial_size) {
6515 if (ptr != buf)
6516 g_free (ptr);
6517 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6518 initial_size = size;
6519 size++;
6523 /* Count strings */
6524 dname = ptr;
6525 ndrives = 0;
6526 do {
6527 while (*dname++);
6528 ndrives++;
6529 } while (*dname);
6531 dname = ptr;
6532 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6533 ndrives = 0;
6534 do {
6535 len = 0;
6536 u16 = dname;
6537 while (*u16) { u16++; len ++; }
6538 drivestr = mono_string_new_utf16 (domain, dname, len);
6539 mono_array_setref (result, ndrives++, drivestr);
6540 while (*dname++);
6541 } while (*dname);
6543 if (ptr != buf)
6544 g_free (ptr);
6546 return result;
6549 static MonoString *
6550 ves_icall_System_Environment_InternalGetHome (void)
6552 MONO_ARCH_SAVE_REGS;
6554 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6557 static const char *encodings [] = {
6558 (char *) 1,
6559 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6560 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6561 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6562 (char *) 2,
6563 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6564 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6565 "x_unicode_2_0_utf_7",
6566 (char *) 3,
6567 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6568 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6569 (char *) 4,
6570 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6571 "iso_10646_ucs2",
6572 (char *) 5,
6573 "unicodefffe", "utf_16be",
6574 (char *) 6,
6575 "iso_8859_1",
6576 (char *) 0
6580 * Returns the internal codepage, if the value of "int_code_page" is
6581 * 1 at entry, and we can not compute a suitable code page number,
6582 * returns the code page as a string
6584 static MonoString*
6585 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6587 const char *cset;
6588 const char *p;
6589 char *c;
6590 char *codepage = NULL;
6591 int code;
6592 int want_name = *int_code_page;
6593 int i;
6595 *int_code_page = -1;
6596 MONO_ARCH_SAVE_REGS;
6598 g_get_charset (&cset);
6599 c = codepage = strdup (cset);
6600 for (c = codepage; *c; c++){
6601 if (isascii (*c) && isalpha (*c))
6602 *c = tolower (*c);
6603 if (*c == '-')
6604 *c = '_';
6606 /* g_print ("charset: %s\n", cset); */
6608 /* handle some common aliases */
6609 p = encodings [0];
6610 code = 0;
6611 for (i = 0; p != 0; ){
6612 if ((gssize) p < 7){
6613 code = (gssize) p;
6614 p = encodings [++i];
6615 continue;
6617 if (strcmp (p, codepage) == 0){
6618 *int_code_page = code;
6619 break;
6621 p = encodings [++i];
6624 if (strstr (codepage, "utf_8") != NULL)
6625 *int_code_page |= 0x10000000;
6626 free (codepage);
6628 if (want_name && *int_code_page == -1)
6629 return mono_string_new (mono_domain_get (), cset);
6630 else
6631 return NULL;
6634 static MonoBoolean
6635 ves_icall_System_Environment_get_HasShutdownStarted (void)
6637 if (mono_runtime_is_shutting_down ())
6638 return TRUE;
6640 if (mono_domain_is_unloading (mono_domain_get ()))
6641 return TRUE;
6643 return FALSE;
6646 static void
6647 ves_icall_System_Environment_BroadcastSettingChange (void)
6649 #ifdef HOST_WIN32
6650 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6651 #endif
6654 static void
6655 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6656 MonoReflectionMethod *method,
6657 MonoArray *out_args)
6659 MONO_ARCH_SAVE_REGS;
6661 mono_message_init (mono_object_domain (this), this, method, out_args);
6664 static MonoBoolean
6665 ves_icall_IsTransparentProxy (MonoObject *proxy)
6667 MONO_ARCH_SAVE_REGS;
6669 if (!proxy)
6670 return 0;
6672 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6673 return 1;
6675 return 0;
6678 static MonoReflectionMethod *
6679 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6680 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6682 MonoClass *klass;
6683 MonoMethod *method;
6684 MonoMethod **vtable;
6685 MonoMethod *res = NULL;
6687 MONO_CHECK_ARG_NULL (rtype);
6688 MONO_CHECK_ARG_NULL (rmethod);
6690 method = rmethod->method;
6691 klass = mono_class_from_mono_type (rtype->type);
6693 if (MONO_CLASS_IS_INTERFACE (klass))
6694 return NULL;
6696 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6697 return NULL;
6699 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6700 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6701 return rmethod;
6702 else
6703 return NULL;
6706 mono_class_setup_vtable (klass);
6707 vtable = klass->vtable;
6709 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6710 gboolean variance_used = FALSE;
6711 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6712 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6713 if (offs >= 0)
6714 res = vtable [offs + method->slot];
6715 } else {
6716 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6717 return NULL;
6719 if (method->slot != -1)
6720 res = vtable [method->slot];
6723 if (!res)
6724 return NULL;
6726 return mono_method_get_object (mono_domain_get (), res, NULL);
6729 static void
6730 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6732 MonoClass *klass;
6733 MonoVTable* vtable;
6735 MONO_ARCH_SAVE_REGS;
6737 klass = mono_class_from_mono_type (type->type);
6738 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6740 if (enable) vtable->remote = 1;
6741 else vtable->remote = 0;
6744 static MonoObject *
6745 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6747 MonoClass *klass;
6748 MonoDomain *domain;
6750 MONO_ARCH_SAVE_REGS;
6752 domain = mono_object_domain (type);
6753 klass = mono_class_from_mono_type (type->type);
6755 if (klass->rank >= 1) {
6756 g_assert (klass->rank == 1);
6757 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6758 } else {
6759 /* Bypass remoting object creation check */
6760 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6764 static MonoString *
6765 ves_icall_System_IO_get_temp_path (void)
6767 MONO_ARCH_SAVE_REGS;
6769 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6772 #ifndef PLATFORM_NO_DRIVEINFO
6773 static MonoBoolean
6774 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6775 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6776 gint32 *error)
6778 gboolean result;
6779 ULARGE_INTEGER wapi_free_bytes_avail;
6780 ULARGE_INTEGER wapi_total_number_of_bytes;
6781 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6783 MONO_ARCH_SAVE_REGS;
6785 *error = ERROR_SUCCESS;
6786 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6787 &wapi_total_number_of_free_bytes);
6789 if (result) {
6790 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6791 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6792 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6793 } else {
6794 *free_bytes_avail = 0;
6795 *total_number_of_bytes = 0;
6796 *total_number_of_free_bytes = 0;
6797 *error = GetLastError ();
6800 return result;
6803 static guint32
6804 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6806 MONO_ARCH_SAVE_REGS;
6808 return GetDriveType (mono_string_chars (root_path_name));
6810 #endif
6812 static gpointer
6813 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6815 MONO_ARCH_SAVE_REGS;
6817 return mono_compile_method (method);
6820 static MonoString *
6821 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6823 MonoString *mcpath;
6824 gchar *path;
6826 MONO_ARCH_SAVE_REGS;
6828 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6830 #if defined (HOST_WIN32)
6831 /* Avoid mixing '/' and '\\' */
6833 gint i;
6834 for (i = strlen (path) - 1; i >= 0; i--)
6835 if (path [i] == '/')
6836 path [i] = '\\';
6838 #endif
6839 mcpath = mono_string_new (mono_domain_get (), path);
6840 g_free (path);
6842 return mcpath;
6845 static MonoString *
6846 get_bundled_machine_config (void)
6848 const gchar *machine_config;
6850 MONO_ARCH_SAVE_REGS;
6852 machine_config = mono_get_machine_config ();
6854 if (!machine_config)
6855 return NULL;
6857 return mono_string_new (mono_domain_get (), machine_config);
6860 static MonoString *
6861 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6863 MonoString *ipath;
6864 gchar *path;
6866 MONO_ARCH_SAVE_REGS;
6868 path = g_path_get_dirname (mono_get_config_dir ());
6870 #if defined (HOST_WIN32)
6871 /* Avoid mixing '/' and '\\' */
6873 gint i;
6874 for (i = strlen (path) - 1; i >= 0; i--)
6875 if (path [i] == '/')
6876 path [i] = '\\';
6878 #endif
6879 ipath = mono_string_new (mono_domain_get (), path);
6880 g_free (path);
6882 return ipath;
6885 static gboolean
6886 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6888 MonoPEResourceDataEntry *entry;
6889 MonoImage *image;
6891 MONO_ARCH_SAVE_REGS;
6893 if (!assembly || !result || !size)
6894 return FALSE;
6896 *result = NULL;
6897 *size = 0;
6898 image = assembly->assembly->image;
6899 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6900 if (!entry)
6901 return FALSE;
6903 *result = mono_image_rva_map (image, entry->rde_data_offset);
6904 if (!(*result)) {
6905 g_free (entry);
6906 return FALSE;
6908 *size = entry->rde_size;
6909 g_free (entry);
6910 return TRUE;
6913 static MonoBoolean
6914 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6916 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6919 static void
6920 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6922 #if defined (HOST_WIN32)
6923 OutputDebugString (mono_string_chars (message));
6924 #else
6925 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6926 #endif
6929 /* Only used for value types */
6930 static MonoObject *
6931 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6933 MonoClass *klass;
6934 MonoDomain *domain;
6936 MONO_ARCH_SAVE_REGS;
6938 domain = mono_object_domain (type);
6939 klass = mono_class_from_mono_type (type->type);
6941 if (mono_class_is_nullable (klass))
6942 /* No arguments -> null */
6943 return NULL;
6945 return mono_object_new (domain, klass);
6948 static MonoReflectionMethod *
6949 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6951 MonoClass *klass, *parent;
6952 MonoMethod *method = m->method;
6953 MonoMethod *result = NULL;
6955 MONO_ARCH_SAVE_REGS;
6957 if (method->klass == NULL)
6958 return m;
6960 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6961 MONO_CLASS_IS_INTERFACE (method->klass) ||
6962 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6963 return m;
6965 klass = method->klass;
6966 if (klass->generic_class)
6967 klass = klass->generic_class->container_class;
6969 if (definition) {
6970 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6971 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6972 mono_class_setup_vtable (parent);
6973 if (parent->vtable_size <= method->slot)
6974 break;
6975 klass = parent;
6977 } else {
6978 klass = klass->parent;
6979 if (!klass)
6980 return m;
6983 if (klass == method->klass)
6984 return m;
6986 result = klass->vtable [method->slot];
6987 if (result == NULL) {
6988 /* It is an abstract method */
6989 gpointer iter = NULL;
6990 while ((result = mono_class_get_methods (klass, &iter)))
6991 if (result->slot == method->slot)
6992 break;
6995 if (result == NULL)
6996 return m;
6998 return mono_method_get_object (mono_domain_get (), result, NULL);
7001 static MonoString*
7002 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7004 MonoMethod *method = m->method;
7006 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7007 return m->name;
7010 static void
7011 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7013 MONO_ARCH_SAVE_REGS;
7015 iter->sig = *(MonoMethodSignature**)argsp;
7017 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7018 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7020 iter->next_arg = 0;
7021 /* FIXME: it's not documented what start is exactly... */
7022 if (start) {
7023 iter->args = start;
7024 } else {
7025 iter->args = argsp + sizeof (gpointer);
7027 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7029 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7032 static MonoTypedRef
7033 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7035 guint32 i, arg_size;
7036 gint32 align;
7037 MonoTypedRef res;
7038 MONO_ARCH_SAVE_REGS;
7040 i = iter->sig->sentinelpos + iter->next_arg;
7042 g_assert (i < iter->sig->param_count);
7044 res.type = iter->sig->params [i];
7045 res.klass = mono_class_from_mono_type (res.type);
7046 res.value = iter->args;
7047 arg_size = mono_type_stack_size (res.type, &align);
7048 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7049 if (arg_size <= sizeof (gpointer)) {
7050 int dummy;
7051 int padding = arg_size - mono_type_size (res.type, &dummy);
7052 res.value = (guint8*)res.value + padding;
7054 #endif
7055 iter->args = (char*)iter->args + arg_size;
7056 iter->next_arg++;
7058 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7060 return res;
7063 static MonoTypedRef
7064 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7066 guint32 i, arg_size;
7067 gint32 align;
7068 MonoTypedRef res;
7069 MONO_ARCH_SAVE_REGS;
7071 i = iter->sig->sentinelpos + iter->next_arg;
7073 g_assert (i < iter->sig->param_count);
7075 while (i < iter->sig->param_count) {
7076 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7077 continue;
7078 res.type = iter->sig->params [i];
7079 res.klass = mono_class_from_mono_type (res.type);
7080 /* FIXME: endianess issue... */
7081 res.value = iter->args;
7082 arg_size = mono_type_stack_size (res.type, &align);
7083 iter->args = (char*)iter->args + arg_size;
7084 iter->next_arg++;
7085 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7086 return res;
7088 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7090 res.type = NULL;
7091 res.value = NULL;
7092 res.klass = NULL;
7093 return res;
7096 static MonoType*
7097 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7099 gint i;
7100 MONO_ARCH_SAVE_REGS;
7102 i = iter->sig->sentinelpos + iter->next_arg;
7104 g_assert (i < iter->sig->param_count);
7106 return iter->sig->params [i];
7109 static MonoObject*
7110 mono_TypedReference_ToObject (MonoTypedRef tref)
7112 MONO_ARCH_SAVE_REGS;
7114 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7115 MonoObject** objp = tref.value;
7116 return *objp;
7119 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7122 static MonoObject*
7123 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7125 MONO_ARCH_SAVE_REGS;
7127 if (MONO_TYPE_IS_REFERENCE (type)) {
7128 MonoObject** objp = value;
7129 return *objp;
7132 return mono_value_box (mono_domain_get (), klass, value);
7135 static void
7136 prelink_method (MonoMethod *method)
7138 const char *exc_class, *exc_arg;
7139 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7140 return;
7141 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7142 if (exc_class) {
7143 mono_raise_exception(
7144 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7146 /* create the wrapper, too? */
7149 static void
7150 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7152 MONO_ARCH_SAVE_REGS;
7153 prelink_method (method->method);
7156 static void
7157 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7159 MonoClass *klass = mono_class_from_mono_type (type->type);
7160 MonoMethod* m;
7161 gpointer iter = NULL;
7162 MONO_ARCH_SAVE_REGS;
7164 while ((m = mono_class_get_methods (klass, &iter)))
7165 prelink_method (m);
7168 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7169 static void
7170 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7171 gint32 const **exponents,
7172 gunichar2 const **digitLowerTable,
7173 gunichar2 const **digitUpperTable,
7174 gint64 const **tenPowersList,
7175 gint32 const **decHexDigits)
7177 *mantissas = Formatter_MantissaBitsTable;
7178 *exponents = Formatter_TensExponentTable;
7179 *digitLowerTable = Formatter_DigitLowerTable;
7180 *digitUpperTable = Formatter_DigitUpperTable;
7181 *tenPowersList = Formatter_TenPowersList;
7182 *decHexDigits = Formatter_DecHexDigits;
7185 /* These parameters are "readonly" in corlib/System/Char.cs */
7186 static void
7187 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7188 guint8 const **numeric_data,
7189 gdouble const **numeric_data_values,
7190 guint16 const **to_lower_data_low,
7191 guint16 const **to_lower_data_high,
7192 guint16 const **to_upper_data_low,
7193 guint16 const **to_upper_data_high)
7195 *category_data = CategoryData;
7196 *numeric_data = NumericData;
7197 *numeric_data_values = NumericDataValues;
7198 *to_lower_data_low = ToLowerDataLow;
7199 *to_lower_data_high = ToLowerDataHigh;
7200 *to_upper_data_low = ToUpperDataLow;
7201 *to_upper_data_high = ToUpperDataHigh;
7204 static gint32
7205 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7207 return method->method->token;
7211 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7212 * and avoid useless allocations.
7214 static MonoArray*
7215 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7217 MonoArray *res;
7218 int i, count = 0;
7219 for (i = 0; i < type->num_mods; ++i) {
7220 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7221 count++;
7223 if (!count)
7224 return NULL;
7225 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7226 count = 0;
7227 for (i = 0; i < type->num_mods; ++i) {
7228 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7229 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7230 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7231 count++;
7234 return res;
7237 static MonoArray*
7238 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7240 MonoType *type = param->ClassImpl->type;
7241 MonoClass *member_class = mono_object_class (param->MemberImpl);
7242 MonoMethod *method = NULL;
7243 MonoImage *image;
7244 int pos;
7245 MonoMethodSignature *sig;
7247 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7248 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7249 method = rmethod->method;
7250 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7251 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7252 if (!(method = prop->property->get))
7253 method = prop->property->set;
7254 g_assert (method);
7255 } else {
7256 char *type_name = mono_type_get_full_name (member_class);
7257 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7258 MonoException *ex = mono_get_exception_not_supported (msg);
7259 g_free (type_name);
7260 g_free (msg);
7261 mono_raise_exception (ex);
7264 image = method->klass->image;
7265 pos = param->PositionImpl;
7266 sig = mono_method_signature (method);
7267 if (pos == -1)
7268 type = sig->ret;
7269 else
7270 type = sig->params [pos];
7272 return type_array_from_modifiers (image, type, optional);
7275 static MonoType*
7276 get_property_type (MonoProperty *prop)
7278 MonoMethodSignature *sig;
7279 if (prop->get) {
7280 sig = mono_method_signature (prop->get);
7281 return sig->ret;
7282 } else if (prop->set) {
7283 sig = mono_method_signature (prop->set);
7284 return sig->params [sig->param_count - 1];
7286 return NULL;
7289 static MonoArray*
7290 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7292 MonoType *type = get_property_type (property->property);
7293 MonoImage *image = property->klass->image;
7295 if (!type)
7296 return NULL;
7297 return type_array_from_modifiers (image, type, optional);
7301 *Construct a MonoType suited to be used to decode a constant blob object.
7303 * @type is the target type which will be constructed
7304 * @blob_type is the blob type, for example, that comes from the constant table
7305 * @real_type is the expected constructed type.
7307 static void
7308 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7310 type->type = blob_type;
7311 type->data.klass = NULL;
7312 if (blob_type == MONO_TYPE_CLASS)
7313 type->data.klass = mono_defaults.object_class;
7314 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7315 /* For enums, we need to use the base type */
7316 type->type = MONO_TYPE_VALUETYPE;
7317 type->data.klass = mono_class_from_mono_type (real_type);
7318 } else
7319 type->data.klass = mono_class_from_mono_type (real_type);
7322 static MonoObject*
7323 property_info_get_default_value (MonoReflectionProperty *property)
7325 MonoType blob_type;
7326 MonoProperty *prop = property->property;
7327 MonoType *type = get_property_type (prop);
7328 MonoDomain *domain = mono_object_domain (property);
7329 MonoTypeEnum def_type;
7330 const char *def_value;
7331 MonoObject *o;
7333 g_assert (!prop->parent->image->dynamic);
7335 mono_class_init (prop->parent);
7337 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7338 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7340 def_value = mono_class_get_property_default_value (prop, &def_type);
7342 mono_type_from_blob_type (&blob_type, def_type, type);
7343 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7345 return o;
7348 static MonoBoolean
7349 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7351 MonoCustomAttrInfo *cinfo;
7352 gboolean found;
7354 cinfo = mono_reflection_get_custom_attrs_info (obj);
7355 if (!cinfo)
7356 return FALSE;
7357 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7358 if (!cinfo->cached)
7359 mono_custom_attrs_free (cinfo);
7360 return found;
7363 static MonoArray*
7364 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7366 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7368 if (mono_loader_get_last_error ()) {
7369 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7370 g_assert_not_reached ();
7371 /* Not reached */
7372 return NULL;
7373 } else {
7374 return res;
7378 static MonoString*
7379 ves_icall_Mono_Runtime_GetDisplayName (void)
7381 char *info;
7382 MonoString *display_name;
7384 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7385 display_name = mono_string_new (mono_domain_get (), info);
7386 g_free (info);
7387 return display_name;
7390 static MonoObject *
7391 ves_icall_Mono_Runtime_NewObject (MonoType *t)
7393 return mono_object_new (mono_domain_get (), mono_class_from_mono_type (t));
7396 static MonoString*
7397 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7399 MonoString *message;
7400 guint32 ret;
7401 gunichar2 buf[256];
7403 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7404 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7405 buf, 255, NULL);
7406 if (ret == 0) {
7407 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7408 } else {
7409 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7412 return message;
7415 const static guchar
7416 dbase64 [] = {
7417 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7418 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7419 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7420 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7421 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7422 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7423 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7424 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7427 static MonoArray *
7428 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7430 gint ignored;
7431 gint i;
7432 gunichar2 c;
7433 gunichar2 last, prev_last, prev2_last;
7434 gint olength;
7435 MonoArray *result;
7436 guchar *res_ptr;
7437 gint a [4], b [4];
7438 MonoException *exc;
7440 ignored = 0;
7441 last = prev_last = 0, prev2_last = 0;
7442 for (i = 0; i < ilength; i++) {
7443 c = start [i];
7444 if (c >= sizeof (dbase64)) {
7445 exc = mono_exception_from_name_msg (mono_get_corlib (),
7446 "System", "FormatException",
7447 "Invalid character found.");
7448 mono_raise_exception (exc);
7449 } else if (isspace (c)) {
7450 ignored++;
7451 } else {
7452 prev2_last = prev_last;
7453 prev_last = last;
7454 last = c;
7458 olength = ilength - ignored;
7460 if (allowWhitespaceOnly && olength == 0) {
7461 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7464 if ((olength & 3) != 0 || olength <= 0) {
7465 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7466 "FormatException", "Invalid length.");
7467 mono_raise_exception (exc);
7470 if (prev2_last == '=') {
7471 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7472 mono_raise_exception (exc);
7475 olength = (olength * 3) / 4;
7476 if (last == '=')
7477 olength--;
7479 if (prev_last == '=')
7480 olength--;
7482 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7483 res_ptr = mono_array_addr (result, guchar, 0);
7484 for (i = 0; i < ilength; ) {
7485 int k;
7487 for (k = 0; k < 4 && i < ilength;) {
7488 c = start [i++];
7489 if (isspace (c))
7490 continue;
7492 a [k] = (guchar) c;
7493 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7494 exc = mono_exception_from_name_msg (mono_get_corlib (),
7495 "System", "FormatException",
7496 "Invalid character found.");
7497 mono_raise_exception (exc);
7499 k++;
7502 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7503 if (a [2] != '=')
7504 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7505 if (a [3] != '=')
7506 *res_ptr++ = (b [2] << 6) | b [3];
7508 while (i < ilength && isspace (start [i]))
7509 i++;
7512 return result;
7515 static MonoArray *
7516 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7518 MONO_ARCH_SAVE_REGS;
7520 return base64_to_byte_array (mono_string_chars (str),
7521 mono_string_length (str), allowWhitespaceOnly);
7524 static MonoArray *
7525 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7527 MONO_ARCH_SAVE_REGS;
7529 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7530 length, FALSE);
7533 #define ICALL_TYPE(id,name,first)
7534 #define ICALL(id,name,func) Icall_ ## id,
7536 enum {
7537 #include "metadata/icall-def.h"
7538 Icall_last
7541 #undef ICALL_TYPE
7542 #undef ICALL
7543 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7544 #define ICALL(id,name,func)
7545 enum {
7546 #include "metadata/icall-def.h"
7547 Icall_type_num
7550 #undef ICALL_TYPE
7551 #undef ICALL
7552 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7553 #define ICALL(id,name,func)
7554 typedef struct {
7555 guint16 first_icall;
7556 } IcallTypeDesc;
7558 static const IcallTypeDesc
7559 icall_type_descs [] = {
7560 #include "metadata/icall-def.h"
7561 {Icall_last}
7564 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7566 #undef ICALL_TYPE
7567 #define ICALL_TYPE(id,name,first)
7568 #undef ICALL
7570 #ifdef HAVE_ARRAY_ELEM_INIT
7571 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7572 #define MSGSTRFIELD1(line) str##line
7574 static const struct msgstrtn_t {
7575 #define ICALL(id,name,func)
7576 #undef ICALL_TYPE
7577 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7578 #include "metadata/icall-def.h"
7579 #undef ICALL_TYPE
7580 } icall_type_names_str = {
7581 #define ICALL_TYPE(id,name,first) (name),
7582 #include "metadata/icall-def.h"
7583 #undef ICALL_TYPE
7585 static const guint16 icall_type_names_idx [] = {
7586 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7587 #include "metadata/icall-def.h"
7588 #undef ICALL_TYPE
7590 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7592 static const struct msgstr_t {
7593 #undef ICALL
7594 #define ICALL_TYPE(id,name,first)
7595 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7596 #include "metadata/icall-def.h"
7597 #undef ICALL
7598 } icall_names_str = {
7599 #define ICALL(id,name,func) (name),
7600 #include "metadata/icall-def.h"
7601 #undef ICALL
7603 static const guint16 icall_names_idx [] = {
7604 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7605 #include "metadata/icall-def.h"
7606 #undef ICALL
7608 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7610 #else
7612 #undef ICALL_TYPE
7613 #undef ICALL
7614 #define ICALL_TYPE(id,name,first) name,
7615 #define ICALL(id,name,func)
7616 static const char* const
7617 icall_type_names [] = {
7618 #include "metadata/icall-def.h"
7619 NULL
7622 #define icall_type_name_get(id) (icall_type_names [(id)])
7624 #undef ICALL_TYPE
7625 #undef ICALL
7626 #define ICALL_TYPE(id,name,first)
7627 #define ICALL(id,name,func) name,
7628 static const char* const
7629 icall_names [] = {
7630 #include "metadata/icall-def.h"
7631 NULL
7633 #define icall_name_get(id) icall_names [(id)]
7635 #endif /* !HAVE_ARRAY_ELEM_INIT */
7637 #undef ICALL_TYPE
7638 #undef ICALL
7639 #define ICALL_TYPE(id,name,first)
7640 #define ICALL(id,name,func) func,
7641 static const gconstpointer
7642 icall_functions [] = {
7643 #include "metadata/icall-def.h"
7644 NULL
7647 static GHashTable *icall_hash = NULL;
7648 static GHashTable *jit_icall_hash_name = NULL;
7649 static GHashTable *jit_icall_hash_addr = NULL;
7651 void
7652 mono_icall_init (void)
7654 int i = 0;
7656 /* check that tables are sorted: disable in release */
7657 if (TRUE) {
7658 int j;
7659 const char *prev_class = NULL;
7660 const char *prev_method;
7662 for (i = 0; i < Icall_type_num; ++i) {
7663 const IcallTypeDesc *desc;
7664 int num_icalls;
7665 prev_method = NULL;
7666 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7667 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7668 prev_class = icall_type_name_get (i);
7669 desc = &icall_type_descs [i];
7670 num_icalls = icall_desc_num_icalls (desc);
7671 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7672 for (j = 0; j < num_icalls; ++j) {
7673 const char *methodn = icall_name_get (desc->first_icall + j);
7674 if (prev_method && strcmp (prev_method, methodn) >= 0)
7675 g_print ("method %s should come before method %s\n", methodn, prev_method);
7676 prev_method = methodn;
7681 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7684 void
7685 mono_icall_cleanup (void)
7687 g_hash_table_destroy (icall_hash);
7688 g_hash_table_destroy (jit_icall_hash_name);
7689 g_hash_table_destroy (jit_icall_hash_addr);
7692 void
7693 mono_add_internal_call (const char *name, gconstpointer method)
7695 mono_loader_lock ();
7697 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7699 mono_loader_unlock ();
7702 #ifdef HAVE_ARRAY_ELEM_INIT
7703 static int
7704 compare_method_imap (const void *key, const void *elem)
7706 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7707 return strcmp (key, method_name);
7710 static gpointer
7711 find_method_icall (const IcallTypeDesc *imap, const char *name)
7713 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7714 if (!nameslot)
7715 return NULL;
7716 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7719 static int
7720 compare_class_imap (const void *key, const void *elem)
7722 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7723 return strcmp (key, class_name);
7726 static const IcallTypeDesc*
7727 find_class_icalls (const char *name)
7729 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7730 if (!nameslot)
7731 return NULL;
7732 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7735 #else
7736 static int
7737 compare_method_imap (const void *key, const void *elem)
7739 const char** method_name = (const char**)elem;
7740 return strcmp (key, *method_name);
7743 static gpointer
7744 find_method_icall (const IcallTypeDesc *imap, const char *name)
7746 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7747 if (!nameslot)
7748 return NULL;
7749 return (gpointer)icall_functions [(nameslot - icall_names)];
7752 static int
7753 compare_class_imap (const void *key, const void *elem)
7755 const char** class_name = (const char**)elem;
7756 return strcmp (key, *class_name);
7759 static const IcallTypeDesc*
7760 find_class_icalls (const char *name)
7762 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7763 if (!nameslot)
7764 return NULL;
7765 return &icall_type_descs [nameslot - icall_type_names];
7768 #endif
7771 * we should probably export this as an helper (handle nested types).
7772 * Returns the number of chars written in buf.
7774 static int
7775 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7777 int nspacelen, cnamelen;
7778 nspacelen = strlen (klass->name_space);
7779 cnamelen = strlen (klass->name);
7780 if (nspacelen + cnamelen + 2 > bufsize)
7781 return 0;
7782 if (nspacelen) {
7783 memcpy (buf, klass->name_space, nspacelen);
7784 buf [nspacelen ++] = '.';
7786 memcpy (buf + nspacelen, klass->name, cnamelen);
7787 buf [nspacelen + cnamelen] = 0;
7788 return nspacelen + cnamelen;
7791 gpointer
7792 mono_lookup_internal_call (MonoMethod *method)
7794 char *sigstart;
7795 char *tmpsig;
7796 char mname [2048];
7797 int typelen = 0, mlen, siglen;
7798 gpointer res;
7799 const IcallTypeDesc *imap;
7801 g_assert (method != NULL);
7803 if (method->is_inflated)
7804 method = ((MonoMethodInflated *) method)->declaring;
7806 if (method->klass->nested_in) {
7807 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7808 if (!pos)
7809 return NULL;
7811 mname [pos++] = '/';
7812 mname [pos] = 0;
7814 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7815 if (!typelen)
7816 return NULL;
7818 typelen += pos;
7819 } else {
7820 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7821 if (!typelen)
7822 return NULL;
7825 imap = find_class_icalls (mname);
7827 mname [typelen] = ':';
7828 mname [typelen + 1] = ':';
7830 mlen = strlen (method->name);
7831 memcpy (mname + typelen + 2, method->name, mlen);
7832 sigstart = mname + typelen + 2 + mlen;
7833 *sigstart = 0;
7835 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7836 siglen = strlen (tmpsig);
7837 if (typelen + mlen + siglen + 6 > sizeof (mname))
7838 return NULL;
7839 sigstart [0] = '(';
7840 memcpy (sigstart + 1, tmpsig, siglen);
7841 sigstart [siglen + 1] = ')';
7842 sigstart [siglen + 2] = 0;
7843 g_free (tmpsig);
7845 mono_loader_lock ();
7847 res = g_hash_table_lookup (icall_hash, mname);
7848 if (res) {
7849 mono_loader_unlock ();
7850 return res;
7852 /* try without signature */
7853 *sigstart = 0;
7854 res = g_hash_table_lookup (icall_hash, mname);
7855 if (res) {
7856 mono_loader_unlock ();
7857 return res;
7860 /* it wasn't found in the static call tables */
7861 if (!imap) {
7862 mono_loader_unlock ();
7863 return NULL;
7865 res = find_method_icall (imap, sigstart - mlen);
7866 if (res) {
7867 mono_loader_unlock ();
7868 return res;
7870 /* try _with_ signature */
7871 *sigstart = '(';
7872 res = find_method_icall (imap, sigstart - mlen);
7873 if (res) {
7874 mono_loader_unlock ();
7875 return res;
7878 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7879 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7880 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7881 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7882 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");
7883 g_print ("If you see other errors or faults after this message they are probably related\n");
7884 g_print ("and you need to fix your mono install first.\n");
7886 mono_loader_unlock ();
7888 return NULL;
7891 static MonoType*
7892 type_from_typename (char *typename)
7894 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7896 if (!strcmp (typename, "int"))
7897 klass = mono_defaults.int_class;
7898 else if (!strcmp (typename, "ptr"))
7899 klass = mono_defaults.int_class;
7900 else if (!strcmp (typename, "void"))
7901 klass = mono_defaults.void_class;
7902 else if (!strcmp (typename, "int32"))
7903 klass = mono_defaults.int32_class;
7904 else if (!strcmp (typename, "uint32"))
7905 klass = mono_defaults.uint32_class;
7906 else if (!strcmp (typename, "int8"))
7907 klass = mono_defaults.sbyte_class;
7908 else if (!strcmp (typename, "uint8"))
7909 klass = mono_defaults.byte_class;
7910 else if (!strcmp (typename, "int16"))
7911 klass = mono_defaults.int16_class;
7912 else if (!strcmp (typename, "uint16"))
7913 klass = mono_defaults.uint16_class;
7914 else if (!strcmp (typename, "long"))
7915 klass = mono_defaults.int64_class;
7916 else if (!strcmp (typename, "ulong"))
7917 klass = mono_defaults.uint64_class;
7918 else if (!strcmp (typename, "float"))
7919 klass = mono_defaults.single_class;
7920 else if (!strcmp (typename, "double"))
7921 klass = mono_defaults.double_class;
7922 else if (!strcmp (typename, "object"))
7923 klass = mono_defaults.object_class;
7924 else if (!strcmp (typename, "obj"))
7925 klass = mono_defaults.object_class;
7926 else if (!strcmp (typename, "string"))
7927 klass = mono_defaults.string_class;
7928 else if (!strcmp (typename, "bool"))
7929 klass = mono_defaults.boolean_class;
7930 else if (!strcmp (typename, "boolean"))
7931 klass = mono_defaults.boolean_class;
7932 else {
7933 g_error ("%s", typename);
7934 g_assert_not_reached ();
7936 return &klass->byval_arg;
7939 MonoMethodSignature*
7940 mono_create_icall_signature (const char *sigstr)
7942 gchar **parts;
7943 int i, len;
7944 gchar **tmp;
7945 MonoMethodSignature *res;
7947 mono_loader_lock ();
7948 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7949 if (res) {
7950 mono_loader_unlock ();
7951 return res;
7954 parts = g_strsplit (sigstr, " ", 256);
7956 tmp = parts;
7957 len = 0;
7958 while (*tmp) {
7959 len ++;
7960 tmp ++;
7963 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7964 res->pinvoke = 1;
7966 #ifdef HOST_WIN32
7968 * Under windows, the default pinvoke calling convention is STDCALL but
7969 * we need CDECL.
7971 res->call_convention = MONO_CALL_C;
7972 #endif
7974 res->ret = type_from_typename (parts [0]);
7975 for (i = 1; i < len; ++i) {
7976 res->params [i - 1] = type_from_typename (parts [i]);
7979 g_strfreev (parts);
7981 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7983 mono_loader_unlock ();
7985 return res;
7988 MonoJitICallInfo *
7989 mono_find_jit_icall_by_name (const char *name)
7991 MonoJitICallInfo *info;
7992 g_assert (jit_icall_hash_name);
7994 mono_loader_lock ();
7995 info = g_hash_table_lookup (jit_icall_hash_name, name);
7996 mono_loader_unlock ();
7997 return info;
8000 MonoJitICallInfo *
8001 mono_find_jit_icall_by_addr (gconstpointer addr)
8003 MonoJitICallInfo *info;
8004 g_assert (jit_icall_hash_addr);
8006 mono_loader_lock ();
8007 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8008 mono_loader_unlock ();
8010 return info;
8014 * mono_get_jit_icall_info:
8016 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8017 * caller should access it while holding the loader lock.
8019 GHashTable*
8020 mono_get_jit_icall_info (void)
8022 return jit_icall_hash_name;
8025 void
8026 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8028 mono_loader_lock ();
8029 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8030 mono_loader_unlock ();
8033 MonoJitICallInfo *
8034 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8036 MonoJitICallInfo *info;
8038 g_assert (func);
8039 g_assert (name);
8041 mono_loader_lock ();
8043 if (!jit_icall_hash_name) {
8044 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8045 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8048 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8049 g_warning ("jit icall already defined \"%s\"\n", name);
8050 g_assert_not_reached ();
8053 info = g_new0 (MonoJitICallInfo, 1);
8055 info->name = name;
8056 info->func = func;
8057 info->sig = sig;
8059 if (is_save) {
8060 info->wrapper = func;
8061 } else {
8062 info->wrapper = NULL;
8065 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8066 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8068 mono_loader_unlock ();
8069 return info;