2010-03-04 Geoff Norton <gnorton@novell.com>
[mono.git] / mono / metadata / icall.c
blob8235293f010282b63ce1c75da16ac584fb47c070
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 if (event->event->other) {
2091 int i, n = 0;
2092 while (event->event->other [n])
2093 n++;
2094 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2096 for (i = 0; i < n; i++)
2097 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2101 static MonoArray*
2102 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2104 MonoError error;
2105 MonoDomain *domain = mono_object_domain (type);
2106 MonoArray *intf;
2107 GPtrArray *ifaces = NULL;
2108 int i;
2109 MonoClass *class = mono_class_from_mono_type (type->type);
2110 MonoClass *parent;
2111 MonoBitSet *slots;
2112 MonoGenericContext *context = NULL;
2114 MONO_ARCH_SAVE_REGS;
2116 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2117 context = mono_class_get_context (class);
2118 class = class->generic_class->container_class;
2121 mono_class_setup_vtable (class);
2123 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2125 for (parent = class; parent; parent = parent->parent) {
2126 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent, &error);
2127 if (!mono_error_ok (&error)) {
2128 mono_bitset_free (slots);
2129 mono_error_raise_exception (&error);
2130 return NULL;
2131 } else if (tmp_ifaces) {
2132 for (i = 0; i < tmp_ifaces->len; ++i) {
2133 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2135 if (mono_bitset_test (slots, ic->interface_id))
2136 continue;
2138 mono_bitset_set (slots, ic->interface_id);
2139 if (ifaces == NULL)
2140 ifaces = g_ptr_array_new ();
2141 g_ptr_array_add (ifaces, ic);
2143 g_ptr_array_free (tmp_ifaces, TRUE);
2146 mono_bitset_free (slots);
2148 if (!ifaces)
2149 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2151 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2152 for (i = 0; i < ifaces->len; ++i) {
2153 MonoClass *ic = g_ptr_array_index (ifaces, i);
2154 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2155 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2156 inflated = ret = mono_class_inflate_generic_type (ret, context);
2158 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2159 if (inflated)
2160 mono_metadata_free_type (inflated);
2162 g_ptr_array_free (ifaces, TRUE);
2164 return intf;
2167 static void
2168 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2170 gboolean variance_used;
2171 MonoClass *class = mono_class_from_mono_type (type->type);
2172 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2173 MonoReflectionMethod *member;
2174 MonoMethod* method;
2175 gpointer iter;
2176 int i = 0, len, ioffset;
2177 MonoDomain *domain;
2179 MONO_ARCH_SAVE_REGS;
2181 mono_class_setup_vtable (class);
2183 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2184 if (ioffset == -1)
2185 return;
2187 len = mono_class_num_methods (iclass);
2188 domain = mono_object_domain (type);
2189 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2190 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2191 iter = NULL;
2192 while ((method = mono_class_get_methods (iclass, &iter))) {
2193 member = mono_method_get_object (domain, method, iclass);
2194 mono_array_setref (*methods, i, member);
2195 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2196 mono_array_setref (*targets, i, member);
2198 i ++;
2202 static void
2203 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2205 MonoClass *klass = mono_class_from_mono_type (type->type);
2207 if (klass->image->dynamic) {
2208 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2209 *packing = tb->packing_size;
2210 *size = tb->class_size;
2211 } else {
2212 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2216 static MonoReflectionType*
2217 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2219 MonoClass *class;
2221 MONO_ARCH_SAVE_REGS;
2223 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2224 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2226 class = mono_class_from_mono_type (type->type);
2228 // GetElementType should only return a type for:
2229 // Array Pointer PassedByRef
2230 if (type->type->byref)
2231 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2232 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2233 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2234 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2235 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2236 else
2237 return NULL;
2240 static MonoReflectionType*
2241 ves_icall_get_type_parent (MonoReflectionType *type)
2243 MonoClass *class = mono_class_from_mono_type (type->type);
2245 MONO_ARCH_SAVE_REGS;
2247 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2250 static MonoBoolean
2251 ves_icall_type_ispointer (MonoReflectionType *type)
2253 MONO_ARCH_SAVE_REGS;
2255 return type->type->type == MONO_TYPE_PTR;
2258 static MonoBoolean
2259 ves_icall_type_isprimitive (MonoReflectionType *type)
2261 MONO_ARCH_SAVE_REGS;
2263 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)));
2266 static MonoBoolean
2267 ves_icall_type_isbyref (MonoReflectionType *type)
2269 MONO_ARCH_SAVE_REGS;
2271 return type->type->byref;
2274 static MonoBoolean
2275 ves_icall_type_iscomobject (MonoReflectionType *type)
2277 MonoClass *klass = mono_class_from_mono_type (type->type);
2278 MONO_ARCH_SAVE_REGS;
2280 return (klass && klass->is_com_object);
2283 static MonoReflectionModule*
2284 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2286 MonoClass *class = mono_class_from_mono_type (type->type);
2288 MONO_ARCH_SAVE_REGS;
2290 return mono_module_get_object (mono_object_domain (type), class->image);
2293 static MonoReflectionAssembly*
2294 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2296 MonoDomain *domain = mono_domain_get ();
2297 MonoClass *class = mono_class_from_mono_type (type->type);
2299 MONO_ARCH_SAVE_REGS;
2301 return mono_assembly_get_object (domain, class->image->assembly);
2304 static MonoReflectionType*
2305 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2307 MonoDomain *domain = mono_domain_get ();
2308 MonoClass *class;
2310 MONO_ARCH_SAVE_REGS;
2312 if (type->type->byref)
2313 return NULL;
2314 if (type->type->type == MONO_TYPE_VAR)
2315 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2316 else if (type->type->type == MONO_TYPE_MVAR)
2317 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2318 else
2319 class = mono_class_from_mono_type (type->type)->nested_in;
2321 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2324 static MonoReflectionType*
2325 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2327 MonoDomain *domain = mono_domain_get ();
2328 MonoClass *class = mono_class_from_mono_type (type->type);
2330 MONO_ARCH_SAVE_REGS;
2332 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2333 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2334 else if (class->element_class)
2335 return mono_type_get_object (domain, &class->element_class->byval_arg);
2336 else
2337 return NULL;
2340 static MonoString*
2341 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2343 MonoDomain *domain = mono_domain_get ();
2344 MonoClass *class = mono_class_from_mono_type (type->type);
2346 MONO_ARCH_SAVE_REGS;
2348 if (type->type->byref) {
2349 char *n = g_strdup_printf ("%s&", class->name);
2350 MonoString *res = mono_string_new (domain, n);
2352 g_free (n);
2354 return res;
2355 } else {
2356 return mono_string_new (domain, class->name);
2360 static MonoString*
2361 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2363 MonoDomain *domain = mono_domain_get ();
2364 MonoClass *class = mono_class_from_mono_type (type->type);
2366 MONO_ARCH_SAVE_REGS;
2368 while (class->nested_in)
2369 class = class->nested_in;
2371 if (class->name_space [0] == '\0')
2372 return NULL;
2373 else
2374 return mono_string_new (domain, class->name_space);
2377 static gint32
2378 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2380 MonoClass *class;
2382 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2383 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2385 class = mono_class_from_mono_type (type->type);
2386 return class->rank;
2389 static MonoArray*
2390 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2392 MonoArray *res;
2393 MonoClass *klass, *pklass;
2394 MonoDomain *domain = mono_object_domain (type);
2395 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2396 int i;
2397 MONO_ARCH_SAVE_REGS;
2399 klass = mono_class_from_mono_type (type->type);
2401 if (klass->generic_container) {
2402 MonoGenericContainer *container = klass->generic_container;
2403 res = mono_array_new_specific (array_vtable, container->type_argc);
2404 for (i = 0; i < container->type_argc; ++i) {
2405 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2406 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2408 } else if (klass->generic_class) {
2409 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2410 res = mono_array_new_specific (array_vtable, inst->type_argc);
2411 for (i = 0; i < inst->type_argc; ++i)
2412 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2413 } else {
2414 res = mono_array_new_specific (array_vtable, 0);
2416 return res;
2419 static gboolean
2420 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2422 MonoClass *klass;
2423 MONO_ARCH_SAVE_REGS;
2425 if (!IS_MONOTYPE (type))
2426 return FALSE;
2428 if (type->type->byref)
2429 return FALSE;
2431 klass = mono_class_from_mono_type (type->type);
2433 return klass->generic_container != NULL;
2436 static MonoReflectionType*
2437 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2439 MonoClass *klass;
2440 MONO_ARCH_SAVE_REGS;
2442 if (type->type->byref)
2443 return NULL;
2445 klass = mono_class_from_mono_type (type->type);
2446 if (klass->generic_container) {
2447 return type; /* check this one */
2449 if (klass->generic_class) {
2450 MonoClass *generic_class = klass->generic_class->container_class;
2451 gpointer tb;
2453 tb = mono_class_get_ref_info (generic_class);
2455 if (generic_class->wastypebuilder && tb)
2456 return tb;
2457 else
2458 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2460 return NULL;
2463 static MonoReflectionType*
2464 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2466 MonoType *geninst, **types;
2467 int i, count;
2469 MONO_ARCH_SAVE_REGS;
2471 count = mono_array_length (type_array);
2472 types = g_new0 (MonoType *, count);
2474 for (i = 0; i < count; i++) {
2475 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2476 types [i] = t->type;
2479 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2480 g_free (types);
2481 if (!geninst)
2482 return NULL;
2484 return mono_type_get_object (mono_object_domain (type), geninst);
2487 static gboolean
2488 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2490 MonoClass *klass;
2491 MONO_ARCH_SAVE_REGS;
2493 if (type->type->byref)
2494 return FALSE;
2496 klass = mono_class_from_mono_type (type->type);
2497 return klass->generic_class != NULL;
2500 static gboolean
2501 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2503 MonoClass *klass;
2504 MONO_ARCH_SAVE_REGS;
2506 if (!IS_MONOTYPE (type))
2507 return FALSE;
2509 if (type->type->byref)
2510 return FALSE;
2512 klass = mono_class_from_mono_type (type->type);
2513 return klass->generic_class != NULL || klass->generic_container != NULL;
2516 static gint32
2517 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2519 MONO_ARCH_SAVE_REGS;
2521 if (!IS_MONOTYPE (type))
2522 return -1;
2524 if (is_generic_parameter (type->type))
2525 return mono_type_get_generic_param_num (type->type);
2526 return -1;
2529 static GenericParameterAttributes
2530 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2532 MONO_ARCH_SAVE_REGS;
2534 g_assert (IS_MONOTYPE (type));
2535 g_assert (is_generic_parameter (type->type));
2536 return mono_generic_param_info (type->type->data.generic_param)->flags;
2539 static MonoArray *
2540 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2542 MonoGenericParamInfo *param_info;
2543 MonoDomain *domain;
2544 MonoClass **ptr;
2545 MonoArray *res;
2546 int i, count;
2548 MONO_ARCH_SAVE_REGS;
2550 g_assert (IS_MONOTYPE (type));
2552 domain = mono_object_domain (type);
2553 param_info = mono_generic_param_info (type->type->data.generic_param);
2554 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2557 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2558 for (i = 0; i < count; i++)
2559 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2562 return res;
2565 static MonoBoolean
2566 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2568 MONO_ARCH_SAVE_REGS;
2569 return is_generic_parameter (type->type);
2572 static MonoBoolean
2573 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2575 MONO_ARCH_SAVE_REGS;
2576 return is_generic_parameter (tb->type.type);
2579 static void
2580 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2581 MonoReflectionType *t)
2583 enumtype->type = t->type;
2586 static MonoReflectionMethod*
2587 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2588 MonoReflectionMethod* generic)
2590 MonoDomain *domain;
2591 MonoClass *klass;
2592 MonoMethod *method;
2593 gpointer iter;
2595 MONO_ARCH_SAVE_REGS;
2597 domain = ((MonoObject *)type)->vtable->domain;
2599 klass = mono_class_from_mono_type (type->type);
2601 iter = NULL;
2602 while ((method = mono_class_get_methods (klass, &iter))) {
2603 if (method->token == generic->method->token)
2604 return mono_method_get_object (domain, method, klass);
2607 return NULL;
2612 static MonoReflectionMethod *
2613 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2615 MonoMethod *method;
2616 MonoType *type = ref_type->type;
2618 MONO_ARCH_SAVE_REGS;
2620 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2621 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2622 if (type->type == MONO_TYPE_VAR)
2623 return NULL;
2625 method = mono_type_get_generic_param_owner (type)->owner.method;
2626 g_assert (method);
2627 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2630 static MonoReflectionDllImportAttribute*
2631 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2633 static MonoClass *DllImportAttributeClass = NULL;
2634 MonoDomain *domain = mono_domain_get ();
2635 MonoReflectionDllImportAttribute *attr;
2636 MonoImage *image = method->klass->image;
2637 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2638 MonoTableInfo *tables = image->tables;
2639 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2640 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2641 guint32 im_cols [MONO_IMPLMAP_SIZE];
2642 guint32 scope_token;
2643 const char *import = NULL;
2644 const char *scope = NULL;
2645 guint32 flags;
2647 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2648 return NULL;
2650 if (!DllImportAttributeClass) {
2651 DllImportAttributeClass =
2652 mono_class_from_name (mono_defaults.corlib,
2653 "System.Runtime.InteropServices", "DllImportAttribute");
2654 g_assert (DllImportAttributeClass);
2657 if (method->klass->image->dynamic) {
2658 MonoReflectionMethodAux *method_aux =
2659 g_hash_table_lookup (
2660 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2661 if (method_aux) {
2662 import = method_aux->dllentry;
2663 scope = method_aux->dll;
2666 if (!import || !scope) {
2667 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2668 return NULL;
2671 else {
2672 if (piinfo->implmap_idx) {
2673 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2675 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2676 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2677 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2678 scope = mono_metadata_string_heap (image, scope_token);
2681 flags = piinfo->piflags;
2683 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2685 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2686 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2687 attr->call_conv = (flags & 0x700) >> 8;
2688 attr->charset = ((flags & 0x6) >> 1) + 1;
2689 if (attr->charset == 1)
2690 attr->charset = 2;
2691 attr->exact_spelling = (flags & 0x1) != 0;
2692 attr->set_last_error = (flags & 0x40) != 0;
2693 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2694 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2695 attr->preserve_sig = FALSE;
2697 return attr;
2700 static MonoReflectionMethod *
2701 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2703 MonoMethodInflated *imethod;
2704 MonoMethod *result;
2706 MONO_ARCH_SAVE_REGS;
2708 if (method->method->is_generic)
2709 return method;
2711 if (!method->method->is_inflated)
2712 return NULL;
2714 imethod = (MonoMethodInflated *) method->method;
2716 result = imethod->declaring;
2717 /* Not a generic method. */
2718 if (!result->is_generic)
2719 return NULL;
2721 if (method->method->klass->image->dynamic) {
2722 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2723 MonoReflectionMethod *res;
2726 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2727 * the dynamic case as well ?
2729 mono_loader_lock ();
2730 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2731 mono_loader_unlock ();
2733 if (res)
2734 return res;
2737 if (imethod->context.class_inst) {
2738 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2739 /*Generic methods gets the context of the GTD.*/
2740 if (mono_class_get_context (klass))
2741 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2744 return mono_method_get_object (mono_object_domain (method), result, NULL);
2747 static gboolean
2748 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2750 MONO_ARCH_SAVE_REGS;
2752 return mono_method_signature (method->method)->generic_param_count != 0;
2755 static gboolean
2756 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2758 MONO_ARCH_SAVE_REGS;
2760 return method->method->is_generic;
2763 static MonoArray*
2764 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2766 MonoArray *res;
2767 MonoDomain *domain;
2768 int count, i;
2769 MONO_ARCH_SAVE_REGS;
2771 domain = mono_object_domain (method);
2773 if (method->method->is_inflated) {
2774 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2776 if (inst) {
2777 count = inst->type_argc;
2778 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2780 for (i = 0; i < count; i++)
2781 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2783 return res;
2787 count = mono_method_signature (method->method)->generic_param_count;
2788 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2790 for (i = 0; i < count; i++) {
2791 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2792 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2793 MonoClass *pklass = mono_class_from_generic_parameter (
2794 param, method->method->klass->image, TRUE);
2795 mono_array_setref (res, i,
2796 mono_type_get_object (domain, &pklass->byval_arg));
2799 return res;
2802 static MonoObject *
2803 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2806 * Invoke from reflection is supposed to always be a virtual call (the API
2807 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2808 * greater flexibility.
2810 MonoMethod *m = method->method;
2811 int pcount;
2812 void *obj = this;
2814 MONO_ARCH_SAVE_REGS;
2816 *exc = NULL;
2818 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2819 mono_security_core_clr_ensure_reflection_access_method (m);
2821 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2822 if (this) {
2823 if (!mono_object_isinst (this, m->klass)) {
2824 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2825 return NULL;
2827 m = mono_object_get_virtual_method (this, m);
2828 /* must pass the pointer to the value for valuetype methods */
2829 if (m->klass->valuetype)
2830 obj = mono_object_unbox (this);
2831 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2832 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2833 return NULL;
2837 pcount = params? mono_array_length (params): 0;
2838 if (pcount != mono_method_signature (m)->param_count) {
2839 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2840 return NULL;
2843 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2844 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."));
2845 return NULL;
2848 if (m->klass->image->assembly->ref_only) {
2849 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."));
2850 return NULL;
2853 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2854 int i;
2855 mono_array_size_t *lengths;
2856 mono_array_size_t *lower_bounds;
2857 pcount = mono_array_length (params);
2858 lengths = alloca (sizeof (mono_array_size_t) * pcount);
2859 for (i = 0; i < pcount; ++i)
2860 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2862 if (m->klass->rank == pcount) {
2863 /* Only lengths provided. */
2864 lower_bounds = NULL;
2865 } else {
2866 g_assert (pcount == (m->klass->rank * 2));
2867 /* lower bounds are first. */
2868 lower_bounds = lengths;
2869 lengths += m->klass->rank;
2872 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2874 return mono_runtime_invoke_array (m, obj, params, NULL);
2877 static MonoObject *
2878 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2880 MonoDomain *domain = mono_object_domain (method);
2881 MonoMethod *m = method->method;
2882 MonoMethodSignature *sig = mono_method_signature (m);
2883 MonoArray *out_args;
2884 MonoObject *result;
2885 int i, j, outarg_count = 0;
2887 MONO_ARCH_SAVE_REGS;
2889 if (m->klass == mono_defaults.object_class) {
2891 if (!strcmp (m->name, "FieldGetter")) {
2892 MonoClass *k = this->vtable->klass;
2893 MonoString *name;
2894 char *str;
2896 /* If this is a proxy, then it must be a CBO */
2897 if (k == mono_defaults.transparent_proxy_class) {
2898 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2899 this = tp->rp->unwrapped_server;
2900 g_assert (this);
2901 k = this->vtable->klass;
2904 name = mono_array_get (params, MonoString *, 1);
2905 str = mono_string_to_utf8 (name);
2907 do {
2908 MonoClassField* field = mono_class_get_field_from_name (k, str);
2909 if (field) {
2910 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2911 if (field_klass->valuetype)
2912 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2913 else
2914 result = *((gpointer *)((char *)this + field->offset));
2916 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2917 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2918 mono_array_setref (out_args, 0, result);
2919 g_free (str);
2920 return NULL;
2922 k = k->parent;
2923 } while (k);
2925 g_free (str);
2926 g_assert_not_reached ();
2928 } else if (!strcmp (m->name, "FieldSetter")) {
2929 MonoClass *k = this->vtable->klass;
2930 MonoString *name;
2931 guint32 size;
2932 gint32 align;
2933 char *str;
2935 /* If this is a proxy, then it must be a CBO */
2936 if (k == mono_defaults.transparent_proxy_class) {
2937 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2938 this = tp->rp->unwrapped_server;
2939 g_assert (this);
2940 k = this->vtable->klass;
2943 name = mono_array_get (params, MonoString *, 1);
2944 str = mono_string_to_utf8 (name);
2946 do {
2947 MonoClassField* field = mono_class_get_field_from_name (k, str);
2948 if (field) {
2949 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2950 MonoObject *val = mono_array_get (params, gpointer, 2);
2952 if (field_klass->valuetype) {
2953 size = mono_type_size (field->type, &align);
2954 g_assert (size == mono_class_value_size (field_klass, NULL));
2955 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2956 } else {
2957 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2960 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2961 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2963 g_free (str);
2964 return NULL;
2967 k = k->parent;
2968 } while (k);
2970 g_free (str);
2971 g_assert_not_reached ();
2976 for (i = 0; i < mono_array_length (params); i++) {
2977 if (sig->params [i]->byref)
2978 outarg_count++;
2981 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2983 /* handle constructors only for objects already allocated */
2984 if (!strcmp (method->method->name, ".ctor"))
2985 g_assert (this);
2987 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2988 g_assert (!method->method->klass->valuetype);
2989 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2991 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2992 if (sig->params [i]->byref) {
2993 gpointer arg;
2994 arg = mono_array_get (params, gpointer, i);
2995 mono_array_setref (out_args, j, arg);
2996 j++;
3000 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3002 return result;
3005 static guint64
3006 read_enum_value (char *mem, int type)
3008 switch (type) {
3009 case MONO_TYPE_U1:
3010 return *(guint8*)mem;
3011 case MONO_TYPE_I1:
3012 return *(gint8*)mem;
3013 case MONO_TYPE_U2:
3014 return *(guint16*)mem;
3015 case MONO_TYPE_I2:
3016 return *(gint16*)mem;
3017 case MONO_TYPE_U4:
3018 return *(guint32*)mem;
3019 case MONO_TYPE_I4:
3020 return *(gint32*)mem;
3021 case MONO_TYPE_U8:
3022 return *(guint64*)mem;
3023 case MONO_TYPE_I8:
3024 return *(gint64*)mem;
3025 default:
3026 g_assert_not_reached ();
3028 return 0;
3031 static void
3032 write_enum_value (char *mem, int type, guint64 value)
3034 switch (type) {
3035 case MONO_TYPE_U1:
3036 case MONO_TYPE_I1: {
3037 guint8 *p = (guint8*)mem;
3038 *p = value;
3039 break;
3041 case MONO_TYPE_U2:
3042 case MONO_TYPE_I2: {
3043 guint16 *p = (void*)mem;
3044 *p = value;
3045 break;
3047 case MONO_TYPE_U4:
3048 case MONO_TYPE_I4: {
3049 guint32 *p = (void*)mem;
3050 *p = value;
3051 break;
3053 case MONO_TYPE_U8:
3054 case MONO_TYPE_I8: {
3055 guint64 *p = (void*)mem;
3056 *p = value;
3057 break;
3059 default:
3060 g_assert_not_reached ();
3062 return;
3065 static MonoObject *
3066 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3068 MonoDomain *domain;
3069 MonoClass *enumc, *objc;
3070 MonoObject *res;
3071 guint64 val;
3073 MONO_ARCH_SAVE_REGS;
3075 MONO_CHECK_ARG_NULL (enumType);
3076 MONO_CHECK_ARG_NULL (value);
3078 domain = mono_object_domain (enumType);
3079 enumc = mono_class_from_mono_type (enumType->type);
3080 objc = value->vtable->klass;
3082 if (!enumc->enumtype)
3083 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3084 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3085 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."));
3087 res = mono_object_new (domain, enumc);
3088 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3089 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3091 return res;
3094 static MonoObject *
3095 ves_icall_System_Enum_get_value (MonoObject *this)
3097 MonoObject *res;
3098 MonoClass *enumc;
3099 gpointer dst;
3100 gpointer src;
3101 int size;
3103 MONO_ARCH_SAVE_REGS;
3105 if (!this)
3106 return NULL;
3108 g_assert (this->vtable->klass->enumtype);
3110 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3111 res = mono_object_new (mono_object_domain (this), enumc);
3112 dst = (char *)res + sizeof (MonoObject);
3113 src = (char *)this + sizeof (MonoObject);
3114 size = mono_class_value_size (enumc, NULL);
3116 memcpy (dst, src, size);
3118 return res;
3121 static MonoReflectionType *
3122 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3124 MONO_ARCH_SAVE_REGS;
3126 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3129 static int
3130 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3132 gpointer tdata = (char *)this + sizeof (MonoObject);
3133 gpointer odata = (char *)other + sizeof (MonoObject);
3134 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3135 g_assert (basetype);
3137 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3138 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3139 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3140 if (me == other) \
3141 return 0; \
3142 return me > other ? 1 : -1; \
3143 } while (0)
3145 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3146 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3147 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3148 if (me == other) \
3149 return 0; \
3150 return me - other; \
3151 } while (0)
3153 switch (basetype->type) {
3154 case MONO_TYPE_U1:
3155 COMPARE_ENUM_VALUES (guint8);
3156 case MONO_TYPE_I1:
3157 COMPARE_ENUM_VALUES (gint8);
3158 case MONO_TYPE_CHAR:
3159 case MONO_TYPE_U2:
3160 COMPARE_ENUM_VALUES_RANGE (guint16);
3161 case MONO_TYPE_I2:
3162 COMPARE_ENUM_VALUES (gint16);
3163 case MONO_TYPE_U4:
3164 COMPARE_ENUM_VALUES (guint32);
3165 case MONO_TYPE_I4:
3166 COMPARE_ENUM_VALUES (gint32);
3167 case MONO_TYPE_U8:
3168 COMPARE_ENUM_VALUES (guint64);
3169 case MONO_TYPE_I8:
3170 COMPARE_ENUM_VALUES (gint64);
3171 default:
3172 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3174 #undef COMPARE_ENUM_VALUES_RANGE
3175 #undef COMPARE_ENUM_VALUES
3176 return 0;
3179 static int
3180 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3182 gpointer data = (char *)this + sizeof (MonoObject);
3183 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3184 g_assert (basetype);
3186 switch (basetype->type) {
3187 case MONO_TYPE_I1:
3188 return *((gint8*)data);
3189 case MONO_TYPE_U1:
3190 return *((guint8*)data);
3191 case MONO_TYPE_CHAR:
3192 case MONO_TYPE_U2:
3193 return *((guint16*)data);
3195 case MONO_TYPE_I2:
3196 return *((gint16*)data);
3197 case MONO_TYPE_U4:
3198 return *((guint32*)data);
3199 case MONO_TYPE_I4:
3200 return *((gint32*)data);
3201 case MONO_TYPE_U8:
3202 case MONO_TYPE_I8: {
3203 gint64 value = *((gint64*)data);
3204 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3206 default:
3207 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3209 return 0;
3212 static void
3213 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3215 MonoDomain *domain = mono_object_domain (type);
3216 MonoClass *enumc = mono_class_from_mono_type (type->type);
3217 guint j = 0, nvalues, crow;
3218 gpointer iter;
3219 MonoClassField *field;
3221 MONO_ARCH_SAVE_REGS;
3223 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3224 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3225 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3226 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3228 crow = -1;
3229 iter = NULL;
3230 while ((field = mono_class_get_fields (enumc, &iter))) {
3231 const char *p;
3232 int len;
3233 MonoTypeEnum def_type;
3235 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3236 continue;
3237 if (mono_field_is_deleted (field))
3238 continue;
3239 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3241 p = mono_class_get_field_default_value (field, &def_type);
3242 len = mono_metadata_decode_blob_size (p, &p);
3243 switch (mono_class_enum_basetype (enumc)->type) {
3244 case MONO_TYPE_U1:
3245 case MONO_TYPE_I1:
3246 mono_array_set (info->values, gchar, j, *p);
3247 break;
3248 case MONO_TYPE_CHAR:
3249 case MONO_TYPE_U2:
3250 case MONO_TYPE_I2:
3251 mono_array_set (info->values, gint16, j, read16 (p));
3252 break;
3253 case MONO_TYPE_U4:
3254 case MONO_TYPE_I4:
3255 mono_array_set (info->values, gint32, j, read32 (p));
3256 break;
3257 case MONO_TYPE_U8:
3258 case MONO_TYPE_I8:
3259 mono_array_set (info->values, gint64, j, read64 (p));
3260 break;
3261 default:
3262 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3264 ++j;
3268 enum {
3269 BFLAGS_IgnoreCase = 1,
3270 BFLAGS_DeclaredOnly = 2,
3271 BFLAGS_Instance = 4,
3272 BFLAGS_Static = 8,
3273 BFLAGS_Public = 0x10,
3274 BFLAGS_NonPublic = 0x20,
3275 BFLAGS_FlattenHierarchy = 0x40,
3276 BFLAGS_InvokeMethod = 0x100,
3277 BFLAGS_CreateInstance = 0x200,
3278 BFLAGS_GetField = 0x400,
3279 BFLAGS_SetField = 0x800,
3280 BFLAGS_GetProperty = 0x1000,
3281 BFLAGS_SetProperty = 0x2000,
3282 BFLAGS_ExactBinding = 0x10000,
3283 BFLAGS_SuppressChangeType = 0x20000,
3284 BFLAGS_OptionalParamBinding = 0x40000
3287 static MonoReflectionField *
3288 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3290 MonoDomain *domain;
3291 MonoClass *startklass, *klass;
3292 int match;
3293 MonoClassField *field;
3294 gpointer iter;
3295 char *utf8_name;
3296 int (*compare_func) (const char *s1, const char *s2) = NULL;
3297 domain = ((MonoObject *)type)->vtable->domain;
3298 klass = startklass = mono_class_from_mono_type (type->type);
3300 MONO_ARCH_SAVE_REGS;
3302 if (!name)
3303 mono_raise_exception (mono_get_exception_argument_null ("name"));
3304 if (type->type->byref)
3305 return NULL;
3307 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3309 handle_parent:
3310 if (klass->exception_type != MONO_EXCEPTION_NONE)
3311 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3313 iter = NULL;
3314 while ((field = mono_class_get_fields (klass, &iter))) {
3315 match = 0;
3317 if (field->type == NULL)
3318 continue;
3319 if (mono_field_is_deleted (field))
3320 continue;
3321 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3322 if (bflags & BFLAGS_Public)
3323 match++;
3324 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3325 if (bflags & BFLAGS_NonPublic) {
3326 match++;
3329 if (!match)
3330 continue;
3331 match = 0;
3332 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3333 if (bflags & BFLAGS_Static)
3334 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3335 match++;
3336 } else {
3337 if (bflags & BFLAGS_Instance)
3338 match++;
3341 if (!match)
3342 continue;
3344 utf8_name = mono_string_to_utf8 (name);
3346 if (compare_func (mono_field_get_name (field), utf8_name)) {
3347 g_free (utf8_name);
3348 continue;
3350 g_free (utf8_name);
3352 return mono_field_get_object (domain, klass, field);
3354 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3355 goto handle_parent;
3357 return NULL;
3360 static MonoArray*
3361 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3363 MonoDomain *domain;
3364 MonoClass *startklass, *klass, *refklass;
3365 MonoArray *res;
3366 MonoObject *member;
3367 int i, match;
3368 gpointer iter;
3369 MonoClassField *field;
3370 MonoPtrArray tmp_array;
3372 MONO_ARCH_SAVE_REGS;
3374 domain = ((MonoObject *)type)->vtable->domain;
3375 if (type->type->byref)
3376 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3377 klass = startklass = mono_class_from_mono_type (type->type);
3378 refklass = mono_class_from_mono_type (reftype->type);
3380 mono_ptr_array_init (tmp_array, 2);
3382 handle_parent:
3383 if (klass->exception_type != MONO_EXCEPTION_NONE)
3384 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3386 iter = NULL;
3387 while ((field = mono_class_get_fields (klass, &iter))) {
3388 match = 0;
3389 if (mono_field_is_deleted (field))
3390 continue;
3391 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3392 if (bflags & BFLAGS_Public)
3393 match++;
3394 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3395 if (bflags & BFLAGS_NonPublic) {
3396 match++;
3399 if (!match)
3400 continue;
3401 match = 0;
3402 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3403 if (bflags & BFLAGS_Static)
3404 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3405 match++;
3406 } else {
3407 if (bflags & BFLAGS_Instance)
3408 match++;
3411 if (!match)
3412 continue;
3413 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3414 mono_ptr_array_append (tmp_array, member);
3416 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3417 goto handle_parent;
3419 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3421 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3422 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3424 mono_ptr_array_destroy (tmp_array);
3426 return res;
3429 static gboolean
3430 method_nonpublic (MonoMethod* method, gboolean start_klass)
3432 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3433 case METHOD_ATTRIBUTE_ASSEM:
3434 return (start_klass || mono_defaults.generic_ilist_class);
3435 case METHOD_ATTRIBUTE_PRIVATE:
3436 return start_klass;
3437 case METHOD_ATTRIBUTE_PUBLIC:
3438 return FALSE;
3439 default:
3440 return TRUE;
3444 static MonoArray*
3445 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3447 static MonoClass *MethodInfo_array;
3448 MonoDomain *domain;
3449 MonoClass *startklass, *klass, *refklass;
3450 MonoArray *res;
3451 MonoMethod *method;
3452 gpointer iter;
3453 MonoObject *member;
3454 int i, len, match, nslots;
3455 /*FIXME, use MonoBitSet*/
3456 guint32 method_slots_default [8];
3457 guint32 *method_slots = NULL;
3458 gchar *mname = NULL;
3459 int (*compare_func) (const char *s1, const char *s2) = NULL;
3460 MonoVTable *array_vtable;
3461 MonoException *ex;
3462 MonoPtrArray tmp_array;
3464 MONO_ARCH_SAVE_REGS;
3466 mono_ptr_array_init (tmp_array, 4);
3468 if (!MethodInfo_array) {
3469 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3470 mono_memory_barrier ();
3471 MethodInfo_array = klass;
3474 domain = ((MonoObject *)type)->vtable->domain;
3475 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3476 if (type->type->byref)
3477 return mono_array_new_specific (array_vtable, 0);
3478 klass = startklass = mono_class_from_mono_type (type->type);
3479 refklass = mono_class_from_mono_type (reftype->type);
3480 len = 0;
3481 if (name != NULL) {
3482 mname = mono_string_to_utf8 (name);
3483 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3486 /* An optimization for calls made from Delegate:CreateDelegate () */
3487 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3488 method = mono_get_delegate_invoke (klass);
3489 if (mono_loader_get_last_error ())
3490 goto loader_error;
3492 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3494 res = mono_array_new_specific (array_vtable, 1);
3495 mono_array_setref (res, 0, member);
3496 g_free (mname);
3497 return res;
3500 mono_class_setup_vtable (klass);
3501 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3502 goto loader_error;
3504 if (is_generic_parameter (type->type))
3505 nslots = mono_class_get_vtable_size (klass->parent);
3506 else
3507 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3508 if (nslots >= sizeof (method_slots_default) * 8) {
3509 method_slots = g_new0 (guint32, nslots / 32 + 1);
3510 } else {
3511 method_slots = method_slots_default;
3512 memset (method_slots, 0, sizeof (method_slots_default));
3514 handle_parent:
3515 mono_class_setup_vtable (klass);
3516 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3517 goto loader_error;
3519 iter = NULL;
3520 while ((method = mono_class_get_methods (klass, &iter))) {
3521 match = 0;
3522 if (method->slot != -1) {
3523 g_assert (method->slot < nslots);
3524 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3525 continue;
3526 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3527 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3530 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3531 continue;
3532 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3533 if (bflags & BFLAGS_Public)
3534 match++;
3535 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3536 match++;
3538 if (!match)
3539 continue;
3540 match = 0;
3541 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3542 if (bflags & BFLAGS_Static)
3543 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3544 match++;
3545 } else {
3546 if (bflags & BFLAGS_Instance)
3547 match++;
3550 if (!match)
3551 continue;
3553 if (name != NULL) {
3554 if (compare_func (mname, method->name))
3555 continue;
3558 match = 0;
3560 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3562 mono_ptr_array_append (tmp_array, member);
3564 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3565 goto handle_parent;
3567 g_free (mname);
3568 if (method_slots != method_slots_default)
3569 g_free (method_slots);
3571 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3573 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3574 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3576 mono_ptr_array_destroy (tmp_array);
3577 return res;
3579 loader_error:
3580 g_free (mname);
3581 if (method_slots != method_slots_default)
3582 g_free (method_slots);
3583 mono_ptr_array_destroy (tmp_array);
3584 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3585 ex = mono_class_get_exception_for_failure (klass);
3586 } else {
3587 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3588 mono_loader_clear_error ();
3590 mono_raise_exception (ex);
3591 return NULL;
3594 static MonoArray*
3595 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3597 MonoDomain *domain;
3598 static MonoClass *System_Reflection_ConstructorInfo;
3599 MonoClass *startklass, *klass, *refklass;
3600 MonoArray *res;
3601 MonoMethod *method;
3602 MonoObject *member;
3603 int i, match;
3604 gpointer iter = NULL;
3605 MonoPtrArray tmp_array;
3607 MONO_ARCH_SAVE_REGS;
3609 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3611 domain = ((MonoObject *)type)->vtable->domain;
3612 if (type->type->byref)
3613 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3614 klass = startklass = mono_class_from_mono_type (type->type);
3615 refklass = mono_class_from_mono_type (reftype->type);
3617 if (klass->exception_type != MONO_EXCEPTION_NONE)
3618 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3620 if (!System_Reflection_ConstructorInfo)
3621 System_Reflection_ConstructorInfo = mono_class_from_name (
3622 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3624 iter = NULL;
3625 while ((method = mono_class_get_methods (klass, &iter))) {
3626 match = 0;
3627 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3628 continue;
3629 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3630 if (bflags & BFLAGS_Public)
3631 match++;
3632 } else {
3633 if (bflags & BFLAGS_NonPublic)
3634 match++;
3636 if (!match)
3637 continue;
3638 match = 0;
3639 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3640 if (bflags & BFLAGS_Static)
3641 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3642 match++;
3643 } else {
3644 if (bflags & BFLAGS_Instance)
3645 match++;
3648 if (!match)
3649 continue;
3650 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3652 mono_ptr_array_append (tmp_array, member);
3655 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3657 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3658 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3660 mono_ptr_array_destroy (tmp_array);
3662 return res;
3665 static guint
3666 property_hash (gconstpointer data)
3668 MonoProperty *prop = (MonoProperty*)data;
3670 return g_str_hash (prop->name);
3673 static gboolean
3674 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3676 // Properties are hide-by-name-and-signature
3677 if (!g_str_equal (prop1->name, prop2->name))
3678 return FALSE;
3680 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3681 return FALSE;
3682 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3683 return FALSE;
3684 return TRUE;
3687 static gboolean
3688 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3690 if (!accessor)
3691 return FALSE;
3693 return method_nonpublic (accessor, start_klass);
3696 static MonoArray*
3697 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3699 MonoDomain *domain;
3700 static MonoClass *System_Reflection_PropertyInfo;
3701 MonoClass *startklass, *klass;
3702 MonoArray *res;
3703 MonoMethod *method;
3704 MonoProperty *prop;
3705 int i, match;
3706 guint32 flags;
3707 gchar *propname = NULL;
3708 int (*compare_func) (const char *s1, const char *s2) = NULL;
3709 gpointer iter;
3710 GHashTable *properties;
3711 MonoPtrArray tmp_array;
3713 MONO_ARCH_SAVE_REGS;
3715 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3717 if (!System_Reflection_PropertyInfo)
3718 System_Reflection_PropertyInfo = mono_class_from_name (
3719 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3721 domain = ((MonoObject *)type)->vtable->domain;
3722 if (type->type->byref)
3723 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3724 klass = startklass = mono_class_from_mono_type (type->type);
3725 if (name != NULL) {
3726 propname = mono_string_to_utf8 (name);
3727 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3730 mono_class_setup_vtable (klass);
3732 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3733 handle_parent:
3734 mono_class_setup_vtable (klass);
3735 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3736 g_hash_table_destroy (properties);
3737 if (name != NULL)
3738 g_free (propname);
3739 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3742 iter = NULL;
3743 while ((prop = mono_class_get_properties (klass, &iter))) {
3744 match = 0;
3745 method = prop->get;
3746 if (!method)
3747 method = prop->set;
3748 if (method)
3749 flags = method->flags;
3750 else
3751 flags = 0;
3752 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3753 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3754 if (bflags & BFLAGS_Public)
3755 match++;
3756 } else if (bflags & BFLAGS_NonPublic) {
3757 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3758 property_accessor_nonpublic(prop->set, startklass == klass)) {
3759 match++;
3762 if (!match)
3763 continue;
3764 match = 0;
3765 if (flags & METHOD_ATTRIBUTE_STATIC) {
3766 if (bflags & BFLAGS_Static)
3767 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3768 match++;
3769 } else {
3770 if (bflags & BFLAGS_Instance)
3771 match++;
3774 if (!match)
3775 continue;
3776 match = 0;
3778 if (name != NULL) {
3779 if (compare_func (propname, prop->name))
3780 continue;
3783 if (g_hash_table_lookup (properties, prop))
3784 continue;
3786 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3788 g_hash_table_insert (properties, prop, prop);
3790 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3791 goto handle_parent;
3793 g_hash_table_destroy (properties);
3794 g_free (propname);
3796 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3797 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3798 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3800 mono_ptr_array_destroy (tmp_array);
3802 return res;
3805 static MonoReflectionEvent *
3806 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3808 MonoDomain *domain;
3809 MonoClass *klass, *startklass;
3810 gpointer iter;
3811 MonoEvent *event;
3812 MonoMethod *method;
3813 gchar *event_name;
3815 MONO_ARCH_SAVE_REGS;
3817 event_name = mono_string_to_utf8 (name);
3818 if (type->type->byref)
3819 return NULL;
3820 klass = startklass = mono_class_from_mono_type (type->type);
3821 domain = mono_object_domain (type);
3823 handle_parent:
3824 if (klass->exception_type != MONO_EXCEPTION_NONE)
3825 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3827 iter = NULL;
3828 while ((event = mono_class_get_events (klass, &iter))) {
3829 if (strcmp (event->name, event_name))
3830 continue;
3832 method = event->add;
3833 if (!method)
3834 method = event->remove;
3835 if (!method)
3836 method = event->raise;
3837 if (method) {
3838 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3839 if (!(bflags & BFLAGS_Public))
3840 continue;
3841 } else {
3842 if (!(bflags & BFLAGS_NonPublic))
3843 continue;
3844 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3845 continue;
3848 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3849 if (!(bflags & BFLAGS_Static))
3850 continue;
3851 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3852 continue;
3853 } else {
3854 if (!(bflags & BFLAGS_Instance))
3855 continue;
3857 } else
3858 if (!(bflags & BFLAGS_NonPublic))
3859 continue;
3861 g_free (event_name);
3862 return mono_event_get_object (domain, startklass, event);
3865 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3866 goto handle_parent;
3868 g_free (event_name);
3869 return NULL;
3872 static MonoArray*
3873 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3875 MonoDomain *domain;
3876 static MonoClass *System_Reflection_EventInfo;
3877 MonoClass *startklass, *klass;
3878 MonoArray *res;
3879 MonoMethod *method;
3880 MonoEvent *event;
3881 int i, match;
3882 gpointer iter;
3884 MonoPtrArray tmp_array;
3886 MONO_ARCH_SAVE_REGS;
3888 mono_ptr_array_init (tmp_array, 4);
3890 if (!System_Reflection_EventInfo)
3891 System_Reflection_EventInfo = mono_class_from_name (
3892 mono_defaults.corlib, "System.Reflection", "EventInfo");
3894 domain = mono_object_domain (type);
3895 if (type->type->byref)
3896 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3897 klass = startklass = mono_class_from_mono_type (type->type);
3899 handle_parent:
3900 if (klass->exception_type != MONO_EXCEPTION_NONE)
3901 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3903 iter = NULL;
3904 while ((event = mono_class_get_events (klass, &iter))) {
3905 match = 0;
3906 method = event->add;
3907 if (!method)
3908 method = event->remove;
3909 if (!method)
3910 method = event->raise;
3911 if (method) {
3912 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3913 if (bflags & BFLAGS_Public)
3914 match++;
3915 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3916 if (bflags & BFLAGS_NonPublic)
3917 match++;
3920 else
3921 if (bflags & BFLAGS_NonPublic)
3922 match ++;
3923 if (!match)
3924 continue;
3925 match = 0;
3926 if (method) {
3927 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3928 if (bflags & BFLAGS_Static)
3929 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3930 match++;
3931 } else {
3932 if (bflags & BFLAGS_Instance)
3933 match++;
3936 else
3937 if (bflags & BFLAGS_Instance)
3938 match ++;
3939 if (!match)
3940 continue;
3941 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3943 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3944 goto handle_parent;
3946 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3948 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3949 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3951 mono_ptr_array_destroy (tmp_array);
3953 return res;
3956 static MonoReflectionType *
3957 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3959 MonoDomain *domain;
3960 MonoClass *klass;
3961 MonoClass *nested;
3962 char *str;
3963 gpointer iter;
3965 MONO_ARCH_SAVE_REGS;
3967 if (name == NULL)
3968 mono_raise_exception (mono_get_exception_argument_null ("name"));
3970 domain = ((MonoObject *)type)->vtable->domain;
3971 if (type->type->byref)
3972 return NULL;
3973 klass = mono_class_from_mono_type (type->type);
3974 str = mono_string_to_utf8 (name);
3976 handle_parent:
3977 if (klass->exception_type != MONO_EXCEPTION_NONE)
3978 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3981 * If a nested type is generic, return its generic type definition.
3982 * Note that this means that the return value is essentially a
3983 * nested type of the generic type definition of @klass.
3985 * A note in MSDN claims that a generic type definition can have
3986 * nested types that aren't generic. In any case, the container of that
3987 * nested type would be the generic type definition.
3989 if (klass->generic_class)
3990 klass = klass->generic_class->container_class;
3992 iter = NULL;
3993 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3994 int match = 0;
3995 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3996 if (bflags & BFLAGS_Public)
3997 match++;
3998 } else {
3999 if (bflags & BFLAGS_NonPublic)
4000 match++;
4002 if (!match)
4003 continue;
4004 if (strcmp (nested->name, str) == 0){
4005 g_free (str);
4006 return mono_type_get_object (domain, &nested->byval_arg);
4009 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4010 goto handle_parent;
4011 g_free (str);
4012 return NULL;
4015 static MonoArray*
4016 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4018 MonoDomain *domain;
4019 MonoClass *klass;
4020 MonoArray *res;
4021 MonoObject *member;
4022 int i, match;
4023 MonoClass *nested;
4024 gpointer iter;
4025 MonoPtrArray tmp_array;
4027 MONO_ARCH_SAVE_REGS;
4029 domain = ((MonoObject *)type)->vtable->domain;
4030 if (type->type->byref)
4031 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4032 klass = mono_class_from_mono_type (type->type);
4033 if (klass->exception_type != MONO_EXCEPTION_NONE)
4034 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4037 * If a nested type is generic, return its generic type definition.
4038 * Note that this means that the return value is essentially the set
4039 * of nested types of the generic type definition of @klass.
4041 * A note in MSDN claims that a generic type definition can have
4042 * nested types that aren't generic. In any case, the container of that
4043 * nested type would be the generic type definition.
4045 if (klass->generic_class)
4046 klass = klass->generic_class->container_class;
4048 mono_ptr_array_init (tmp_array, 1);
4049 iter = NULL;
4050 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4051 match = 0;
4052 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4053 if (bflags & BFLAGS_Public)
4054 match++;
4055 } else {
4056 if (bflags & BFLAGS_NonPublic)
4057 match++;
4059 if (!match)
4060 continue;
4061 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4062 mono_ptr_array_append (tmp_array, member);
4065 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4067 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4068 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4070 mono_ptr_array_destroy (tmp_array);
4072 return res;
4075 static MonoReflectionType*
4076 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4078 gchar *str;
4079 MonoType *type = NULL;
4080 MonoTypeNameParse info;
4081 gboolean type_resolve;
4083 MONO_ARCH_SAVE_REGS;
4085 /* On MS.NET, this does not fire a TypeResolve event */
4086 type_resolve = TRUE;
4087 str = mono_string_to_utf8 (name);
4088 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4089 if (!mono_reflection_parse_type (str, &info)) {
4090 g_free (str);
4091 mono_reflection_free_type_info (&info);
4092 if (throwOnError) /* uhm: this is a parse error, though... */
4093 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4094 /*g_print ("failed parse\n");*/
4095 return NULL;
4098 if (info.assembly.name) {
4099 g_free (str);
4100 mono_reflection_free_type_info (&info);
4101 if (throwOnError) {
4102 /* 1.0 and 2.0 throw different exceptions */
4103 if (mono_defaults.generic_ilist_class)
4104 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4105 else
4106 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4108 return NULL;
4111 if (module != NULL) {
4112 if (module->image)
4113 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4114 else
4115 type = NULL;
4117 else
4118 if (assembly->assembly->dynamic) {
4119 /* Enumerate all modules */
4120 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4121 int i;
4123 type = NULL;
4124 if (abuilder->modules) {
4125 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4126 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4127 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4128 if (type)
4129 break;
4133 if (!type && abuilder->loaded_modules) {
4134 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4135 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4136 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4137 if (type)
4138 break;
4142 else
4143 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4144 g_free (str);
4145 mono_reflection_free_type_info (&info);
4146 if (!type) {
4147 MonoException *e = NULL;
4149 if (throwOnError)
4150 e = mono_get_exception_type_load (name, NULL);
4152 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4153 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4155 mono_loader_clear_error ();
4157 if (e != NULL)
4158 mono_raise_exception (e);
4160 return NULL;
4163 if (type->type == MONO_TYPE_CLASS) {
4164 MonoClass *klass = mono_type_get_class (type);
4166 if (mono_is_security_manager_active () && !klass->exception_type)
4167 /* Some security problems are detected during generic vtable construction */
4168 mono_class_setup_vtable (klass);
4169 /* need to report exceptions ? */
4170 if (throwOnError && klass->exception_type) {
4171 /* report SecurityException (or others) that occured when loading the assembly */
4172 MonoException *exc = mono_class_get_exception_for_failure (klass);
4173 mono_loader_clear_error ();
4174 mono_raise_exception (exc);
4175 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4176 return NULL;
4180 /* g_print ("got it\n"); */
4181 return mono_type_get_object (mono_object_domain (assembly), type);
4184 static gboolean
4185 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4187 gchar *content;
4188 gchar *shadow_ini_file;
4189 gsize len;
4191 /* Check for shadow-copied assembly */
4192 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4193 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4194 content = NULL;
4195 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4196 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4197 if (content) {
4198 g_free (content);
4199 content = NULL;
4202 g_free (shadow_ini_file);
4203 if (content != NULL) {
4204 if (*filename)
4205 g_free (*filename);
4206 *filename = content;
4207 return TRUE;
4210 return FALSE;
4213 static MonoString *
4214 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4216 MonoDomain *domain = mono_object_domain (assembly);
4217 MonoAssembly *mass = assembly->assembly;
4218 MonoString *res = NULL;
4219 gchar *uri;
4220 gchar *absolute;
4221 gchar *dirname;
4223 MONO_ARCH_SAVE_REGS;
4225 if (g_path_is_absolute (mass->image->name)) {
4226 absolute = g_strdup (mass->image->name);
4227 dirname = g_path_get_dirname (absolute);
4228 } else {
4229 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4230 dirname = g_strdup (mass->basedir);
4233 replace_shadow_path (domain, dirname, &absolute);
4234 g_free (dirname);
4235 #if HOST_WIN32
4237 gint i;
4238 for (i = strlen (absolute) - 1; i >= 0; i--)
4239 if (absolute [i] == '\\')
4240 absolute [i] = '/';
4242 #endif
4243 if (escaped) {
4244 uri = g_filename_to_uri (absolute, NULL, NULL);
4245 } else {
4246 const char *prepend = "file://";
4247 #if HOST_WIN32
4248 if (*absolute == '/' && *(absolute + 1) == '/') {
4249 prepend = "file:";
4250 } else {
4251 prepend = "file:///";
4253 #endif
4254 uri = g_strconcat (prepend, absolute, NULL);
4257 if (uri) {
4258 res = mono_string_new (domain, uri);
4259 g_free (uri);
4261 g_free (absolute);
4262 return res;
4265 static MonoBoolean
4266 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4268 MonoAssembly *mass = assembly->assembly;
4270 MONO_ARCH_SAVE_REGS;
4272 return mass->in_gac;
4275 static MonoReflectionAssembly*
4276 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4278 gchar *name;
4279 MonoAssembly *res;
4280 MonoImageOpenStatus status;
4282 MONO_ARCH_SAVE_REGS;
4284 name = mono_string_to_utf8 (mname);
4285 res = mono_assembly_load_with_partial_name (name, &status);
4287 g_free (name);
4289 if (res == NULL)
4290 return NULL;
4291 return mono_assembly_get_object (mono_domain_get (), res);
4294 static MonoString *
4295 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4297 MonoDomain *domain = mono_object_domain (assembly);
4298 MonoString *res;
4300 MONO_ARCH_SAVE_REGS;
4302 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4304 return res;
4307 static MonoBoolean
4308 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4310 MONO_ARCH_SAVE_REGS;
4312 return assembly->assembly->ref_only;
4315 static MonoString *
4316 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4318 MonoDomain *domain = mono_object_domain (assembly);
4320 MONO_ARCH_SAVE_REGS;
4322 return mono_string_new (domain, assembly->assembly->image->version);
4325 static MonoReflectionMethod*
4326 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4328 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4330 MONO_ARCH_SAVE_REGS;
4332 if (!token)
4333 return NULL;
4334 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4337 static MonoReflectionModule*
4338 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4340 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4343 static MonoArray*
4344 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4346 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4347 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4348 int i;
4349 const char *val;
4351 MONO_ARCH_SAVE_REGS;
4353 for (i = 0; i < table->rows; ++i) {
4354 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4355 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4357 return result;
4360 static MonoObject*
4361 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4363 static MonoClass *System_Version = NULL;
4364 static MonoMethod *create_version = NULL;
4365 MonoObject *result;
4366 gpointer args [4];
4368 if (!System_Version) {
4369 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4370 g_assert (System_Version);
4373 if (!create_version) {
4374 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4375 create_version = mono_method_desc_search_in_class (desc, System_Version);
4376 g_assert (create_version);
4377 mono_method_desc_free (desc);
4380 args [0] = &major;
4381 args [1] = &minor;
4382 args [2] = &build;
4383 args [3] = &revision;
4384 result = mono_object_new (domain, System_Version);
4385 mono_runtime_invoke (create_version, result, args, NULL);
4387 return result;
4390 static MonoArray*
4391 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4393 static MonoClass *System_Reflection_AssemblyName;
4394 MonoArray *result;
4395 MonoDomain *domain = mono_object_domain (assembly);
4396 int i, count = 0;
4397 static MonoMethod *create_culture = NULL;
4398 MonoImage *image = assembly->assembly->image;
4399 MonoTableInfo *t;
4401 MONO_ARCH_SAVE_REGS;
4403 if (!System_Reflection_AssemblyName)
4404 System_Reflection_AssemblyName = mono_class_from_name (
4405 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4407 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4408 count = t->rows;
4410 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4412 if (count > 0 && !create_culture) {
4413 MonoMethodDesc *desc = mono_method_desc_new (
4414 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4415 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4416 g_assert (create_culture);
4417 mono_method_desc_free (desc);
4420 for (i = 0; i < count; i++) {
4421 MonoReflectionAssemblyName *aname;
4422 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4424 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4426 aname = (MonoReflectionAssemblyName *) mono_object_new (
4427 domain, System_Reflection_AssemblyName);
4429 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4431 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4432 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4433 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4434 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4435 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4436 aname->versioncompat = 1; /* SameMachine (default) */
4437 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4438 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4440 if (create_culture) {
4441 gpointer args [2];
4442 MonoBoolean assembly_ref = 1;
4443 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4444 args [1] = &assembly_ref;
4445 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4448 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4449 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4450 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4452 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4453 /* public key token isn't copied - the class library will
4454 automatically generate it from the public key if required */
4455 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4456 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4457 } else {
4458 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4459 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4461 } else {
4462 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4465 /* note: this function doesn't return the codebase on purpose (i.e. it can
4466 be used under partial trust as path information isn't present). */
4468 mono_array_setref (result, i, aname);
4470 return result;
4473 typedef struct {
4474 MonoArray *res;
4475 int idx;
4476 } NameSpaceInfo;
4478 static void
4479 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4481 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4483 mono_array_setref (info->res, info->idx, name);
4484 info->idx++;
4487 static MonoArray*
4488 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4490 MonoImage *img = assembly->assembly->image;
4491 MonoArray *res;
4492 NameSpaceInfo info;
4493 int len;
4495 MONO_ARCH_SAVE_REGS;
4497 mono_image_lock (img);
4498 mono_image_init_name_cache (img);
4500 RETRY_LEN:
4501 len = g_hash_table_size (img->name_cache);
4502 mono_image_unlock (img);
4504 /*we can't create objects holding the image lock */
4505 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4507 mono_image_lock (img);
4508 /*len might have changed, create a new array*/
4509 if (len != g_hash_table_size (img->name_cache))
4510 goto RETRY_LEN;
4512 info.res = res;
4513 info.idx = 0;
4514 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4515 mono_image_unlock (img);
4517 return res;
4520 /* move this in some file in mono/util/ */
4521 static char *
4522 g_concat_dir_and_file (const char *dir, const char *file)
4524 g_return_val_if_fail (dir != NULL, NULL);
4525 g_return_val_if_fail (file != NULL, NULL);
4528 * If the directory name doesn't have a / on the end, we need
4529 * to add one so we get a proper path to the file
4531 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4532 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4533 else
4534 return g_strconcat (dir, file, NULL);
4537 static void *
4538 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4540 char *n = mono_string_to_utf8 (name);
4541 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4542 guint32 i;
4543 guint32 cols [MONO_MANIFEST_SIZE];
4544 guint32 impl, file_idx;
4545 const char *val;
4546 MonoImage *module;
4548 MONO_ARCH_SAVE_REGS;
4550 for (i = 0; i < table->rows; ++i) {
4551 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4552 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4553 if (strcmp (val, n) == 0)
4554 break;
4556 g_free (n);
4557 if (i == table->rows)
4558 return NULL;
4559 /* FIXME */
4560 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4561 if (impl) {
4563 * this code should only be called after obtaining the
4564 * ResourceInfo and handling the other cases.
4566 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4567 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4569 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4570 if (!module)
4571 return NULL;
4573 else
4574 module = assembly->assembly->image;
4576 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4578 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4581 static gboolean
4582 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4584 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4585 int i;
4586 guint32 cols [MONO_MANIFEST_SIZE];
4587 guint32 file_cols [MONO_FILE_SIZE];
4588 const char *val;
4589 char *n;
4591 MONO_ARCH_SAVE_REGS;
4593 n = mono_string_to_utf8 (name);
4594 for (i = 0; i < table->rows; ++i) {
4595 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4596 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4597 if (strcmp (val, n) == 0)
4598 break;
4600 g_free (n);
4601 if (i == table->rows)
4602 return FALSE;
4604 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4605 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4607 else {
4608 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4609 case MONO_IMPLEMENTATION_FILE:
4610 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4611 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4612 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4613 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4614 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4615 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4616 info->location = 0;
4617 else
4618 info->location = RESOURCE_LOCATION_EMBEDDED;
4619 break;
4621 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4622 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4623 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4624 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4625 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4626 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4627 g_free (msg);
4628 mono_raise_exception (ex);
4630 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4632 /* Obtain info recursively */
4633 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4634 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4635 break;
4637 case MONO_IMPLEMENTATION_EXP_TYPE:
4638 g_assert_not_reached ();
4639 break;
4643 return TRUE;
4646 static MonoObject*
4647 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4649 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4650 MonoArray *result = NULL;
4651 int i, count;
4652 const char *val;
4653 char *n;
4655 MONO_ARCH_SAVE_REGS;
4657 /* check hash if needed */
4658 if (name) {
4659 n = mono_string_to_utf8 (name);
4660 for (i = 0; i < table->rows; ++i) {
4661 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4662 if (strcmp (val, n) == 0) {
4663 MonoString *fn;
4664 g_free (n);
4665 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4666 fn = mono_string_new (mono_object_domain (assembly), n);
4667 g_free (n);
4668 return (MonoObject*)fn;
4671 g_free (n);
4672 return NULL;
4675 count = 0;
4676 for (i = 0; i < table->rows; ++i) {
4677 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4678 count ++;
4681 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4683 count = 0;
4684 for (i = 0; i < table->rows; ++i) {
4685 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4686 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4687 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4688 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4689 g_free (n);
4690 count ++;
4693 return (MonoObject*)result;
4696 static MonoArray*
4697 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4699 MonoDomain *domain = mono_domain_get();
4700 MonoArray *res;
4701 MonoClass *klass;
4702 int i, j, file_count = 0;
4703 MonoImage **modules;
4704 guint32 module_count, real_module_count;
4705 MonoTableInfo *table;
4706 guint32 cols [MONO_FILE_SIZE];
4707 MonoImage *image = assembly->assembly->image;
4709 g_assert (image != NULL);
4710 g_assert (!assembly->assembly->dynamic);
4712 table = &image->tables [MONO_TABLE_FILE];
4713 file_count = table->rows;
4715 modules = image->modules;
4716 module_count = image->module_count;
4718 real_module_count = 0;
4719 for (i = 0; i < module_count; ++i)
4720 if (modules [i])
4721 real_module_count ++;
4723 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4724 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4726 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4727 j = 1;
4728 for (i = 0; i < module_count; ++i)
4729 if (modules [i]) {
4730 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4731 ++j;
4734 for (i = 0; i < file_count; ++i, ++j) {
4735 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4736 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4737 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4738 else {
4739 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4740 if (!m) {
4741 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4742 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4744 mono_array_setref (res, j, mono_module_get_object (domain, m));
4748 return res;
4751 static MonoReflectionMethod*
4752 ves_icall_GetCurrentMethod (void)
4754 MonoMethod *m = mono_method_get_last_managed ();
4756 while (m->is_inflated)
4757 m = ((MonoMethodInflated*)m)->declaring;
4759 return mono_method_get_object (mono_domain_get (), m, NULL);
4763 static MonoMethod*
4764 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4766 int offset = -1, i;
4767 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4768 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4769 //method is inflated, we should inflate it on the other class
4770 MonoGenericContext ctx;
4771 ctx.method_inst = inflated->context.method_inst;
4772 ctx.class_inst = inflated->context.class_inst;
4773 if (klass->generic_class)
4774 ctx.class_inst = klass->generic_class->context.class_inst;
4775 else if (klass->generic_container)
4776 ctx.class_inst = klass->generic_container->context.class_inst;
4777 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4780 mono_class_setup_methods (method->klass);
4781 if (method->klass->exception_type)
4782 return NULL;
4783 for (i = 0; i < method->klass->method.count; ++i) {
4784 if (method->klass->methods [i] == method) {
4785 offset = i;
4786 break;
4789 mono_class_setup_methods (klass);
4790 if (klass->exception_type)
4791 return NULL;
4792 g_assert (offset >= 0 && offset < klass->method.count);
4793 return klass->methods [offset];
4796 static MonoReflectionMethod*
4797 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4799 MonoClass *klass;
4800 if (type) {
4801 klass = mono_class_from_mono_type (type);
4802 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4803 return NULL;
4804 if (method->klass != klass) {
4805 method = mono_method_get_equivalent_method (method, klass);
4806 if (!method)
4807 return NULL;
4809 } else
4810 klass = method->klass;
4811 return mono_method_get_object (mono_domain_get (), method, klass);
4814 static MonoReflectionMethod*
4815 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4817 return mono_method_get_object (mono_domain_get (), method, NULL);
4820 static MonoReflectionMethodBody*
4821 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4823 return mono_method_body_get_object (mono_domain_get (), method);
4826 static MonoReflectionAssembly*
4827 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4829 MonoMethod *dest = NULL;
4831 MONO_ARCH_SAVE_REGS;
4833 mono_stack_walk_no_il (get_executing, &dest);
4834 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4838 static MonoReflectionAssembly*
4839 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4841 MonoDomain* domain = mono_domain_get ();
4843 MONO_ARCH_SAVE_REGS;
4845 if (!domain->entry_assembly)
4846 return NULL;
4848 return mono_assembly_get_object (domain, domain->entry_assembly);
4851 static MonoReflectionAssembly*
4852 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4854 MonoMethod *m;
4855 MonoMethod *dest;
4857 MONO_ARCH_SAVE_REGS;
4859 dest = NULL;
4860 mono_stack_walk_no_il (get_executing, &dest);
4861 m = dest;
4862 mono_stack_walk_no_il (get_caller, &dest);
4863 if (!dest)
4864 dest = m;
4865 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4868 static MonoString *
4869 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4870 gboolean assembly_qualified)
4872 MonoDomain *domain = mono_object_domain (object);
4873 MonoTypeNameFormat format;
4874 MonoString *res;
4875 gchar *name;
4877 MONO_ARCH_SAVE_REGS;
4878 if (full_name)
4879 format = assembly_qualified ?
4880 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4881 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4882 else
4883 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4885 name = mono_type_get_name_full (object->type, format);
4886 if (!name)
4887 return NULL;
4889 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4890 g_free (name);
4891 return NULL;
4894 res = mono_string_new (domain, name);
4895 g_free (name);
4897 return res;
4900 static int
4901 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4903 MonoClass *klass = mono_class_from_mono_type (this->type);
4904 return mono_security_core_clr_class_level (klass);
4907 static void
4908 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4910 static MonoMethod *create_culture = NULL;
4911 gpointer args [2];
4912 guint32 pkey_len;
4913 const char *pkey_ptr;
4914 gchar *codebase;
4915 MonoBoolean assembly_ref = 0;
4917 MONO_ARCH_SAVE_REGS;
4919 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4920 aname->major = name->major;
4921 aname->minor = name->minor;
4922 aname->build = name->build;
4923 aname->flags = name->flags;
4924 aname->revision = name->revision;
4925 aname->hashalg = name->hash_alg;
4926 aname->versioncompat = 1; /* SameMachine (default) */
4928 if (by_default_version)
4929 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4931 codebase = NULL;
4932 if (absolute != NULL && *absolute != '\0') {
4933 const gchar *prepend = "file://";
4934 gchar *result;
4936 codebase = g_strdup (absolute);
4938 #if HOST_WIN32
4940 gint i;
4941 for (i = strlen (codebase) - 1; i >= 0; i--)
4942 if (codebase [i] == '\\')
4943 codebase [i] = '/';
4945 if (*codebase == '/' && *(codebase + 1) == '/') {
4946 prepend = "file:";
4947 } else {
4948 prepend = "file:///";
4951 #endif
4952 result = g_strconcat (prepend, codebase, NULL);
4953 g_free (codebase);
4954 codebase = result;
4957 if (codebase) {
4958 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4959 g_free (codebase);
4962 if (!create_culture) {
4963 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4964 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4965 g_assert (create_culture);
4966 mono_method_desc_free (desc);
4969 if (name->culture) {
4970 args [0] = mono_string_new (domain, name->culture);
4971 args [1] = &assembly_ref;
4972 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4975 if (name->public_key) {
4976 pkey_ptr = (char*)name->public_key;
4977 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4979 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4980 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4981 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4982 } else if (default_publickey) {
4983 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4984 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4987 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4988 if (name->public_key_token [0]) {
4989 int i, j;
4990 char *p;
4992 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4993 p = mono_array_addr (aname->keyToken, char, 0);
4995 for (i = 0, j = 0; i < 8; i++) {
4996 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4997 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4998 p++;
5000 } else if (default_token) {
5001 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5005 static MonoString *
5006 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5008 MonoDomain *domain = mono_object_domain (assembly);
5009 MonoAssembly *mass = assembly->assembly;
5010 MonoString *res;
5011 gchar *name;
5013 name = g_strdup_printf (
5014 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5015 mass->aname.name,
5016 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5017 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5018 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5019 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5021 res = mono_string_new (domain, name);
5022 g_free (name);
5024 return res;
5027 static void
5028 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5030 gchar *absolute;
5031 MonoAssembly *mass = assembly->assembly;
5033 MONO_ARCH_SAVE_REGS;
5035 if (g_path_is_absolute (mass->image->name)) {
5036 fill_reflection_assembly_name (mono_object_domain (assembly),
5037 aname, &mass->aname, mass->image->name, TRUE,
5038 TRUE, TRUE);
5039 return;
5041 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5043 fill_reflection_assembly_name (mono_object_domain (assembly),
5044 aname, &mass->aname, absolute, TRUE, TRUE,
5045 TRUE);
5047 g_free (absolute);
5050 static void
5051 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5053 char *filename;
5054 MonoImageOpenStatus status = MONO_IMAGE_OK;
5055 gboolean res;
5056 MonoImage *image;
5057 MonoAssemblyName name;
5058 char *dirname
5060 MONO_ARCH_SAVE_REGS;
5062 filename = mono_string_to_utf8 (fname);
5064 dirname = g_path_get_dirname (filename);
5065 replace_shadow_path (mono_domain_get (), dirname, &filename);
5066 g_free (dirname);
5068 image = mono_image_open (filename, &status);
5070 if (!image){
5071 MonoException *exc;
5073 g_free (filename);
5074 if (status == MONO_IMAGE_IMAGE_INVALID)
5075 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5076 else
5077 exc = mono_get_exception_file_not_found2 (NULL, fname);
5078 mono_raise_exception (exc);
5081 res = mono_assembly_fill_assembly_name (image, &name);
5082 if (!res) {
5083 mono_image_close (image);
5084 g_free (filename);
5085 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5088 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5089 TRUE, FALSE, TRUE);
5091 g_free (filename);
5092 mono_image_close (image);
5095 static MonoBoolean
5096 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5097 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5099 MonoBoolean result = FALSE;
5100 MonoDeclSecurityEntry entry;
5102 /* SecurityAction.RequestMinimum */
5103 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5104 *minimum = entry.blob;
5105 *minLength = entry.size;
5106 result = TRUE;
5108 /* SecurityAction.RequestOptional */
5109 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5110 *optional = entry.blob;
5111 *optLength = entry.size;
5112 result = TRUE;
5114 /* SecurityAction.RequestRefuse */
5115 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5116 *refused = entry.blob;
5117 *refLength = entry.size;
5118 result = TRUE;
5121 return result;
5124 static MonoArray*
5125 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5127 MonoArray *res;
5128 MonoClass *klass;
5129 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5130 int i, count;
5131 guint32 attrs, visibility;
5133 /* we start the count from 1 because we skip the special type <Module> */
5134 if (exportedOnly) {
5135 count = 0;
5136 for (i = 1; i < tdef->rows; ++i) {
5137 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5138 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5139 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5140 count++;
5142 } else {
5143 count = tdef->rows - 1;
5145 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5146 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5147 count = 0;
5148 for (i = 1; i < tdef->rows; ++i) {
5149 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5150 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5151 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5152 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5153 if (klass) {
5154 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5155 } else {
5156 MonoLoaderError *error;
5157 MonoException *ex;
5159 error = mono_loader_get_last_error ();
5160 g_assert (error != NULL);
5162 ex = mono_loader_error_prepare_exception (error);
5163 mono_array_setref (*exceptions, count, ex);
5165 if (mono_loader_get_last_error ())
5166 mono_loader_clear_error ();
5167 count++;
5171 return res;
5174 static MonoArray*
5175 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5177 MonoArray *res = NULL;
5178 MonoArray *exceptions = NULL;
5179 MonoImage *image = NULL;
5180 MonoTableInfo *table = NULL;
5181 MonoDomain *domain;
5182 GList *list = NULL;
5183 int i, len, ex_count;
5185 MONO_ARCH_SAVE_REGS;
5187 domain = mono_object_domain (assembly);
5189 g_assert (!assembly->assembly->dynamic);
5190 image = assembly->assembly->image;
5191 table = &image->tables [MONO_TABLE_FILE];
5192 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5194 /* Append data from all modules in the assembly */
5195 for (i = 0; i < table->rows; ++i) {
5196 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5197 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5198 if (loaded_image) {
5199 MonoArray *ex2;
5200 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5201 /* Append the new types to the end of the array */
5202 if (mono_array_length (res2) > 0) {
5203 guint32 len1, len2;
5204 MonoArray *res3, *ex3;
5206 len1 = mono_array_length (res);
5207 len2 = mono_array_length (res2);
5209 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5210 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5211 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5212 res = res3;
5214 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5215 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5216 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5217 exceptions = ex3;
5223 /* the ReflectionTypeLoadException must have all the types (Types property),
5224 * NULL replacing types which throws an exception. The LoaderException must
5225 * contain all exceptions for NULL items.
5228 len = mono_array_length (res);
5230 ex_count = 0;
5231 for (i = 0; i < len; i++) {
5232 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5233 MonoClass *klass;
5235 if (t) {
5236 klass = mono_type_get_class (t->type);
5237 if ((klass != NULL) && klass->exception_type) {
5238 /* keep the class in the list */
5239 list = g_list_append (list, klass);
5240 /* and replace Type with NULL */
5241 mono_array_setref (res, i, NULL);
5243 } else {
5244 ex_count ++;
5248 if (list || ex_count) {
5249 GList *tmp = NULL;
5250 MonoException *exc = NULL;
5251 MonoArray *exl = NULL;
5252 int j, length = g_list_length (list) + ex_count;
5254 mono_loader_clear_error ();
5256 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5257 /* Types for which mono_class_get () succeeded */
5258 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5259 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5260 mono_array_setref (exl, i, exc);
5262 /* Types for which it don't */
5263 for (j = 0; j < mono_array_length (exceptions); ++j) {
5264 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5265 if (exc) {
5266 g_assert (i < length);
5267 mono_array_setref (exl, i, exc);
5268 i ++;
5271 g_list_free (list);
5272 list = NULL;
5274 exc = mono_get_exception_reflection_type_load (res, exl);
5275 mono_loader_clear_error ();
5276 mono_raise_exception (exc);
5279 return res;
5282 static gboolean
5283 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5285 MonoAssemblyName aname;
5286 MonoDomain *domain = mono_object_domain (name);
5287 char *val;
5288 gboolean is_version_defined;
5289 gboolean is_token_defined;
5291 aname.public_key = NULL;
5292 val = mono_string_to_utf8 (assname);
5293 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5294 g_free ((guint8*) aname.public_key);
5295 g_free (val);
5296 return FALSE;
5299 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5300 FALSE, is_token_defined);
5302 mono_assembly_name_free (&aname);
5303 g_free ((guint8*) aname.public_key);
5304 g_free (val);
5306 return TRUE;
5309 static MonoReflectionType*
5310 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5312 MonoDomain *domain = mono_object_domain (module);
5313 MonoClass *klass;
5315 MONO_ARCH_SAVE_REGS;
5317 g_assert (module->image);
5319 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5320 /* These images do not have a global type */
5321 return NULL;
5323 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5324 return mono_type_get_object (domain, &klass->byval_arg);
5327 static void
5328 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5330 /*if (module->image)
5331 mono_image_close (module->image);*/
5334 static MonoString*
5335 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5337 MonoDomain *domain = mono_object_domain (module);
5339 MONO_ARCH_SAVE_REGS;
5341 g_assert (module->image);
5342 return mono_string_new (domain, module->image->guid);
5345 static gpointer
5346 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5348 #ifdef HOST_WIN32
5349 if (module->image && module->image->is_module_handle)
5350 return module->image->raw_data;
5351 #endif
5353 return (gpointer) (-1);
5356 static void
5357 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5359 if (image->dynamic) {
5360 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5361 *pe_kind = dyn->pe_kind;
5362 *machine = dyn->machine;
5364 else {
5365 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5366 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5370 static gint32
5371 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5373 return (image->md_version_major << 16) | (image->md_version_minor);
5376 static MonoArray*
5377 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5379 MonoArray *exceptions;
5380 int i;
5382 MONO_ARCH_SAVE_REGS;
5384 if (!module->image)
5385 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5386 else {
5387 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5388 for (i = 0; i < mono_array_length (exceptions); ++i) {
5389 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5390 if (ex)
5391 mono_raise_exception (ex);
5393 return res;
5397 static gboolean
5398 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5400 guint32 cols [MONO_MEMBERREF_SIZE];
5401 const char *sig;
5402 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5403 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5404 mono_metadata_decode_blob_size (sig, &sig);
5405 return (*sig != 0x6);
5408 static void
5409 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5411 if (type_args)
5412 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5413 mono_array_addr (type_args, MonoType*, 0));
5414 else
5415 context->class_inst = NULL;
5416 if (method_args)
5417 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5418 mono_array_addr (method_args, MonoType*, 0));
5419 else
5420 context->method_inst = NULL;
5423 static MonoType*
5424 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5426 MonoClass *klass;
5427 int table = mono_metadata_token_table (token);
5428 int index = mono_metadata_token_index (token);
5429 MonoGenericContext context;
5431 *error = ResolveTokenError_Other;
5433 /* Validate token */
5434 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5435 (table != MONO_TABLE_TYPESPEC)) {
5436 *error = ResolveTokenError_BadTable;
5437 return NULL;
5440 if (image->dynamic) {
5441 if (type_args || method_args)
5442 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5443 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5444 if (!klass)
5445 return NULL;
5446 return &klass->byval_arg;
5449 if ((index <= 0) || (index > image->tables [table].rows)) {
5450 *error = ResolveTokenError_OutOfRange;
5451 return NULL;
5454 init_generic_context_from_args (&context, type_args, method_args);
5455 klass = mono_class_get_full (image, token, &context);
5457 if (mono_loader_get_last_error ())
5458 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5460 if (klass)
5461 return &klass->byval_arg;
5462 else
5463 return NULL;
5466 static MonoMethod*
5467 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5469 int table = mono_metadata_token_table (token);
5470 int index = mono_metadata_token_index (token);
5471 MonoGenericContext context;
5472 MonoMethod *method;
5474 *error = ResolveTokenError_Other;
5476 /* Validate token */
5477 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5478 (table != MONO_TABLE_MEMBERREF)) {
5479 *error = ResolveTokenError_BadTable;
5480 return NULL;
5483 if (image->dynamic) {
5484 if (type_args || method_args)
5485 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5486 /* FIXME: validate memberref token type */
5487 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5490 if ((index <= 0) || (index > image->tables [table].rows)) {
5491 *error = ResolveTokenError_OutOfRange;
5492 return NULL;
5494 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5495 *error = ResolveTokenError_BadTable;
5496 return NULL;
5499 init_generic_context_from_args (&context, type_args, method_args);
5500 method = mono_get_method_full (image, token, NULL, &context);
5502 if (mono_loader_get_last_error ())
5503 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5505 return method;
5508 static MonoString*
5509 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5511 int index = mono_metadata_token_index (token);
5513 *error = ResolveTokenError_Other;
5515 /* Validate token */
5516 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5517 *error = ResolveTokenError_BadTable;
5518 return NULL;
5521 if (image->dynamic)
5522 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5524 if ((index <= 0) || (index >= image->heap_us.size)) {
5525 *error = ResolveTokenError_OutOfRange;
5526 return NULL;
5529 /* FIXME: What to do if the index points into the middle of a string ? */
5531 return mono_ldstr (mono_domain_get (), image, index);
5534 static MonoClassField*
5535 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5537 MonoClass *klass;
5538 int table = mono_metadata_token_table (token);
5539 int index = mono_metadata_token_index (token);
5540 MonoGenericContext context;
5541 MonoClassField *field;
5543 *error = ResolveTokenError_Other;
5545 /* Validate token */
5546 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5547 *error = ResolveTokenError_BadTable;
5548 return NULL;
5551 if (image->dynamic) {
5552 if (type_args || method_args)
5553 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5554 /* FIXME: validate memberref token type */
5555 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5558 if ((index <= 0) || (index > image->tables [table].rows)) {
5559 *error = ResolveTokenError_OutOfRange;
5560 return NULL;
5562 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5563 *error = ResolveTokenError_BadTable;
5564 return NULL;
5567 init_generic_context_from_args (&context, type_args, method_args);
5568 field = mono_field_from_token (image, token, &klass, &context);
5570 if (mono_loader_get_last_error ())
5571 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5573 return field;
5577 static MonoObject*
5578 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5580 int table = mono_metadata_token_table (token);
5582 *error = ResolveTokenError_Other;
5584 switch (table) {
5585 case MONO_TABLE_TYPEDEF:
5586 case MONO_TABLE_TYPEREF:
5587 case MONO_TABLE_TYPESPEC: {
5588 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5589 if (t)
5590 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5591 else
5592 return NULL;
5594 case MONO_TABLE_METHOD:
5595 case MONO_TABLE_METHODSPEC: {
5596 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5597 if (m)
5598 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5599 else
5600 return NULL;
5602 case MONO_TABLE_FIELD: {
5603 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5604 if (f)
5605 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5606 else
5607 return NULL;
5609 case MONO_TABLE_MEMBERREF:
5610 if (mono_metadata_memberref_is_method (image, token)) {
5611 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5612 if (m)
5613 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5614 else
5615 return NULL;
5617 else {
5618 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5619 if (f)
5620 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5621 else
5622 return NULL;
5624 break;
5626 default:
5627 *error = ResolveTokenError_BadTable;
5630 return NULL;
5633 static MonoArray*
5634 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5636 int table = mono_metadata_token_table (token);
5637 int idx = mono_metadata_token_index (token);
5638 MonoTableInfo *tables = image->tables;
5639 guint32 sig, len;
5640 const char *ptr;
5641 MonoArray *res;
5643 *error = ResolveTokenError_OutOfRange;
5645 /* FIXME: Support other tables ? */
5646 if (table != MONO_TABLE_STANDALONESIG)
5647 return NULL;
5649 if (image->dynamic)
5650 return NULL;
5652 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5653 return NULL;
5655 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5657 ptr = mono_metadata_blob_heap (image, sig);
5658 len = mono_metadata_decode_blob_size (ptr, &ptr);
5660 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5661 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5662 return res;
5665 static MonoReflectionType*
5666 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5668 MonoClass *klass;
5669 int isbyref = 0, rank;
5670 char *str = mono_string_to_utf8 (smodifiers);
5671 char *p;
5673 MONO_ARCH_SAVE_REGS;
5675 klass = mono_class_from_mono_type (tb->type.type);
5676 p = str;
5677 /* logic taken from mono_reflection_parse_type(): keep in sync */
5678 while (*p) {
5679 switch (*p) {
5680 case '&':
5681 if (isbyref) { /* only one level allowed by the spec */
5682 g_free (str);
5683 return NULL;
5685 isbyref = 1;
5686 p++;
5687 g_free (str);
5688 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5689 break;
5690 case '*':
5691 klass = mono_ptr_class_get (&klass->byval_arg);
5692 mono_class_init (klass);
5693 p++;
5694 break;
5695 case '[':
5696 rank = 1;
5697 p++;
5698 while (*p) {
5699 if (*p == ']')
5700 break;
5701 if (*p == ',')
5702 rank++;
5703 else if (*p != '*') { /* '*' means unknown lower bound */
5704 g_free (str);
5705 return NULL;
5707 ++p;
5709 if (*p != ']') {
5710 g_free (str);
5711 return NULL;
5713 p++;
5714 klass = mono_array_class_get (klass, rank);
5715 mono_class_init (klass);
5716 break;
5717 default:
5718 break;
5721 g_free (str);
5722 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5725 static MonoBoolean
5726 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5728 MonoType *type;
5729 MonoBoolean res;
5731 MONO_ARCH_SAVE_REGS;
5733 type = t->type;
5734 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5736 return res;
5739 static MonoReflectionType *
5740 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5742 MonoClass *klass, *aklass;
5744 MONO_ARCH_SAVE_REGS;
5746 klass = mono_class_from_mono_type (type->type);
5747 if (rank == 0) //single dimentional array
5748 aklass = mono_array_class_get (klass, 1);
5749 else
5750 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5752 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5755 static MonoReflectionType *
5756 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5758 MonoClass *klass;
5760 MONO_ARCH_SAVE_REGS;
5762 klass = mono_class_from_mono_type (type->type);
5764 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5767 static MonoReflectionType *
5768 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5770 MonoClass *pklass;
5772 MONO_ARCH_SAVE_REGS;
5774 pklass = mono_ptr_class_get (type->type);
5776 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5779 static MonoObject *
5780 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5781 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5783 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5784 MonoObject *delegate;
5785 gpointer func;
5786 MonoMethod *method = info->method;
5788 MONO_ARCH_SAVE_REGS;
5790 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5792 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5793 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5794 return NULL;
5797 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5799 if (method->dynamic) {
5800 /* Creating a trampoline would leak memory */
5801 func = mono_compile_method (method);
5802 } else {
5803 func = mono_create_ftnptr (mono_domain_get (),
5804 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5807 mono_delegate_ctor_with_method (delegate, target, func, method);
5809 return delegate;
5812 static void
5813 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5815 /* Reset the invoke impl to the default one */
5816 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5820 * Magic number to convert a time which is relative to
5821 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5823 #define EPOCH_ADJUST ((guint64)62135596800LL)
5826 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5828 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5830 #ifdef HOST_WIN32
5831 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5832 static void
5833 convert_to_absolute_date(SYSTEMTIME *date)
5835 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5836 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5837 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5838 /* from the calendar FAQ */
5839 int a = (14 - date->wMonth) / 12;
5840 int y = date->wYear - a;
5841 int m = date->wMonth + 12 * a - 2;
5842 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5844 /* d is now the day of the week for the first of the month (0 == Sunday) */
5846 int day_of_week = date->wDayOfWeek;
5848 /* set day_in_month to the first day in the month which falls on day_of_week */
5849 int day_in_month = 1 + (day_of_week - d);
5850 if (day_in_month <= 0)
5851 day_in_month += 7;
5853 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5854 date->wDay = day_in_month + (date->wDay - 1) * 7;
5855 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5856 date->wDay -= 7;
5858 #endif
5860 #ifndef HOST_WIN32
5862 * Return's the offset from GMT of a local time.
5864 * tm is a local time
5865 * t is the same local time as seconds.
5867 static int
5868 gmt_offset(struct tm *tm, time_t t)
5870 #if defined (HAVE_TM_GMTOFF)
5871 return tm->tm_gmtoff;
5872 #else
5873 struct tm g;
5874 time_t t2;
5875 g = *gmtime(&t);
5876 g.tm_isdst = tm->tm_isdst;
5877 t2 = mktime(&g);
5878 return (int)difftime(t, t2);
5879 #endif
5881 #endif
5883 * This is heavily based on zdump.c from glibc 2.2.
5885 * * data[0]: start of daylight saving time (in DateTime ticks).
5886 * * data[1]: end of daylight saving time (in DateTime ticks).
5887 * * data[2]: utcoffset (in TimeSpan ticks).
5888 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5889 * * name[0]: name of this timezone when not daylight saving.
5890 * * name[1]: name of this timezone when daylight saving.
5892 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5893 * the class library allows years between 1 and 9999.
5895 * Returns true on success and zero on failure.
5897 static guint32
5898 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5900 #ifndef HOST_WIN32
5901 MonoDomain *domain = mono_domain_get ();
5902 struct tm start, tt;
5903 time_t t;
5905 long int gmtoff;
5906 int is_daylight = 0, day;
5907 char tzone [64];
5909 MONO_ARCH_SAVE_REGS;
5911 MONO_CHECK_ARG_NULL (data);
5912 MONO_CHECK_ARG_NULL (names);
5914 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5915 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5918 * no info is better than crashing: we'll need our own tz data
5919 * to make this work properly, anyway. The range is probably
5920 * reduced to 1970 .. 2037 because that is what mktime is
5921 * guaranteed to support (we get into an infinite loop
5922 * otherwise).
5925 memset (&start, 0, sizeof (start));
5927 start.tm_mday = 1;
5928 start.tm_year = year-1900;
5930 t = mktime (&start);
5932 if ((year < 1970) || (year > 2037) || (t == -1)) {
5933 t = time (NULL);
5934 tt = *localtime (&t);
5935 strftime (tzone, sizeof (tzone), "%Z", &tt);
5936 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5937 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5938 return 1;
5941 gmtoff = gmt_offset (&start, t);
5943 /* For each day of the year, calculate the tm_gmtoff. */
5944 for (day = 0; day < 365; day++) {
5946 t += 3600*24;
5947 tt = *localtime (&t);
5949 /* Daylight saving starts or ends here. */
5950 if (gmt_offset (&tt, t) != gmtoff) {
5951 struct tm tt1;
5952 time_t t1;
5954 /* Try to find the exact hour when daylight saving starts/ends. */
5955 t1 = t;
5956 do {
5957 t1 -= 3600;
5958 tt1 = *localtime (&t1);
5959 } while (gmt_offset (&tt1, t1) != gmtoff);
5961 /* Try to find the exact minute when daylight saving starts/ends. */
5962 do {
5963 t1 += 60;
5964 tt1 = *localtime (&t1);
5965 } while (gmt_offset (&tt1, t1) == gmtoff);
5966 t1+=gmtoff;
5967 strftime (tzone, sizeof (tzone), "%Z", &tt);
5969 /* Write data, if we're already in daylight saving, we're done. */
5970 if (is_daylight) {
5971 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5972 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5973 return 1;
5974 } else {
5975 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5976 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5977 is_daylight = 1;
5980 /* This is only set once when we enter daylight saving. */
5981 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5982 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5984 gmtoff = gmt_offset (&tt, t);
5988 if (!is_daylight) {
5989 strftime (tzone, sizeof (tzone), "%Z", &tt);
5990 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5991 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5992 mono_array_set ((*data), gint64, 0, 0);
5993 mono_array_set ((*data), gint64, 1, 0);
5994 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5995 mono_array_set ((*data), gint64, 3, 0);
5998 return 1;
5999 #else
6000 MonoDomain *domain = mono_domain_get ();
6001 TIME_ZONE_INFORMATION tz_info;
6002 FILETIME ft;
6003 int i;
6004 int err, tz_id;
6006 tz_id = GetTimeZoneInformation (&tz_info);
6007 if (tz_id == TIME_ZONE_ID_INVALID)
6008 return 0;
6010 MONO_CHECK_ARG_NULL (data);
6011 MONO_CHECK_ARG_NULL (names);
6013 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6014 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6016 for (i = 0; i < 32; ++i)
6017 if (!tz_info.DaylightName [i])
6018 break;
6019 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6020 for (i = 0; i < 32; ++i)
6021 if (!tz_info.StandardName [i])
6022 break;
6023 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6025 if ((year <= 1601) || (year > 30827)) {
6027 * According to MSDN, the MS time functions can't handle dates outside
6028 * this interval.
6030 return 1;
6033 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6034 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6035 tz_info.StandardDate.wYear = year;
6036 convert_to_absolute_date(&tz_info.StandardDate);
6037 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6038 //g_assert(err);
6039 if (err == 0)
6040 return 0;
6042 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6043 tz_info.DaylightDate.wYear = year;
6044 convert_to_absolute_date(&tz_info.DaylightDate);
6045 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6046 //g_assert(err);
6047 if (err == 0)
6048 return 0;
6050 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6052 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6053 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6055 return 1;
6056 #endif
6059 static gpointer
6060 ves_icall_System_Object_obj_address (MonoObject *this)
6062 MONO_ARCH_SAVE_REGS;
6064 return this;
6067 /* System.Buffer */
6069 static inline gint32
6070 mono_array_get_byte_length (MonoArray *array)
6072 MonoClass *klass;
6073 int length;
6074 int i;
6076 klass = array->obj.vtable->klass;
6078 if (array->bounds == NULL)
6079 length = array->max_length;
6080 else {
6081 length = 1;
6082 for (i = 0; i < klass->rank; ++ i)
6083 length *= array->bounds [i].length;
6086 switch (klass->element_class->byval_arg.type) {
6087 case MONO_TYPE_I1:
6088 case MONO_TYPE_U1:
6089 case MONO_TYPE_BOOLEAN:
6090 return length;
6091 case MONO_TYPE_I2:
6092 case MONO_TYPE_U2:
6093 case MONO_TYPE_CHAR:
6094 return length << 1;
6095 case MONO_TYPE_I4:
6096 case MONO_TYPE_U4:
6097 case MONO_TYPE_R4:
6098 return length << 2;
6099 case MONO_TYPE_I:
6100 case MONO_TYPE_U:
6101 return length * sizeof (gpointer);
6102 case MONO_TYPE_I8:
6103 case MONO_TYPE_U8:
6104 case MONO_TYPE_R8:
6105 return length << 3;
6106 default:
6107 return -1;
6111 static gint32
6112 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6114 MONO_ARCH_SAVE_REGS;
6116 return mono_array_get_byte_length (array);
6119 static gint8
6120 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6122 MONO_ARCH_SAVE_REGS;
6124 return mono_array_get (array, gint8, idx);
6127 static void
6128 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6130 MONO_ARCH_SAVE_REGS;
6132 mono_array_set (array, gint8, idx, value);
6135 static MonoBoolean
6136 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6138 guint8 *src_buf, *dest_buf;
6140 MONO_ARCH_SAVE_REGS;
6142 /* watch out for integer overflow */
6143 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6144 return FALSE;
6146 src_buf = (guint8 *)src->vector + src_offset;
6147 dest_buf = (guint8 *)dest->vector + dest_offset;
6149 if (src != dest)
6150 memcpy (dest_buf, src_buf, count);
6151 else
6152 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6154 return TRUE;
6157 static MonoObject *
6158 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6160 MonoDomain *domain = mono_object_domain (this);
6161 MonoObject *res;
6162 MonoRealProxy *rp = ((MonoRealProxy *)this);
6163 MonoTransparentProxy *tp;
6164 MonoType *type;
6165 MonoClass *klass;
6167 MONO_ARCH_SAVE_REGS;
6169 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6170 tp = (MonoTransparentProxy*) res;
6172 MONO_OBJECT_SETREF (tp, rp, rp);
6173 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6174 klass = mono_class_from_mono_type (type);
6176 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6177 tp->remote_class = mono_remote_class (domain, class_name, klass);
6179 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6180 return res;
6183 static MonoReflectionType *
6184 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6186 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6189 /* System.Environment */
6191 MonoString*
6192 ves_icall_System_Environment_get_UserName (void)
6194 MONO_ARCH_SAVE_REGS;
6196 /* using glib is more portable */
6197 return mono_string_new (mono_domain_get (), g_get_user_name ());
6201 static MonoString *
6202 ves_icall_System_Environment_get_MachineName (void)
6204 #if defined (HOST_WIN32)
6205 gunichar2 *buf;
6206 guint32 len;
6207 MonoString *result;
6209 len = MAX_COMPUTERNAME_LENGTH + 1;
6210 buf = g_new (gunichar2, len);
6212 result = NULL;
6213 if (GetComputerName (buf, (PDWORD) &len))
6214 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6216 g_free (buf);
6217 return result;
6218 #elif !defined(DISABLE_SOCKETS)
6219 gchar buf [256];
6220 MonoString *result;
6222 if (gethostname (buf, sizeof (buf)) == 0)
6223 result = mono_string_new (mono_domain_get (), buf);
6224 else
6225 result = NULL;
6227 return result;
6228 #else
6229 return mono_string_new (mono_domain_get (), "mono");
6230 #endif
6233 static int
6234 ves_icall_System_Environment_get_Platform (void)
6236 #if defined (TARGET_WIN32)
6237 /* Win32NT */
6238 return 2;
6239 #elif defined(__MACH__)
6240 /* OSX */
6242 // For compatibility with our client code, this will be 4 for a while.
6243 // We will eventually move to 6 to match .NET, but it requires all client
6244 // code to be updated and the documentation everywhere to be updated
6245 // first.
6247 return 4;
6248 #else
6249 /* Unix */
6250 return 4;
6251 #endif
6254 static MonoString *
6255 ves_icall_System_Environment_get_NewLine (void)
6257 MONO_ARCH_SAVE_REGS;
6259 #if defined (HOST_WIN32)
6260 return mono_string_new (mono_domain_get (), "\r\n");
6261 #else
6262 return mono_string_new (mono_domain_get (), "\n");
6263 #endif
6266 static MonoString *
6267 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6269 const gchar *value;
6270 gchar *utf8_name;
6272 MONO_ARCH_SAVE_REGS;
6274 if (name == NULL)
6275 return NULL;
6277 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6278 value = g_getenv (utf8_name);
6280 g_free (utf8_name);
6282 if (value == 0)
6283 return NULL;
6285 return mono_string_new (mono_domain_get (), value);
6289 * There is no standard way to get at environ.
6291 #ifndef _MSC_VER
6292 #ifndef __MINGW32_VERSION
6293 #ifdef __APPLE__
6294 /* Apple defines this in crt_externs.h but doesn't provide that header for
6295 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6296 * in fact exist on all implementations (so far)
6298 gchar ***_NSGetEnviron(void);
6299 #define environ (*_NSGetEnviron())
6300 #else
6301 extern
6302 char **environ;
6303 #endif
6304 #endif
6305 #endif
6307 static MonoArray *
6308 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6310 #ifdef HOST_WIN32
6311 MonoArray *names;
6312 MonoDomain *domain;
6313 MonoString *str;
6314 WCHAR* env_strings;
6315 WCHAR* env_string;
6316 WCHAR* equal_str;
6317 int n = 0;
6319 env_strings = GetEnvironmentStrings();
6321 if (env_strings) {
6322 env_string = env_strings;
6323 while (*env_string != '\0') {
6324 /* weird case that MS seems to skip */
6325 if (*env_string != '=')
6326 n++;
6327 while (*env_string != '\0')
6328 env_string++;
6329 env_string++;
6333 domain = mono_domain_get ();
6334 names = mono_array_new (domain, mono_defaults.string_class, n);
6336 if (env_strings) {
6337 n = 0;
6338 env_string = env_strings;
6339 while (*env_string != '\0') {
6340 /* weird case that MS seems to skip */
6341 if (*env_string != '=') {
6342 equal_str = wcschr(env_string, '=');
6343 g_assert(equal_str);
6344 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6345 mono_array_setref (names, n, str);
6346 n++;
6348 while (*env_string != '\0')
6349 env_string++;
6350 env_string++;
6353 FreeEnvironmentStrings (env_strings);
6356 return names;
6358 #else
6359 MonoArray *names;
6360 MonoDomain *domain;
6361 MonoString *str;
6362 gchar **e, **parts;
6363 int n;
6365 MONO_ARCH_SAVE_REGS;
6367 n = 0;
6368 for (e = environ; *e != 0; ++ e)
6369 ++ n;
6371 domain = mono_domain_get ();
6372 names = mono_array_new (domain, mono_defaults.string_class, n);
6374 n = 0;
6375 for (e = environ; *e != 0; ++ e) {
6376 parts = g_strsplit (*e, "=", 2);
6377 if (*parts != 0) {
6378 str = mono_string_new (domain, *parts);
6379 mono_array_setref (names, n, str);
6382 g_strfreev (parts);
6384 ++ n;
6387 return names;
6388 #endif
6392 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6394 #if !GLIB_CHECK_VERSION(2,4,0)
6395 #define g_setenv(a,b,c) setenv(a,b,c)
6396 #define g_unsetenv(a) unsetenv(a)
6397 #endif
6399 static void
6400 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6402 MonoError error;
6403 #ifdef HOST_WIN32
6405 gunichar2 *utf16_name, *utf16_value;
6406 #else
6407 gchar *utf8_name, *utf8_value;
6408 #endif
6410 MONO_ARCH_SAVE_REGS;
6412 #ifdef HOST_WIN32
6413 utf16_name = mono_string_to_utf16 (name);
6414 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6415 SetEnvironmentVariable (utf16_name, NULL);
6416 g_free (utf16_name);
6417 return;
6420 utf16_value = mono_string_to_utf16 (value);
6422 SetEnvironmentVariable (utf16_name, utf16_value);
6424 g_free (utf16_name);
6425 g_free (utf16_value);
6426 #else
6427 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6429 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6430 g_unsetenv (utf8_name);
6431 g_free (utf8_name);
6432 return;
6435 utf8_value = mono_string_to_utf8_checked (value, &error);
6436 if (!mono_error_ok (&error)) {
6437 g_free (utf8_name);
6438 mono_error_raise_exception (&error);
6440 g_setenv (utf8_name, utf8_value, TRUE);
6442 g_free (utf8_name);
6443 g_free (utf8_value);
6444 #endif
6447 static void
6448 ves_icall_System_Environment_Exit (int result)
6450 MONO_ARCH_SAVE_REGS;
6452 mono_threads_set_shutting_down ();
6454 mono_runtime_set_shutting_down ();
6456 /* Suspend all managed threads since the runtime is going away */
6457 mono_thread_suspend_all_other_threads ();
6459 mono_runtime_quit ();
6461 /* we may need to do some cleanup here... */
6462 exit (result);
6465 static MonoString*
6466 ves_icall_System_Environment_GetGacPath (void)
6468 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6471 static MonoString*
6472 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6474 #if defined (HOST_WIN32)
6475 #ifndef CSIDL_FLAG_CREATE
6476 #define CSIDL_FLAG_CREATE 0x8000
6477 #endif
6479 WCHAR path [MAX_PATH];
6480 /* Create directory if no existing */
6481 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6482 int len = 0;
6483 while (path [len])
6484 ++ len;
6485 return mono_string_new_utf16 (mono_domain_get (), path, len);
6487 #else
6488 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6489 #endif
6490 return mono_string_new (mono_domain_get (), "");
6493 static MonoArray *
6494 ves_icall_System_Environment_GetLogicalDrives (void)
6496 gunichar2 buf [128], *ptr, *dname;
6497 gunichar2 *u16;
6498 guint initial_size = 127, size = 128;
6499 gint ndrives;
6500 MonoArray *result;
6501 MonoString *drivestr;
6502 MonoDomain *domain = mono_domain_get ();
6503 gint len;
6505 MONO_ARCH_SAVE_REGS;
6507 buf [0] = '\0';
6508 ptr = buf;
6510 while (size > initial_size) {
6511 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6512 if (size > initial_size) {
6513 if (ptr != buf)
6514 g_free (ptr);
6515 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6516 initial_size = size;
6517 size++;
6521 /* Count strings */
6522 dname = ptr;
6523 ndrives = 0;
6524 do {
6525 while (*dname++);
6526 ndrives++;
6527 } while (*dname);
6529 dname = ptr;
6530 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6531 ndrives = 0;
6532 do {
6533 len = 0;
6534 u16 = dname;
6535 while (*u16) { u16++; len ++; }
6536 drivestr = mono_string_new_utf16 (domain, dname, len);
6537 mono_array_setref (result, ndrives++, drivestr);
6538 while (*dname++);
6539 } while (*dname);
6541 if (ptr != buf)
6542 g_free (ptr);
6544 return result;
6547 static MonoString *
6548 ves_icall_System_Environment_InternalGetHome (void)
6550 MONO_ARCH_SAVE_REGS;
6552 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6555 static const char *encodings [] = {
6556 (char *) 1,
6557 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6558 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6559 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6560 (char *) 2,
6561 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6562 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6563 "x_unicode_2_0_utf_7",
6564 (char *) 3,
6565 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6566 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6567 (char *) 4,
6568 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6569 "iso_10646_ucs2",
6570 (char *) 5,
6571 "unicodefffe", "utf_16be",
6572 (char *) 6,
6573 "iso_8859_1",
6574 (char *) 0
6578 * Returns the internal codepage, if the value of "int_code_page" is
6579 * 1 at entry, and we can not compute a suitable code page number,
6580 * returns the code page as a string
6582 static MonoString*
6583 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6585 const char *cset;
6586 const char *p;
6587 char *c;
6588 char *codepage = NULL;
6589 int code;
6590 int want_name = *int_code_page;
6591 int i;
6593 *int_code_page = -1;
6594 MONO_ARCH_SAVE_REGS;
6596 g_get_charset (&cset);
6597 c = codepage = strdup (cset);
6598 for (c = codepage; *c; c++){
6599 if (isascii (*c) && isalpha (*c))
6600 *c = tolower (*c);
6601 if (*c == '-')
6602 *c = '_';
6604 /* g_print ("charset: %s\n", cset); */
6606 /* handle some common aliases */
6607 p = encodings [0];
6608 code = 0;
6609 for (i = 0; p != 0; ){
6610 if ((gssize) p < 7){
6611 code = (gssize) p;
6612 p = encodings [++i];
6613 continue;
6615 if (strcmp (p, codepage) == 0){
6616 *int_code_page = code;
6617 break;
6619 p = encodings [++i];
6622 if (strstr (codepage, "utf_8") != NULL)
6623 *int_code_page |= 0x10000000;
6624 free (codepage);
6626 if (want_name && *int_code_page == -1)
6627 return mono_string_new (mono_domain_get (), cset);
6628 else
6629 return NULL;
6632 static MonoBoolean
6633 ves_icall_System_Environment_get_HasShutdownStarted (void)
6635 if (mono_runtime_is_shutting_down ())
6636 return TRUE;
6638 if (mono_domain_is_unloading (mono_domain_get ()))
6639 return TRUE;
6641 return FALSE;
6644 static void
6645 ves_icall_System_Environment_BroadcastSettingChange (void)
6647 #ifdef HOST_WIN32
6648 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6649 #endif
6652 static void
6653 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6654 MonoReflectionMethod *method,
6655 MonoArray *out_args)
6657 MONO_ARCH_SAVE_REGS;
6659 mono_message_init (mono_object_domain (this), this, method, out_args);
6662 static MonoBoolean
6663 ves_icall_IsTransparentProxy (MonoObject *proxy)
6665 MONO_ARCH_SAVE_REGS;
6667 if (!proxy)
6668 return 0;
6670 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6671 return 1;
6673 return 0;
6676 static MonoReflectionMethod *
6677 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6678 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6680 MonoClass *klass;
6681 MonoMethod *method;
6682 MonoMethod **vtable;
6683 MonoMethod *res = NULL;
6685 MONO_CHECK_ARG_NULL (rtype);
6686 MONO_CHECK_ARG_NULL (rmethod);
6688 method = rmethod->method;
6689 klass = mono_class_from_mono_type (rtype->type);
6691 if (MONO_CLASS_IS_INTERFACE (klass))
6692 return NULL;
6694 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6695 return NULL;
6697 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6698 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6699 return rmethod;
6700 else
6701 return NULL;
6704 mono_class_setup_vtable (klass);
6705 vtable = klass->vtable;
6707 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6708 gboolean variance_used = FALSE;
6709 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6710 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6711 if (offs >= 0)
6712 res = vtable [offs + method->slot];
6713 } else {
6714 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6715 return NULL;
6717 if (method->slot != -1)
6718 res = vtable [method->slot];
6721 if (!res)
6722 return NULL;
6724 return mono_method_get_object (mono_domain_get (), res, NULL);
6727 static void
6728 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6730 MonoClass *klass;
6731 MonoVTable* vtable;
6733 MONO_ARCH_SAVE_REGS;
6735 klass = mono_class_from_mono_type (type->type);
6736 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6738 if (enable) vtable->remote = 1;
6739 else vtable->remote = 0;
6742 static MonoObject *
6743 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6745 MonoClass *klass;
6746 MonoDomain *domain;
6748 MONO_ARCH_SAVE_REGS;
6750 domain = mono_object_domain (type);
6751 klass = mono_class_from_mono_type (type->type);
6753 if (klass->rank >= 1) {
6754 g_assert (klass->rank == 1);
6755 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6756 } else {
6757 /* Bypass remoting object creation check */
6758 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6762 static MonoString *
6763 ves_icall_System_IO_get_temp_path (void)
6765 MONO_ARCH_SAVE_REGS;
6767 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6770 #ifndef PLATFORM_NO_DRIVEINFO
6771 static MonoBoolean
6772 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6773 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6774 gint32 *error)
6776 gboolean result;
6777 ULARGE_INTEGER wapi_free_bytes_avail;
6778 ULARGE_INTEGER wapi_total_number_of_bytes;
6779 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6781 MONO_ARCH_SAVE_REGS;
6783 *error = ERROR_SUCCESS;
6784 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6785 &wapi_total_number_of_free_bytes);
6787 if (result) {
6788 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6789 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6790 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6791 } else {
6792 *free_bytes_avail = 0;
6793 *total_number_of_bytes = 0;
6794 *total_number_of_free_bytes = 0;
6795 *error = GetLastError ();
6798 return result;
6801 static guint32
6802 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6804 MONO_ARCH_SAVE_REGS;
6806 return GetDriveType (mono_string_chars (root_path_name));
6808 #endif
6810 static gpointer
6811 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6813 MONO_ARCH_SAVE_REGS;
6815 return mono_compile_method (method);
6818 static MonoString *
6819 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6821 MonoString *mcpath;
6822 gchar *path;
6824 MONO_ARCH_SAVE_REGS;
6826 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6828 #if defined (HOST_WIN32)
6829 /* Avoid mixing '/' and '\\' */
6831 gint i;
6832 for (i = strlen (path) - 1; i >= 0; i--)
6833 if (path [i] == '/')
6834 path [i] = '\\';
6836 #endif
6837 mcpath = mono_string_new (mono_domain_get (), path);
6838 g_free (path);
6840 return mcpath;
6843 static MonoString *
6844 get_bundled_machine_config (void)
6846 const gchar *machine_config;
6848 MONO_ARCH_SAVE_REGS;
6850 machine_config = mono_get_machine_config ();
6852 if (!machine_config)
6853 return NULL;
6855 return mono_string_new (mono_domain_get (), machine_config);
6858 static MonoString *
6859 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6861 MonoString *ipath;
6862 gchar *path;
6864 MONO_ARCH_SAVE_REGS;
6866 path = g_path_get_dirname (mono_get_config_dir ());
6868 #if defined (HOST_WIN32)
6869 /* Avoid mixing '/' and '\\' */
6871 gint i;
6872 for (i = strlen (path) - 1; i >= 0; i--)
6873 if (path [i] == '/')
6874 path [i] = '\\';
6876 #endif
6877 ipath = mono_string_new (mono_domain_get (), path);
6878 g_free (path);
6880 return ipath;
6883 static gboolean
6884 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6886 MonoPEResourceDataEntry *entry;
6887 MonoImage *image;
6889 MONO_ARCH_SAVE_REGS;
6891 if (!assembly || !result || !size)
6892 return FALSE;
6894 *result = NULL;
6895 *size = 0;
6896 image = assembly->assembly->image;
6897 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6898 if (!entry)
6899 return FALSE;
6901 *result = mono_image_rva_map (image, entry->rde_data_offset);
6902 if (!(*result)) {
6903 g_free (entry);
6904 return FALSE;
6906 *size = entry->rde_size;
6907 g_free (entry);
6908 return TRUE;
6911 static MonoBoolean
6912 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6914 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6917 static void
6918 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6920 #if defined (HOST_WIN32)
6921 OutputDebugString (mono_string_chars (message));
6922 #else
6923 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6924 #endif
6927 /* Only used for value types */
6928 static MonoObject *
6929 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6931 MonoClass *klass;
6932 MonoDomain *domain;
6934 MONO_ARCH_SAVE_REGS;
6936 domain = mono_object_domain (type);
6937 klass = mono_class_from_mono_type (type->type);
6939 if (mono_class_is_nullable (klass))
6940 /* No arguments -> null */
6941 return NULL;
6943 return mono_object_new (domain, klass);
6946 static MonoReflectionMethod *
6947 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6949 MonoClass *klass, *parent;
6950 MonoMethod *method = m->method;
6951 MonoMethod *result = NULL;
6953 MONO_ARCH_SAVE_REGS;
6955 if (method->klass == NULL)
6956 return m;
6958 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6959 MONO_CLASS_IS_INTERFACE (method->klass) ||
6960 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6961 return m;
6963 klass = method->klass;
6964 if (klass->generic_class)
6965 klass = klass->generic_class->container_class;
6967 if (definition) {
6968 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6969 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6970 mono_class_setup_vtable (parent);
6971 if (parent->vtable_size <= method->slot)
6972 break;
6973 klass = parent;
6975 } else {
6976 klass = klass->parent;
6977 if (!klass)
6978 return m;
6981 if (klass == method->klass)
6982 return m;
6984 result = klass->vtable [method->slot];
6985 if (result == NULL) {
6986 /* It is an abstract method */
6987 gpointer iter = NULL;
6988 while ((result = mono_class_get_methods (klass, &iter)))
6989 if (result->slot == method->slot)
6990 break;
6993 if (result == NULL)
6994 return m;
6996 return mono_method_get_object (mono_domain_get (), result, NULL);
6999 static MonoString*
7000 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7002 MonoMethod *method = m->method;
7004 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7005 return m->name;
7008 static void
7009 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7011 MONO_ARCH_SAVE_REGS;
7013 iter->sig = *(MonoMethodSignature**)argsp;
7015 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7016 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7018 iter->next_arg = 0;
7019 /* FIXME: it's not documented what start is exactly... */
7020 if (start) {
7021 iter->args = start;
7022 } else {
7023 iter->args = argsp + sizeof (gpointer);
7025 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7027 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7030 static MonoTypedRef
7031 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7033 guint32 i, arg_size;
7034 gint32 align;
7035 MonoTypedRef res;
7036 MONO_ARCH_SAVE_REGS;
7038 i = iter->sig->sentinelpos + iter->next_arg;
7040 g_assert (i < iter->sig->param_count);
7042 res.type = iter->sig->params [i];
7043 res.klass = mono_class_from_mono_type (res.type);
7044 res.value = iter->args;
7045 arg_size = mono_type_stack_size (res.type, &align);
7046 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7047 if (arg_size <= sizeof (gpointer)) {
7048 int dummy;
7049 int padding = arg_size - mono_type_size (res.type, &dummy);
7050 res.value = (guint8*)res.value + padding;
7052 #endif
7053 iter->args = (char*)iter->args + arg_size;
7054 iter->next_arg++;
7056 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7058 return res;
7061 static MonoTypedRef
7062 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7064 guint32 i, arg_size;
7065 gint32 align;
7066 MonoTypedRef res;
7067 MONO_ARCH_SAVE_REGS;
7069 i = iter->sig->sentinelpos + iter->next_arg;
7071 g_assert (i < iter->sig->param_count);
7073 while (i < iter->sig->param_count) {
7074 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7075 continue;
7076 res.type = iter->sig->params [i];
7077 res.klass = mono_class_from_mono_type (res.type);
7078 /* FIXME: endianess issue... */
7079 res.value = iter->args;
7080 arg_size = mono_type_stack_size (res.type, &align);
7081 iter->args = (char*)iter->args + arg_size;
7082 iter->next_arg++;
7083 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7084 return res;
7086 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7088 res.type = NULL;
7089 res.value = NULL;
7090 res.klass = NULL;
7091 return res;
7094 static MonoType*
7095 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7097 gint i;
7098 MONO_ARCH_SAVE_REGS;
7100 i = iter->sig->sentinelpos + iter->next_arg;
7102 g_assert (i < iter->sig->param_count);
7104 return iter->sig->params [i];
7107 static MonoObject*
7108 mono_TypedReference_ToObject (MonoTypedRef tref)
7110 MONO_ARCH_SAVE_REGS;
7112 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7113 MonoObject** objp = tref.value;
7114 return *objp;
7117 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7120 static MonoObject*
7121 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7123 MONO_ARCH_SAVE_REGS;
7125 if (MONO_TYPE_IS_REFERENCE (type)) {
7126 MonoObject** objp = value;
7127 return *objp;
7130 return mono_value_box (mono_domain_get (), klass, value);
7133 static void
7134 prelink_method (MonoMethod *method)
7136 const char *exc_class, *exc_arg;
7137 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7138 return;
7139 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7140 if (exc_class) {
7141 mono_raise_exception(
7142 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7144 /* create the wrapper, too? */
7147 static void
7148 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7150 MONO_ARCH_SAVE_REGS;
7151 prelink_method (method->method);
7154 static void
7155 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7157 MonoClass *klass = mono_class_from_mono_type (type->type);
7158 MonoMethod* m;
7159 gpointer iter = NULL;
7160 MONO_ARCH_SAVE_REGS;
7162 while ((m = mono_class_get_methods (klass, &iter)))
7163 prelink_method (m);
7166 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7167 static void
7168 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7169 gint32 const **exponents,
7170 gunichar2 const **digitLowerTable,
7171 gunichar2 const **digitUpperTable,
7172 gint64 const **tenPowersList,
7173 gint32 const **decHexDigits)
7175 *mantissas = Formatter_MantissaBitsTable;
7176 *exponents = Formatter_TensExponentTable;
7177 *digitLowerTable = Formatter_DigitLowerTable;
7178 *digitUpperTable = Formatter_DigitUpperTable;
7179 *tenPowersList = Formatter_TenPowersList;
7180 *decHexDigits = Formatter_DecHexDigits;
7183 /* These parameters are "readonly" in corlib/System/Char.cs */
7184 static void
7185 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7186 guint8 const **numeric_data,
7187 gdouble const **numeric_data_values,
7188 guint16 const **to_lower_data_low,
7189 guint16 const **to_lower_data_high,
7190 guint16 const **to_upper_data_low,
7191 guint16 const **to_upper_data_high)
7193 *category_data = CategoryData;
7194 *numeric_data = NumericData;
7195 *numeric_data_values = NumericDataValues;
7196 *to_lower_data_low = ToLowerDataLow;
7197 *to_lower_data_high = ToLowerDataHigh;
7198 *to_upper_data_low = ToUpperDataLow;
7199 *to_upper_data_high = ToUpperDataHigh;
7202 static gint32
7203 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7205 return method->method->token;
7209 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7210 * and avoid useless allocations.
7212 static MonoArray*
7213 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7215 MonoArray *res;
7216 int i, count = 0;
7217 for (i = 0; i < type->num_mods; ++i) {
7218 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7219 count++;
7221 if (!count)
7222 return NULL;
7223 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7224 count = 0;
7225 for (i = 0; i < type->num_mods; ++i) {
7226 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7227 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7228 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7229 count++;
7232 return res;
7235 static MonoArray*
7236 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7238 MonoType *type = param->ClassImpl->type;
7239 MonoClass *member_class = mono_object_class (param->MemberImpl);
7240 MonoMethod *method = NULL;
7241 MonoImage *image;
7242 int pos;
7243 MonoMethodSignature *sig;
7245 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7246 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7247 method = rmethod->method;
7248 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7249 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7250 if (!(method = prop->property->get))
7251 method = prop->property->set;
7252 g_assert (method);
7253 } else {
7254 char *type_name = mono_type_get_full_name (member_class);
7255 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7256 MonoException *ex = mono_get_exception_not_supported (msg);
7257 g_free (type_name);
7258 g_free (msg);
7259 mono_raise_exception (ex);
7262 image = method->klass->image;
7263 pos = param->PositionImpl;
7264 sig = mono_method_signature (method);
7265 if (pos == -1)
7266 type = sig->ret;
7267 else
7268 type = sig->params [pos];
7270 return type_array_from_modifiers (image, type, optional);
7273 static MonoType*
7274 get_property_type (MonoProperty *prop)
7276 MonoMethodSignature *sig;
7277 if (prop->get) {
7278 sig = mono_method_signature (prop->get);
7279 return sig->ret;
7280 } else if (prop->set) {
7281 sig = mono_method_signature (prop->set);
7282 return sig->params [sig->param_count - 1];
7284 return NULL;
7287 static MonoArray*
7288 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7290 MonoType *type = get_property_type (property->property);
7291 MonoImage *image = property->klass->image;
7293 if (!type)
7294 return NULL;
7295 return type_array_from_modifiers (image, type, optional);
7299 *Construct a MonoType suited to be used to decode a constant blob object.
7301 * @type is the target type which will be constructed
7302 * @blob_type is the blob type, for example, that comes from the constant table
7303 * @real_type is the expected constructed type.
7305 static void
7306 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7308 type->type = blob_type;
7309 type->data.klass = NULL;
7310 if (blob_type == MONO_TYPE_CLASS)
7311 type->data.klass = mono_defaults.object_class;
7312 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7313 /* For enums, we need to use the base type */
7314 type->type = MONO_TYPE_VALUETYPE;
7315 type->data.klass = mono_class_from_mono_type (real_type);
7316 } else
7317 type->data.klass = mono_class_from_mono_type (real_type);
7320 static MonoObject*
7321 property_info_get_default_value (MonoReflectionProperty *property)
7323 MonoType blob_type;
7324 MonoProperty *prop = property->property;
7325 MonoType *type = get_property_type (prop);
7326 MonoDomain *domain = mono_object_domain (property);
7327 MonoTypeEnum def_type;
7328 const char *def_value;
7329 MonoObject *o;
7331 g_assert (!prop->parent->image->dynamic);
7333 mono_class_init (prop->parent);
7335 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7336 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7338 def_value = mono_class_get_property_default_value (prop, &def_type);
7340 mono_type_from_blob_type (&blob_type, def_type, type);
7341 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7343 return o;
7346 static MonoBoolean
7347 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7349 MonoCustomAttrInfo *cinfo;
7350 gboolean found;
7352 cinfo = mono_reflection_get_custom_attrs_info (obj);
7353 if (!cinfo)
7354 return FALSE;
7355 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7356 if (!cinfo->cached)
7357 mono_custom_attrs_free (cinfo);
7358 return found;
7361 static MonoArray*
7362 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7364 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7366 if (mono_loader_get_last_error ()) {
7367 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7368 g_assert_not_reached ();
7369 /* Not reached */
7370 return NULL;
7371 } else {
7372 return res;
7376 static MonoString*
7377 ves_icall_Mono_Runtime_GetDisplayName (void)
7379 char *info;
7380 MonoString *display_name;
7382 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7383 display_name = mono_string_new (mono_domain_get (), info);
7384 g_free (info);
7385 return display_name;
7388 static MonoObject *
7389 ves_icall_Mono_Runtime_NewObject (MonoType *t)
7391 return mono_object_new (mono_domain_get (), mono_class_from_mono_type (t));
7394 static MonoString*
7395 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7397 MonoString *message;
7398 guint32 ret;
7399 gunichar2 buf[256];
7401 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7402 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7403 buf, 255, NULL);
7404 if (ret == 0) {
7405 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7406 } else {
7407 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7410 return message;
7413 const static guchar
7414 dbase64 [] = {
7415 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7416 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7417 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7418 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7419 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7420 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7421 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7422 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7425 static MonoArray *
7426 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7428 gint ignored;
7429 gint i;
7430 gunichar2 c;
7431 gunichar2 last, prev_last, prev2_last;
7432 gint olength;
7433 MonoArray *result;
7434 guchar *res_ptr;
7435 gint a [4], b [4];
7436 MonoException *exc;
7438 ignored = 0;
7439 last = prev_last = 0, prev2_last = 0;
7440 for (i = 0; i < ilength; i++) {
7441 c = start [i];
7442 if (c >= sizeof (dbase64)) {
7443 exc = mono_exception_from_name_msg (mono_get_corlib (),
7444 "System", "FormatException",
7445 "Invalid character found.");
7446 mono_raise_exception (exc);
7447 } else if (isspace (c)) {
7448 ignored++;
7449 } else {
7450 prev2_last = prev_last;
7451 prev_last = last;
7452 last = c;
7456 olength = ilength - ignored;
7458 if (allowWhitespaceOnly && olength == 0) {
7459 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7462 if ((olength & 3) != 0 || olength <= 0) {
7463 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7464 "FormatException", "Invalid length.");
7465 mono_raise_exception (exc);
7468 if (prev2_last == '=') {
7469 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7470 mono_raise_exception (exc);
7473 olength = (olength * 3) / 4;
7474 if (last == '=')
7475 olength--;
7477 if (prev_last == '=')
7478 olength--;
7480 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7481 res_ptr = mono_array_addr (result, guchar, 0);
7482 for (i = 0; i < ilength; ) {
7483 int k;
7485 for (k = 0; k < 4 && i < ilength;) {
7486 c = start [i++];
7487 if (isspace (c))
7488 continue;
7490 a [k] = (guchar) c;
7491 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7492 exc = mono_exception_from_name_msg (mono_get_corlib (),
7493 "System", "FormatException",
7494 "Invalid character found.");
7495 mono_raise_exception (exc);
7497 k++;
7500 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7501 if (a [2] != '=')
7502 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7503 if (a [3] != '=')
7504 *res_ptr++ = (b [2] << 6) | b [3];
7506 while (i < ilength && isspace (start [i]))
7507 i++;
7510 return result;
7513 static MonoArray *
7514 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7516 MONO_ARCH_SAVE_REGS;
7518 return base64_to_byte_array (mono_string_chars (str),
7519 mono_string_length (str), allowWhitespaceOnly);
7522 static MonoArray *
7523 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7525 MONO_ARCH_SAVE_REGS;
7527 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7528 length, FALSE);
7531 #define ICALL_TYPE(id,name,first)
7532 #define ICALL(id,name,func) Icall_ ## id,
7534 enum {
7535 #include "metadata/icall-def.h"
7536 Icall_last
7539 #undef ICALL_TYPE
7540 #undef ICALL
7541 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7542 #define ICALL(id,name,func)
7543 enum {
7544 #include "metadata/icall-def.h"
7545 Icall_type_num
7548 #undef ICALL_TYPE
7549 #undef ICALL
7550 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7551 #define ICALL(id,name,func)
7552 typedef struct {
7553 guint16 first_icall;
7554 } IcallTypeDesc;
7556 static const IcallTypeDesc
7557 icall_type_descs [] = {
7558 #include "metadata/icall-def.h"
7559 {Icall_last}
7562 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7564 #undef ICALL_TYPE
7565 #define ICALL_TYPE(id,name,first)
7566 #undef ICALL
7568 #ifdef HAVE_ARRAY_ELEM_INIT
7569 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7570 #define MSGSTRFIELD1(line) str##line
7572 static const struct msgstrtn_t {
7573 #define ICALL(id,name,func)
7574 #undef ICALL_TYPE
7575 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7576 #include "metadata/icall-def.h"
7577 #undef ICALL_TYPE
7578 } icall_type_names_str = {
7579 #define ICALL_TYPE(id,name,first) (name),
7580 #include "metadata/icall-def.h"
7581 #undef ICALL_TYPE
7583 static const guint16 icall_type_names_idx [] = {
7584 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7585 #include "metadata/icall-def.h"
7586 #undef ICALL_TYPE
7588 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7590 static const struct msgstr_t {
7591 #undef ICALL
7592 #define ICALL_TYPE(id,name,first)
7593 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7594 #include "metadata/icall-def.h"
7595 #undef ICALL
7596 } icall_names_str = {
7597 #define ICALL(id,name,func) (name),
7598 #include "metadata/icall-def.h"
7599 #undef ICALL
7601 static const guint16 icall_names_idx [] = {
7602 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7603 #include "metadata/icall-def.h"
7604 #undef ICALL
7606 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7608 #else
7610 #undef ICALL_TYPE
7611 #undef ICALL
7612 #define ICALL_TYPE(id,name,first) name,
7613 #define ICALL(id,name,func)
7614 static const char* const
7615 icall_type_names [] = {
7616 #include "metadata/icall-def.h"
7617 NULL
7620 #define icall_type_name_get(id) (icall_type_names [(id)])
7622 #undef ICALL_TYPE
7623 #undef ICALL
7624 #define ICALL_TYPE(id,name,first)
7625 #define ICALL(id,name,func) name,
7626 static const char* const
7627 icall_names [] = {
7628 #include "metadata/icall-def.h"
7629 NULL
7631 #define icall_name_get(id) icall_names [(id)]
7633 #endif /* !HAVE_ARRAY_ELEM_INIT */
7635 #undef ICALL_TYPE
7636 #undef ICALL
7637 #define ICALL_TYPE(id,name,first)
7638 #define ICALL(id,name,func) func,
7639 static const gconstpointer
7640 icall_functions [] = {
7641 #include "metadata/icall-def.h"
7642 NULL
7645 static GHashTable *icall_hash = NULL;
7646 static GHashTable *jit_icall_hash_name = NULL;
7647 static GHashTable *jit_icall_hash_addr = NULL;
7649 void
7650 mono_icall_init (void)
7652 int i = 0;
7654 /* check that tables are sorted: disable in release */
7655 if (TRUE) {
7656 int j;
7657 const char *prev_class = NULL;
7658 const char *prev_method;
7660 for (i = 0; i < Icall_type_num; ++i) {
7661 const IcallTypeDesc *desc;
7662 int num_icalls;
7663 prev_method = NULL;
7664 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7665 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7666 prev_class = icall_type_name_get (i);
7667 desc = &icall_type_descs [i];
7668 num_icalls = icall_desc_num_icalls (desc);
7669 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7670 for (j = 0; j < num_icalls; ++j) {
7671 const char *methodn = icall_name_get (desc->first_icall + j);
7672 if (prev_method && strcmp (prev_method, methodn) >= 0)
7673 g_print ("method %s should come before method %s\n", methodn, prev_method);
7674 prev_method = methodn;
7679 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7682 void
7683 mono_icall_cleanup (void)
7685 g_hash_table_destroy (icall_hash);
7686 g_hash_table_destroy (jit_icall_hash_name);
7687 g_hash_table_destroy (jit_icall_hash_addr);
7690 void
7691 mono_add_internal_call (const char *name, gconstpointer method)
7693 mono_loader_lock ();
7695 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7697 mono_loader_unlock ();
7700 #ifdef HAVE_ARRAY_ELEM_INIT
7701 static int
7702 compare_method_imap (const void *key, const void *elem)
7704 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7705 return strcmp (key, method_name);
7708 static gpointer
7709 find_method_icall (const IcallTypeDesc *imap, const char *name)
7711 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7712 if (!nameslot)
7713 return NULL;
7714 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7717 static int
7718 compare_class_imap (const void *key, const void *elem)
7720 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7721 return strcmp (key, class_name);
7724 static const IcallTypeDesc*
7725 find_class_icalls (const char *name)
7727 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7728 if (!nameslot)
7729 return NULL;
7730 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7733 #else
7734 static int
7735 compare_method_imap (const void *key, const void *elem)
7737 const char** method_name = (const char**)elem;
7738 return strcmp (key, *method_name);
7741 static gpointer
7742 find_method_icall (const IcallTypeDesc *imap, const char *name)
7744 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7745 if (!nameslot)
7746 return NULL;
7747 return (gpointer)icall_functions [(nameslot - icall_names)];
7750 static int
7751 compare_class_imap (const void *key, const void *elem)
7753 const char** class_name = (const char**)elem;
7754 return strcmp (key, *class_name);
7757 static const IcallTypeDesc*
7758 find_class_icalls (const char *name)
7760 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7761 if (!nameslot)
7762 return NULL;
7763 return &icall_type_descs [nameslot - icall_type_names];
7766 #endif
7769 * we should probably export this as an helper (handle nested types).
7770 * Returns the number of chars written in buf.
7772 static int
7773 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7775 int nspacelen, cnamelen;
7776 nspacelen = strlen (klass->name_space);
7777 cnamelen = strlen (klass->name);
7778 if (nspacelen + cnamelen + 2 > bufsize)
7779 return 0;
7780 if (nspacelen) {
7781 memcpy (buf, klass->name_space, nspacelen);
7782 buf [nspacelen ++] = '.';
7784 memcpy (buf + nspacelen, klass->name, cnamelen);
7785 buf [nspacelen + cnamelen] = 0;
7786 return nspacelen + cnamelen;
7789 gpointer
7790 mono_lookup_internal_call (MonoMethod *method)
7792 char *sigstart;
7793 char *tmpsig;
7794 char mname [2048];
7795 int typelen = 0, mlen, siglen;
7796 gpointer res;
7797 const IcallTypeDesc *imap;
7799 g_assert (method != NULL);
7801 if (method->is_inflated)
7802 method = ((MonoMethodInflated *) method)->declaring;
7804 if (method->klass->nested_in) {
7805 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7806 if (!pos)
7807 return NULL;
7809 mname [pos++] = '/';
7810 mname [pos] = 0;
7812 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7813 if (!typelen)
7814 return NULL;
7816 typelen += pos;
7817 } else {
7818 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7819 if (!typelen)
7820 return NULL;
7823 imap = find_class_icalls (mname);
7825 mname [typelen] = ':';
7826 mname [typelen + 1] = ':';
7828 mlen = strlen (method->name);
7829 memcpy (mname + typelen + 2, method->name, mlen);
7830 sigstart = mname + typelen + 2 + mlen;
7831 *sigstart = 0;
7833 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7834 siglen = strlen (tmpsig);
7835 if (typelen + mlen + siglen + 6 > sizeof (mname))
7836 return NULL;
7837 sigstart [0] = '(';
7838 memcpy (sigstart + 1, tmpsig, siglen);
7839 sigstart [siglen + 1] = ')';
7840 sigstart [siglen + 2] = 0;
7841 g_free (tmpsig);
7843 mono_loader_lock ();
7845 res = g_hash_table_lookup (icall_hash, mname);
7846 if (res) {
7847 mono_loader_unlock ();
7848 return res;
7850 /* try without signature */
7851 *sigstart = 0;
7852 res = g_hash_table_lookup (icall_hash, mname);
7853 if (res) {
7854 mono_loader_unlock ();
7855 return res;
7858 /* it wasn't found in the static call tables */
7859 if (!imap) {
7860 mono_loader_unlock ();
7861 return NULL;
7863 res = find_method_icall (imap, sigstart - mlen);
7864 if (res) {
7865 mono_loader_unlock ();
7866 return res;
7868 /* try _with_ signature */
7869 *sigstart = '(';
7870 res = find_method_icall (imap, sigstart - mlen);
7871 if (res) {
7872 mono_loader_unlock ();
7873 return res;
7876 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7877 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7878 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7879 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7880 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");
7881 g_print ("If you see other errors or faults after this message they are probably related\n");
7882 g_print ("and you need to fix your mono install first.\n");
7884 mono_loader_unlock ();
7886 return NULL;
7889 static MonoType*
7890 type_from_typename (char *typename)
7892 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7894 if (!strcmp (typename, "int"))
7895 klass = mono_defaults.int_class;
7896 else if (!strcmp (typename, "ptr"))
7897 klass = mono_defaults.int_class;
7898 else if (!strcmp (typename, "void"))
7899 klass = mono_defaults.void_class;
7900 else if (!strcmp (typename, "int32"))
7901 klass = mono_defaults.int32_class;
7902 else if (!strcmp (typename, "uint32"))
7903 klass = mono_defaults.uint32_class;
7904 else if (!strcmp (typename, "int8"))
7905 klass = mono_defaults.sbyte_class;
7906 else if (!strcmp (typename, "uint8"))
7907 klass = mono_defaults.byte_class;
7908 else if (!strcmp (typename, "int16"))
7909 klass = mono_defaults.int16_class;
7910 else if (!strcmp (typename, "uint16"))
7911 klass = mono_defaults.uint16_class;
7912 else if (!strcmp (typename, "long"))
7913 klass = mono_defaults.int64_class;
7914 else if (!strcmp (typename, "ulong"))
7915 klass = mono_defaults.uint64_class;
7916 else if (!strcmp (typename, "float"))
7917 klass = mono_defaults.single_class;
7918 else if (!strcmp (typename, "double"))
7919 klass = mono_defaults.double_class;
7920 else if (!strcmp (typename, "object"))
7921 klass = mono_defaults.object_class;
7922 else if (!strcmp (typename, "obj"))
7923 klass = mono_defaults.object_class;
7924 else if (!strcmp (typename, "string"))
7925 klass = mono_defaults.string_class;
7926 else if (!strcmp (typename, "bool"))
7927 klass = mono_defaults.boolean_class;
7928 else if (!strcmp (typename, "boolean"))
7929 klass = mono_defaults.boolean_class;
7930 else {
7931 g_error ("%s", typename);
7932 g_assert_not_reached ();
7934 return &klass->byval_arg;
7937 MonoMethodSignature*
7938 mono_create_icall_signature (const char *sigstr)
7940 gchar **parts;
7941 int i, len;
7942 gchar **tmp;
7943 MonoMethodSignature *res;
7945 mono_loader_lock ();
7946 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7947 if (res) {
7948 mono_loader_unlock ();
7949 return res;
7952 parts = g_strsplit (sigstr, " ", 256);
7954 tmp = parts;
7955 len = 0;
7956 while (*tmp) {
7957 len ++;
7958 tmp ++;
7961 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7962 res->pinvoke = 1;
7964 #ifdef HOST_WIN32
7966 * Under windows, the default pinvoke calling convention is STDCALL but
7967 * we need CDECL.
7969 res->call_convention = MONO_CALL_C;
7970 #endif
7972 res->ret = type_from_typename (parts [0]);
7973 for (i = 1; i < len; ++i) {
7974 res->params [i - 1] = type_from_typename (parts [i]);
7977 g_strfreev (parts);
7979 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7981 mono_loader_unlock ();
7983 return res;
7986 MonoJitICallInfo *
7987 mono_find_jit_icall_by_name (const char *name)
7989 MonoJitICallInfo *info;
7990 g_assert (jit_icall_hash_name);
7992 mono_loader_lock ();
7993 info = g_hash_table_lookup (jit_icall_hash_name, name);
7994 mono_loader_unlock ();
7995 return info;
7998 MonoJitICallInfo *
7999 mono_find_jit_icall_by_addr (gconstpointer addr)
8001 MonoJitICallInfo *info;
8002 g_assert (jit_icall_hash_addr);
8004 mono_loader_lock ();
8005 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8006 mono_loader_unlock ();
8008 return info;
8012 * mono_get_jit_icall_info:
8014 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8015 * caller should access it while holding the loader lock.
8017 GHashTable*
8018 mono_get_jit_icall_info (void)
8020 return jit_icall_hash_name;
8023 void
8024 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8026 mono_loader_lock ();
8027 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8028 mono_loader_unlock ();
8031 MonoJitICallInfo *
8032 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8034 MonoJitICallInfo *info;
8036 g_assert (func);
8037 g_assert (name);
8039 mono_loader_lock ();
8041 if (!jit_icall_hash_name) {
8042 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8043 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8046 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8047 g_warning ("jit icall already defined \"%s\"\n", name);
8048 g_assert_not_reached ();
8051 info = g_new0 (MonoJitICallInfo, 1);
8053 info->name = name;
8054 info->func = func;
8055 info->sig = sig;
8057 if (is_save) {
8058 info->wrapper = func;
8059 } else {
8060 info->wrapper = NULL;
8063 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8064 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8066 mono_loader_unlock ();
8067 return info;