2010-04-08 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / icall.c
blob819beaa026be44e228fc9f9cac83ee8fd80aa978
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 uintptr_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(intptr_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, (intptr_t*)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 uintptr_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(intptr_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, (intptr_t*)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 uintptr_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 MonoClass *fklass = field->klass;
1753 MonoClassField *cf = field->field;
1754 MonoDomain *domain = mono_object_domain (field);
1756 if (fklass->image->assembly->ref_only)
1757 mono_raise_exception (mono_get_exception_invalid_operation (
1758 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1760 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1761 mono_security_core_clr_ensure_reflection_access_field (cf);
1763 return mono_field_get_value_object (domain, cf, obj);
1766 static void
1767 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1769 MonoClassField *cf = field->field;
1770 gchar *v;
1772 MONO_ARCH_SAVE_REGS;
1774 if (field->klass->image->assembly->ref_only)
1775 mono_raise_exception (mono_get_exception_invalid_operation (
1776 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1778 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1779 mono_security_core_clr_ensure_reflection_access_field (cf);
1781 v = (gchar *) value;
1782 if (!cf->type->byref) {
1783 switch (cf->type->type) {
1784 case MONO_TYPE_U1:
1785 case MONO_TYPE_I1:
1786 case MONO_TYPE_BOOLEAN:
1787 case MONO_TYPE_U2:
1788 case MONO_TYPE_I2:
1789 case MONO_TYPE_CHAR:
1790 case MONO_TYPE_U:
1791 case MONO_TYPE_I:
1792 case MONO_TYPE_U4:
1793 case MONO_TYPE_I4:
1794 case MONO_TYPE_R4:
1795 case MONO_TYPE_U8:
1796 case MONO_TYPE_I8:
1797 case MONO_TYPE_R8:
1798 case MONO_TYPE_VALUETYPE:
1799 if (v != NULL)
1800 v += sizeof (MonoObject);
1801 break;
1802 case MONO_TYPE_STRING:
1803 case MONO_TYPE_OBJECT:
1804 case MONO_TYPE_CLASS:
1805 case MONO_TYPE_ARRAY:
1806 case MONO_TYPE_SZARRAY:
1807 /* Do nothing */
1808 break;
1809 case MONO_TYPE_GENERICINST: {
1810 MonoGenericClass *gclass = cf->type->data.generic_class;
1811 g_assert (!gclass->context.class_inst->is_open);
1813 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1814 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1815 MonoObject *nullable;
1818 * Convert the boxed vtype into a Nullable structure.
1819 * This is complicated by the fact that Nullables have
1820 * a variable structure.
1822 nullable = mono_object_new (mono_domain_get (), nklass);
1824 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1826 v = mono_object_unbox (nullable);
1828 else
1829 if (gclass->container_class->valuetype && (v != NULL))
1830 v += sizeof (MonoObject);
1831 break;
1833 default:
1834 g_error ("type 0x%x not handled in "
1835 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1836 return;
1840 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1841 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1842 if (!vtable->initialized)
1843 mono_runtime_class_init (vtable);
1844 mono_field_static_set_value (vtable, cf, v);
1845 } else {
1846 mono_field_set_value (obj, cf, v);
1850 static MonoObject *
1851 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1853 MonoObject *o = NULL;
1854 MonoClassField *field = this->field;
1855 MonoClass *klass;
1856 MonoDomain *domain = mono_object_domain (this);
1857 gchar *v;
1858 MonoTypeEnum def_type;
1859 const char *def_value;
1861 MONO_ARCH_SAVE_REGS;
1863 mono_class_init (field->parent);
1865 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1866 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1868 if (field->parent->image->dynamic) {
1869 /* FIXME: */
1870 g_assert_not_reached ();
1873 def_value = mono_class_get_field_default_value (field, &def_type);
1875 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1876 switch (def_type) {
1877 case MONO_TYPE_U1:
1878 case MONO_TYPE_I1:
1879 case MONO_TYPE_BOOLEAN:
1880 case MONO_TYPE_U2:
1881 case MONO_TYPE_I2:
1882 case MONO_TYPE_CHAR:
1883 case MONO_TYPE_U:
1884 case MONO_TYPE_I:
1885 case MONO_TYPE_U4:
1886 case MONO_TYPE_I4:
1887 case MONO_TYPE_R4:
1888 case MONO_TYPE_U8:
1889 case MONO_TYPE_I8:
1890 case MONO_TYPE_R8: {
1891 MonoType *t;
1893 /* boxed value type */
1894 t = g_new0 (MonoType, 1);
1895 t->type = def_type;
1896 klass = mono_class_from_mono_type (t);
1897 g_free (t);
1898 o = mono_object_new (domain, klass);
1899 v = ((gchar *) o) + sizeof (MonoObject);
1900 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1901 break;
1903 case MONO_TYPE_STRING:
1904 case MONO_TYPE_CLASS:
1905 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1906 break;
1907 default:
1908 g_assert_not_reached ();
1911 return o;
1914 static MonoReflectionType*
1915 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1917 MonoMethod *method = rmethod->method.method;
1919 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1922 /* From MonoProperty.cs */
1923 typedef enum {
1924 PInfo_Attributes = 1,
1925 PInfo_GetMethod = 1 << 1,
1926 PInfo_SetMethod = 1 << 2,
1927 PInfo_ReflectedType = 1 << 3,
1928 PInfo_DeclaringType = 1 << 4,
1929 PInfo_Name = 1 << 5
1930 } PInfo;
1932 static void
1933 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1935 MonoDomain *domain = mono_object_domain (property);
1937 MONO_ARCH_SAVE_REGS;
1939 if ((req_info & PInfo_ReflectedType) != 0)
1940 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1941 else if ((req_info & PInfo_DeclaringType) != 0)
1942 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1944 if ((req_info & PInfo_Name) != 0)
1945 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1947 if ((req_info & PInfo_Attributes) != 0)
1948 info->attrs = property->property->attrs;
1950 if ((req_info & PInfo_GetMethod) != 0)
1951 MONO_STRUCT_SETREF (info, get, property->property->get ?
1952 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1954 if ((req_info & PInfo_SetMethod) != 0)
1955 MONO_STRUCT_SETREF (info, set, property->property->set ?
1956 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1958 * There may be other methods defined for properties, though, it seems they are not exposed
1959 * in the reflection API
1963 static void
1964 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1966 MonoDomain *domain = mono_object_domain (event);
1968 MONO_ARCH_SAVE_REGS;
1970 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
1971 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
1973 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
1974 info->attrs = event->event->attrs;
1975 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
1976 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
1977 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
1979 #ifndef MONO_SMALL_CONFIG
1980 if (event->event->other) {
1981 int i, n = 0;
1982 while (event->event->other [n])
1983 n++;
1984 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
1986 for (i = 0; i < n; i++)
1987 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
1989 #endif
1992 static MonoArray*
1993 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
1995 MonoError error;
1996 MonoDomain *domain = mono_object_domain (type);
1997 MonoArray *intf;
1998 GPtrArray *ifaces = NULL;
1999 int i;
2000 MonoClass *class = mono_class_from_mono_type (type->type);
2001 MonoClass *parent;
2002 MonoBitSet *slots;
2003 MonoGenericContext *context = NULL;
2005 MONO_ARCH_SAVE_REGS;
2007 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2008 context = mono_class_get_context (class);
2009 class = class->generic_class->container_class;
2012 mono_class_setup_vtable (class);
2014 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2016 for (parent = class; parent; parent = parent->parent) {
2017 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent, &error);
2018 if (!mono_error_ok (&error)) {
2019 mono_bitset_free (slots);
2020 mono_error_raise_exception (&error);
2021 return NULL;
2022 } else if (tmp_ifaces) {
2023 for (i = 0; i < tmp_ifaces->len; ++i) {
2024 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2026 if (mono_bitset_test (slots, ic->interface_id))
2027 continue;
2029 mono_bitset_set (slots, ic->interface_id);
2030 if (ifaces == NULL)
2031 ifaces = g_ptr_array_new ();
2032 g_ptr_array_add (ifaces, ic);
2034 g_ptr_array_free (tmp_ifaces, TRUE);
2037 mono_bitset_free (slots);
2039 if (!ifaces)
2040 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2042 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2043 for (i = 0; i < ifaces->len; ++i) {
2044 MonoClass *ic = g_ptr_array_index (ifaces, i);
2045 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2046 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2047 inflated = ret = mono_class_inflate_generic_type (ret, context);
2049 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2050 if (inflated)
2051 mono_metadata_free_type (inflated);
2053 g_ptr_array_free (ifaces, TRUE);
2055 return intf;
2058 static void
2059 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2061 gboolean variance_used;
2062 MonoClass *class = mono_class_from_mono_type (type->type);
2063 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2064 MonoReflectionMethod *member;
2065 MonoMethod* method;
2066 gpointer iter;
2067 int i = 0, len, ioffset;
2068 MonoDomain *domain;
2070 MONO_ARCH_SAVE_REGS;
2072 mono_class_setup_vtable (class);
2074 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2075 if (ioffset == -1)
2076 return;
2078 len = mono_class_num_methods (iclass);
2079 domain = mono_object_domain (type);
2080 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2081 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2082 iter = NULL;
2083 while ((method = mono_class_get_methods (iclass, &iter))) {
2084 member = mono_method_get_object (domain, method, iclass);
2085 mono_array_setref (*methods, i, member);
2086 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2087 mono_array_setref (*targets, i, member);
2089 i ++;
2093 static void
2094 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2096 MonoClass *klass = mono_class_from_mono_type (type->type);
2098 if (klass->image->dynamic) {
2099 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2100 *packing = tb->packing_size;
2101 *size = tb->class_size;
2102 } else {
2103 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2107 static MonoReflectionType*
2108 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2110 MonoClass *class;
2112 MONO_ARCH_SAVE_REGS;
2114 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2115 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2117 class = mono_class_from_mono_type (type->type);
2119 // GetElementType should only return a type for:
2120 // Array Pointer PassedByRef
2121 if (type->type->byref)
2122 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2123 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2124 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2125 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2126 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2127 else
2128 return NULL;
2131 static MonoReflectionType*
2132 ves_icall_get_type_parent (MonoReflectionType *type)
2134 MonoClass *class = mono_class_from_mono_type (type->type);
2136 MONO_ARCH_SAVE_REGS;
2138 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2141 static MonoBoolean
2142 ves_icall_type_ispointer (MonoReflectionType *type)
2144 MONO_ARCH_SAVE_REGS;
2146 return type->type->type == MONO_TYPE_PTR;
2149 static MonoBoolean
2150 ves_icall_type_isprimitive (MonoReflectionType *type)
2152 MONO_ARCH_SAVE_REGS;
2154 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)));
2157 static MonoBoolean
2158 ves_icall_type_isbyref (MonoReflectionType *type)
2160 MONO_ARCH_SAVE_REGS;
2162 return type->type->byref;
2165 static MonoBoolean
2166 ves_icall_type_iscomobject (MonoReflectionType *type)
2168 MonoClass *klass = mono_class_from_mono_type (type->type);
2169 MONO_ARCH_SAVE_REGS;
2171 return (klass && klass->is_com_object);
2174 static MonoReflectionModule*
2175 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2177 MonoClass *class = mono_class_from_mono_type (type->type);
2179 MONO_ARCH_SAVE_REGS;
2181 return mono_module_get_object (mono_object_domain (type), class->image);
2184 static MonoReflectionAssembly*
2185 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2187 MonoDomain *domain = mono_domain_get ();
2188 MonoClass *class = mono_class_from_mono_type (type->type);
2190 MONO_ARCH_SAVE_REGS;
2192 return mono_assembly_get_object (domain, class->image->assembly);
2195 static MonoReflectionType*
2196 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2198 MonoDomain *domain = mono_domain_get ();
2199 MonoClass *class;
2201 MONO_ARCH_SAVE_REGS;
2203 if (type->type->byref)
2204 return NULL;
2205 if (type->type->type == MONO_TYPE_VAR)
2206 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2207 else if (type->type->type == MONO_TYPE_MVAR)
2208 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2209 else
2210 class = mono_class_from_mono_type (type->type)->nested_in;
2212 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2215 static MonoReflectionType*
2216 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2218 MonoDomain *domain = mono_domain_get ();
2219 MonoClass *class = mono_class_from_mono_type (type->type);
2221 MONO_ARCH_SAVE_REGS;
2223 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2224 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2225 else if (class->element_class)
2226 return mono_type_get_object (domain, &class->element_class->byval_arg);
2227 else
2228 return NULL;
2231 static MonoString*
2232 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2234 MonoDomain *domain = mono_domain_get ();
2235 MonoClass *class = mono_class_from_mono_type (type->type);
2237 MONO_ARCH_SAVE_REGS;
2239 if (type->type->byref) {
2240 char *n = g_strdup_printf ("%s&", class->name);
2241 MonoString *res = mono_string_new (domain, n);
2243 g_free (n);
2245 return res;
2246 } else {
2247 return mono_string_new (domain, class->name);
2251 static MonoString*
2252 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2254 MonoDomain *domain = mono_domain_get ();
2255 MonoClass *class = mono_class_from_mono_type (type->type);
2257 MONO_ARCH_SAVE_REGS;
2259 while (class->nested_in)
2260 class = class->nested_in;
2262 if (class->name_space [0] == '\0')
2263 return NULL;
2264 else
2265 return mono_string_new (domain, class->name_space);
2268 static gint32
2269 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2271 MonoClass *class;
2273 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2274 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2276 class = mono_class_from_mono_type (type->type);
2277 return class->rank;
2280 static MonoArray*
2281 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2283 MonoArray *res;
2284 MonoClass *klass, *pklass;
2285 MonoDomain *domain = mono_object_domain (type);
2286 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2287 int i;
2288 MONO_ARCH_SAVE_REGS;
2290 klass = mono_class_from_mono_type (type->type);
2292 if (klass->generic_container) {
2293 MonoGenericContainer *container = klass->generic_container;
2294 res = mono_array_new_specific (array_vtable, container->type_argc);
2295 for (i = 0; i < container->type_argc; ++i) {
2296 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2297 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2299 } else if (klass->generic_class) {
2300 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2301 res = mono_array_new_specific (array_vtable, inst->type_argc);
2302 for (i = 0; i < inst->type_argc; ++i)
2303 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2304 } else {
2305 res = mono_array_new_specific (array_vtable, 0);
2307 return res;
2310 static gboolean
2311 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2313 MonoClass *klass;
2314 MONO_ARCH_SAVE_REGS;
2316 if (!IS_MONOTYPE (type))
2317 return FALSE;
2319 if (type->type->byref)
2320 return FALSE;
2322 klass = mono_class_from_mono_type (type->type);
2324 return klass->generic_container != NULL;
2327 static MonoReflectionType*
2328 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2330 MonoClass *klass;
2331 MONO_ARCH_SAVE_REGS;
2333 if (type->type->byref)
2334 return NULL;
2336 klass = mono_class_from_mono_type (type->type);
2337 if (klass->generic_container) {
2338 return type; /* check this one */
2340 if (klass->generic_class) {
2341 MonoClass *generic_class = klass->generic_class->container_class;
2342 gpointer tb;
2344 tb = mono_class_get_ref_info (generic_class);
2346 if (generic_class->wastypebuilder && tb)
2347 return tb;
2348 else
2349 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2351 return NULL;
2354 static MonoReflectionType*
2355 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2357 MonoType *geninst, **types;
2358 int i, count;
2360 MONO_ARCH_SAVE_REGS;
2362 count = mono_array_length (type_array);
2363 types = g_new0 (MonoType *, count);
2365 for (i = 0; i < count; i++) {
2366 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2367 types [i] = t->type;
2370 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2371 g_free (types);
2372 if (!geninst)
2373 return NULL;
2375 return mono_type_get_object (mono_object_domain (type), geninst);
2378 static gboolean
2379 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2381 MonoClass *klass;
2382 MONO_ARCH_SAVE_REGS;
2384 if (type->type->byref)
2385 return FALSE;
2387 klass = mono_class_from_mono_type (type->type);
2388 return klass->generic_class != NULL;
2391 static gboolean
2392 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2394 MonoClass *klass;
2395 MONO_ARCH_SAVE_REGS;
2397 if (!IS_MONOTYPE (type))
2398 return FALSE;
2400 if (type->type->byref)
2401 return FALSE;
2403 klass = mono_class_from_mono_type (type->type);
2404 return klass->generic_class != NULL || klass->generic_container != NULL;
2407 static gint32
2408 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2410 MONO_ARCH_SAVE_REGS;
2412 if (!IS_MONOTYPE (type))
2413 return -1;
2415 if (is_generic_parameter (type->type))
2416 return mono_type_get_generic_param_num (type->type);
2417 return -1;
2420 static GenericParameterAttributes
2421 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2423 MONO_ARCH_SAVE_REGS;
2425 g_assert (IS_MONOTYPE (type));
2426 g_assert (is_generic_parameter (type->type));
2427 return mono_generic_param_info (type->type->data.generic_param)->flags;
2430 static MonoArray *
2431 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2433 MonoGenericParamInfo *param_info;
2434 MonoDomain *domain;
2435 MonoClass **ptr;
2436 MonoArray *res;
2437 int i, count;
2439 MONO_ARCH_SAVE_REGS;
2441 g_assert (IS_MONOTYPE (type));
2443 domain = mono_object_domain (type);
2444 param_info = mono_generic_param_info (type->type->data.generic_param);
2445 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2448 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2449 for (i = 0; i < count; i++)
2450 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2453 return res;
2456 static MonoBoolean
2457 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2459 MONO_ARCH_SAVE_REGS;
2460 return is_generic_parameter (type->type);
2463 static MonoBoolean
2464 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2466 MONO_ARCH_SAVE_REGS;
2467 return is_generic_parameter (tb->type.type);
2470 static void
2471 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2472 MonoReflectionType *t)
2474 enumtype->type = t->type;
2477 static MonoReflectionMethod*
2478 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2479 MonoReflectionMethod* generic)
2481 MonoDomain *domain;
2482 MonoClass *klass;
2483 MonoMethod *method;
2484 gpointer iter;
2486 MONO_ARCH_SAVE_REGS;
2488 domain = ((MonoObject *)type)->vtable->domain;
2490 klass = mono_class_from_mono_type (type->type);
2492 iter = NULL;
2493 while ((method = mono_class_get_methods (klass, &iter))) {
2494 if (method->token == generic->method->token)
2495 return mono_method_get_object (domain, method, klass);
2498 return NULL;
2503 static MonoReflectionMethod *
2504 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2506 MonoMethod *method;
2507 MonoType *type = ref_type->type;
2509 MONO_ARCH_SAVE_REGS;
2511 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2512 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2513 if (type->type == MONO_TYPE_VAR)
2514 return NULL;
2516 method = mono_type_get_generic_param_owner (type)->owner.method;
2517 g_assert (method);
2518 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2521 static MonoReflectionDllImportAttribute*
2522 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2524 static MonoClass *DllImportAttributeClass = NULL;
2525 MonoDomain *domain = mono_domain_get ();
2526 MonoReflectionDllImportAttribute *attr;
2527 MonoImage *image = method->klass->image;
2528 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2529 MonoTableInfo *tables = image->tables;
2530 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2531 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2532 guint32 im_cols [MONO_IMPLMAP_SIZE];
2533 guint32 scope_token;
2534 const char *import = NULL;
2535 const char *scope = NULL;
2536 guint32 flags;
2538 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2539 return NULL;
2541 if (!DllImportAttributeClass) {
2542 DllImportAttributeClass =
2543 mono_class_from_name (mono_defaults.corlib,
2544 "System.Runtime.InteropServices", "DllImportAttribute");
2545 g_assert (DllImportAttributeClass);
2548 if (method->klass->image->dynamic) {
2549 MonoReflectionMethodAux *method_aux =
2550 g_hash_table_lookup (
2551 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2552 if (method_aux) {
2553 import = method_aux->dllentry;
2554 scope = method_aux->dll;
2557 if (!import || !scope) {
2558 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2559 return NULL;
2562 else {
2563 if (piinfo->implmap_idx) {
2564 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2566 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2567 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2568 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2569 scope = mono_metadata_string_heap (image, scope_token);
2572 flags = piinfo->piflags;
2574 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2576 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2577 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2578 attr->call_conv = (flags & 0x700) >> 8;
2579 attr->charset = ((flags & 0x6) >> 1) + 1;
2580 if (attr->charset == 1)
2581 attr->charset = 2;
2582 attr->exact_spelling = (flags & 0x1) != 0;
2583 attr->set_last_error = (flags & 0x40) != 0;
2584 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2585 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2586 attr->preserve_sig = FALSE;
2588 return attr;
2591 static MonoReflectionMethod *
2592 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2594 MonoMethodInflated *imethod;
2595 MonoMethod *result;
2597 MONO_ARCH_SAVE_REGS;
2599 if (method->method->is_generic)
2600 return method;
2602 if (!method->method->is_inflated)
2603 return NULL;
2605 imethod = (MonoMethodInflated *) method->method;
2607 result = imethod->declaring;
2608 /* Not a generic method. */
2609 if (!result->is_generic)
2610 return NULL;
2612 if (method->method->klass->image->dynamic) {
2613 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2614 MonoReflectionMethod *res;
2617 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2618 * the dynamic case as well ?
2620 mono_loader_lock ();
2621 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2622 mono_loader_unlock ();
2624 if (res)
2625 return res;
2628 if (imethod->context.class_inst) {
2629 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2630 /*Generic methods gets the context of the GTD.*/
2631 if (mono_class_get_context (klass))
2632 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2635 return mono_method_get_object (mono_object_domain (method), result, NULL);
2638 static gboolean
2639 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2641 MONO_ARCH_SAVE_REGS;
2643 return mono_method_signature (method->method)->generic_param_count != 0;
2646 static gboolean
2647 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2649 MONO_ARCH_SAVE_REGS;
2651 return method->method->is_generic;
2654 static MonoArray*
2655 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2657 MonoArray *res;
2658 MonoDomain *domain;
2659 int count, i;
2660 MONO_ARCH_SAVE_REGS;
2662 domain = mono_object_domain (method);
2664 if (method->method->is_inflated) {
2665 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2667 if (inst) {
2668 count = inst->type_argc;
2669 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2671 for (i = 0; i < count; i++)
2672 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2674 return res;
2678 count = mono_method_signature (method->method)->generic_param_count;
2679 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2681 for (i = 0; i < count; i++) {
2682 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2683 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2684 MonoClass *pklass = mono_class_from_generic_parameter (
2685 param, method->method->klass->image, TRUE);
2686 mono_array_setref (res, i,
2687 mono_type_get_object (domain, &pklass->byval_arg));
2690 return res;
2693 static MonoObject *
2694 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2697 * Invoke from reflection is supposed to always be a virtual call (the API
2698 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2699 * greater flexibility.
2701 MonoMethod *m = method->method;
2702 int pcount;
2703 void *obj = this;
2705 MONO_ARCH_SAVE_REGS;
2707 *exc = NULL;
2709 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2710 mono_security_core_clr_ensure_reflection_access_method (m);
2712 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2713 if (this) {
2714 if (!mono_object_isinst (this, m->klass)) {
2715 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2716 return NULL;
2718 m = mono_object_get_virtual_method (this, m);
2719 /* must pass the pointer to the value for valuetype methods */
2720 if (m->klass->valuetype)
2721 obj = mono_object_unbox (this);
2722 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2723 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2724 return NULL;
2728 pcount = params? mono_array_length (params): 0;
2729 if (pcount != mono_method_signature (m)->param_count) {
2730 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2731 return NULL;
2734 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2735 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."));
2736 return NULL;
2739 if (m->klass->image->assembly->ref_only) {
2740 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."));
2741 return NULL;
2744 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2745 int i;
2746 uintptr_t *lengths;
2747 intptr_t *lower_bounds;
2748 pcount = mono_array_length (params);
2749 lengths = alloca (sizeof (uintptr_t) * pcount);
2750 /* Note: the synthetized array .ctors have int32 as argument type */
2751 for (i = 0; i < pcount; ++i)
2752 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2754 if (m->klass->rank == pcount) {
2755 /* Only lengths provided. */
2756 lower_bounds = NULL;
2757 } else {
2758 g_assert (pcount == (m->klass->rank * 2));
2759 /* lower bounds are first. */
2760 lower_bounds = (intptr_t*)lengths;
2761 lengths += m->klass->rank;
2764 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2766 return mono_runtime_invoke_array (m, obj, params, NULL);
2769 static MonoObject *
2770 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2772 MonoDomain *domain = mono_object_domain (method);
2773 MonoMethod *m = method->method;
2774 MonoMethodSignature *sig = mono_method_signature (m);
2775 MonoArray *out_args;
2776 MonoObject *result;
2777 int i, j, outarg_count = 0;
2779 MONO_ARCH_SAVE_REGS;
2781 if (m->klass == mono_defaults.object_class) {
2783 if (!strcmp (m->name, "FieldGetter")) {
2784 MonoClass *k = this->vtable->klass;
2785 MonoString *name;
2786 char *str;
2788 /* If this is a proxy, then it must be a CBO */
2789 if (k == mono_defaults.transparent_proxy_class) {
2790 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2791 this = tp->rp->unwrapped_server;
2792 g_assert (this);
2793 k = this->vtable->klass;
2796 name = mono_array_get (params, MonoString *, 1);
2797 str = mono_string_to_utf8 (name);
2799 do {
2800 MonoClassField* field = mono_class_get_field_from_name (k, str);
2801 if (field) {
2802 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2803 if (field_klass->valuetype)
2804 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2805 else
2806 result = *((gpointer *)((char *)this + field->offset));
2808 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2809 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2810 mono_array_setref (out_args, 0, result);
2811 g_free (str);
2812 return NULL;
2814 k = k->parent;
2815 } while (k);
2817 g_free (str);
2818 g_assert_not_reached ();
2820 } else if (!strcmp (m->name, "FieldSetter")) {
2821 MonoClass *k = this->vtable->klass;
2822 MonoString *name;
2823 guint32 size;
2824 gint32 align;
2825 char *str;
2827 /* If this is a proxy, then it must be a CBO */
2828 if (k == mono_defaults.transparent_proxy_class) {
2829 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2830 this = tp->rp->unwrapped_server;
2831 g_assert (this);
2832 k = this->vtable->klass;
2835 name = mono_array_get (params, MonoString *, 1);
2836 str = mono_string_to_utf8 (name);
2838 do {
2839 MonoClassField* field = mono_class_get_field_from_name (k, str);
2840 if (field) {
2841 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2842 MonoObject *val = mono_array_get (params, gpointer, 2);
2844 if (field_klass->valuetype) {
2845 size = mono_type_size (field->type, &align);
2846 g_assert (size == mono_class_value_size (field_klass, NULL));
2847 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2848 } else {
2849 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2852 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2853 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2855 g_free (str);
2856 return NULL;
2859 k = k->parent;
2860 } while (k);
2862 g_free (str);
2863 g_assert_not_reached ();
2868 for (i = 0; i < mono_array_length (params); i++) {
2869 if (sig->params [i]->byref)
2870 outarg_count++;
2873 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2875 /* handle constructors only for objects already allocated */
2876 if (!strcmp (method->method->name, ".ctor"))
2877 g_assert (this);
2879 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2880 g_assert (!method->method->klass->valuetype);
2881 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2883 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2884 if (sig->params [i]->byref) {
2885 gpointer arg;
2886 arg = mono_array_get (params, gpointer, i);
2887 mono_array_setref (out_args, j, arg);
2888 j++;
2892 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2894 return result;
2897 static guint64
2898 read_enum_value (char *mem, int type)
2900 switch (type) {
2901 case MONO_TYPE_U1:
2902 return *(guint8*)mem;
2903 case MONO_TYPE_I1:
2904 return *(gint8*)mem;
2905 case MONO_TYPE_U2:
2906 return *(guint16*)mem;
2907 case MONO_TYPE_I2:
2908 return *(gint16*)mem;
2909 case MONO_TYPE_U4:
2910 return *(guint32*)mem;
2911 case MONO_TYPE_I4:
2912 return *(gint32*)mem;
2913 case MONO_TYPE_U8:
2914 return *(guint64*)mem;
2915 case MONO_TYPE_I8:
2916 return *(gint64*)mem;
2917 default:
2918 g_assert_not_reached ();
2920 return 0;
2923 static void
2924 write_enum_value (char *mem, int type, guint64 value)
2926 switch (type) {
2927 case MONO_TYPE_U1:
2928 case MONO_TYPE_I1: {
2929 guint8 *p = (guint8*)mem;
2930 *p = value;
2931 break;
2933 case MONO_TYPE_U2:
2934 case MONO_TYPE_I2: {
2935 guint16 *p = (void*)mem;
2936 *p = value;
2937 break;
2939 case MONO_TYPE_U4:
2940 case MONO_TYPE_I4: {
2941 guint32 *p = (void*)mem;
2942 *p = value;
2943 break;
2945 case MONO_TYPE_U8:
2946 case MONO_TYPE_I8: {
2947 guint64 *p = (void*)mem;
2948 *p = value;
2949 break;
2951 default:
2952 g_assert_not_reached ();
2954 return;
2957 static MonoObject *
2958 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
2960 MonoDomain *domain;
2961 MonoClass *enumc, *objc;
2962 MonoObject *res;
2963 MonoType *etype;
2964 guint64 val;
2966 MONO_ARCH_SAVE_REGS;
2968 MONO_CHECK_ARG_NULL (enumType);
2969 MONO_CHECK_ARG_NULL (value);
2971 domain = mono_object_domain (enumType);
2972 enumc = mono_class_from_mono_type (enumType->type);
2973 objc = value->vtable->klass;
2975 if (!enumc->enumtype)
2976 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
2977 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
2978 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."));
2980 etype = mono_class_enum_basetype (enumc);
2981 if (!etype)
2982 /* MS throws this for typebuilders */
2983 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
2985 res = mono_object_new (domain, enumc);
2986 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
2987 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
2989 return res;
2992 static MonoObject *
2993 ves_icall_System_Enum_get_value (MonoObject *this)
2995 MonoObject *res;
2996 MonoClass *enumc;
2997 gpointer dst;
2998 gpointer src;
2999 int size;
3001 MONO_ARCH_SAVE_REGS;
3003 if (!this)
3004 return NULL;
3006 g_assert (this->vtable->klass->enumtype);
3008 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3009 res = mono_object_new (mono_object_domain (this), enumc);
3010 dst = (char *)res + sizeof (MonoObject);
3011 src = (char *)this + sizeof (MonoObject);
3012 size = mono_class_value_size (enumc, NULL);
3014 memcpy (dst, src, size);
3016 return res;
3019 static MonoReflectionType *
3020 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3022 MonoType *etype;
3024 MONO_ARCH_SAVE_REGS;
3026 etype = mono_class_enum_basetype (mono_class_from_mono_type (type->type));
3027 if (!etype)
3028 /* MS throws this for typebuilders */
3029 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3031 return mono_type_get_object (mono_object_domain (type), etype);
3034 static int
3035 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3037 gpointer tdata = (char *)this + sizeof (MonoObject);
3038 gpointer odata = (char *)other + sizeof (MonoObject);
3039 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3040 g_assert (basetype);
3042 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3043 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3044 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3045 if (me == other) \
3046 return 0; \
3047 return me > other ? 1 : -1; \
3048 } while (0)
3050 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3051 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3052 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3053 if (me == other) \
3054 return 0; \
3055 return me - other; \
3056 } while (0)
3058 switch (basetype->type) {
3059 case MONO_TYPE_U1:
3060 COMPARE_ENUM_VALUES (guint8);
3061 case MONO_TYPE_I1:
3062 COMPARE_ENUM_VALUES (gint8);
3063 case MONO_TYPE_CHAR:
3064 case MONO_TYPE_U2:
3065 COMPARE_ENUM_VALUES_RANGE (guint16);
3066 case MONO_TYPE_I2:
3067 COMPARE_ENUM_VALUES (gint16);
3068 case MONO_TYPE_U4:
3069 COMPARE_ENUM_VALUES (guint32);
3070 case MONO_TYPE_I4:
3071 COMPARE_ENUM_VALUES (gint32);
3072 case MONO_TYPE_U8:
3073 COMPARE_ENUM_VALUES (guint64);
3074 case MONO_TYPE_I8:
3075 COMPARE_ENUM_VALUES (gint64);
3076 default:
3077 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3079 #undef COMPARE_ENUM_VALUES_RANGE
3080 #undef COMPARE_ENUM_VALUES
3081 return 0;
3084 static int
3085 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3087 gpointer data = (char *)this + sizeof (MonoObject);
3088 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3089 g_assert (basetype);
3091 switch (basetype->type) {
3092 case MONO_TYPE_I1:
3093 return *((gint8*)data);
3094 case MONO_TYPE_U1:
3095 return *((guint8*)data);
3096 case MONO_TYPE_CHAR:
3097 case MONO_TYPE_U2:
3098 return *((guint16*)data);
3100 case MONO_TYPE_I2:
3101 return *((gint16*)data);
3102 case MONO_TYPE_U4:
3103 return *((guint32*)data);
3104 case MONO_TYPE_I4:
3105 return *((gint32*)data);
3106 case MONO_TYPE_U8:
3107 case MONO_TYPE_I8: {
3108 gint64 value = *((gint64*)data);
3109 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3111 default:
3112 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3114 return 0;
3117 static void
3118 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3120 MonoDomain *domain = mono_object_domain (type);
3121 MonoClass *enumc = mono_class_from_mono_type (type->type);
3122 guint j = 0, nvalues, crow;
3123 gpointer iter;
3124 MonoClassField *field;
3126 MONO_ARCH_SAVE_REGS;
3128 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3129 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3130 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3131 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3133 crow = -1;
3134 iter = NULL;
3135 while ((field = mono_class_get_fields (enumc, &iter))) {
3136 const char *p;
3137 int len;
3138 MonoTypeEnum def_type;
3140 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3141 continue;
3142 if (mono_field_is_deleted (field))
3143 continue;
3144 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3146 p = mono_class_get_field_default_value (field, &def_type);
3147 len = mono_metadata_decode_blob_size (p, &p);
3148 switch (mono_class_enum_basetype (enumc)->type) {
3149 case MONO_TYPE_U1:
3150 case MONO_TYPE_I1:
3151 mono_array_set (info->values, gchar, j, *p);
3152 break;
3153 case MONO_TYPE_CHAR:
3154 case MONO_TYPE_U2:
3155 case MONO_TYPE_I2:
3156 mono_array_set (info->values, gint16, j, read16 (p));
3157 break;
3158 case MONO_TYPE_U4:
3159 case MONO_TYPE_I4:
3160 mono_array_set (info->values, gint32, j, read32 (p));
3161 break;
3162 case MONO_TYPE_U8:
3163 case MONO_TYPE_I8:
3164 mono_array_set (info->values, gint64, j, read64 (p));
3165 break;
3166 default:
3167 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3169 ++j;
3173 enum {
3174 BFLAGS_IgnoreCase = 1,
3175 BFLAGS_DeclaredOnly = 2,
3176 BFLAGS_Instance = 4,
3177 BFLAGS_Static = 8,
3178 BFLAGS_Public = 0x10,
3179 BFLAGS_NonPublic = 0x20,
3180 BFLAGS_FlattenHierarchy = 0x40,
3181 BFLAGS_InvokeMethod = 0x100,
3182 BFLAGS_CreateInstance = 0x200,
3183 BFLAGS_GetField = 0x400,
3184 BFLAGS_SetField = 0x800,
3185 BFLAGS_GetProperty = 0x1000,
3186 BFLAGS_SetProperty = 0x2000,
3187 BFLAGS_ExactBinding = 0x10000,
3188 BFLAGS_SuppressChangeType = 0x20000,
3189 BFLAGS_OptionalParamBinding = 0x40000
3192 static MonoReflectionField *
3193 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3195 MonoDomain *domain;
3196 MonoClass *startklass, *klass;
3197 int match;
3198 MonoClassField *field;
3199 gpointer iter;
3200 char *utf8_name;
3201 int (*compare_func) (const char *s1, const char *s2) = NULL;
3202 domain = ((MonoObject *)type)->vtable->domain;
3203 klass = startklass = mono_class_from_mono_type (type->type);
3205 MONO_ARCH_SAVE_REGS;
3207 if (!name)
3208 mono_raise_exception (mono_get_exception_argument_null ("name"));
3209 if (type->type->byref)
3210 return NULL;
3212 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3214 handle_parent:
3215 if (klass->exception_type != MONO_EXCEPTION_NONE)
3216 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3218 iter = NULL;
3219 while ((field = mono_class_get_fields (klass, &iter))) {
3220 match = 0;
3222 if (field->type == NULL)
3223 continue;
3224 if (mono_field_is_deleted (field))
3225 continue;
3226 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3227 if (bflags & BFLAGS_Public)
3228 match++;
3229 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3230 if (bflags & BFLAGS_NonPublic) {
3231 match++;
3234 if (!match)
3235 continue;
3236 match = 0;
3237 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3238 if (bflags & BFLAGS_Static)
3239 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3240 match++;
3241 } else {
3242 if (bflags & BFLAGS_Instance)
3243 match++;
3246 if (!match)
3247 continue;
3249 utf8_name = mono_string_to_utf8 (name);
3251 if (compare_func (mono_field_get_name (field), utf8_name)) {
3252 g_free (utf8_name);
3253 continue;
3255 g_free (utf8_name);
3257 return mono_field_get_object (domain, klass, field);
3259 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3260 goto handle_parent;
3262 return NULL;
3265 static MonoArray*
3266 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3268 MonoDomain *domain;
3269 MonoClass *startklass, *klass, *refklass;
3270 MonoArray *res;
3271 MonoObject *member;
3272 int i, match;
3273 gpointer iter;
3274 MonoClassField *field;
3275 MonoPtrArray tmp_array;
3277 MONO_ARCH_SAVE_REGS;
3279 domain = ((MonoObject *)type)->vtable->domain;
3280 if (type->type->byref)
3281 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3282 klass = startklass = mono_class_from_mono_type (type->type);
3283 refklass = mono_class_from_mono_type (reftype->type);
3285 mono_ptr_array_init (tmp_array, 2);
3287 handle_parent:
3288 if (klass->exception_type != MONO_EXCEPTION_NONE)
3289 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3291 iter = NULL;
3292 while ((field = mono_class_get_fields (klass, &iter))) {
3293 match = 0;
3294 if (mono_field_is_deleted (field))
3295 continue;
3296 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3297 if (bflags & BFLAGS_Public)
3298 match++;
3299 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3300 if (bflags & BFLAGS_NonPublic) {
3301 match++;
3304 if (!match)
3305 continue;
3306 match = 0;
3307 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3308 if (bflags & BFLAGS_Static)
3309 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3310 match++;
3311 } else {
3312 if (bflags & BFLAGS_Instance)
3313 match++;
3316 if (!match)
3317 continue;
3318 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3319 mono_ptr_array_append (tmp_array, member);
3321 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3322 goto handle_parent;
3324 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3326 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3327 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3329 mono_ptr_array_destroy (tmp_array);
3331 return res;
3334 static gboolean
3335 method_nonpublic (MonoMethod* method, gboolean start_klass)
3337 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3338 case METHOD_ATTRIBUTE_ASSEM:
3339 return (start_klass || mono_defaults.generic_ilist_class);
3340 case METHOD_ATTRIBUTE_PRIVATE:
3341 return start_klass;
3342 case METHOD_ATTRIBUTE_PUBLIC:
3343 return FALSE;
3344 default:
3345 return TRUE;
3349 static MonoArray*
3350 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3352 static MonoClass *MethodInfo_array;
3353 MonoDomain *domain;
3354 MonoClass *startklass, *klass, *refklass;
3355 MonoArray *res;
3356 MonoMethod *method;
3357 gpointer iter;
3358 MonoObject *member;
3359 int i, len, match, nslots;
3360 /*FIXME, use MonoBitSet*/
3361 guint32 method_slots_default [8];
3362 guint32 *method_slots = NULL;
3363 gchar *mname = NULL;
3364 int (*compare_func) (const char *s1, const char *s2) = NULL;
3365 MonoVTable *array_vtable;
3366 MonoException *ex;
3367 MonoPtrArray tmp_array;
3369 MONO_ARCH_SAVE_REGS;
3371 mono_ptr_array_init (tmp_array, 4);
3373 if (!MethodInfo_array) {
3374 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3375 mono_memory_barrier ();
3376 MethodInfo_array = klass;
3379 domain = ((MonoObject *)type)->vtable->domain;
3380 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3381 if (type->type->byref)
3382 return mono_array_new_specific (array_vtable, 0);
3383 klass = startklass = mono_class_from_mono_type (type->type);
3384 refklass = mono_class_from_mono_type (reftype->type);
3385 len = 0;
3386 if (name != NULL) {
3387 mname = mono_string_to_utf8 (name);
3388 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3391 /* An optimization for calls made from Delegate:CreateDelegate () */
3392 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3393 method = mono_get_delegate_invoke (klass);
3394 if (mono_loader_get_last_error ())
3395 goto loader_error;
3397 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3399 res = mono_array_new_specific (array_vtable, 1);
3400 mono_array_setref (res, 0, member);
3401 g_free (mname);
3402 return res;
3405 mono_class_setup_vtable (klass);
3406 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3407 goto loader_error;
3409 if (is_generic_parameter (type->type))
3410 nslots = mono_class_get_vtable_size (klass->parent);
3411 else
3412 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3413 if (nslots >= sizeof (method_slots_default) * 8) {
3414 method_slots = g_new0 (guint32, nslots / 32 + 1);
3415 } else {
3416 method_slots = method_slots_default;
3417 memset (method_slots, 0, sizeof (method_slots_default));
3419 handle_parent:
3420 mono_class_setup_vtable (klass);
3421 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3422 goto loader_error;
3424 iter = NULL;
3425 while ((method = mono_class_get_methods (klass, &iter))) {
3426 match = 0;
3427 if (method->slot != -1) {
3428 g_assert (method->slot < nslots);
3429 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3430 continue;
3431 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3432 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3435 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3436 continue;
3437 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3438 if (bflags & BFLAGS_Public)
3439 match++;
3440 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3441 match++;
3443 if (!match)
3444 continue;
3445 match = 0;
3446 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3447 if (bflags & BFLAGS_Static)
3448 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3449 match++;
3450 } else {
3451 if (bflags & BFLAGS_Instance)
3452 match++;
3455 if (!match)
3456 continue;
3458 if (name != NULL) {
3459 if (compare_func (mname, method->name))
3460 continue;
3463 match = 0;
3465 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3467 mono_ptr_array_append (tmp_array, member);
3469 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3470 goto handle_parent;
3472 g_free (mname);
3473 if (method_slots != method_slots_default)
3474 g_free (method_slots);
3476 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3478 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3479 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3481 mono_ptr_array_destroy (tmp_array);
3482 return res;
3484 loader_error:
3485 g_free (mname);
3486 if (method_slots != method_slots_default)
3487 g_free (method_slots);
3488 mono_ptr_array_destroy (tmp_array);
3489 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3490 ex = mono_class_get_exception_for_failure (klass);
3491 } else {
3492 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3493 mono_loader_clear_error ();
3495 mono_raise_exception (ex);
3496 return NULL;
3499 static MonoArray*
3500 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3502 MonoDomain *domain;
3503 static MonoClass *System_Reflection_ConstructorInfo;
3504 MonoClass *startklass, *klass, *refklass;
3505 MonoArray *res;
3506 MonoMethod *method;
3507 MonoObject *member;
3508 int i, match;
3509 gpointer iter = NULL;
3510 MonoPtrArray tmp_array;
3512 MONO_ARCH_SAVE_REGS;
3514 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3516 domain = ((MonoObject *)type)->vtable->domain;
3517 if (type->type->byref)
3518 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3519 klass = startklass = mono_class_from_mono_type (type->type);
3520 refklass = mono_class_from_mono_type (reftype->type);
3522 if (klass->exception_type != MONO_EXCEPTION_NONE)
3523 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3525 if (!System_Reflection_ConstructorInfo)
3526 System_Reflection_ConstructorInfo = mono_class_from_name (
3527 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3529 iter = NULL;
3530 while ((method = mono_class_get_methods (klass, &iter))) {
3531 match = 0;
3532 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3533 continue;
3534 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3535 if (bflags & BFLAGS_Public)
3536 match++;
3537 } else {
3538 if (bflags & BFLAGS_NonPublic)
3539 match++;
3541 if (!match)
3542 continue;
3543 match = 0;
3544 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3545 if (bflags & BFLAGS_Static)
3546 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3547 match++;
3548 } else {
3549 if (bflags & BFLAGS_Instance)
3550 match++;
3553 if (!match)
3554 continue;
3555 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3557 mono_ptr_array_append (tmp_array, member);
3560 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3562 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3563 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3565 mono_ptr_array_destroy (tmp_array);
3567 return res;
3570 static guint
3571 property_hash (gconstpointer data)
3573 MonoProperty *prop = (MonoProperty*)data;
3575 return g_str_hash (prop->name);
3578 static gboolean
3579 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3581 // Properties are hide-by-name-and-signature
3582 if (!g_str_equal (prop1->name, prop2->name))
3583 return FALSE;
3585 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3586 return FALSE;
3587 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3588 return FALSE;
3589 return TRUE;
3592 static gboolean
3593 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3595 if (!accessor)
3596 return FALSE;
3598 return method_nonpublic (accessor, start_klass);
3601 static MonoArray*
3602 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3604 MonoDomain *domain;
3605 static MonoClass *System_Reflection_PropertyInfo;
3606 MonoClass *startklass, *klass;
3607 MonoArray *res;
3608 MonoMethod *method;
3609 MonoProperty *prop;
3610 int i, match;
3611 guint32 flags;
3612 gchar *propname = NULL;
3613 int (*compare_func) (const char *s1, const char *s2) = NULL;
3614 gpointer iter;
3615 GHashTable *properties;
3616 MonoPtrArray tmp_array;
3618 MONO_ARCH_SAVE_REGS;
3620 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3622 if (!System_Reflection_PropertyInfo)
3623 System_Reflection_PropertyInfo = mono_class_from_name (
3624 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3626 domain = ((MonoObject *)type)->vtable->domain;
3627 if (type->type->byref)
3628 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3629 klass = startklass = mono_class_from_mono_type (type->type);
3630 if (name != NULL) {
3631 propname = mono_string_to_utf8 (name);
3632 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3635 mono_class_setup_vtable (klass);
3637 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3638 handle_parent:
3639 mono_class_setup_vtable (klass);
3640 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3641 g_hash_table_destroy (properties);
3642 if (name != NULL)
3643 g_free (propname);
3644 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3647 iter = NULL;
3648 while ((prop = mono_class_get_properties (klass, &iter))) {
3649 match = 0;
3650 method = prop->get;
3651 if (!method)
3652 method = prop->set;
3653 if (method)
3654 flags = method->flags;
3655 else
3656 flags = 0;
3657 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3658 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3659 if (bflags & BFLAGS_Public)
3660 match++;
3661 } else if (bflags & BFLAGS_NonPublic) {
3662 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3663 property_accessor_nonpublic(prop->set, startklass == klass)) {
3664 match++;
3667 if (!match)
3668 continue;
3669 match = 0;
3670 if (flags & METHOD_ATTRIBUTE_STATIC) {
3671 if (bflags & BFLAGS_Static)
3672 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3673 match++;
3674 } else {
3675 if (bflags & BFLAGS_Instance)
3676 match++;
3679 if (!match)
3680 continue;
3681 match = 0;
3683 if (name != NULL) {
3684 if (compare_func (propname, prop->name))
3685 continue;
3688 if (g_hash_table_lookup (properties, prop))
3689 continue;
3691 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3693 g_hash_table_insert (properties, prop, prop);
3695 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3696 goto handle_parent;
3698 g_hash_table_destroy (properties);
3699 g_free (propname);
3701 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3702 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3703 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3705 mono_ptr_array_destroy (tmp_array);
3707 return res;
3710 static MonoReflectionEvent *
3711 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3713 MonoDomain *domain;
3714 MonoClass *klass, *startklass;
3715 gpointer iter;
3716 MonoEvent *event;
3717 MonoMethod *method;
3718 gchar *event_name;
3720 MONO_ARCH_SAVE_REGS;
3722 event_name = mono_string_to_utf8 (name);
3723 if (type->type->byref)
3724 return NULL;
3725 klass = startklass = mono_class_from_mono_type (type->type);
3726 domain = mono_object_domain (type);
3728 handle_parent:
3729 if (klass->exception_type != MONO_EXCEPTION_NONE)
3730 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3732 iter = NULL;
3733 while ((event = mono_class_get_events (klass, &iter))) {
3734 if (strcmp (event->name, event_name))
3735 continue;
3737 method = event->add;
3738 if (!method)
3739 method = event->remove;
3740 if (!method)
3741 method = event->raise;
3742 if (method) {
3743 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3744 if (!(bflags & BFLAGS_Public))
3745 continue;
3746 } else {
3747 if (!(bflags & BFLAGS_NonPublic))
3748 continue;
3749 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3750 continue;
3753 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3754 if (!(bflags & BFLAGS_Static))
3755 continue;
3756 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3757 continue;
3758 } else {
3759 if (!(bflags & BFLAGS_Instance))
3760 continue;
3762 } else
3763 if (!(bflags & BFLAGS_NonPublic))
3764 continue;
3766 g_free (event_name);
3767 return mono_event_get_object (domain, startklass, event);
3770 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3771 goto handle_parent;
3773 g_free (event_name);
3774 return NULL;
3777 static MonoArray*
3778 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3780 MonoDomain *domain;
3781 static MonoClass *System_Reflection_EventInfo;
3782 MonoClass *startklass, *klass;
3783 MonoArray *res;
3784 MonoMethod *method;
3785 MonoEvent *event;
3786 int i, match;
3787 gpointer iter;
3789 MonoPtrArray tmp_array;
3791 MONO_ARCH_SAVE_REGS;
3793 mono_ptr_array_init (tmp_array, 4);
3795 if (!System_Reflection_EventInfo)
3796 System_Reflection_EventInfo = mono_class_from_name (
3797 mono_defaults.corlib, "System.Reflection", "EventInfo");
3799 domain = mono_object_domain (type);
3800 if (type->type->byref)
3801 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3802 klass = startklass = mono_class_from_mono_type (type->type);
3804 handle_parent:
3805 if (klass->exception_type != MONO_EXCEPTION_NONE)
3806 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3808 iter = NULL;
3809 while ((event = mono_class_get_events (klass, &iter))) {
3810 match = 0;
3811 method = event->add;
3812 if (!method)
3813 method = event->remove;
3814 if (!method)
3815 method = event->raise;
3816 if (method) {
3817 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3818 if (bflags & BFLAGS_Public)
3819 match++;
3820 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3821 if (bflags & BFLAGS_NonPublic)
3822 match++;
3825 else
3826 if (bflags & BFLAGS_NonPublic)
3827 match ++;
3828 if (!match)
3829 continue;
3830 match = 0;
3831 if (method) {
3832 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3833 if (bflags & BFLAGS_Static)
3834 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3835 match++;
3836 } else {
3837 if (bflags & BFLAGS_Instance)
3838 match++;
3841 else
3842 if (bflags & BFLAGS_Instance)
3843 match ++;
3844 if (!match)
3845 continue;
3846 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3848 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3849 goto handle_parent;
3851 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3853 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3854 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3856 mono_ptr_array_destroy (tmp_array);
3858 return res;
3861 static MonoReflectionType *
3862 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3864 MonoDomain *domain;
3865 MonoClass *klass;
3866 MonoClass *nested;
3867 char *str;
3868 gpointer iter;
3870 MONO_ARCH_SAVE_REGS;
3872 if (name == NULL)
3873 mono_raise_exception (mono_get_exception_argument_null ("name"));
3875 domain = ((MonoObject *)type)->vtable->domain;
3876 if (type->type->byref)
3877 return NULL;
3878 klass = mono_class_from_mono_type (type->type);
3879 str = mono_string_to_utf8 (name);
3881 handle_parent:
3882 if (klass->exception_type != MONO_EXCEPTION_NONE)
3883 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3886 * If a nested type is generic, return its generic type definition.
3887 * Note that this means that the return value is essentially a
3888 * nested type of the generic type definition of @klass.
3890 * A note in MSDN claims that a generic type definition can have
3891 * nested types that aren't generic. In any case, the container of that
3892 * nested type would be the generic type definition.
3894 if (klass->generic_class)
3895 klass = klass->generic_class->container_class;
3897 iter = NULL;
3898 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3899 int match = 0;
3900 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3901 if (bflags & BFLAGS_Public)
3902 match++;
3903 } else {
3904 if (bflags & BFLAGS_NonPublic)
3905 match++;
3907 if (!match)
3908 continue;
3909 if (strcmp (nested->name, str) == 0){
3910 g_free (str);
3911 return mono_type_get_object (domain, &nested->byval_arg);
3914 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3915 goto handle_parent;
3916 g_free (str);
3917 return NULL;
3920 static MonoArray*
3921 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
3923 MonoDomain *domain;
3924 MonoClass *klass;
3925 MonoArray *res;
3926 MonoObject *member;
3927 int i, match;
3928 MonoClass *nested;
3929 gpointer iter;
3930 MonoPtrArray tmp_array;
3932 MONO_ARCH_SAVE_REGS;
3934 domain = ((MonoObject *)type)->vtable->domain;
3935 if (type->type->byref)
3936 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3937 klass = mono_class_from_mono_type (type->type);
3938 if (klass->exception_type != MONO_EXCEPTION_NONE)
3939 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3942 * If a nested type is generic, return its generic type definition.
3943 * Note that this means that the return value is essentially the set
3944 * of nested types of the generic type definition of @klass.
3946 * A note in MSDN claims that a generic type definition can have
3947 * nested types that aren't generic. In any case, the container of that
3948 * nested type would be the generic type definition.
3950 if (klass->generic_class)
3951 klass = klass->generic_class->container_class;
3953 mono_ptr_array_init (tmp_array, 1);
3954 iter = NULL;
3955 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3956 match = 0;
3957 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3958 if (bflags & BFLAGS_Public)
3959 match++;
3960 } else {
3961 if (bflags & BFLAGS_NonPublic)
3962 match++;
3964 if (!match)
3965 continue;
3966 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
3967 mono_ptr_array_append (tmp_array, member);
3970 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
3972 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3973 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3975 mono_ptr_array_destroy (tmp_array);
3977 return res;
3980 static MonoReflectionType*
3981 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
3983 gchar *str;
3984 MonoType *type = NULL;
3985 MonoTypeNameParse info;
3986 gboolean type_resolve;
3988 MONO_ARCH_SAVE_REGS;
3990 /* On MS.NET, this does not fire a TypeResolve event */
3991 type_resolve = TRUE;
3992 str = mono_string_to_utf8 (name);
3993 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
3994 if (!mono_reflection_parse_type (str, &info)) {
3995 g_free (str);
3996 mono_reflection_free_type_info (&info);
3997 if (throwOnError) /* uhm: this is a parse error, though... */
3998 mono_raise_exception (mono_get_exception_type_load (name, NULL));
3999 /*g_print ("failed parse\n");*/
4000 return NULL;
4003 if (info.assembly.name) {
4004 g_free (str);
4005 mono_reflection_free_type_info (&info);
4006 if (throwOnError) {
4007 /* 1.0 and 2.0 throw different exceptions */
4008 if (mono_defaults.generic_ilist_class)
4009 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4010 else
4011 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4013 return NULL;
4016 if (module != NULL) {
4017 if (module->image)
4018 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4019 else
4020 type = NULL;
4022 else
4023 if (assembly->assembly->dynamic) {
4024 /* Enumerate all modules */
4025 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4026 int i;
4028 type = NULL;
4029 if (abuilder->modules) {
4030 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4031 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4032 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4033 if (type)
4034 break;
4038 if (!type && abuilder->loaded_modules) {
4039 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4040 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4041 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4042 if (type)
4043 break;
4047 else
4048 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4049 g_free (str);
4050 mono_reflection_free_type_info (&info);
4051 if (!type) {
4052 MonoException *e = NULL;
4054 if (throwOnError)
4055 e = mono_get_exception_type_load (name, NULL);
4057 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4058 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4060 mono_loader_clear_error ();
4062 if (e != NULL)
4063 mono_raise_exception (e);
4065 return NULL;
4068 if (type->type == MONO_TYPE_CLASS) {
4069 MonoClass *klass = mono_type_get_class (type);
4071 if (mono_is_security_manager_active () && !klass->exception_type)
4072 /* Some security problems are detected during generic vtable construction */
4073 mono_class_setup_vtable (klass);
4074 /* need to report exceptions ? */
4075 if (throwOnError && klass->exception_type) {
4076 /* report SecurityException (or others) that occured when loading the assembly */
4077 MonoException *exc = mono_class_get_exception_for_failure (klass);
4078 mono_loader_clear_error ();
4079 mono_raise_exception (exc);
4080 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4081 return NULL;
4085 /* g_print ("got it\n"); */
4086 return mono_type_get_object (mono_object_domain (assembly), type);
4089 static gboolean
4090 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4092 gchar *content;
4093 gchar *shadow_ini_file;
4094 gsize len;
4096 /* Check for shadow-copied assembly */
4097 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4098 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4099 content = NULL;
4100 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4101 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4102 if (content) {
4103 g_free (content);
4104 content = NULL;
4107 g_free (shadow_ini_file);
4108 if (content != NULL) {
4109 if (*filename)
4110 g_free (*filename);
4111 *filename = content;
4112 return TRUE;
4115 return FALSE;
4118 static MonoString *
4119 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4121 MonoDomain *domain = mono_object_domain (assembly);
4122 MonoAssembly *mass = assembly->assembly;
4123 MonoString *res = NULL;
4124 gchar *uri;
4125 gchar *absolute;
4126 gchar *dirname;
4128 MONO_ARCH_SAVE_REGS;
4130 if (g_path_is_absolute (mass->image->name)) {
4131 absolute = g_strdup (mass->image->name);
4132 dirname = g_path_get_dirname (absolute);
4133 } else {
4134 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4135 dirname = g_strdup (mass->basedir);
4138 replace_shadow_path (domain, dirname, &absolute);
4139 g_free (dirname);
4140 #if HOST_WIN32
4142 gint i;
4143 for (i = strlen (absolute) - 1; i >= 0; i--)
4144 if (absolute [i] == '\\')
4145 absolute [i] = '/';
4147 #endif
4148 if (escaped) {
4149 uri = g_filename_to_uri (absolute, NULL, NULL);
4150 } else {
4151 const char *prepend = "file://";
4152 #if HOST_WIN32
4153 if (*absolute == '/' && *(absolute + 1) == '/') {
4154 prepend = "file:";
4155 } else {
4156 prepend = "file:///";
4158 #endif
4159 uri = g_strconcat (prepend, absolute, NULL);
4162 if (uri) {
4163 res = mono_string_new (domain, uri);
4164 g_free (uri);
4166 g_free (absolute);
4167 return res;
4170 static MonoBoolean
4171 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4173 MonoAssembly *mass = assembly->assembly;
4175 MONO_ARCH_SAVE_REGS;
4177 return mass->in_gac;
4180 static MonoReflectionAssembly*
4181 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4183 gchar *name;
4184 MonoAssembly *res;
4185 MonoImageOpenStatus status;
4187 MONO_ARCH_SAVE_REGS;
4189 name = mono_string_to_utf8 (mname);
4190 res = mono_assembly_load_with_partial_name (name, &status);
4192 g_free (name);
4194 if (res == NULL)
4195 return NULL;
4196 return mono_assembly_get_object (mono_domain_get (), res);
4199 static MonoString *
4200 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4202 MonoDomain *domain = mono_object_domain (assembly);
4203 MonoString *res;
4205 MONO_ARCH_SAVE_REGS;
4207 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4209 return res;
4212 static MonoBoolean
4213 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4215 MONO_ARCH_SAVE_REGS;
4217 return assembly->assembly->ref_only;
4220 static MonoString *
4221 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4223 MonoDomain *domain = mono_object_domain (assembly);
4225 MONO_ARCH_SAVE_REGS;
4227 return mono_string_new (domain, assembly->assembly->image->version);
4230 static MonoReflectionMethod*
4231 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4233 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4235 MONO_ARCH_SAVE_REGS;
4237 if (!token)
4238 return NULL;
4239 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4242 static MonoReflectionModule*
4243 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4245 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4248 static MonoArray*
4249 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4251 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4252 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4253 int i;
4254 const char *val;
4256 MONO_ARCH_SAVE_REGS;
4258 for (i = 0; i < table->rows; ++i) {
4259 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4260 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4262 return result;
4265 static MonoObject*
4266 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4268 static MonoClass *System_Version = NULL;
4269 static MonoMethod *create_version = NULL;
4270 MonoObject *result;
4271 gpointer args [4];
4273 if (!System_Version) {
4274 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4275 g_assert (System_Version);
4278 if (!create_version) {
4279 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4280 create_version = mono_method_desc_search_in_class (desc, System_Version);
4281 g_assert (create_version);
4282 mono_method_desc_free (desc);
4285 args [0] = &major;
4286 args [1] = &minor;
4287 args [2] = &build;
4288 args [3] = &revision;
4289 result = mono_object_new (domain, System_Version);
4290 mono_runtime_invoke (create_version, result, args, NULL);
4292 return result;
4295 static MonoArray*
4296 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4298 static MonoClass *System_Reflection_AssemblyName;
4299 MonoArray *result;
4300 MonoDomain *domain = mono_object_domain (assembly);
4301 int i, count = 0;
4302 static MonoMethod *create_culture = NULL;
4303 MonoImage *image = assembly->assembly->image;
4304 MonoTableInfo *t;
4306 MONO_ARCH_SAVE_REGS;
4308 if (!System_Reflection_AssemblyName)
4309 System_Reflection_AssemblyName = mono_class_from_name (
4310 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4312 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4313 count = t->rows;
4315 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4317 if (count > 0 && !create_culture) {
4318 MonoMethodDesc *desc = mono_method_desc_new (
4319 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4320 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4321 g_assert (create_culture);
4322 mono_method_desc_free (desc);
4325 for (i = 0; i < count; i++) {
4326 MonoReflectionAssemblyName *aname;
4327 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4329 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4331 aname = (MonoReflectionAssemblyName *) mono_object_new (
4332 domain, System_Reflection_AssemblyName);
4334 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4336 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4337 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4338 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4339 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4340 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4341 aname->versioncompat = 1; /* SameMachine (default) */
4342 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4343 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4345 if (create_culture) {
4346 gpointer args [2];
4347 MonoBoolean assembly_ref = 1;
4348 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4349 args [1] = &assembly_ref;
4350 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4353 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4354 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4355 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4357 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4358 /* public key token isn't copied - the class library will
4359 automatically generate it from the public key if required */
4360 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4361 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4362 } else {
4363 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4364 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4366 } else {
4367 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4370 /* note: this function doesn't return the codebase on purpose (i.e. it can
4371 be used under partial trust as path information isn't present). */
4373 mono_array_setref (result, i, aname);
4375 return result;
4378 typedef struct {
4379 MonoArray *res;
4380 int idx;
4381 } NameSpaceInfo;
4383 static void
4384 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4386 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4388 mono_array_setref (info->res, info->idx, name);
4389 info->idx++;
4392 static MonoArray*
4393 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4395 MonoImage *img = assembly->assembly->image;
4396 MonoArray *res;
4397 NameSpaceInfo info;
4398 int len;
4400 MONO_ARCH_SAVE_REGS;
4402 mono_image_lock (img);
4403 mono_image_init_name_cache (img);
4405 RETRY_LEN:
4406 len = g_hash_table_size (img->name_cache);
4407 mono_image_unlock (img);
4409 /*we can't create objects holding the image lock */
4410 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4412 mono_image_lock (img);
4413 /*len might have changed, create a new array*/
4414 if (len != g_hash_table_size (img->name_cache))
4415 goto RETRY_LEN;
4417 info.res = res;
4418 info.idx = 0;
4419 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4420 mono_image_unlock (img);
4422 return res;
4425 /* move this in some file in mono/util/ */
4426 static char *
4427 g_concat_dir_and_file (const char *dir, const char *file)
4429 g_return_val_if_fail (dir != NULL, NULL);
4430 g_return_val_if_fail (file != NULL, NULL);
4433 * If the directory name doesn't have a / on the end, we need
4434 * to add one so we get a proper path to the file
4436 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4437 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4438 else
4439 return g_strconcat (dir, file, NULL);
4442 static void *
4443 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4445 char *n = mono_string_to_utf8 (name);
4446 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4447 guint32 i;
4448 guint32 cols [MONO_MANIFEST_SIZE];
4449 guint32 impl, file_idx;
4450 const char *val;
4451 MonoImage *module;
4453 MONO_ARCH_SAVE_REGS;
4455 for (i = 0; i < table->rows; ++i) {
4456 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4457 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4458 if (strcmp (val, n) == 0)
4459 break;
4461 g_free (n);
4462 if (i == table->rows)
4463 return NULL;
4464 /* FIXME */
4465 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4466 if (impl) {
4468 * this code should only be called after obtaining the
4469 * ResourceInfo and handling the other cases.
4471 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4472 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4474 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4475 if (!module)
4476 return NULL;
4478 else
4479 module = assembly->assembly->image;
4481 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4483 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4486 static gboolean
4487 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4489 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4490 int i;
4491 guint32 cols [MONO_MANIFEST_SIZE];
4492 guint32 file_cols [MONO_FILE_SIZE];
4493 const char *val;
4494 char *n;
4496 MONO_ARCH_SAVE_REGS;
4498 n = mono_string_to_utf8 (name);
4499 for (i = 0; i < table->rows; ++i) {
4500 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4501 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4502 if (strcmp (val, n) == 0)
4503 break;
4505 g_free (n);
4506 if (i == table->rows)
4507 return FALSE;
4509 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4510 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4512 else {
4513 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4514 case MONO_IMPLEMENTATION_FILE:
4515 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4516 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4517 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4518 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4519 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4520 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4521 info->location = 0;
4522 else
4523 info->location = RESOURCE_LOCATION_EMBEDDED;
4524 break;
4526 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4527 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4528 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4529 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4530 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4531 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4532 g_free (msg);
4533 mono_raise_exception (ex);
4535 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4537 /* Obtain info recursively */
4538 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4539 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4540 break;
4542 case MONO_IMPLEMENTATION_EXP_TYPE:
4543 g_assert_not_reached ();
4544 break;
4548 return TRUE;
4551 static MonoObject*
4552 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4554 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4555 MonoArray *result = NULL;
4556 int i, count;
4557 const char *val;
4558 char *n;
4560 MONO_ARCH_SAVE_REGS;
4562 /* check hash if needed */
4563 if (name) {
4564 n = mono_string_to_utf8 (name);
4565 for (i = 0; i < table->rows; ++i) {
4566 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4567 if (strcmp (val, n) == 0) {
4568 MonoString *fn;
4569 g_free (n);
4570 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4571 fn = mono_string_new (mono_object_domain (assembly), n);
4572 g_free (n);
4573 return (MonoObject*)fn;
4576 g_free (n);
4577 return NULL;
4580 count = 0;
4581 for (i = 0; i < table->rows; ++i) {
4582 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4583 count ++;
4586 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4588 count = 0;
4589 for (i = 0; i < table->rows; ++i) {
4590 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4591 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4592 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4593 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4594 g_free (n);
4595 count ++;
4598 return (MonoObject*)result;
4601 static MonoArray*
4602 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4604 MonoDomain *domain = mono_domain_get();
4605 MonoArray *res;
4606 MonoClass *klass;
4607 int i, j, file_count = 0;
4608 MonoImage **modules;
4609 guint32 module_count, real_module_count;
4610 MonoTableInfo *table;
4611 guint32 cols [MONO_FILE_SIZE];
4612 MonoImage *image = assembly->assembly->image;
4614 g_assert (image != NULL);
4615 g_assert (!assembly->assembly->dynamic);
4617 table = &image->tables [MONO_TABLE_FILE];
4618 file_count = table->rows;
4620 modules = image->modules;
4621 module_count = image->module_count;
4623 real_module_count = 0;
4624 for (i = 0; i < module_count; ++i)
4625 if (modules [i])
4626 real_module_count ++;
4628 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4629 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4631 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4632 j = 1;
4633 for (i = 0; i < module_count; ++i)
4634 if (modules [i]) {
4635 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4636 ++j;
4639 for (i = 0; i < file_count; ++i, ++j) {
4640 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4641 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4642 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4643 else {
4644 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4645 if (!m) {
4646 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4647 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4649 mono_array_setref (res, j, mono_module_get_object (domain, m));
4653 return res;
4656 static MonoReflectionMethod*
4657 ves_icall_GetCurrentMethod (void)
4659 MonoMethod *m = mono_method_get_last_managed ();
4661 while (m->is_inflated)
4662 m = ((MonoMethodInflated*)m)->declaring;
4664 return mono_method_get_object (mono_domain_get (), m, NULL);
4668 static MonoMethod*
4669 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4671 int offset = -1, i;
4672 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4673 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4674 //method is inflated, we should inflate it on the other class
4675 MonoGenericContext ctx;
4676 ctx.method_inst = inflated->context.method_inst;
4677 ctx.class_inst = inflated->context.class_inst;
4678 if (klass->generic_class)
4679 ctx.class_inst = klass->generic_class->context.class_inst;
4680 else if (klass->generic_container)
4681 ctx.class_inst = klass->generic_container->context.class_inst;
4682 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4685 mono_class_setup_methods (method->klass);
4686 if (method->klass->exception_type)
4687 return NULL;
4688 for (i = 0; i < method->klass->method.count; ++i) {
4689 if (method->klass->methods [i] == method) {
4690 offset = i;
4691 break;
4694 mono_class_setup_methods (klass);
4695 if (klass->exception_type)
4696 return NULL;
4697 g_assert (offset >= 0 && offset < klass->method.count);
4698 return klass->methods [offset];
4701 static MonoReflectionMethod*
4702 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4704 MonoClass *klass;
4705 if (type) {
4706 klass = mono_class_from_mono_type (type);
4707 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4708 return NULL;
4709 if (method->klass != klass) {
4710 method = mono_method_get_equivalent_method (method, klass);
4711 if (!method)
4712 return NULL;
4714 } else
4715 klass = method->klass;
4716 return mono_method_get_object (mono_domain_get (), method, klass);
4719 static MonoReflectionMethod*
4720 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4722 return mono_method_get_object (mono_domain_get (), method, NULL);
4725 static MonoReflectionMethodBody*
4726 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4728 return mono_method_body_get_object (mono_domain_get (), method);
4731 static MonoReflectionAssembly*
4732 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4734 MonoMethod *dest = NULL;
4736 MONO_ARCH_SAVE_REGS;
4738 mono_stack_walk_no_il (get_executing, &dest);
4739 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4743 static MonoReflectionAssembly*
4744 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4746 MonoDomain* domain = mono_domain_get ();
4748 MONO_ARCH_SAVE_REGS;
4750 if (!domain->entry_assembly)
4751 return NULL;
4753 return mono_assembly_get_object (domain, domain->entry_assembly);
4756 static MonoReflectionAssembly*
4757 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4759 MonoMethod *m;
4760 MonoMethod *dest;
4762 MONO_ARCH_SAVE_REGS;
4764 dest = NULL;
4765 mono_stack_walk_no_il (get_executing, &dest);
4766 m = dest;
4767 mono_stack_walk_no_il (get_caller, &dest);
4768 if (!dest)
4769 dest = m;
4770 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4773 static MonoString *
4774 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4775 gboolean assembly_qualified)
4777 MonoDomain *domain = mono_object_domain (object);
4778 MonoTypeNameFormat format;
4779 MonoString *res;
4780 gchar *name;
4782 MONO_ARCH_SAVE_REGS;
4783 if (full_name)
4784 format = assembly_qualified ?
4785 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4786 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4787 else
4788 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4790 name = mono_type_get_name_full (object->type, format);
4791 if (!name)
4792 return NULL;
4794 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4795 g_free (name);
4796 return NULL;
4799 res = mono_string_new (domain, name);
4800 g_free (name);
4802 return res;
4805 static int
4806 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4808 MonoClass *klass = mono_class_from_mono_type (this->type);
4809 return mono_security_core_clr_class_level (klass);
4812 static void
4813 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4815 static MonoMethod *create_culture = NULL;
4816 gpointer args [2];
4817 guint32 pkey_len;
4818 const char *pkey_ptr;
4819 gchar *codebase;
4820 MonoBoolean assembly_ref = 0;
4822 MONO_ARCH_SAVE_REGS;
4824 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4825 aname->major = name->major;
4826 aname->minor = name->minor;
4827 aname->build = name->build;
4828 aname->flags = name->flags;
4829 aname->revision = name->revision;
4830 aname->hashalg = name->hash_alg;
4831 aname->versioncompat = 1; /* SameMachine (default) */
4833 if (by_default_version)
4834 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4836 codebase = NULL;
4837 if (absolute != NULL && *absolute != '\0') {
4838 const gchar *prepend = "file://";
4839 gchar *result;
4841 codebase = g_strdup (absolute);
4843 #if HOST_WIN32
4845 gint i;
4846 for (i = strlen (codebase) - 1; i >= 0; i--)
4847 if (codebase [i] == '\\')
4848 codebase [i] = '/';
4850 if (*codebase == '/' && *(codebase + 1) == '/') {
4851 prepend = "file:";
4852 } else {
4853 prepend = "file:///";
4856 #endif
4857 result = g_strconcat (prepend, codebase, NULL);
4858 g_free (codebase);
4859 codebase = result;
4862 if (codebase) {
4863 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4864 g_free (codebase);
4867 if (!create_culture) {
4868 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4869 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4870 g_assert (create_culture);
4871 mono_method_desc_free (desc);
4874 if (name->culture) {
4875 args [0] = mono_string_new (domain, name->culture);
4876 args [1] = &assembly_ref;
4877 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4880 if (name->public_key) {
4881 pkey_ptr = (char*)name->public_key;
4882 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4884 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4885 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4886 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4887 } else if (default_publickey) {
4888 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4889 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4892 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4893 if (name->public_key_token [0]) {
4894 int i, j;
4895 char *p;
4897 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4898 p = mono_array_addr (aname->keyToken, char, 0);
4900 for (i = 0, j = 0; i < 8; i++) {
4901 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4902 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4903 p++;
4905 } else if (default_token) {
4906 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4910 static MonoString *
4911 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4913 MonoDomain *domain = mono_object_domain (assembly);
4914 MonoAssembly *mass = assembly->assembly;
4915 MonoString *res;
4916 gchar *name;
4918 name = g_strdup_printf (
4919 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
4920 mass->aname.name,
4921 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
4922 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
4923 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
4924 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
4926 res = mono_string_new (domain, name);
4927 g_free (name);
4929 return res;
4932 static void
4933 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4935 gchar *absolute;
4936 MonoAssembly *mass = assembly->assembly;
4938 MONO_ARCH_SAVE_REGS;
4940 if (g_path_is_absolute (mass->image->name)) {
4941 fill_reflection_assembly_name (mono_object_domain (assembly),
4942 aname, &mass->aname, mass->image->name, TRUE,
4943 TRUE, TRUE);
4944 return;
4946 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4948 fill_reflection_assembly_name (mono_object_domain (assembly),
4949 aname, &mass->aname, absolute, TRUE, TRUE,
4950 TRUE);
4952 g_free (absolute);
4955 static void
4956 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4958 char *filename;
4959 MonoImageOpenStatus status = MONO_IMAGE_OK;
4960 gboolean res;
4961 MonoImage *image;
4962 MonoAssemblyName name;
4963 char *dirname
4965 MONO_ARCH_SAVE_REGS;
4967 filename = mono_string_to_utf8 (fname);
4969 dirname = g_path_get_dirname (filename);
4970 replace_shadow_path (mono_domain_get (), dirname, &filename);
4971 g_free (dirname);
4973 image = mono_image_open (filename, &status);
4975 if (!image){
4976 MonoException *exc;
4978 g_free (filename);
4979 if (status == MONO_IMAGE_IMAGE_INVALID)
4980 exc = mono_get_exception_bad_image_format2 (NULL, fname);
4981 else
4982 exc = mono_get_exception_file_not_found2 (NULL, fname);
4983 mono_raise_exception (exc);
4986 res = mono_assembly_fill_assembly_name (image, &name);
4987 if (!res) {
4988 mono_image_close (image);
4989 g_free (filename);
4990 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4993 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
4994 TRUE, FALSE, TRUE);
4996 g_free (filename);
4997 mono_image_close (image);
5000 static MonoBoolean
5001 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5002 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5004 MonoBoolean result = FALSE;
5005 MonoDeclSecurityEntry entry;
5007 /* SecurityAction.RequestMinimum */
5008 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5009 *minimum = entry.blob;
5010 *minLength = entry.size;
5011 result = TRUE;
5013 /* SecurityAction.RequestOptional */
5014 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5015 *optional = entry.blob;
5016 *optLength = entry.size;
5017 result = TRUE;
5019 /* SecurityAction.RequestRefuse */
5020 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5021 *refused = entry.blob;
5022 *refLength = entry.size;
5023 result = TRUE;
5026 return result;
5029 static MonoArray*
5030 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5032 MonoArray *res;
5033 MonoClass *klass;
5034 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5035 int i, count;
5036 guint32 attrs, visibility;
5038 /* we start the count from 1 because we skip the special type <Module> */
5039 if (exportedOnly) {
5040 count = 0;
5041 for (i = 1; i < tdef->rows; ++i) {
5042 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5043 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5044 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5045 count++;
5047 } else {
5048 count = tdef->rows - 1;
5050 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5051 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5052 count = 0;
5053 for (i = 1; i < tdef->rows; ++i) {
5054 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5055 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5056 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5057 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5058 if (klass) {
5059 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5060 } else {
5061 MonoLoaderError *error;
5062 MonoException *ex;
5064 error = mono_loader_get_last_error ();
5065 g_assert (error != NULL);
5067 ex = mono_loader_error_prepare_exception (error);
5068 mono_array_setref (*exceptions, count, ex);
5070 if (mono_loader_get_last_error ())
5071 mono_loader_clear_error ();
5072 count++;
5076 return res;
5079 static MonoArray*
5080 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5082 MonoArray *res = NULL;
5083 MonoArray *exceptions = NULL;
5084 MonoImage *image = NULL;
5085 MonoTableInfo *table = NULL;
5086 MonoDomain *domain;
5087 GList *list = NULL;
5088 int i, len, ex_count;
5090 MONO_ARCH_SAVE_REGS;
5092 domain = mono_object_domain (assembly);
5094 g_assert (!assembly->assembly->dynamic);
5095 image = assembly->assembly->image;
5096 table = &image->tables [MONO_TABLE_FILE];
5097 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5099 /* Append data from all modules in the assembly */
5100 for (i = 0; i < table->rows; ++i) {
5101 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5102 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5103 if (loaded_image) {
5104 MonoArray *ex2;
5105 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5106 /* Append the new types to the end of the array */
5107 if (mono_array_length (res2) > 0) {
5108 guint32 len1, len2;
5109 MonoArray *res3, *ex3;
5111 len1 = mono_array_length (res);
5112 len2 = mono_array_length (res2);
5114 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5115 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5116 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5117 res = res3;
5119 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5120 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5121 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5122 exceptions = ex3;
5128 /* the ReflectionTypeLoadException must have all the types (Types property),
5129 * NULL replacing types which throws an exception. The LoaderException must
5130 * contain all exceptions for NULL items.
5133 len = mono_array_length (res);
5135 ex_count = 0;
5136 for (i = 0; i < len; i++) {
5137 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5138 MonoClass *klass;
5140 if (t) {
5141 klass = mono_type_get_class (t->type);
5142 if ((klass != NULL) && klass->exception_type) {
5143 /* keep the class in the list */
5144 list = g_list_append (list, klass);
5145 /* and replace Type with NULL */
5146 mono_array_setref (res, i, NULL);
5148 } else {
5149 ex_count ++;
5153 if (list || ex_count) {
5154 GList *tmp = NULL;
5155 MonoException *exc = NULL;
5156 MonoArray *exl = NULL;
5157 int j, length = g_list_length (list) + ex_count;
5159 mono_loader_clear_error ();
5161 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5162 /* Types for which mono_class_get () succeeded */
5163 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5164 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5165 mono_array_setref (exl, i, exc);
5167 /* Types for which it don't */
5168 for (j = 0; j < mono_array_length (exceptions); ++j) {
5169 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5170 if (exc) {
5171 g_assert (i < length);
5172 mono_array_setref (exl, i, exc);
5173 i ++;
5176 g_list_free (list);
5177 list = NULL;
5179 exc = mono_get_exception_reflection_type_load (res, exl);
5180 mono_loader_clear_error ();
5181 mono_raise_exception (exc);
5184 return res;
5187 static gboolean
5188 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5190 MonoAssemblyName aname;
5191 MonoDomain *domain = mono_object_domain (name);
5192 char *val;
5193 gboolean is_version_defined;
5194 gboolean is_token_defined;
5196 aname.public_key = NULL;
5197 val = mono_string_to_utf8 (assname);
5198 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5199 g_free ((guint8*) aname.public_key);
5200 g_free (val);
5201 return FALSE;
5204 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5205 FALSE, is_token_defined);
5207 mono_assembly_name_free (&aname);
5208 g_free ((guint8*) aname.public_key);
5209 g_free (val);
5211 return TRUE;
5214 static MonoReflectionType*
5215 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5217 MonoDomain *domain = mono_object_domain (module);
5218 MonoClass *klass;
5220 MONO_ARCH_SAVE_REGS;
5222 g_assert (module->image);
5224 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5225 /* These images do not have a global type */
5226 return NULL;
5228 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5229 return mono_type_get_object (domain, &klass->byval_arg);
5232 static void
5233 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5235 /*if (module->image)
5236 mono_image_close (module->image);*/
5239 static MonoString*
5240 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5242 MonoDomain *domain = mono_object_domain (module);
5244 MONO_ARCH_SAVE_REGS;
5246 g_assert (module->image);
5247 return mono_string_new (domain, module->image->guid);
5250 static gpointer
5251 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5253 #ifdef HOST_WIN32
5254 if (module->image && module->image->is_module_handle)
5255 return module->image->raw_data;
5256 #endif
5258 return (gpointer) (-1);
5261 static void
5262 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5264 if (image->dynamic) {
5265 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5266 *pe_kind = dyn->pe_kind;
5267 *machine = dyn->machine;
5269 else {
5270 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5271 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5275 static gint32
5276 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5278 return (image->md_version_major << 16) | (image->md_version_minor);
5281 static MonoArray*
5282 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5284 MonoArray *exceptions;
5285 int i;
5287 MONO_ARCH_SAVE_REGS;
5289 if (!module->image)
5290 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5291 else {
5292 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5293 for (i = 0; i < mono_array_length (exceptions); ++i) {
5294 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5295 if (ex)
5296 mono_raise_exception (ex);
5298 return res;
5302 static gboolean
5303 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5305 guint32 cols [MONO_MEMBERREF_SIZE];
5306 const char *sig;
5307 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5308 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5309 mono_metadata_decode_blob_size (sig, &sig);
5310 return (*sig != 0x6);
5313 static void
5314 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5316 if (type_args)
5317 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5318 mono_array_addr (type_args, MonoType*, 0));
5319 else
5320 context->class_inst = NULL;
5321 if (method_args)
5322 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5323 mono_array_addr (method_args, MonoType*, 0));
5324 else
5325 context->method_inst = NULL;
5328 static MonoType*
5329 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5331 MonoClass *klass;
5332 int table = mono_metadata_token_table (token);
5333 int index = mono_metadata_token_index (token);
5334 MonoGenericContext context;
5336 *error = ResolveTokenError_Other;
5338 /* Validate token */
5339 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5340 (table != MONO_TABLE_TYPESPEC)) {
5341 *error = ResolveTokenError_BadTable;
5342 return NULL;
5345 if (image->dynamic) {
5346 if (type_args || method_args)
5347 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5348 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5349 if (!klass)
5350 return NULL;
5351 return &klass->byval_arg;
5354 if ((index <= 0) || (index > image->tables [table].rows)) {
5355 *error = ResolveTokenError_OutOfRange;
5356 return NULL;
5359 init_generic_context_from_args (&context, type_args, method_args);
5360 klass = mono_class_get_full (image, token, &context);
5362 if (mono_loader_get_last_error ())
5363 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5365 if (klass)
5366 return &klass->byval_arg;
5367 else
5368 return NULL;
5371 static MonoMethod*
5372 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5374 int table = mono_metadata_token_table (token);
5375 int index = mono_metadata_token_index (token);
5376 MonoGenericContext context;
5377 MonoMethod *method;
5379 *error = ResolveTokenError_Other;
5381 /* Validate token */
5382 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5383 (table != MONO_TABLE_MEMBERREF)) {
5384 *error = ResolveTokenError_BadTable;
5385 return NULL;
5388 if (image->dynamic) {
5389 if (type_args || method_args)
5390 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5391 /* FIXME: validate memberref token type */
5392 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5395 if ((index <= 0) || (index > image->tables [table].rows)) {
5396 *error = ResolveTokenError_OutOfRange;
5397 return NULL;
5399 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5400 *error = ResolveTokenError_BadTable;
5401 return NULL;
5404 init_generic_context_from_args (&context, type_args, method_args);
5405 method = mono_get_method_full (image, token, NULL, &context);
5407 if (mono_loader_get_last_error ())
5408 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5410 return method;
5413 static MonoString*
5414 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5416 int index = mono_metadata_token_index (token);
5418 *error = ResolveTokenError_Other;
5420 /* Validate token */
5421 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5422 *error = ResolveTokenError_BadTable;
5423 return NULL;
5426 if (image->dynamic)
5427 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5429 if ((index <= 0) || (index >= image->heap_us.size)) {
5430 *error = ResolveTokenError_OutOfRange;
5431 return NULL;
5434 /* FIXME: What to do if the index points into the middle of a string ? */
5436 return mono_ldstr (mono_domain_get (), image, index);
5439 static MonoClassField*
5440 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5442 MonoClass *klass;
5443 int table = mono_metadata_token_table (token);
5444 int index = mono_metadata_token_index (token);
5445 MonoGenericContext context;
5446 MonoClassField *field;
5448 *error = ResolveTokenError_Other;
5450 /* Validate token */
5451 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5452 *error = ResolveTokenError_BadTable;
5453 return NULL;
5456 if (image->dynamic) {
5457 if (type_args || method_args)
5458 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5459 /* FIXME: validate memberref token type */
5460 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5463 if ((index <= 0) || (index > image->tables [table].rows)) {
5464 *error = ResolveTokenError_OutOfRange;
5465 return NULL;
5467 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5468 *error = ResolveTokenError_BadTable;
5469 return NULL;
5472 init_generic_context_from_args (&context, type_args, method_args);
5473 field = mono_field_from_token (image, token, &klass, &context);
5475 if (mono_loader_get_last_error ())
5476 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5478 return field;
5482 static MonoObject*
5483 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5485 int table = mono_metadata_token_table (token);
5487 *error = ResolveTokenError_Other;
5489 switch (table) {
5490 case MONO_TABLE_TYPEDEF:
5491 case MONO_TABLE_TYPEREF:
5492 case MONO_TABLE_TYPESPEC: {
5493 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5494 if (t)
5495 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5496 else
5497 return NULL;
5499 case MONO_TABLE_METHOD:
5500 case MONO_TABLE_METHODSPEC: {
5501 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5502 if (m)
5503 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5504 else
5505 return NULL;
5507 case MONO_TABLE_FIELD: {
5508 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5509 if (f)
5510 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5511 else
5512 return NULL;
5514 case MONO_TABLE_MEMBERREF:
5515 if (mono_metadata_memberref_is_method (image, token)) {
5516 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5517 if (m)
5518 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5519 else
5520 return NULL;
5522 else {
5523 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5524 if (f)
5525 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5526 else
5527 return NULL;
5529 break;
5531 default:
5532 *error = ResolveTokenError_BadTable;
5535 return NULL;
5538 static MonoArray*
5539 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5541 int table = mono_metadata_token_table (token);
5542 int idx = mono_metadata_token_index (token);
5543 MonoTableInfo *tables = image->tables;
5544 guint32 sig, len;
5545 const char *ptr;
5546 MonoArray *res;
5548 *error = ResolveTokenError_OutOfRange;
5550 /* FIXME: Support other tables ? */
5551 if (table != MONO_TABLE_STANDALONESIG)
5552 return NULL;
5554 if (image->dynamic)
5555 return NULL;
5557 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5558 return NULL;
5560 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5562 ptr = mono_metadata_blob_heap (image, sig);
5563 len = mono_metadata_decode_blob_size (ptr, &ptr);
5565 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5566 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5567 return res;
5570 static MonoReflectionType*
5571 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5573 MonoClass *klass;
5574 int isbyref = 0, rank;
5575 char *str = mono_string_to_utf8 (smodifiers);
5576 char *p;
5578 MONO_ARCH_SAVE_REGS;
5580 klass = mono_class_from_mono_type (tb->type.type);
5581 p = str;
5582 /* logic taken from mono_reflection_parse_type(): keep in sync */
5583 while (*p) {
5584 switch (*p) {
5585 case '&':
5586 if (isbyref) { /* only one level allowed by the spec */
5587 g_free (str);
5588 return NULL;
5590 isbyref = 1;
5591 p++;
5592 g_free (str);
5593 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5594 break;
5595 case '*':
5596 klass = mono_ptr_class_get (&klass->byval_arg);
5597 mono_class_init (klass);
5598 p++;
5599 break;
5600 case '[':
5601 rank = 1;
5602 p++;
5603 while (*p) {
5604 if (*p == ']')
5605 break;
5606 if (*p == ',')
5607 rank++;
5608 else if (*p != '*') { /* '*' means unknown lower bound */
5609 g_free (str);
5610 return NULL;
5612 ++p;
5614 if (*p != ']') {
5615 g_free (str);
5616 return NULL;
5618 p++;
5619 klass = mono_array_class_get (klass, rank);
5620 mono_class_init (klass);
5621 break;
5622 default:
5623 break;
5626 g_free (str);
5627 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5630 static MonoBoolean
5631 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5633 MonoType *type;
5634 MonoBoolean res;
5636 MONO_ARCH_SAVE_REGS;
5638 type = t->type;
5639 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5641 return res;
5644 static MonoReflectionType *
5645 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5647 MonoClass *klass, *aklass;
5649 MONO_ARCH_SAVE_REGS;
5651 klass = mono_class_from_mono_type (type->type);
5652 if (rank == 0) //single dimentional array
5653 aklass = mono_array_class_get (klass, 1);
5654 else
5655 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5657 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5660 static MonoReflectionType *
5661 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5663 MonoClass *klass;
5665 MONO_ARCH_SAVE_REGS;
5667 klass = mono_class_from_mono_type (type->type);
5669 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5672 static MonoReflectionType *
5673 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5675 MonoClass *pklass;
5677 MONO_ARCH_SAVE_REGS;
5679 pklass = mono_ptr_class_get (type->type);
5681 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5684 static MonoObject *
5685 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5686 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5688 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5689 MonoObject *delegate;
5690 gpointer func;
5691 MonoMethod *method = info->method;
5693 MONO_ARCH_SAVE_REGS;
5695 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5697 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5698 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5699 return NULL;
5702 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5704 if (method->dynamic) {
5705 /* Creating a trampoline would leak memory */
5706 func = mono_compile_method (method);
5707 } else {
5708 func = mono_create_ftnptr (mono_domain_get (),
5709 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5712 mono_delegate_ctor_with_method (delegate, target, func, method);
5714 return delegate;
5717 static void
5718 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5720 /* Reset the invoke impl to the default one */
5721 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5725 * Magic number to convert a time which is relative to
5726 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5728 #define EPOCH_ADJUST ((guint64)62135596800LL)
5731 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5733 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5735 #ifdef HOST_WIN32
5736 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5737 static void
5738 convert_to_absolute_date(SYSTEMTIME *date)
5740 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5741 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5742 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5743 /* from the calendar FAQ */
5744 int a = (14 - date->wMonth) / 12;
5745 int y = date->wYear - a;
5746 int m = date->wMonth + 12 * a - 2;
5747 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5749 /* d is now the day of the week for the first of the month (0 == Sunday) */
5751 int day_of_week = date->wDayOfWeek;
5753 /* set day_in_month to the first day in the month which falls on day_of_week */
5754 int day_in_month = 1 + (day_of_week - d);
5755 if (day_in_month <= 0)
5756 day_in_month += 7;
5758 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5759 date->wDay = day_in_month + (date->wDay - 1) * 7;
5760 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5761 date->wDay -= 7;
5763 #endif
5765 #ifndef HOST_WIN32
5767 * Return's the offset from GMT of a local time.
5769 * tm is a local time
5770 * t is the same local time as seconds.
5772 static int
5773 gmt_offset(struct tm *tm, time_t t)
5775 #if defined (HAVE_TM_GMTOFF)
5776 return tm->tm_gmtoff;
5777 #else
5778 struct tm g;
5779 time_t t2;
5780 g = *gmtime(&t);
5781 g.tm_isdst = tm->tm_isdst;
5782 t2 = mktime(&g);
5783 return (int)difftime(t, t2);
5784 #endif
5786 #endif
5788 * This is heavily based on zdump.c from glibc 2.2.
5790 * * data[0]: start of daylight saving time (in DateTime ticks).
5791 * * data[1]: end of daylight saving time (in DateTime ticks).
5792 * * data[2]: utcoffset (in TimeSpan ticks).
5793 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5794 * * name[0]: name of this timezone when not daylight saving.
5795 * * name[1]: name of this timezone when daylight saving.
5797 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5798 * the class library allows years between 1 and 9999.
5800 * Returns true on success and zero on failure.
5802 static guint32
5803 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5805 #ifndef HOST_WIN32
5806 MonoDomain *domain = mono_domain_get ();
5807 struct tm start, tt;
5808 time_t t;
5810 long int gmtoff;
5811 int is_daylight = 0, day;
5812 char tzone [64];
5814 MONO_ARCH_SAVE_REGS;
5816 MONO_CHECK_ARG_NULL (data);
5817 MONO_CHECK_ARG_NULL (names);
5819 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5820 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5823 * no info is better than crashing: we'll need our own tz data
5824 * to make this work properly, anyway. The range is probably
5825 * reduced to 1970 .. 2037 because that is what mktime is
5826 * guaranteed to support (we get into an infinite loop
5827 * otherwise).
5830 memset (&start, 0, sizeof (start));
5832 start.tm_mday = 1;
5833 start.tm_year = year-1900;
5835 t = mktime (&start);
5837 if ((year < 1970) || (year > 2037) || (t == -1)) {
5838 t = time (NULL);
5839 tt = *localtime (&t);
5840 strftime (tzone, sizeof (tzone), "%Z", &tt);
5841 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5842 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5843 return 1;
5846 gmtoff = gmt_offset (&start, t);
5848 /* For each day of the year, calculate the tm_gmtoff. */
5849 for (day = 0; day < 365; day++) {
5851 t += 3600*24;
5852 tt = *localtime (&t);
5854 /* Daylight saving starts or ends here. */
5855 if (gmt_offset (&tt, t) != gmtoff) {
5856 struct tm tt1;
5857 time_t t1;
5859 /* Try to find the exact hour when daylight saving starts/ends. */
5860 t1 = t;
5861 do {
5862 t1 -= 3600;
5863 tt1 = *localtime (&t1);
5864 } while (gmt_offset (&tt1, t1) != gmtoff);
5866 /* Try to find the exact minute when daylight saving starts/ends. */
5867 do {
5868 t1 += 60;
5869 tt1 = *localtime (&t1);
5870 } while (gmt_offset (&tt1, t1) == gmtoff);
5871 t1+=gmtoff;
5872 strftime (tzone, sizeof (tzone), "%Z", &tt);
5874 /* Write data, if we're already in daylight saving, we're done. */
5875 if (is_daylight) {
5876 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5877 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5878 return 1;
5879 } else {
5880 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5881 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5882 is_daylight = 1;
5885 /* This is only set once when we enter daylight saving. */
5886 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5887 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5889 gmtoff = gmt_offset (&tt, t);
5893 if (!is_daylight) {
5894 strftime (tzone, sizeof (tzone), "%Z", &tt);
5895 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5896 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5897 mono_array_set ((*data), gint64, 0, 0);
5898 mono_array_set ((*data), gint64, 1, 0);
5899 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5900 mono_array_set ((*data), gint64, 3, 0);
5903 return 1;
5904 #else
5905 MonoDomain *domain = mono_domain_get ();
5906 TIME_ZONE_INFORMATION tz_info;
5907 FILETIME ft;
5908 int i;
5909 int err, tz_id;
5911 tz_id = GetTimeZoneInformation (&tz_info);
5912 if (tz_id == TIME_ZONE_ID_INVALID)
5913 return 0;
5915 MONO_CHECK_ARG_NULL (data);
5916 MONO_CHECK_ARG_NULL (names);
5918 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
5919 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
5921 for (i = 0; i < 32; ++i)
5922 if (!tz_info.DaylightName [i])
5923 break;
5924 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
5925 for (i = 0; i < 32; ++i)
5926 if (!tz_info.StandardName [i])
5927 break;
5928 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
5930 if ((year <= 1601) || (year > 30827)) {
5932 * According to MSDN, the MS time functions can't handle dates outside
5933 * this interval.
5935 return 1;
5938 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
5939 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
5940 tz_info.StandardDate.wYear = year;
5941 convert_to_absolute_date(&tz_info.StandardDate);
5942 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
5943 //g_assert(err);
5944 if (err == 0)
5945 return 0;
5947 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5948 tz_info.DaylightDate.wYear = year;
5949 convert_to_absolute_date(&tz_info.DaylightDate);
5950 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
5951 //g_assert(err);
5952 if (err == 0)
5953 return 0;
5955 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5957 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
5958 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
5960 return 1;
5961 #endif
5964 static gpointer
5965 ves_icall_System_Object_obj_address (MonoObject *this)
5967 MONO_ARCH_SAVE_REGS;
5969 return this;
5972 /* System.Buffer */
5974 static inline gint32
5975 mono_array_get_byte_length (MonoArray *array)
5977 MonoClass *klass;
5978 int length;
5979 int i;
5981 klass = array->obj.vtable->klass;
5983 if (array->bounds == NULL)
5984 length = array->max_length;
5985 else {
5986 length = 1;
5987 for (i = 0; i < klass->rank; ++ i)
5988 length *= array->bounds [i].length;
5991 switch (klass->element_class->byval_arg.type) {
5992 case MONO_TYPE_I1:
5993 case MONO_TYPE_U1:
5994 case MONO_TYPE_BOOLEAN:
5995 return length;
5996 case MONO_TYPE_I2:
5997 case MONO_TYPE_U2:
5998 case MONO_TYPE_CHAR:
5999 return length << 1;
6000 case MONO_TYPE_I4:
6001 case MONO_TYPE_U4:
6002 case MONO_TYPE_R4:
6003 return length << 2;
6004 case MONO_TYPE_I:
6005 case MONO_TYPE_U:
6006 return length * sizeof (gpointer);
6007 case MONO_TYPE_I8:
6008 case MONO_TYPE_U8:
6009 case MONO_TYPE_R8:
6010 return length << 3;
6011 default:
6012 return -1;
6016 static gint32
6017 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6019 MONO_ARCH_SAVE_REGS;
6021 return mono_array_get_byte_length (array);
6024 static gint8
6025 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6027 MONO_ARCH_SAVE_REGS;
6029 return mono_array_get (array, gint8, idx);
6032 static void
6033 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6035 MONO_ARCH_SAVE_REGS;
6037 mono_array_set (array, gint8, idx, value);
6040 static MonoBoolean
6041 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6043 guint8 *src_buf, *dest_buf;
6045 MONO_ARCH_SAVE_REGS;
6047 /* watch out for integer overflow */
6048 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6049 return FALSE;
6051 src_buf = (guint8 *)src->vector + src_offset;
6052 dest_buf = (guint8 *)dest->vector + dest_offset;
6054 if (src != dest)
6055 memcpy (dest_buf, src_buf, count);
6056 else
6057 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6059 return TRUE;
6062 static MonoObject *
6063 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6065 MonoDomain *domain = mono_object_domain (this);
6066 MonoObject *res;
6067 MonoRealProxy *rp = ((MonoRealProxy *)this);
6068 MonoTransparentProxy *tp;
6069 MonoType *type;
6070 MonoClass *klass;
6072 MONO_ARCH_SAVE_REGS;
6074 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6075 tp = (MonoTransparentProxy*) res;
6077 MONO_OBJECT_SETREF (tp, rp, rp);
6078 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6079 klass = mono_class_from_mono_type (type);
6081 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6082 tp->remote_class = mono_remote_class (domain, class_name, klass);
6084 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6085 return res;
6088 static MonoReflectionType *
6089 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6091 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6094 /* System.Environment */
6096 MonoString*
6097 ves_icall_System_Environment_get_UserName (void)
6099 MONO_ARCH_SAVE_REGS;
6101 /* using glib is more portable */
6102 return mono_string_new (mono_domain_get (), g_get_user_name ());
6106 static MonoString *
6107 ves_icall_System_Environment_get_MachineName (void)
6109 #if defined (HOST_WIN32)
6110 gunichar2 *buf;
6111 guint32 len;
6112 MonoString *result;
6114 len = MAX_COMPUTERNAME_LENGTH + 1;
6115 buf = g_new (gunichar2, len);
6117 result = NULL;
6118 if (GetComputerName (buf, (PDWORD) &len))
6119 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6121 g_free (buf);
6122 return result;
6123 #elif !defined(DISABLE_SOCKETS)
6124 gchar buf [256];
6125 MonoString *result;
6127 if (gethostname (buf, sizeof (buf)) == 0)
6128 result = mono_string_new (mono_domain_get (), buf);
6129 else
6130 result = NULL;
6132 return result;
6133 #else
6134 return mono_string_new (mono_domain_get (), "mono");
6135 #endif
6138 static int
6139 ves_icall_System_Environment_get_Platform (void)
6141 #if defined (TARGET_WIN32)
6142 /* Win32NT */
6143 return 2;
6144 #elif defined(__MACH__)
6145 /* OSX */
6147 // For compatibility with our client code, this will be 4 for a while.
6148 // We will eventually move to 6 to match .NET, but it requires all client
6149 // code to be updated and the documentation everywhere to be updated
6150 // first.
6152 return 4;
6153 #else
6154 /* Unix */
6155 return 4;
6156 #endif
6159 static MonoString *
6160 ves_icall_System_Environment_get_NewLine (void)
6162 MONO_ARCH_SAVE_REGS;
6164 #if defined (HOST_WIN32)
6165 return mono_string_new (mono_domain_get (), "\r\n");
6166 #else
6167 return mono_string_new (mono_domain_get (), "\n");
6168 #endif
6171 static MonoString *
6172 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6174 const gchar *value;
6175 gchar *utf8_name;
6177 MONO_ARCH_SAVE_REGS;
6179 if (name == NULL)
6180 return NULL;
6182 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6183 value = g_getenv (utf8_name);
6185 g_free (utf8_name);
6187 if (value == 0)
6188 return NULL;
6190 return mono_string_new (mono_domain_get (), value);
6194 * There is no standard way to get at environ.
6196 #ifndef _MSC_VER
6197 #ifndef __MINGW32_VERSION
6198 #ifdef __APPLE__
6199 /* Apple defines this in crt_externs.h but doesn't provide that header for
6200 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6201 * in fact exist on all implementations (so far)
6203 gchar ***_NSGetEnviron(void);
6204 #define environ (*_NSGetEnviron())
6205 #else
6206 extern
6207 char **environ;
6208 #endif
6209 #endif
6210 #endif
6212 static MonoArray *
6213 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6215 #ifdef HOST_WIN32
6216 MonoArray *names;
6217 MonoDomain *domain;
6218 MonoString *str;
6219 WCHAR* env_strings;
6220 WCHAR* env_string;
6221 WCHAR* equal_str;
6222 int n = 0;
6224 env_strings = GetEnvironmentStrings();
6226 if (env_strings) {
6227 env_string = env_strings;
6228 while (*env_string != '\0') {
6229 /* weird case that MS seems to skip */
6230 if (*env_string != '=')
6231 n++;
6232 while (*env_string != '\0')
6233 env_string++;
6234 env_string++;
6238 domain = mono_domain_get ();
6239 names = mono_array_new (domain, mono_defaults.string_class, n);
6241 if (env_strings) {
6242 n = 0;
6243 env_string = env_strings;
6244 while (*env_string != '\0') {
6245 /* weird case that MS seems to skip */
6246 if (*env_string != '=') {
6247 equal_str = wcschr(env_string, '=');
6248 g_assert(equal_str);
6249 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6250 mono_array_setref (names, n, str);
6251 n++;
6253 while (*env_string != '\0')
6254 env_string++;
6255 env_string++;
6258 FreeEnvironmentStrings (env_strings);
6261 return names;
6263 #else
6264 MonoArray *names;
6265 MonoDomain *domain;
6266 MonoString *str;
6267 gchar **e, **parts;
6268 int n;
6270 MONO_ARCH_SAVE_REGS;
6272 n = 0;
6273 for (e = environ; *e != 0; ++ e)
6274 ++ n;
6276 domain = mono_domain_get ();
6277 names = mono_array_new (domain, mono_defaults.string_class, n);
6279 n = 0;
6280 for (e = environ; *e != 0; ++ e) {
6281 parts = g_strsplit (*e, "=", 2);
6282 if (*parts != 0) {
6283 str = mono_string_new (domain, *parts);
6284 mono_array_setref (names, n, str);
6287 g_strfreev (parts);
6289 ++ n;
6292 return names;
6293 #endif
6297 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6299 #if !GLIB_CHECK_VERSION(2,4,0)
6300 #define g_setenv(a,b,c) setenv(a,b,c)
6301 #define g_unsetenv(a) unsetenv(a)
6302 #endif
6304 static void
6305 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6307 MonoError error;
6308 #ifdef HOST_WIN32
6310 gunichar2 *utf16_name, *utf16_value;
6311 #else
6312 gchar *utf8_name, *utf8_value;
6313 #endif
6315 MONO_ARCH_SAVE_REGS;
6317 #ifdef HOST_WIN32
6318 utf16_name = mono_string_to_utf16 (name);
6319 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6320 SetEnvironmentVariable (utf16_name, NULL);
6321 g_free (utf16_name);
6322 return;
6325 utf16_value = mono_string_to_utf16 (value);
6327 SetEnvironmentVariable (utf16_name, utf16_value);
6329 g_free (utf16_name);
6330 g_free (utf16_value);
6331 #else
6332 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6334 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6335 g_unsetenv (utf8_name);
6336 g_free (utf8_name);
6337 return;
6340 utf8_value = mono_string_to_utf8_checked (value, &error);
6341 if (!mono_error_ok (&error)) {
6342 g_free (utf8_name);
6343 mono_error_raise_exception (&error);
6345 g_setenv (utf8_name, utf8_value, TRUE);
6347 g_free (utf8_name);
6348 g_free (utf8_value);
6349 #endif
6352 static void
6353 ves_icall_System_Environment_Exit (int result)
6355 MONO_ARCH_SAVE_REGS;
6357 mono_threads_set_shutting_down ();
6359 mono_runtime_set_shutting_down ();
6361 /* This will kill the tp threads which cannot be suspended */
6362 mono_thread_pool_cleanup ();
6364 /* Suspend all managed threads since the runtime is going away */
6365 mono_thread_suspend_all_other_threads ();
6367 mono_runtime_quit ();
6369 /* we may need to do some cleanup here... */
6370 exit (result);
6373 static MonoString*
6374 ves_icall_System_Environment_GetGacPath (void)
6376 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6379 static MonoString*
6380 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6382 #if defined (HOST_WIN32)
6383 #ifndef CSIDL_FLAG_CREATE
6384 #define CSIDL_FLAG_CREATE 0x8000
6385 #endif
6387 WCHAR path [MAX_PATH];
6388 /* Create directory if no existing */
6389 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6390 int len = 0;
6391 while (path [len])
6392 ++ len;
6393 return mono_string_new_utf16 (mono_domain_get (), path, len);
6395 #else
6396 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6397 #endif
6398 return mono_string_new (mono_domain_get (), "");
6401 static MonoArray *
6402 ves_icall_System_Environment_GetLogicalDrives (void)
6404 gunichar2 buf [128], *ptr, *dname;
6405 gunichar2 *u16;
6406 guint initial_size = 127, size = 128;
6407 gint ndrives;
6408 MonoArray *result;
6409 MonoString *drivestr;
6410 MonoDomain *domain = mono_domain_get ();
6411 gint len;
6413 MONO_ARCH_SAVE_REGS;
6415 buf [0] = '\0';
6416 ptr = buf;
6418 while (size > initial_size) {
6419 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6420 if (size > initial_size) {
6421 if (ptr != buf)
6422 g_free (ptr);
6423 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6424 initial_size = size;
6425 size++;
6429 /* Count strings */
6430 dname = ptr;
6431 ndrives = 0;
6432 do {
6433 while (*dname++);
6434 ndrives++;
6435 } while (*dname);
6437 dname = ptr;
6438 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6439 ndrives = 0;
6440 do {
6441 len = 0;
6442 u16 = dname;
6443 while (*u16) { u16++; len ++; }
6444 drivestr = mono_string_new_utf16 (domain, dname, len);
6445 mono_array_setref (result, ndrives++, drivestr);
6446 while (*dname++);
6447 } while (*dname);
6449 if (ptr != buf)
6450 g_free (ptr);
6452 return result;
6455 static MonoString *
6456 ves_icall_System_Environment_InternalGetHome (void)
6458 MONO_ARCH_SAVE_REGS;
6460 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6463 static const char *encodings [] = {
6464 (char *) 1,
6465 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6466 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6467 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6468 (char *) 2,
6469 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6470 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6471 "x_unicode_2_0_utf_7",
6472 (char *) 3,
6473 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6474 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6475 (char *) 4,
6476 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6477 "iso_10646_ucs2",
6478 (char *) 5,
6479 "unicodefffe", "utf_16be",
6480 (char *) 6,
6481 "iso_8859_1",
6482 (char *) 0
6486 * Returns the internal codepage, if the value of "int_code_page" is
6487 * 1 at entry, and we can not compute a suitable code page number,
6488 * returns the code page as a string
6490 static MonoString*
6491 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6493 const char *cset;
6494 const char *p;
6495 char *c;
6496 char *codepage = NULL;
6497 int code;
6498 int want_name = *int_code_page;
6499 int i;
6501 *int_code_page = -1;
6502 MONO_ARCH_SAVE_REGS;
6504 g_get_charset (&cset);
6505 c = codepage = strdup (cset);
6506 for (c = codepage; *c; c++){
6507 if (isascii (*c) && isalpha (*c))
6508 *c = tolower (*c);
6509 if (*c == '-')
6510 *c = '_';
6512 /* g_print ("charset: %s\n", cset); */
6514 /* handle some common aliases */
6515 p = encodings [0];
6516 code = 0;
6517 for (i = 0; p != 0; ){
6518 if ((gssize) p < 7){
6519 code = (gssize) p;
6520 p = encodings [++i];
6521 continue;
6523 if (strcmp (p, codepage) == 0){
6524 *int_code_page = code;
6525 break;
6527 p = encodings [++i];
6530 if (strstr (codepage, "utf_8") != NULL)
6531 *int_code_page |= 0x10000000;
6532 free (codepage);
6534 if (want_name && *int_code_page == -1)
6535 return mono_string_new (mono_domain_get (), cset);
6536 else
6537 return NULL;
6540 static MonoBoolean
6541 ves_icall_System_Environment_get_HasShutdownStarted (void)
6543 if (mono_runtime_is_shutting_down ())
6544 return TRUE;
6546 if (mono_domain_is_unloading (mono_domain_get ()))
6547 return TRUE;
6549 return FALSE;
6552 static void
6553 ves_icall_System_Environment_BroadcastSettingChange (void)
6555 #ifdef HOST_WIN32
6556 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6557 #endif
6560 static void
6561 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6562 MonoReflectionMethod *method,
6563 MonoArray *out_args)
6565 MONO_ARCH_SAVE_REGS;
6567 mono_message_init (mono_object_domain (this), this, method, out_args);
6570 static MonoBoolean
6571 ves_icall_IsTransparentProxy (MonoObject *proxy)
6573 MONO_ARCH_SAVE_REGS;
6575 if (!proxy)
6576 return 0;
6578 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6579 return 1;
6581 return 0;
6584 static MonoReflectionMethod *
6585 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6586 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6588 MonoClass *klass;
6589 MonoMethod *method;
6590 MonoMethod **vtable;
6591 MonoMethod *res = NULL;
6593 MONO_CHECK_ARG_NULL (rtype);
6594 MONO_CHECK_ARG_NULL (rmethod);
6596 method = rmethod->method;
6597 klass = mono_class_from_mono_type (rtype->type);
6599 if (MONO_CLASS_IS_INTERFACE (klass))
6600 return NULL;
6602 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6603 return NULL;
6605 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6606 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6607 return rmethod;
6608 else
6609 return NULL;
6612 mono_class_setup_vtable (klass);
6613 vtable = klass->vtable;
6615 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6616 gboolean variance_used = FALSE;
6617 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6618 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6619 if (offs >= 0)
6620 res = vtable [offs + method->slot];
6621 } else {
6622 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6623 return NULL;
6625 if (method->slot != -1)
6626 res = vtable [method->slot];
6629 if (!res)
6630 return NULL;
6632 return mono_method_get_object (mono_domain_get (), res, NULL);
6635 static void
6636 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6638 MonoClass *klass;
6639 MonoVTable* vtable;
6641 MONO_ARCH_SAVE_REGS;
6643 klass = mono_class_from_mono_type (type->type);
6644 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6646 if (enable) vtable->remote = 1;
6647 else vtable->remote = 0;
6650 static MonoObject *
6651 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6653 MonoClass *klass;
6654 MonoDomain *domain;
6656 MONO_ARCH_SAVE_REGS;
6658 domain = mono_object_domain (type);
6659 klass = mono_class_from_mono_type (type->type);
6661 if (klass->rank >= 1) {
6662 g_assert (klass->rank == 1);
6663 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6664 } else {
6665 /* Bypass remoting object creation check */
6666 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6670 static MonoString *
6671 ves_icall_System_IO_get_temp_path (void)
6673 MONO_ARCH_SAVE_REGS;
6675 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6678 #ifndef PLATFORM_NO_DRIVEINFO
6679 static MonoBoolean
6680 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6681 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6682 gint32 *error)
6684 gboolean result;
6685 ULARGE_INTEGER wapi_free_bytes_avail;
6686 ULARGE_INTEGER wapi_total_number_of_bytes;
6687 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6689 MONO_ARCH_SAVE_REGS;
6691 *error = ERROR_SUCCESS;
6692 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6693 &wapi_total_number_of_free_bytes);
6695 if (result) {
6696 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6697 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6698 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6699 } else {
6700 *free_bytes_avail = 0;
6701 *total_number_of_bytes = 0;
6702 *total_number_of_free_bytes = 0;
6703 *error = GetLastError ();
6706 return result;
6709 static guint32
6710 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6712 MONO_ARCH_SAVE_REGS;
6714 return GetDriveType (mono_string_chars (root_path_name));
6716 #endif
6718 static gpointer
6719 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6721 MONO_ARCH_SAVE_REGS;
6723 return mono_compile_method (method);
6726 static MonoString *
6727 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6729 MonoString *mcpath;
6730 gchar *path;
6732 MONO_ARCH_SAVE_REGS;
6734 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6736 #if defined (HOST_WIN32)
6737 /* Avoid mixing '/' and '\\' */
6739 gint i;
6740 for (i = strlen (path) - 1; i >= 0; i--)
6741 if (path [i] == '/')
6742 path [i] = '\\';
6744 #endif
6745 mcpath = mono_string_new (mono_domain_get (), path);
6746 g_free (path);
6748 return mcpath;
6751 static MonoString *
6752 get_bundled_machine_config (void)
6754 const gchar *machine_config;
6756 MONO_ARCH_SAVE_REGS;
6758 machine_config = mono_get_machine_config ();
6760 if (!machine_config)
6761 return NULL;
6763 return mono_string_new (mono_domain_get (), machine_config);
6766 static MonoString *
6767 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6769 MonoString *ipath;
6770 gchar *path;
6772 MONO_ARCH_SAVE_REGS;
6774 path = g_path_get_dirname (mono_get_config_dir ());
6776 #if defined (HOST_WIN32)
6777 /* Avoid mixing '/' and '\\' */
6779 gint i;
6780 for (i = strlen (path) - 1; i >= 0; i--)
6781 if (path [i] == '/')
6782 path [i] = '\\';
6784 #endif
6785 ipath = mono_string_new (mono_domain_get (), path);
6786 g_free (path);
6788 return ipath;
6791 static gboolean
6792 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6794 MonoPEResourceDataEntry *entry;
6795 MonoImage *image;
6797 MONO_ARCH_SAVE_REGS;
6799 if (!assembly || !result || !size)
6800 return FALSE;
6802 *result = NULL;
6803 *size = 0;
6804 image = assembly->assembly->image;
6805 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6806 if (!entry)
6807 return FALSE;
6809 *result = mono_image_rva_map (image, entry->rde_data_offset);
6810 if (!(*result)) {
6811 g_free (entry);
6812 return FALSE;
6814 *size = entry->rde_size;
6815 g_free (entry);
6816 return TRUE;
6819 static MonoBoolean
6820 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6822 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6825 static void
6826 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6828 #if defined (HOST_WIN32)
6829 OutputDebugString (mono_string_chars (message));
6830 #else
6831 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6832 #endif
6835 /* Only used for value types */
6836 static MonoObject *
6837 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6839 MonoClass *klass;
6840 MonoDomain *domain;
6842 MONO_ARCH_SAVE_REGS;
6844 domain = mono_object_domain (type);
6845 klass = mono_class_from_mono_type (type->type);
6847 if (mono_class_is_nullable (klass))
6848 /* No arguments -> null */
6849 return NULL;
6851 return mono_object_new (domain, klass);
6854 static MonoReflectionMethod *
6855 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6857 MonoClass *klass, *parent;
6858 MonoMethod *method = m->method;
6859 MonoMethod *result = NULL;
6861 MONO_ARCH_SAVE_REGS;
6863 if (method->klass == NULL)
6864 return m;
6866 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6867 MONO_CLASS_IS_INTERFACE (method->klass) ||
6868 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6869 return m;
6871 klass = method->klass;
6872 if (klass->generic_class)
6873 klass = klass->generic_class->container_class;
6875 if (definition) {
6876 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6877 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6878 mono_class_setup_vtable (parent);
6879 if (parent->vtable_size <= method->slot)
6880 break;
6881 klass = parent;
6883 } else {
6884 klass = klass->parent;
6885 if (!klass)
6886 return m;
6889 if (klass == method->klass)
6890 return m;
6892 result = klass->vtable [method->slot];
6893 if (result == NULL) {
6894 /* It is an abstract method */
6895 gpointer iter = NULL;
6896 while ((result = mono_class_get_methods (klass, &iter)))
6897 if (result->slot == method->slot)
6898 break;
6901 if (result == NULL)
6902 return m;
6904 return mono_method_get_object (mono_domain_get (), result, NULL);
6907 static MonoString*
6908 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6910 MonoMethod *method = m->method;
6912 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6913 return m->name;
6916 static void
6917 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6919 MONO_ARCH_SAVE_REGS;
6921 iter->sig = *(MonoMethodSignature**)argsp;
6923 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6924 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6926 iter->next_arg = 0;
6927 /* FIXME: it's not documented what start is exactly... */
6928 if (start) {
6929 iter->args = start;
6930 } else {
6931 iter->args = argsp + sizeof (gpointer);
6933 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6935 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6938 static MonoTypedRef
6939 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6941 guint32 i, arg_size;
6942 gint32 align;
6943 MonoTypedRef res;
6944 MONO_ARCH_SAVE_REGS;
6946 i = iter->sig->sentinelpos + iter->next_arg;
6948 g_assert (i < iter->sig->param_count);
6950 res.type = iter->sig->params [i];
6951 res.klass = mono_class_from_mono_type (res.type);
6952 res.value = iter->args;
6953 arg_size = mono_type_stack_size (res.type, &align);
6954 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
6955 if (arg_size <= sizeof (gpointer)) {
6956 int dummy;
6957 int padding = arg_size - mono_type_size (res.type, &dummy);
6958 res.value = (guint8*)res.value + padding;
6960 #endif
6961 iter->args = (char*)iter->args + arg_size;
6962 iter->next_arg++;
6964 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6966 return res;
6969 static MonoTypedRef
6970 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6972 guint32 i, arg_size;
6973 gint32 align;
6974 MonoTypedRef res;
6975 MONO_ARCH_SAVE_REGS;
6977 i = iter->sig->sentinelpos + iter->next_arg;
6979 g_assert (i < iter->sig->param_count);
6981 while (i < iter->sig->param_count) {
6982 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6983 continue;
6984 res.type = iter->sig->params [i];
6985 res.klass = mono_class_from_mono_type (res.type);
6986 /* FIXME: endianess issue... */
6987 res.value = iter->args;
6988 arg_size = mono_type_stack_size (res.type, &align);
6989 iter->args = (char*)iter->args + arg_size;
6990 iter->next_arg++;
6991 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6992 return res;
6994 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
6996 res.type = NULL;
6997 res.value = NULL;
6998 res.klass = NULL;
6999 return res;
7002 static MonoType*
7003 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7005 gint i;
7006 MONO_ARCH_SAVE_REGS;
7008 i = iter->sig->sentinelpos + iter->next_arg;
7010 g_assert (i < iter->sig->param_count);
7012 return iter->sig->params [i];
7015 static MonoObject*
7016 mono_TypedReference_ToObject (MonoTypedRef tref)
7018 MONO_ARCH_SAVE_REGS;
7020 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7021 MonoObject** objp = tref.value;
7022 return *objp;
7025 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7028 static MonoObject*
7029 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7031 MONO_ARCH_SAVE_REGS;
7033 if (MONO_TYPE_IS_REFERENCE (type)) {
7034 MonoObject** objp = value;
7035 return *objp;
7038 return mono_value_box (mono_domain_get (), klass, value);
7041 static void
7042 prelink_method (MonoMethod *method)
7044 const char *exc_class, *exc_arg;
7045 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7046 return;
7047 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7048 if (exc_class) {
7049 mono_raise_exception(
7050 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7052 /* create the wrapper, too? */
7055 static void
7056 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7058 MONO_ARCH_SAVE_REGS;
7059 prelink_method (method->method);
7062 static void
7063 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7065 MonoClass *klass = mono_class_from_mono_type (type->type);
7066 MonoMethod* m;
7067 gpointer iter = NULL;
7068 MONO_ARCH_SAVE_REGS;
7070 while ((m = mono_class_get_methods (klass, &iter)))
7071 prelink_method (m);
7074 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7075 static void
7076 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7077 gint32 const **exponents,
7078 gunichar2 const **digitLowerTable,
7079 gunichar2 const **digitUpperTable,
7080 gint64 const **tenPowersList,
7081 gint32 const **decHexDigits)
7083 *mantissas = Formatter_MantissaBitsTable;
7084 *exponents = Formatter_TensExponentTable;
7085 *digitLowerTable = Formatter_DigitLowerTable;
7086 *digitUpperTable = Formatter_DigitUpperTable;
7087 *tenPowersList = Formatter_TenPowersList;
7088 *decHexDigits = Formatter_DecHexDigits;
7091 /* These parameters are "readonly" in corlib/System/Char.cs */
7092 static void
7093 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7094 guint8 const **numeric_data,
7095 gdouble const **numeric_data_values,
7096 guint16 const **to_lower_data_low,
7097 guint16 const **to_lower_data_high,
7098 guint16 const **to_upper_data_low,
7099 guint16 const **to_upper_data_high)
7101 *category_data = CategoryData;
7102 *numeric_data = NumericData;
7103 *numeric_data_values = NumericDataValues;
7104 *to_lower_data_low = ToLowerDataLow;
7105 *to_lower_data_high = ToLowerDataHigh;
7106 *to_upper_data_low = ToUpperDataLow;
7107 *to_upper_data_high = ToUpperDataHigh;
7110 static gint32
7111 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7113 return method->method->token;
7117 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7118 * and avoid useless allocations.
7120 static MonoArray*
7121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7123 MonoArray *res;
7124 int i, count = 0;
7125 for (i = 0; i < type->num_mods; ++i) {
7126 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7127 count++;
7129 if (!count)
7130 return NULL;
7131 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7132 count = 0;
7133 for (i = 0; i < type->num_mods; ++i) {
7134 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7135 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7136 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7137 count++;
7140 return res;
7143 static MonoArray*
7144 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7146 MonoType *type = param->ClassImpl->type;
7147 MonoClass *member_class = mono_object_class (param->MemberImpl);
7148 MonoMethod *method = NULL;
7149 MonoImage *image;
7150 int pos;
7151 MonoMethodSignature *sig;
7153 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7154 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7155 method = rmethod->method;
7156 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7157 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7158 if (!(method = prop->property->get))
7159 method = prop->property->set;
7160 g_assert (method);
7161 } else {
7162 char *type_name = mono_type_get_full_name (member_class);
7163 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7164 MonoException *ex = mono_get_exception_not_supported (msg);
7165 g_free (type_name);
7166 g_free (msg);
7167 mono_raise_exception (ex);
7170 image = method->klass->image;
7171 pos = param->PositionImpl;
7172 sig = mono_method_signature (method);
7173 if (pos == -1)
7174 type = sig->ret;
7175 else
7176 type = sig->params [pos];
7178 return type_array_from_modifiers (image, type, optional);
7181 static MonoType*
7182 get_property_type (MonoProperty *prop)
7184 MonoMethodSignature *sig;
7185 if (prop->get) {
7186 sig = mono_method_signature (prop->get);
7187 return sig->ret;
7188 } else if (prop->set) {
7189 sig = mono_method_signature (prop->set);
7190 return sig->params [sig->param_count - 1];
7192 return NULL;
7195 static MonoArray*
7196 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7198 MonoType *type = get_property_type (property->property);
7199 MonoImage *image = property->klass->image;
7201 if (!type)
7202 return NULL;
7203 return type_array_from_modifiers (image, type, optional);
7207 *Construct a MonoType suited to be used to decode a constant blob object.
7209 * @type is the target type which will be constructed
7210 * @blob_type is the blob type, for example, that comes from the constant table
7211 * @real_type is the expected constructed type.
7213 static void
7214 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7216 type->type = blob_type;
7217 type->data.klass = NULL;
7218 if (blob_type == MONO_TYPE_CLASS)
7219 type->data.klass = mono_defaults.object_class;
7220 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7221 /* For enums, we need to use the base type */
7222 type->type = MONO_TYPE_VALUETYPE;
7223 type->data.klass = mono_class_from_mono_type (real_type);
7224 } else
7225 type->data.klass = mono_class_from_mono_type (real_type);
7228 static MonoObject*
7229 property_info_get_default_value (MonoReflectionProperty *property)
7231 MonoType blob_type;
7232 MonoProperty *prop = property->property;
7233 MonoType *type = get_property_type (prop);
7234 MonoDomain *domain = mono_object_domain (property);
7235 MonoTypeEnum def_type;
7236 const char *def_value;
7237 MonoObject *o;
7239 g_assert (!prop->parent->image->dynamic);
7241 mono_class_init (prop->parent);
7243 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7244 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7246 def_value = mono_class_get_property_default_value (prop, &def_type);
7248 mono_type_from_blob_type (&blob_type, def_type, type);
7249 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7251 return o;
7254 static MonoBoolean
7255 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7257 MonoCustomAttrInfo *cinfo;
7258 gboolean found;
7260 cinfo = mono_reflection_get_custom_attrs_info (obj);
7261 if (!cinfo)
7262 return FALSE;
7263 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7264 if (!cinfo->cached)
7265 mono_custom_attrs_free (cinfo);
7266 return found;
7269 static MonoArray*
7270 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7272 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7274 if (mono_loader_get_last_error ()) {
7275 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7276 g_assert_not_reached ();
7277 /* Not reached */
7278 return NULL;
7279 } else {
7280 return res;
7284 static MonoString*
7285 ves_icall_Mono_Runtime_GetDisplayName (void)
7287 char *info;
7288 MonoString *display_name;
7290 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7291 display_name = mono_string_new (mono_domain_get (), info);
7292 g_free (info);
7293 return display_name;
7296 static MonoString*
7297 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7299 MonoString *message;
7300 guint32 ret;
7301 gunichar2 buf[256];
7303 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7304 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7305 buf, 255, NULL);
7306 if (ret == 0) {
7307 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7308 } else {
7309 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7312 return message;
7315 const static guchar
7316 dbase64 [] = {
7317 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7318 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7319 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7320 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7321 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7322 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7323 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7324 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7327 static MonoArray *
7328 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7330 gint ignored;
7331 gint i;
7332 gunichar2 c;
7333 gunichar2 last, prev_last, prev2_last;
7334 gint olength;
7335 MonoArray *result;
7336 guchar *res_ptr;
7337 gint a [4], b [4];
7338 MonoException *exc;
7340 ignored = 0;
7341 last = prev_last = 0, prev2_last = 0;
7342 for (i = 0; i < ilength; i++) {
7343 c = start [i];
7344 if (c >= sizeof (dbase64)) {
7345 exc = mono_exception_from_name_msg (mono_get_corlib (),
7346 "System", "FormatException",
7347 "Invalid character found.");
7348 mono_raise_exception (exc);
7349 } else if (isspace (c)) {
7350 ignored++;
7351 } else {
7352 prev2_last = prev_last;
7353 prev_last = last;
7354 last = c;
7358 olength = ilength - ignored;
7360 if (allowWhitespaceOnly && olength == 0) {
7361 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7364 if ((olength & 3) != 0 || olength <= 0) {
7365 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7366 "FormatException", "Invalid length.");
7367 mono_raise_exception (exc);
7370 if (prev2_last == '=') {
7371 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7372 mono_raise_exception (exc);
7375 olength = (olength * 3) / 4;
7376 if (last == '=')
7377 olength--;
7379 if (prev_last == '=')
7380 olength--;
7382 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7383 res_ptr = mono_array_addr (result, guchar, 0);
7384 for (i = 0; i < ilength; ) {
7385 int k;
7387 for (k = 0; k < 4 && i < ilength;) {
7388 c = start [i++];
7389 if (isspace (c))
7390 continue;
7392 a [k] = (guchar) c;
7393 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7394 exc = mono_exception_from_name_msg (mono_get_corlib (),
7395 "System", "FormatException",
7396 "Invalid character found.");
7397 mono_raise_exception (exc);
7399 k++;
7402 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7403 if (a [2] != '=')
7404 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7405 if (a [3] != '=')
7406 *res_ptr++ = (b [2] << 6) | b [3];
7408 while (i < ilength && isspace (start [i]))
7409 i++;
7412 return result;
7415 static MonoArray *
7416 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7418 MONO_ARCH_SAVE_REGS;
7420 return base64_to_byte_array (mono_string_chars (str),
7421 mono_string_length (str), allowWhitespaceOnly);
7424 static MonoArray *
7425 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7427 MONO_ARCH_SAVE_REGS;
7429 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7430 length, FALSE);
7433 #define ICALL_TYPE(id,name,first)
7434 #define ICALL(id,name,func) Icall_ ## id,
7436 enum {
7437 #include "metadata/icall-def.h"
7438 Icall_last
7441 #undef ICALL_TYPE
7442 #undef ICALL
7443 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7444 #define ICALL(id,name,func)
7445 enum {
7446 #include "metadata/icall-def.h"
7447 Icall_type_num
7450 #undef ICALL_TYPE
7451 #undef ICALL
7452 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7453 #define ICALL(id,name,func)
7454 typedef struct {
7455 guint16 first_icall;
7456 } IcallTypeDesc;
7458 static const IcallTypeDesc
7459 icall_type_descs [] = {
7460 #include "metadata/icall-def.h"
7461 {Icall_last}
7464 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7466 #undef ICALL_TYPE
7467 #define ICALL_TYPE(id,name,first)
7468 #undef ICALL
7470 #ifdef HAVE_ARRAY_ELEM_INIT
7471 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7472 #define MSGSTRFIELD1(line) str##line
7474 static const struct msgstrtn_t {
7475 #define ICALL(id,name,func)
7476 #undef ICALL_TYPE
7477 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7478 #include "metadata/icall-def.h"
7479 #undef ICALL_TYPE
7480 } icall_type_names_str = {
7481 #define ICALL_TYPE(id,name,first) (name),
7482 #include "metadata/icall-def.h"
7483 #undef ICALL_TYPE
7485 static const guint16 icall_type_names_idx [] = {
7486 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7487 #include "metadata/icall-def.h"
7488 #undef ICALL_TYPE
7490 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7492 static const struct msgstr_t {
7493 #undef ICALL
7494 #define ICALL_TYPE(id,name,first)
7495 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7496 #include "metadata/icall-def.h"
7497 #undef ICALL
7498 } icall_names_str = {
7499 #define ICALL(id,name,func) (name),
7500 #include "metadata/icall-def.h"
7501 #undef ICALL
7503 static const guint16 icall_names_idx [] = {
7504 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7505 #include "metadata/icall-def.h"
7506 #undef ICALL
7508 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7510 #else
7512 #undef ICALL_TYPE
7513 #undef ICALL
7514 #define ICALL_TYPE(id,name,first) name,
7515 #define ICALL(id,name,func)
7516 static const char* const
7517 icall_type_names [] = {
7518 #include "metadata/icall-def.h"
7519 NULL
7522 #define icall_type_name_get(id) (icall_type_names [(id)])
7524 #undef ICALL_TYPE
7525 #undef ICALL
7526 #define ICALL_TYPE(id,name,first)
7527 #define ICALL(id,name,func) name,
7528 static const char* const
7529 icall_names [] = {
7530 #include "metadata/icall-def.h"
7531 NULL
7533 #define icall_name_get(id) icall_names [(id)]
7535 #endif /* !HAVE_ARRAY_ELEM_INIT */
7537 #undef ICALL_TYPE
7538 #undef ICALL
7539 #define ICALL_TYPE(id,name,first)
7540 #define ICALL(id,name,func) func,
7541 static const gconstpointer
7542 icall_functions [] = {
7543 #include "metadata/icall-def.h"
7544 NULL
7547 static GHashTable *icall_hash = NULL;
7548 static GHashTable *jit_icall_hash_name = NULL;
7549 static GHashTable *jit_icall_hash_addr = NULL;
7551 void
7552 mono_icall_init (void)
7554 int i = 0;
7556 /* check that tables are sorted: disable in release */
7557 if (TRUE) {
7558 int j;
7559 const char *prev_class = NULL;
7560 const char *prev_method;
7562 for (i = 0; i < Icall_type_num; ++i) {
7563 const IcallTypeDesc *desc;
7564 int num_icalls;
7565 prev_method = NULL;
7566 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7567 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7568 prev_class = icall_type_name_get (i);
7569 desc = &icall_type_descs [i];
7570 num_icalls = icall_desc_num_icalls (desc);
7571 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7572 for (j = 0; j < num_icalls; ++j) {
7573 const char *methodn = icall_name_get (desc->first_icall + j);
7574 if (prev_method && strcmp (prev_method, methodn) >= 0)
7575 g_print ("method %s should come before method %s\n", methodn, prev_method);
7576 prev_method = methodn;
7581 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7584 void
7585 mono_icall_cleanup (void)
7587 g_hash_table_destroy (icall_hash);
7588 g_hash_table_destroy (jit_icall_hash_name);
7589 g_hash_table_destroy (jit_icall_hash_addr);
7592 void
7593 mono_add_internal_call (const char *name, gconstpointer method)
7595 mono_loader_lock ();
7597 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7599 mono_loader_unlock ();
7602 #ifdef HAVE_ARRAY_ELEM_INIT
7603 static int
7604 compare_method_imap (const void *key, const void *elem)
7606 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7607 return strcmp (key, method_name);
7610 static gpointer
7611 find_method_icall (const IcallTypeDesc *imap, const char *name)
7613 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7614 if (!nameslot)
7615 return NULL;
7616 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7619 static int
7620 compare_class_imap (const void *key, const void *elem)
7622 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7623 return strcmp (key, class_name);
7626 static const IcallTypeDesc*
7627 find_class_icalls (const char *name)
7629 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7630 if (!nameslot)
7631 return NULL;
7632 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7635 #else
7636 static int
7637 compare_method_imap (const void *key, const void *elem)
7639 const char** method_name = (const char**)elem;
7640 return strcmp (key, *method_name);
7643 static gpointer
7644 find_method_icall (const IcallTypeDesc *imap, const char *name)
7646 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7647 if (!nameslot)
7648 return NULL;
7649 return (gpointer)icall_functions [(nameslot - icall_names)];
7652 static int
7653 compare_class_imap (const void *key, const void *elem)
7655 const char** class_name = (const char**)elem;
7656 return strcmp (key, *class_name);
7659 static const IcallTypeDesc*
7660 find_class_icalls (const char *name)
7662 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7663 if (!nameslot)
7664 return NULL;
7665 return &icall_type_descs [nameslot - icall_type_names];
7668 #endif
7671 * we should probably export this as an helper (handle nested types).
7672 * Returns the number of chars written in buf.
7674 static int
7675 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7677 int nspacelen, cnamelen;
7678 nspacelen = strlen (klass->name_space);
7679 cnamelen = strlen (klass->name);
7680 if (nspacelen + cnamelen + 2 > bufsize)
7681 return 0;
7682 if (nspacelen) {
7683 memcpy (buf, klass->name_space, nspacelen);
7684 buf [nspacelen ++] = '.';
7686 memcpy (buf + nspacelen, klass->name, cnamelen);
7687 buf [nspacelen + cnamelen] = 0;
7688 return nspacelen + cnamelen;
7691 gpointer
7692 mono_lookup_internal_call (MonoMethod *method)
7694 char *sigstart;
7695 char *tmpsig;
7696 char mname [2048];
7697 int typelen = 0, mlen, siglen;
7698 gpointer res;
7699 const IcallTypeDesc *imap;
7701 g_assert (method != NULL);
7703 if (method->is_inflated)
7704 method = ((MonoMethodInflated *) method)->declaring;
7706 if (method->klass->nested_in) {
7707 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7708 if (!pos)
7709 return NULL;
7711 mname [pos++] = '/';
7712 mname [pos] = 0;
7714 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7715 if (!typelen)
7716 return NULL;
7718 typelen += pos;
7719 } else {
7720 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7721 if (!typelen)
7722 return NULL;
7725 imap = find_class_icalls (mname);
7727 mname [typelen] = ':';
7728 mname [typelen + 1] = ':';
7730 mlen = strlen (method->name);
7731 memcpy (mname + typelen + 2, method->name, mlen);
7732 sigstart = mname + typelen + 2 + mlen;
7733 *sigstart = 0;
7735 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7736 siglen = strlen (tmpsig);
7737 if (typelen + mlen + siglen + 6 > sizeof (mname))
7738 return NULL;
7739 sigstart [0] = '(';
7740 memcpy (sigstart + 1, tmpsig, siglen);
7741 sigstart [siglen + 1] = ')';
7742 sigstart [siglen + 2] = 0;
7743 g_free (tmpsig);
7745 mono_loader_lock ();
7747 res = g_hash_table_lookup (icall_hash, mname);
7748 if (res) {
7749 mono_loader_unlock ();
7750 return res;
7752 /* try without signature */
7753 *sigstart = 0;
7754 res = g_hash_table_lookup (icall_hash, mname);
7755 if (res) {
7756 mono_loader_unlock ();
7757 return res;
7760 /* it wasn't found in the static call tables */
7761 if (!imap) {
7762 mono_loader_unlock ();
7763 return NULL;
7765 res = find_method_icall (imap, sigstart - mlen);
7766 if (res) {
7767 mono_loader_unlock ();
7768 return res;
7770 /* try _with_ signature */
7771 *sigstart = '(';
7772 res = find_method_icall (imap, sigstart - mlen);
7773 if (res) {
7774 mono_loader_unlock ();
7775 return res;
7778 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7779 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7780 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7781 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7782 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");
7783 g_print ("If you see other errors or faults after this message they are probably related\n");
7784 g_print ("and you need to fix your mono install first.\n");
7786 mono_loader_unlock ();
7788 return NULL;
7791 static MonoType*
7792 type_from_typename (char *typename)
7794 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7796 if (!strcmp (typename, "int"))
7797 klass = mono_defaults.int_class;
7798 else if (!strcmp (typename, "ptr"))
7799 klass = mono_defaults.int_class;
7800 else if (!strcmp (typename, "void"))
7801 klass = mono_defaults.void_class;
7802 else if (!strcmp (typename, "int32"))
7803 klass = mono_defaults.int32_class;
7804 else if (!strcmp (typename, "uint32"))
7805 klass = mono_defaults.uint32_class;
7806 else if (!strcmp (typename, "int8"))
7807 klass = mono_defaults.sbyte_class;
7808 else if (!strcmp (typename, "uint8"))
7809 klass = mono_defaults.byte_class;
7810 else if (!strcmp (typename, "int16"))
7811 klass = mono_defaults.int16_class;
7812 else if (!strcmp (typename, "uint16"))
7813 klass = mono_defaults.uint16_class;
7814 else if (!strcmp (typename, "long"))
7815 klass = mono_defaults.int64_class;
7816 else if (!strcmp (typename, "ulong"))
7817 klass = mono_defaults.uint64_class;
7818 else if (!strcmp (typename, "float"))
7819 klass = mono_defaults.single_class;
7820 else if (!strcmp (typename, "double"))
7821 klass = mono_defaults.double_class;
7822 else if (!strcmp (typename, "object"))
7823 klass = mono_defaults.object_class;
7824 else if (!strcmp (typename, "obj"))
7825 klass = mono_defaults.object_class;
7826 else if (!strcmp (typename, "string"))
7827 klass = mono_defaults.string_class;
7828 else if (!strcmp (typename, "bool"))
7829 klass = mono_defaults.boolean_class;
7830 else if (!strcmp (typename, "boolean"))
7831 klass = mono_defaults.boolean_class;
7832 else {
7833 g_error ("%s", typename);
7834 g_assert_not_reached ();
7836 return &klass->byval_arg;
7839 MonoMethodSignature*
7840 mono_create_icall_signature (const char *sigstr)
7842 gchar **parts;
7843 int i, len;
7844 gchar **tmp;
7845 MonoMethodSignature *res;
7847 mono_loader_lock ();
7848 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7849 if (res) {
7850 mono_loader_unlock ();
7851 return res;
7854 parts = g_strsplit (sigstr, " ", 256);
7856 tmp = parts;
7857 len = 0;
7858 while (*tmp) {
7859 len ++;
7860 tmp ++;
7863 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7864 res->pinvoke = 1;
7866 #ifdef HOST_WIN32
7868 * Under windows, the default pinvoke calling convention is STDCALL but
7869 * we need CDECL.
7871 res->call_convention = MONO_CALL_C;
7872 #endif
7874 res->ret = type_from_typename (parts [0]);
7875 for (i = 1; i < len; ++i) {
7876 res->params [i - 1] = type_from_typename (parts [i]);
7879 g_strfreev (parts);
7881 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7883 mono_loader_unlock ();
7885 return res;
7888 MonoJitICallInfo *
7889 mono_find_jit_icall_by_name (const char *name)
7891 MonoJitICallInfo *info;
7892 g_assert (jit_icall_hash_name);
7894 mono_loader_lock ();
7895 info = g_hash_table_lookup (jit_icall_hash_name, name);
7896 mono_loader_unlock ();
7897 return info;
7900 MonoJitICallInfo *
7901 mono_find_jit_icall_by_addr (gconstpointer addr)
7903 MonoJitICallInfo *info;
7904 g_assert (jit_icall_hash_addr);
7906 mono_loader_lock ();
7907 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7908 mono_loader_unlock ();
7910 return info;
7914 * mono_get_jit_icall_info:
7916 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7917 * caller should access it while holding the loader lock.
7919 GHashTable*
7920 mono_get_jit_icall_info (void)
7922 return jit_icall_hash_name;
7925 void
7926 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7928 mono_loader_lock ();
7929 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7930 mono_loader_unlock ();
7933 MonoJitICallInfo *
7934 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7936 MonoJitICallInfo *info;
7938 g_assert (func);
7939 g_assert (name);
7941 mono_loader_lock ();
7943 if (!jit_icall_hash_name) {
7944 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7945 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7948 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7949 g_warning ("jit icall already defined \"%s\"\n", name);
7950 g_assert_not_reached ();
7953 info = g_new0 (MonoJitICallInfo, 1);
7955 info->name = name;
7956 info->func = func;
7957 info->sig = sig;
7959 if (is_save) {
7960 info->wrapper = func;
7961 } else {
7962 info->wrapper = NULL;
7965 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7966 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7968 mono_loader_unlock ();
7969 return info;