2010-04-14 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / icall.c
blob06f00f0f637ad229a639ef2ef5e6ff3447614884
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 (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2714 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2715 return NULL;
2718 if (this) {
2719 if (!mono_object_isinst (this, m->klass)) {
2720 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2721 return NULL;
2723 m = mono_object_get_virtual_method (this, m);
2724 /* must pass the pointer to the value for valuetype methods */
2725 if (m->klass->valuetype)
2726 obj = mono_object_unbox (this);
2727 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2728 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2729 return NULL;
2733 pcount = params? mono_array_length (params): 0;
2734 if (pcount != mono_method_signature (m)->param_count) {
2735 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2736 return NULL;
2739 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2740 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."));
2741 return NULL;
2744 if (m->klass->image->assembly->ref_only) {
2745 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."));
2746 return NULL;
2749 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2750 int i;
2751 uintptr_t *lengths;
2752 intptr_t *lower_bounds;
2753 pcount = mono_array_length (params);
2754 lengths = alloca (sizeof (uintptr_t) * pcount);
2755 /* Note: the synthetized array .ctors have int32 as argument type */
2756 for (i = 0; i < pcount; ++i)
2757 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2759 if (m->klass->rank == pcount) {
2760 /* Only lengths provided. */
2761 lower_bounds = NULL;
2762 } else {
2763 g_assert (pcount == (m->klass->rank * 2));
2764 /* lower bounds are first. */
2765 lower_bounds = (intptr_t*)lengths;
2766 lengths += m->klass->rank;
2769 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2771 return mono_runtime_invoke_array (m, obj, params, NULL);
2774 static MonoObject *
2775 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2777 MonoDomain *domain = mono_object_domain (method);
2778 MonoMethod *m = method->method;
2779 MonoMethodSignature *sig = mono_method_signature (m);
2780 MonoArray *out_args;
2781 MonoObject *result;
2782 int i, j, outarg_count = 0;
2784 MONO_ARCH_SAVE_REGS;
2786 if (m->klass == mono_defaults.object_class) {
2788 if (!strcmp (m->name, "FieldGetter")) {
2789 MonoClass *k = this->vtable->klass;
2790 MonoString *name;
2791 char *str;
2793 /* If this is a proxy, then it must be a CBO */
2794 if (k == mono_defaults.transparent_proxy_class) {
2795 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2796 this = tp->rp->unwrapped_server;
2797 g_assert (this);
2798 k = this->vtable->klass;
2801 name = mono_array_get (params, MonoString *, 1);
2802 str = mono_string_to_utf8 (name);
2804 do {
2805 MonoClassField* field = mono_class_get_field_from_name (k, str);
2806 if (field) {
2807 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2808 if (field_klass->valuetype)
2809 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2810 else
2811 result = *((gpointer *)((char *)this + field->offset));
2813 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2814 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2815 mono_array_setref (out_args, 0, result);
2816 g_free (str);
2817 return NULL;
2819 k = k->parent;
2820 } while (k);
2822 g_free (str);
2823 g_assert_not_reached ();
2825 } else if (!strcmp (m->name, "FieldSetter")) {
2826 MonoClass *k = this->vtable->klass;
2827 MonoString *name;
2828 guint32 size;
2829 gint32 align;
2830 char *str;
2832 /* If this is a proxy, then it must be a CBO */
2833 if (k == mono_defaults.transparent_proxy_class) {
2834 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2835 this = tp->rp->unwrapped_server;
2836 g_assert (this);
2837 k = this->vtable->klass;
2840 name = mono_array_get (params, MonoString *, 1);
2841 str = mono_string_to_utf8 (name);
2843 do {
2844 MonoClassField* field = mono_class_get_field_from_name (k, str);
2845 if (field) {
2846 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2847 MonoObject *val = mono_array_get (params, gpointer, 2);
2849 if (field_klass->valuetype) {
2850 size = mono_type_size (field->type, &align);
2851 g_assert (size == mono_class_value_size (field_klass, NULL));
2852 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2853 } else {
2854 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2857 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2858 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2860 g_free (str);
2861 return NULL;
2864 k = k->parent;
2865 } while (k);
2867 g_free (str);
2868 g_assert_not_reached ();
2873 for (i = 0; i < mono_array_length (params); i++) {
2874 if (sig->params [i]->byref)
2875 outarg_count++;
2878 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2880 /* handle constructors only for objects already allocated */
2881 if (!strcmp (method->method->name, ".ctor"))
2882 g_assert (this);
2884 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2885 g_assert (!method->method->klass->valuetype);
2886 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2888 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2889 if (sig->params [i]->byref) {
2890 gpointer arg;
2891 arg = mono_array_get (params, gpointer, i);
2892 mono_array_setref (out_args, j, arg);
2893 j++;
2897 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2899 return result;
2902 static guint64
2903 read_enum_value (char *mem, int type)
2905 switch (type) {
2906 case MONO_TYPE_U1:
2907 return *(guint8*)mem;
2908 case MONO_TYPE_I1:
2909 return *(gint8*)mem;
2910 case MONO_TYPE_U2:
2911 return *(guint16*)mem;
2912 case MONO_TYPE_I2:
2913 return *(gint16*)mem;
2914 case MONO_TYPE_U4:
2915 return *(guint32*)mem;
2916 case MONO_TYPE_I4:
2917 return *(gint32*)mem;
2918 case MONO_TYPE_U8:
2919 return *(guint64*)mem;
2920 case MONO_TYPE_I8:
2921 return *(gint64*)mem;
2922 default:
2923 g_assert_not_reached ();
2925 return 0;
2928 static void
2929 write_enum_value (char *mem, int type, guint64 value)
2931 switch (type) {
2932 case MONO_TYPE_U1:
2933 case MONO_TYPE_I1: {
2934 guint8 *p = (guint8*)mem;
2935 *p = value;
2936 break;
2938 case MONO_TYPE_U2:
2939 case MONO_TYPE_I2: {
2940 guint16 *p = (void*)mem;
2941 *p = value;
2942 break;
2944 case MONO_TYPE_U4:
2945 case MONO_TYPE_I4: {
2946 guint32 *p = (void*)mem;
2947 *p = value;
2948 break;
2950 case MONO_TYPE_U8:
2951 case MONO_TYPE_I8: {
2952 guint64 *p = (void*)mem;
2953 *p = value;
2954 break;
2956 default:
2957 g_assert_not_reached ();
2959 return;
2962 static MonoObject *
2963 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
2965 MonoDomain *domain;
2966 MonoClass *enumc, *objc;
2967 MonoObject *res;
2968 MonoType *etype;
2969 guint64 val;
2971 MONO_ARCH_SAVE_REGS;
2973 MONO_CHECK_ARG_NULL (enumType);
2974 MONO_CHECK_ARG_NULL (value);
2976 domain = mono_object_domain (enumType);
2977 enumc = mono_class_from_mono_type (enumType->type);
2978 objc = value->vtable->klass;
2980 if (!enumc->enumtype)
2981 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
2982 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
2983 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."));
2985 etype = mono_class_enum_basetype (enumc);
2986 if (!etype)
2987 /* MS throws this for typebuilders */
2988 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
2990 res = mono_object_new (domain, enumc);
2991 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
2992 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
2994 return res;
2997 static MonoObject *
2998 ves_icall_System_Enum_get_value (MonoObject *this)
3000 MonoObject *res;
3001 MonoClass *enumc;
3002 gpointer dst;
3003 gpointer src;
3004 int size;
3006 MONO_ARCH_SAVE_REGS;
3008 if (!this)
3009 return NULL;
3011 g_assert (this->vtable->klass->enumtype);
3013 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3014 res = mono_object_new (mono_object_domain (this), enumc);
3015 dst = (char *)res + sizeof (MonoObject);
3016 src = (char *)this + sizeof (MonoObject);
3017 size = mono_class_value_size (enumc, NULL);
3019 memcpy (dst, src, size);
3021 return res;
3024 static MonoReflectionType *
3025 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3027 MonoType *etype;
3029 MONO_ARCH_SAVE_REGS;
3031 etype = mono_class_enum_basetype (mono_class_from_mono_type (type->type));
3032 if (!etype)
3033 /* MS throws this for typebuilders */
3034 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3036 return mono_type_get_object (mono_object_domain (type), etype);
3039 static int
3040 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3042 gpointer tdata = (char *)this + sizeof (MonoObject);
3043 gpointer odata = (char *)other + sizeof (MonoObject);
3044 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3045 g_assert (basetype);
3047 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3048 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3049 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3050 if (me == other) \
3051 return 0; \
3052 return me > other ? 1 : -1; \
3053 } while (0)
3055 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3056 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3057 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3058 if (me == other) \
3059 return 0; \
3060 return me - other; \
3061 } while (0)
3063 switch (basetype->type) {
3064 case MONO_TYPE_U1:
3065 COMPARE_ENUM_VALUES (guint8);
3066 case MONO_TYPE_I1:
3067 COMPARE_ENUM_VALUES (gint8);
3068 case MONO_TYPE_CHAR:
3069 case MONO_TYPE_U2:
3070 COMPARE_ENUM_VALUES_RANGE (guint16);
3071 case MONO_TYPE_I2:
3072 COMPARE_ENUM_VALUES (gint16);
3073 case MONO_TYPE_U4:
3074 COMPARE_ENUM_VALUES (guint32);
3075 case MONO_TYPE_I4:
3076 COMPARE_ENUM_VALUES (gint32);
3077 case MONO_TYPE_U8:
3078 COMPARE_ENUM_VALUES (guint64);
3079 case MONO_TYPE_I8:
3080 COMPARE_ENUM_VALUES (gint64);
3081 default:
3082 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3084 #undef COMPARE_ENUM_VALUES_RANGE
3085 #undef COMPARE_ENUM_VALUES
3086 return 0;
3089 static int
3090 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3092 gpointer data = (char *)this + sizeof (MonoObject);
3093 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3094 g_assert (basetype);
3096 switch (basetype->type) {
3097 case MONO_TYPE_I1:
3098 return *((gint8*)data);
3099 case MONO_TYPE_U1:
3100 return *((guint8*)data);
3101 case MONO_TYPE_CHAR:
3102 case MONO_TYPE_U2:
3103 return *((guint16*)data);
3105 case MONO_TYPE_I2:
3106 return *((gint16*)data);
3107 case MONO_TYPE_U4:
3108 return *((guint32*)data);
3109 case MONO_TYPE_I4:
3110 return *((gint32*)data);
3111 case MONO_TYPE_U8:
3112 case MONO_TYPE_I8: {
3113 gint64 value = *((gint64*)data);
3114 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3116 default:
3117 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3119 return 0;
3122 static void
3123 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3125 MonoDomain *domain = mono_object_domain (type);
3126 MonoClass *enumc = mono_class_from_mono_type (type->type);
3127 guint j = 0, nvalues, crow;
3128 gpointer iter;
3129 MonoClassField *field;
3131 MONO_ARCH_SAVE_REGS;
3133 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3134 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3135 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3136 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3138 crow = -1;
3139 iter = NULL;
3140 while ((field = mono_class_get_fields (enumc, &iter))) {
3141 const char *p;
3142 int len;
3143 MonoTypeEnum def_type;
3145 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3146 continue;
3147 if (mono_field_is_deleted (field))
3148 continue;
3149 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3151 p = mono_class_get_field_default_value (field, &def_type);
3152 len = mono_metadata_decode_blob_size (p, &p);
3153 switch (mono_class_enum_basetype (enumc)->type) {
3154 case MONO_TYPE_U1:
3155 case MONO_TYPE_I1:
3156 mono_array_set (info->values, gchar, j, *p);
3157 break;
3158 case MONO_TYPE_CHAR:
3159 case MONO_TYPE_U2:
3160 case MONO_TYPE_I2:
3161 mono_array_set (info->values, gint16, j, read16 (p));
3162 break;
3163 case MONO_TYPE_U4:
3164 case MONO_TYPE_I4:
3165 mono_array_set (info->values, gint32, j, read32 (p));
3166 break;
3167 case MONO_TYPE_U8:
3168 case MONO_TYPE_I8:
3169 mono_array_set (info->values, gint64, j, read64 (p));
3170 break;
3171 default:
3172 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3174 ++j;
3178 enum {
3179 BFLAGS_IgnoreCase = 1,
3180 BFLAGS_DeclaredOnly = 2,
3181 BFLAGS_Instance = 4,
3182 BFLAGS_Static = 8,
3183 BFLAGS_Public = 0x10,
3184 BFLAGS_NonPublic = 0x20,
3185 BFLAGS_FlattenHierarchy = 0x40,
3186 BFLAGS_InvokeMethod = 0x100,
3187 BFLAGS_CreateInstance = 0x200,
3188 BFLAGS_GetField = 0x400,
3189 BFLAGS_SetField = 0x800,
3190 BFLAGS_GetProperty = 0x1000,
3191 BFLAGS_SetProperty = 0x2000,
3192 BFLAGS_ExactBinding = 0x10000,
3193 BFLAGS_SuppressChangeType = 0x20000,
3194 BFLAGS_OptionalParamBinding = 0x40000
3197 static MonoReflectionField *
3198 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3200 MonoDomain *domain;
3201 MonoClass *startklass, *klass;
3202 int match;
3203 MonoClassField *field;
3204 gpointer iter;
3205 char *utf8_name;
3206 int (*compare_func) (const char *s1, const char *s2) = NULL;
3207 domain = ((MonoObject *)type)->vtable->domain;
3208 klass = startklass = mono_class_from_mono_type (type->type);
3210 MONO_ARCH_SAVE_REGS;
3212 if (!name)
3213 mono_raise_exception (mono_get_exception_argument_null ("name"));
3214 if (type->type->byref)
3215 return NULL;
3217 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3219 handle_parent:
3220 if (klass->exception_type != MONO_EXCEPTION_NONE)
3221 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3223 iter = NULL;
3224 while ((field = mono_class_get_fields (klass, &iter))) {
3225 match = 0;
3227 if (field->type == NULL)
3228 continue;
3229 if (mono_field_is_deleted (field))
3230 continue;
3231 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3232 if (bflags & BFLAGS_Public)
3233 match++;
3234 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3235 if (bflags & BFLAGS_NonPublic) {
3236 match++;
3239 if (!match)
3240 continue;
3241 match = 0;
3242 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3243 if (bflags & BFLAGS_Static)
3244 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3245 match++;
3246 } else {
3247 if (bflags & BFLAGS_Instance)
3248 match++;
3251 if (!match)
3252 continue;
3254 utf8_name = mono_string_to_utf8 (name);
3256 if (compare_func (mono_field_get_name (field), utf8_name)) {
3257 g_free (utf8_name);
3258 continue;
3260 g_free (utf8_name);
3262 return mono_field_get_object (domain, klass, field);
3264 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3265 goto handle_parent;
3267 return NULL;
3270 static MonoArray*
3271 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3273 MonoDomain *domain;
3274 MonoClass *startklass, *klass, *refklass;
3275 MonoArray *res;
3276 MonoObject *member;
3277 int i, match;
3278 gpointer iter;
3279 MonoClassField *field;
3280 MonoPtrArray tmp_array;
3282 MONO_ARCH_SAVE_REGS;
3284 domain = ((MonoObject *)type)->vtable->domain;
3285 if (type->type->byref)
3286 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3287 klass = startklass = mono_class_from_mono_type (type->type);
3288 refklass = mono_class_from_mono_type (reftype->type);
3290 mono_ptr_array_init (tmp_array, 2);
3292 handle_parent:
3293 if (klass->exception_type != MONO_EXCEPTION_NONE)
3294 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3296 iter = NULL;
3297 while ((field = mono_class_get_fields (klass, &iter))) {
3298 match = 0;
3299 if (mono_field_is_deleted (field))
3300 continue;
3301 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3302 if (bflags & BFLAGS_Public)
3303 match++;
3304 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3305 if (bflags & BFLAGS_NonPublic) {
3306 match++;
3309 if (!match)
3310 continue;
3311 match = 0;
3312 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3313 if (bflags & BFLAGS_Static)
3314 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3315 match++;
3316 } else {
3317 if (bflags & BFLAGS_Instance)
3318 match++;
3321 if (!match)
3322 continue;
3323 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3324 mono_ptr_array_append (tmp_array, member);
3326 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3327 goto handle_parent;
3329 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3331 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3332 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3334 mono_ptr_array_destroy (tmp_array);
3336 return res;
3339 static gboolean
3340 method_nonpublic (MonoMethod* method, gboolean start_klass)
3342 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3343 case METHOD_ATTRIBUTE_ASSEM:
3344 return (start_klass || mono_defaults.generic_ilist_class);
3345 case METHOD_ATTRIBUTE_PRIVATE:
3346 return start_klass;
3347 case METHOD_ATTRIBUTE_PUBLIC:
3348 return FALSE;
3349 default:
3350 return TRUE;
3354 static MonoArray*
3355 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3357 static MonoClass *MethodInfo_array;
3358 MonoDomain *domain;
3359 MonoClass *startklass, *klass, *refklass;
3360 MonoArray *res;
3361 MonoMethod *method;
3362 gpointer iter;
3363 MonoObject *member;
3364 int i, len, match, nslots;
3365 /*FIXME, use MonoBitSet*/
3366 guint32 method_slots_default [8];
3367 guint32 *method_slots = NULL;
3368 gchar *mname = NULL;
3369 int (*compare_func) (const char *s1, const char *s2) = NULL;
3370 MonoVTable *array_vtable;
3371 MonoException *ex;
3372 MonoPtrArray tmp_array;
3374 MONO_ARCH_SAVE_REGS;
3376 mono_ptr_array_init (tmp_array, 4);
3378 if (!MethodInfo_array) {
3379 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3380 mono_memory_barrier ();
3381 MethodInfo_array = klass;
3384 domain = ((MonoObject *)type)->vtable->domain;
3385 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3386 if (type->type->byref)
3387 return mono_array_new_specific (array_vtable, 0);
3388 klass = startklass = mono_class_from_mono_type (type->type);
3389 refklass = mono_class_from_mono_type (reftype->type);
3390 len = 0;
3391 if (name != NULL) {
3392 mname = mono_string_to_utf8 (name);
3393 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3396 /* An optimization for calls made from Delegate:CreateDelegate () */
3397 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3398 method = mono_get_delegate_invoke (klass);
3399 if (mono_loader_get_last_error ())
3400 goto loader_error;
3402 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3404 res = mono_array_new_specific (array_vtable, 1);
3405 mono_array_setref (res, 0, member);
3406 g_free (mname);
3407 return res;
3410 mono_class_setup_vtable (klass);
3411 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3412 goto loader_error;
3414 if (is_generic_parameter (type->type))
3415 nslots = mono_class_get_vtable_size (klass->parent);
3416 else
3417 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3418 if (nslots >= sizeof (method_slots_default) * 8) {
3419 method_slots = g_new0 (guint32, nslots / 32 + 1);
3420 } else {
3421 method_slots = method_slots_default;
3422 memset (method_slots, 0, sizeof (method_slots_default));
3424 handle_parent:
3425 mono_class_setup_vtable (klass);
3426 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3427 goto loader_error;
3429 iter = NULL;
3430 while ((method = mono_class_get_methods (klass, &iter))) {
3431 match = 0;
3432 if (method->slot != -1) {
3433 g_assert (method->slot < nslots);
3434 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3435 continue;
3436 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3437 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3440 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3441 continue;
3442 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3443 if (bflags & BFLAGS_Public)
3444 match++;
3445 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3446 match++;
3448 if (!match)
3449 continue;
3450 match = 0;
3451 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3452 if (bflags & BFLAGS_Static)
3453 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3454 match++;
3455 } else {
3456 if (bflags & BFLAGS_Instance)
3457 match++;
3460 if (!match)
3461 continue;
3463 if (name != NULL) {
3464 if (compare_func (mname, method->name))
3465 continue;
3468 match = 0;
3470 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3472 mono_ptr_array_append (tmp_array, member);
3474 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3475 goto handle_parent;
3477 g_free (mname);
3478 if (method_slots != method_slots_default)
3479 g_free (method_slots);
3481 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3483 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3484 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3486 mono_ptr_array_destroy (tmp_array);
3487 return res;
3489 loader_error:
3490 g_free (mname);
3491 if (method_slots != method_slots_default)
3492 g_free (method_slots);
3493 mono_ptr_array_destroy (tmp_array);
3494 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3495 ex = mono_class_get_exception_for_failure (klass);
3496 } else {
3497 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3498 mono_loader_clear_error ();
3500 mono_raise_exception (ex);
3501 return NULL;
3504 static MonoArray*
3505 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3507 MonoDomain *domain;
3508 static MonoClass *System_Reflection_ConstructorInfo;
3509 MonoClass *startklass, *klass, *refklass;
3510 MonoArray *res;
3511 MonoMethod *method;
3512 MonoObject *member;
3513 int i, match;
3514 gpointer iter = NULL;
3515 MonoPtrArray tmp_array;
3517 MONO_ARCH_SAVE_REGS;
3519 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3521 domain = ((MonoObject *)type)->vtable->domain;
3522 if (type->type->byref)
3523 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3524 klass = startklass = mono_class_from_mono_type (type->type);
3525 refklass = mono_class_from_mono_type (reftype->type);
3527 if (klass->exception_type != MONO_EXCEPTION_NONE)
3528 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3530 if (!System_Reflection_ConstructorInfo)
3531 System_Reflection_ConstructorInfo = mono_class_from_name (
3532 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3534 iter = NULL;
3535 while ((method = mono_class_get_methods (klass, &iter))) {
3536 match = 0;
3537 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3538 continue;
3539 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3540 if (bflags & BFLAGS_Public)
3541 match++;
3542 } else {
3543 if (bflags & BFLAGS_NonPublic)
3544 match++;
3546 if (!match)
3547 continue;
3548 match = 0;
3549 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3550 if (bflags & BFLAGS_Static)
3551 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3552 match++;
3553 } else {
3554 if (bflags & BFLAGS_Instance)
3555 match++;
3558 if (!match)
3559 continue;
3560 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3562 mono_ptr_array_append (tmp_array, member);
3565 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3567 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3568 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3570 mono_ptr_array_destroy (tmp_array);
3572 return res;
3575 static guint
3576 property_hash (gconstpointer data)
3578 MonoProperty *prop = (MonoProperty*)data;
3580 return g_str_hash (prop->name);
3583 static gboolean
3584 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3586 // Properties are hide-by-name-and-signature
3587 if (!g_str_equal (prop1->name, prop2->name))
3588 return FALSE;
3590 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3591 return FALSE;
3592 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3593 return FALSE;
3594 return TRUE;
3597 static gboolean
3598 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3600 if (!accessor)
3601 return FALSE;
3603 return method_nonpublic (accessor, start_klass);
3606 static MonoArray*
3607 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3609 MonoDomain *domain;
3610 static MonoClass *System_Reflection_PropertyInfo;
3611 MonoClass *startklass, *klass;
3612 MonoArray *res;
3613 MonoMethod *method;
3614 MonoProperty *prop;
3615 int i, match;
3616 guint32 flags;
3617 gchar *propname = NULL;
3618 int (*compare_func) (const char *s1, const char *s2) = NULL;
3619 gpointer iter;
3620 GHashTable *properties;
3621 MonoPtrArray tmp_array;
3623 MONO_ARCH_SAVE_REGS;
3625 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3627 if (!System_Reflection_PropertyInfo)
3628 System_Reflection_PropertyInfo = mono_class_from_name (
3629 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3631 domain = ((MonoObject *)type)->vtable->domain;
3632 if (type->type->byref)
3633 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3634 klass = startklass = mono_class_from_mono_type (type->type);
3635 if (name != NULL) {
3636 propname = mono_string_to_utf8 (name);
3637 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3640 mono_class_setup_vtable (klass);
3642 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3643 handle_parent:
3644 mono_class_setup_vtable (klass);
3645 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3646 g_hash_table_destroy (properties);
3647 if (name != NULL)
3648 g_free (propname);
3649 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3652 iter = NULL;
3653 while ((prop = mono_class_get_properties (klass, &iter))) {
3654 match = 0;
3655 method = prop->get;
3656 if (!method)
3657 method = prop->set;
3658 if (method)
3659 flags = method->flags;
3660 else
3661 flags = 0;
3662 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3663 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3664 if (bflags & BFLAGS_Public)
3665 match++;
3666 } else if (bflags & BFLAGS_NonPublic) {
3667 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3668 property_accessor_nonpublic(prop->set, startklass == klass)) {
3669 match++;
3672 if (!match)
3673 continue;
3674 match = 0;
3675 if (flags & METHOD_ATTRIBUTE_STATIC) {
3676 if (bflags & BFLAGS_Static)
3677 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3678 match++;
3679 } else {
3680 if (bflags & BFLAGS_Instance)
3681 match++;
3684 if (!match)
3685 continue;
3686 match = 0;
3688 if (name != NULL) {
3689 if (compare_func (propname, prop->name))
3690 continue;
3693 if (g_hash_table_lookup (properties, prop))
3694 continue;
3696 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3698 g_hash_table_insert (properties, prop, prop);
3700 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3701 goto handle_parent;
3703 g_hash_table_destroy (properties);
3704 g_free (propname);
3706 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3707 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3708 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3710 mono_ptr_array_destroy (tmp_array);
3712 return res;
3715 static MonoReflectionEvent *
3716 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3718 MonoDomain *domain;
3719 MonoClass *klass, *startklass;
3720 gpointer iter;
3721 MonoEvent *event;
3722 MonoMethod *method;
3723 gchar *event_name;
3725 MONO_ARCH_SAVE_REGS;
3727 event_name = mono_string_to_utf8 (name);
3728 if (type->type->byref)
3729 return NULL;
3730 klass = startklass = mono_class_from_mono_type (type->type);
3731 domain = mono_object_domain (type);
3733 handle_parent:
3734 if (klass->exception_type != MONO_EXCEPTION_NONE)
3735 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3737 iter = NULL;
3738 while ((event = mono_class_get_events (klass, &iter))) {
3739 if (strcmp (event->name, event_name))
3740 continue;
3742 method = event->add;
3743 if (!method)
3744 method = event->remove;
3745 if (!method)
3746 method = event->raise;
3747 if (method) {
3748 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3749 if (!(bflags & BFLAGS_Public))
3750 continue;
3751 } else {
3752 if (!(bflags & BFLAGS_NonPublic))
3753 continue;
3754 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3755 continue;
3758 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3759 if (!(bflags & BFLAGS_Static))
3760 continue;
3761 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3762 continue;
3763 } else {
3764 if (!(bflags & BFLAGS_Instance))
3765 continue;
3767 } else
3768 if (!(bflags & BFLAGS_NonPublic))
3769 continue;
3771 g_free (event_name);
3772 return mono_event_get_object (domain, startklass, event);
3775 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3776 goto handle_parent;
3778 g_free (event_name);
3779 return NULL;
3782 static MonoArray*
3783 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3785 MonoDomain *domain;
3786 static MonoClass *System_Reflection_EventInfo;
3787 MonoClass *startklass, *klass;
3788 MonoArray *res;
3789 MonoMethod *method;
3790 MonoEvent *event;
3791 int i, match;
3792 gpointer iter;
3794 MonoPtrArray tmp_array;
3796 MONO_ARCH_SAVE_REGS;
3798 mono_ptr_array_init (tmp_array, 4);
3800 if (!System_Reflection_EventInfo)
3801 System_Reflection_EventInfo = mono_class_from_name (
3802 mono_defaults.corlib, "System.Reflection", "EventInfo");
3804 domain = mono_object_domain (type);
3805 if (type->type->byref)
3806 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3807 klass = startklass = mono_class_from_mono_type (type->type);
3809 handle_parent:
3810 if (klass->exception_type != MONO_EXCEPTION_NONE)
3811 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3813 iter = NULL;
3814 while ((event = mono_class_get_events (klass, &iter))) {
3815 match = 0;
3816 method = event->add;
3817 if (!method)
3818 method = event->remove;
3819 if (!method)
3820 method = event->raise;
3821 if (method) {
3822 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3823 if (bflags & BFLAGS_Public)
3824 match++;
3825 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3826 if (bflags & BFLAGS_NonPublic)
3827 match++;
3830 else
3831 if (bflags & BFLAGS_NonPublic)
3832 match ++;
3833 if (!match)
3834 continue;
3835 match = 0;
3836 if (method) {
3837 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3838 if (bflags & BFLAGS_Static)
3839 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3840 match++;
3841 } else {
3842 if (bflags & BFLAGS_Instance)
3843 match++;
3846 else
3847 if (bflags & BFLAGS_Instance)
3848 match ++;
3849 if (!match)
3850 continue;
3851 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3853 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3854 goto handle_parent;
3856 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3858 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3859 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3861 mono_ptr_array_destroy (tmp_array);
3863 return res;
3866 static MonoReflectionType *
3867 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3869 MonoDomain *domain;
3870 MonoClass *klass;
3871 MonoClass *nested;
3872 char *str;
3873 gpointer iter;
3875 MONO_ARCH_SAVE_REGS;
3877 if (name == NULL)
3878 mono_raise_exception (mono_get_exception_argument_null ("name"));
3880 domain = ((MonoObject *)type)->vtable->domain;
3881 if (type->type->byref)
3882 return NULL;
3883 klass = mono_class_from_mono_type (type->type);
3884 str = mono_string_to_utf8 (name);
3886 handle_parent:
3887 if (klass->exception_type != MONO_EXCEPTION_NONE)
3888 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3891 * If a nested type is generic, return its generic type definition.
3892 * Note that this means that the return value is essentially a
3893 * nested type of the generic type definition of @klass.
3895 * A note in MSDN claims that a generic type definition can have
3896 * nested types that aren't generic. In any case, the container of that
3897 * nested type would be the generic type definition.
3899 if (klass->generic_class)
3900 klass = klass->generic_class->container_class;
3902 iter = NULL;
3903 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3904 int match = 0;
3905 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3906 if (bflags & BFLAGS_Public)
3907 match++;
3908 } else {
3909 if (bflags & BFLAGS_NonPublic)
3910 match++;
3912 if (!match)
3913 continue;
3914 if (strcmp (nested->name, str) == 0){
3915 g_free (str);
3916 return mono_type_get_object (domain, &nested->byval_arg);
3919 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3920 goto handle_parent;
3921 g_free (str);
3922 return NULL;
3925 static MonoArray*
3926 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
3928 MonoDomain *domain;
3929 MonoClass *klass;
3930 MonoArray *res;
3931 MonoObject *member;
3932 int i, match;
3933 MonoClass *nested;
3934 gpointer iter;
3935 MonoPtrArray tmp_array;
3937 MONO_ARCH_SAVE_REGS;
3939 domain = ((MonoObject *)type)->vtable->domain;
3940 if (type->type->byref)
3941 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3942 klass = mono_class_from_mono_type (type->type);
3943 if (klass->exception_type != MONO_EXCEPTION_NONE)
3944 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3947 * If a nested type is generic, return its generic type definition.
3948 * Note that this means that the return value is essentially the set
3949 * of nested types of the generic type definition of @klass.
3951 * A note in MSDN claims that a generic type definition can have
3952 * nested types that aren't generic. In any case, the container of that
3953 * nested type would be the generic type definition.
3955 if (klass->generic_class)
3956 klass = klass->generic_class->container_class;
3958 mono_ptr_array_init (tmp_array, 1);
3959 iter = NULL;
3960 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3961 match = 0;
3962 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3963 if (bflags & BFLAGS_Public)
3964 match++;
3965 } else {
3966 if (bflags & BFLAGS_NonPublic)
3967 match++;
3969 if (!match)
3970 continue;
3971 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
3972 mono_ptr_array_append (tmp_array, member);
3975 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
3977 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3978 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3980 mono_ptr_array_destroy (tmp_array);
3982 return res;
3985 static MonoReflectionType*
3986 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
3988 gchar *str;
3989 MonoType *type = NULL;
3990 MonoTypeNameParse info;
3991 gboolean type_resolve;
3993 MONO_ARCH_SAVE_REGS;
3995 /* On MS.NET, this does not fire a TypeResolve event */
3996 type_resolve = TRUE;
3997 str = mono_string_to_utf8 (name);
3998 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
3999 if (!mono_reflection_parse_type (str, &info)) {
4000 g_free (str);
4001 mono_reflection_free_type_info (&info);
4002 if (throwOnError) /* uhm: this is a parse error, though... */
4003 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4004 /*g_print ("failed parse\n");*/
4005 return NULL;
4008 if (info.assembly.name) {
4009 g_free (str);
4010 mono_reflection_free_type_info (&info);
4011 if (throwOnError) {
4012 /* 1.0 and 2.0 throw different exceptions */
4013 if (mono_defaults.generic_ilist_class)
4014 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4015 else
4016 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4018 return NULL;
4021 if (module != NULL) {
4022 if (module->image)
4023 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4024 else
4025 type = NULL;
4027 else
4028 if (assembly->assembly->dynamic) {
4029 /* Enumerate all modules */
4030 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4031 int i;
4033 type = NULL;
4034 if (abuilder->modules) {
4035 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4036 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4037 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4038 if (type)
4039 break;
4043 if (!type && abuilder->loaded_modules) {
4044 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4045 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4046 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4047 if (type)
4048 break;
4052 else
4053 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4054 g_free (str);
4055 mono_reflection_free_type_info (&info);
4056 if (!type) {
4057 MonoException *e = NULL;
4059 if (throwOnError)
4060 e = mono_get_exception_type_load (name, NULL);
4062 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4063 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4065 mono_loader_clear_error ();
4067 if (e != NULL)
4068 mono_raise_exception (e);
4070 return NULL;
4073 if (type->type == MONO_TYPE_CLASS) {
4074 MonoClass *klass = mono_type_get_class (type);
4076 if (mono_is_security_manager_active () && !klass->exception_type)
4077 /* Some security problems are detected during generic vtable construction */
4078 mono_class_setup_vtable (klass);
4079 /* need to report exceptions ? */
4080 if (throwOnError && klass->exception_type) {
4081 /* report SecurityException (or others) that occured when loading the assembly */
4082 MonoException *exc = mono_class_get_exception_for_failure (klass);
4083 mono_loader_clear_error ();
4084 mono_raise_exception (exc);
4085 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4086 return NULL;
4090 /* g_print ("got it\n"); */
4091 return mono_type_get_object (mono_object_domain (assembly), type);
4094 static gboolean
4095 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4097 gchar *content;
4098 gchar *shadow_ini_file;
4099 gsize len;
4101 /* Check for shadow-copied assembly */
4102 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4103 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4104 content = NULL;
4105 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4106 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4107 if (content) {
4108 g_free (content);
4109 content = NULL;
4112 g_free (shadow_ini_file);
4113 if (content != NULL) {
4114 if (*filename)
4115 g_free (*filename);
4116 *filename = content;
4117 return TRUE;
4120 return FALSE;
4123 static MonoString *
4124 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4126 MonoDomain *domain = mono_object_domain (assembly);
4127 MonoAssembly *mass = assembly->assembly;
4128 MonoString *res = NULL;
4129 gchar *uri;
4130 gchar *absolute;
4131 gchar *dirname;
4133 MONO_ARCH_SAVE_REGS;
4135 if (g_path_is_absolute (mass->image->name)) {
4136 absolute = g_strdup (mass->image->name);
4137 dirname = g_path_get_dirname (absolute);
4138 } else {
4139 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4140 dirname = g_strdup (mass->basedir);
4143 replace_shadow_path (domain, dirname, &absolute);
4144 g_free (dirname);
4145 #if HOST_WIN32
4147 gint i;
4148 for (i = strlen (absolute) - 1; i >= 0; i--)
4149 if (absolute [i] == '\\')
4150 absolute [i] = '/';
4152 #endif
4153 if (escaped) {
4154 uri = g_filename_to_uri (absolute, NULL, NULL);
4155 } else {
4156 const char *prepend = "file://";
4157 #if HOST_WIN32
4158 if (*absolute == '/' && *(absolute + 1) == '/') {
4159 prepend = "file:";
4160 } else {
4161 prepend = "file:///";
4163 #endif
4164 uri = g_strconcat (prepend, absolute, NULL);
4167 if (uri) {
4168 res = mono_string_new (domain, uri);
4169 g_free (uri);
4171 g_free (absolute);
4172 return res;
4175 static MonoBoolean
4176 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4178 MonoAssembly *mass = assembly->assembly;
4180 MONO_ARCH_SAVE_REGS;
4182 return mass->in_gac;
4185 static MonoReflectionAssembly*
4186 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4188 gchar *name;
4189 MonoAssembly *res;
4190 MonoImageOpenStatus status;
4192 MONO_ARCH_SAVE_REGS;
4194 name = mono_string_to_utf8 (mname);
4195 res = mono_assembly_load_with_partial_name (name, &status);
4197 g_free (name);
4199 if (res == NULL)
4200 return NULL;
4201 return mono_assembly_get_object (mono_domain_get (), res);
4204 static MonoString *
4205 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4207 MonoDomain *domain = mono_object_domain (assembly);
4208 MonoString *res;
4210 MONO_ARCH_SAVE_REGS;
4212 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4214 return res;
4217 static MonoBoolean
4218 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4220 MONO_ARCH_SAVE_REGS;
4222 return assembly->assembly->ref_only;
4225 static MonoString *
4226 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4228 MonoDomain *domain = mono_object_domain (assembly);
4230 MONO_ARCH_SAVE_REGS;
4232 return mono_string_new (domain, assembly->assembly->image->version);
4235 static MonoReflectionMethod*
4236 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4238 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4240 MONO_ARCH_SAVE_REGS;
4242 if (!token)
4243 return NULL;
4244 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4247 static MonoReflectionModule*
4248 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4250 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4253 static MonoArray*
4254 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4256 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4257 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4258 int i;
4259 const char *val;
4261 MONO_ARCH_SAVE_REGS;
4263 for (i = 0; i < table->rows; ++i) {
4264 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4265 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4267 return result;
4270 static MonoObject*
4271 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4273 static MonoClass *System_Version = NULL;
4274 static MonoMethod *create_version = NULL;
4275 MonoObject *result;
4276 gpointer args [4];
4278 if (!System_Version) {
4279 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4280 g_assert (System_Version);
4283 if (!create_version) {
4284 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4285 create_version = mono_method_desc_search_in_class (desc, System_Version);
4286 g_assert (create_version);
4287 mono_method_desc_free (desc);
4290 args [0] = &major;
4291 args [1] = &minor;
4292 args [2] = &build;
4293 args [3] = &revision;
4294 result = mono_object_new (domain, System_Version);
4295 mono_runtime_invoke (create_version, result, args, NULL);
4297 return result;
4300 static MonoArray*
4301 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4303 static MonoClass *System_Reflection_AssemblyName;
4304 MonoArray *result;
4305 MonoDomain *domain = mono_object_domain (assembly);
4306 int i, count = 0;
4307 static MonoMethod *create_culture = NULL;
4308 MonoImage *image = assembly->assembly->image;
4309 MonoTableInfo *t;
4311 MONO_ARCH_SAVE_REGS;
4313 if (!System_Reflection_AssemblyName)
4314 System_Reflection_AssemblyName = mono_class_from_name (
4315 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4317 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4318 count = t->rows;
4320 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4322 if (count > 0 && !create_culture) {
4323 MonoMethodDesc *desc = mono_method_desc_new (
4324 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4325 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4326 g_assert (create_culture);
4327 mono_method_desc_free (desc);
4330 for (i = 0; i < count; i++) {
4331 MonoReflectionAssemblyName *aname;
4332 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4334 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4336 aname = (MonoReflectionAssemblyName *) mono_object_new (
4337 domain, System_Reflection_AssemblyName);
4339 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4341 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4342 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4343 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4344 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4345 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4346 aname->versioncompat = 1; /* SameMachine (default) */
4347 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4348 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4350 if (create_culture) {
4351 gpointer args [2];
4352 MonoBoolean assembly_ref = 1;
4353 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4354 args [1] = &assembly_ref;
4355 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4358 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4359 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4360 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4362 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4363 /* public key token isn't copied - the class library will
4364 automatically generate it from the public key if required */
4365 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4366 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4367 } else {
4368 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4369 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4371 } else {
4372 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4375 /* note: this function doesn't return the codebase on purpose (i.e. it can
4376 be used under partial trust as path information isn't present). */
4378 mono_array_setref (result, i, aname);
4380 return result;
4383 typedef struct {
4384 MonoArray *res;
4385 int idx;
4386 } NameSpaceInfo;
4388 static void
4389 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4391 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4393 mono_array_setref (info->res, info->idx, name);
4394 info->idx++;
4397 static MonoArray*
4398 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4400 MonoImage *img = assembly->assembly->image;
4401 MonoArray *res;
4402 NameSpaceInfo info;
4403 int len;
4405 MONO_ARCH_SAVE_REGS;
4407 mono_image_lock (img);
4408 mono_image_init_name_cache (img);
4410 RETRY_LEN:
4411 len = g_hash_table_size (img->name_cache);
4412 mono_image_unlock (img);
4414 /*we can't create objects holding the image lock */
4415 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4417 mono_image_lock (img);
4418 /*len might have changed, create a new array*/
4419 if (len != g_hash_table_size (img->name_cache))
4420 goto RETRY_LEN;
4422 info.res = res;
4423 info.idx = 0;
4424 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4425 mono_image_unlock (img);
4427 return res;
4430 /* move this in some file in mono/util/ */
4431 static char *
4432 g_concat_dir_and_file (const char *dir, const char *file)
4434 g_return_val_if_fail (dir != NULL, NULL);
4435 g_return_val_if_fail (file != NULL, NULL);
4438 * If the directory name doesn't have a / on the end, we need
4439 * to add one so we get a proper path to the file
4441 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4442 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4443 else
4444 return g_strconcat (dir, file, NULL);
4447 static void *
4448 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4450 char *n = mono_string_to_utf8 (name);
4451 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4452 guint32 i;
4453 guint32 cols [MONO_MANIFEST_SIZE];
4454 guint32 impl, file_idx;
4455 const char *val;
4456 MonoImage *module;
4458 MONO_ARCH_SAVE_REGS;
4460 for (i = 0; i < table->rows; ++i) {
4461 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4462 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4463 if (strcmp (val, n) == 0)
4464 break;
4466 g_free (n);
4467 if (i == table->rows)
4468 return NULL;
4469 /* FIXME */
4470 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4471 if (impl) {
4473 * this code should only be called after obtaining the
4474 * ResourceInfo and handling the other cases.
4476 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4477 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4479 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4480 if (!module)
4481 return NULL;
4483 else
4484 module = assembly->assembly->image;
4486 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4488 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4491 static gboolean
4492 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4494 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4495 int i;
4496 guint32 cols [MONO_MANIFEST_SIZE];
4497 guint32 file_cols [MONO_FILE_SIZE];
4498 const char *val;
4499 char *n;
4501 MONO_ARCH_SAVE_REGS;
4503 n = mono_string_to_utf8 (name);
4504 for (i = 0; i < table->rows; ++i) {
4505 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4506 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4507 if (strcmp (val, n) == 0)
4508 break;
4510 g_free (n);
4511 if (i == table->rows)
4512 return FALSE;
4514 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4515 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4517 else {
4518 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4519 case MONO_IMPLEMENTATION_FILE:
4520 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4521 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4522 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4523 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4524 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4525 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4526 info->location = 0;
4527 else
4528 info->location = RESOURCE_LOCATION_EMBEDDED;
4529 break;
4531 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4532 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4533 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4534 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4535 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4536 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4537 g_free (msg);
4538 mono_raise_exception (ex);
4540 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4542 /* Obtain info recursively */
4543 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4544 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4545 break;
4547 case MONO_IMPLEMENTATION_EXP_TYPE:
4548 g_assert_not_reached ();
4549 break;
4553 return TRUE;
4556 static MonoObject*
4557 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4559 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4560 MonoArray *result = NULL;
4561 int i, count;
4562 const char *val;
4563 char *n;
4565 MONO_ARCH_SAVE_REGS;
4567 /* check hash if needed */
4568 if (name) {
4569 n = mono_string_to_utf8 (name);
4570 for (i = 0; i < table->rows; ++i) {
4571 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4572 if (strcmp (val, n) == 0) {
4573 MonoString *fn;
4574 g_free (n);
4575 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4576 fn = mono_string_new (mono_object_domain (assembly), n);
4577 g_free (n);
4578 return (MonoObject*)fn;
4581 g_free (n);
4582 return NULL;
4585 count = 0;
4586 for (i = 0; i < table->rows; ++i) {
4587 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4588 count ++;
4591 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4593 count = 0;
4594 for (i = 0; i < table->rows; ++i) {
4595 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4596 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4597 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4598 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4599 g_free (n);
4600 count ++;
4603 return (MonoObject*)result;
4606 static MonoArray*
4607 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4609 MonoDomain *domain = mono_domain_get();
4610 MonoArray *res;
4611 MonoClass *klass;
4612 int i, j, file_count = 0;
4613 MonoImage **modules;
4614 guint32 module_count, real_module_count;
4615 MonoTableInfo *table;
4616 guint32 cols [MONO_FILE_SIZE];
4617 MonoImage *image = assembly->assembly->image;
4619 g_assert (image != NULL);
4620 g_assert (!assembly->assembly->dynamic);
4622 table = &image->tables [MONO_TABLE_FILE];
4623 file_count = table->rows;
4625 modules = image->modules;
4626 module_count = image->module_count;
4628 real_module_count = 0;
4629 for (i = 0; i < module_count; ++i)
4630 if (modules [i])
4631 real_module_count ++;
4633 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4634 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4636 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4637 j = 1;
4638 for (i = 0; i < module_count; ++i)
4639 if (modules [i]) {
4640 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4641 ++j;
4644 for (i = 0; i < file_count; ++i, ++j) {
4645 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4646 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4647 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4648 else {
4649 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4650 if (!m) {
4651 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4652 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4654 mono_array_setref (res, j, mono_module_get_object (domain, m));
4658 return res;
4661 static MonoReflectionMethod*
4662 ves_icall_GetCurrentMethod (void)
4664 MonoMethod *m = mono_method_get_last_managed ();
4666 while (m->is_inflated)
4667 m = ((MonoMethodInflated*)m)->declaring;
4669 return mono_method_get_object (mono_domain_get (), m, NULL);
4673 static MonoMethod*
4674 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4676 int offset = -1, i;
4677 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4678 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4679 //method is inflated, we should inflate it on the other class
4680 MonoGenericContext ctx;
4681 ctx.method_inst = inflated->context.method_inst;
4682 ctx.class_inst = inflated->context.class_inst;
4683 if (klass->generic_class)
4684 ctx.class_inst = klass->generic_class->context.class_inst;
4685 else if (klass->generic_container)
4686 ctx.class_inst = klass->generic_container->context.class_inst;
4687 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4690 mono_class_setup_methods (method->klass);
4691 if (method->klass->exception_type)
4692 return NULL;
4693 for (i = 0; i < method->klass->method.count; ++i) {
4694 if (method->klass->methods [i] == method) {
4695 offset = i;
4696 break;
4699 mono_class_setup_methods (klass);
4700 if (klass->exception_type)
4701 return NULL;
4702 g_assert (offset >= 0 && offset < klass->method.count);
4703 return klass->methods [offset];
4706 static MonoReflectionMethod*
4707 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4709 MonoClass *klass;
4710 if (type) {
4711 klass = mono_class_from_mono_type (type);
4712 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4713 return NULL;
4714 if (method->klass != klass) {
4715 method = mono_method_get_equivalent_method (method, klass);
4716 if (!method)
4717 return NULL;
4719 } else
4720 klass = method->klass;
4721 return mono_method_get_object (mono_domain_get (), method, klass);
4724 static MonoReflectionMethod*
4725 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4727 return mono_method_get_object (mono_domain_get (), method, NULL);
4730 static MonoReflectionMethodBody*
4731 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4733 return mono_method_body_get_object (mono_domain_get (), method);
4736 static MonoReflectionAssembly*
4737 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4739 MonoMethod *dest = NULL;
4741 MONO_ARCH_SAVE_REGS;
4743 mono_stack_walk_no_il (get_executing, &dest);
4744 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4748 static MonoReflectionAssembly*
4749 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4751 MonoDomain* domain = mono_domain_get ();
4753 MONO_ARCH_SAVE_REGS;
4755 if (!domain->entry_assembly)
4756 return NULL;
4758 return mono_assembly_get_object (domain, domain->entry_assembly);
4761 static MonoReflectionAssembly*
4762 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4764 MonoMethod *m;
4765 MonoMethod *dest;
4767 MONO_ARCH_SAVE_REGS;
4769 dest = NULL;
4770 mono_stack_walk_no_il (get_executing, &dest);
4771 m = dest;
4772 mono_stack_walk_no_il (get_caller, &dest);
4773 if (!dest)
4774 dest = m;
4775 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4778 static MonoString *
4779 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4780 gboolean assembly_qualified)
4782 MonoDomain *domain = mono_object_domain (object);
4783 MonoTypeNameFormat format;
4784 MonoString *res;
4785 gchar *name;
4787 MONO_ARCH_SAVE_REGS;
4788 if (full_name)
4789 format = assembly_qualified ?
4790 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4791 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4792 else
4793 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4795 name = mono_type_get_name_full (object->type, format);
4796 if (!name)
4797 return NULL;
4799 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4800 g_free (name);
4801 return NULL;
4804 res = mono_string_new (domain, name);
4805 g_free (name);
4807 return res;
4810 static int
4811 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4813 MonoClass *klass = mono_class_from_mono_type (this->type);
4814 return mono_security_core_clr_class_level (klass);
4817 static void
4818 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4820 static MonoMethod *create_culture = NULL;
4821 gpointer args [2];
4822 guint32 pkey_len;
4823 const char *pkey_ptr;
4824 gchar *codebase;
4825 MonoBoolean assembly_ref = 0;
4827 MONO_ARCH_SAVE_REGS;
4829 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4830 aname->major = name->major;
4831 aname->minor = name->minor;
4832 aname->build = name->build;
4833 aname->flags = name->flags;
4834 aname->revision = name->revision;
4835 aname->hashalg = name->hash_alg;
4836 aname->versioncompat = 1; /* SameMachine (default) */
4838 if (by_default_version)
4839 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4841 codebase = NULL;
4842 if (absolute != NULL && *absolute != '\0') {
4843 const gchar *prepend = "file://";
4844 gchar *result;
4846 codebase = g_strdup (absolute);
4848 #if HOST_WIN32
4850 gint i;
4851 for (i = strlen (codebase) - 1; i >= 0; i--)
4852 if (codebase [i] == '\\')
4853 codebase [i] = '/';
4855 if (*codebase == '/' && *(codebase + 1) == '/') {
4856 prepend = "file:";
4857 } else {
4858 prepend = "file:///";
4861 #endif
4862 result = g_strconcat (prepend, codebase, NULL);
4863 g_free (codebase);
4864 codebase = result;
4867 if (codebase) {
4868 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4869 g_free (codebase);
4872 if (!create_culture) {
4873 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4874 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4875 g_assert (create_culture);
4876 mono_method_desc_free (desc);
4879 if (name->culture) {
4880 args [0] = mono_string_new (domain, name->culture);
4881 args [1] = &assembly_ref;
4882 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4885 if (name->public_key) {
4886 pkey_ptr = (char*)name->public_key;
4887 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4889 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4890 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4891 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4892 } else if (default_publickey) {
4893 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4894 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4897 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4898 if (name->public_key_token [0]) {
4899 int i, j;
4900 char *p;
4902 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4903 p = mono_array_addr (aname->keyToken, char, 0);
4905 for (i = 0, j = 0; i < 8; i++) {
4906 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4907 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4908 p++;
4910 } else if (default_token) {
4911 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4915 static MonoString *
4916 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4918 MonoDomain *domain = mono_object_domain (assembly);
4919 MonoAssembly *mass = assembly->assembly;
4920 MonoString *res;
4921 gchar *name;
4923 name = g_strdup_printf (
4924 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
4925 mass->aname.name,
4926 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
4927 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
4928 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
4929 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
4931 res = mono_string_new (domain, name);
4932 g_free (name);
4934 return res;
4937 static void
4938 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4940 gchar *absolute;
4941 MonoAssembly *mass = assembly->assembly;
4943 MONO_ARCH_SAVE_REGS;
4945 if (g_path_is_absolute (mass->image->name)) {
4946 fill_reflection_assembly_name (mono_object_domain (assembly),
4947 aname, &mass->aname, mass->image->name, TRUE,
4948 TRUE, TRUE);
4949 return;
4951 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4953 fill_reflection_assembly_name (mono_object_domain (assembly),
4954 aname, &mass->aname, absolute, TRUE, TRUE,
4955 TRUE);
4957 g_free (absolute);
4960 static void
4961 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4963 char *filename;
4964 MonoImageOpenStatus status = MONO_IMAGE_OK;
4965 gboolean res;
4966 MonoImage *image;
4967 MonoAssemblyName name;
4968 char *dirname
4970 MONO_ARCH_SAVE_REGS;
4972 filename = mono_string_to_utf8 (fname);
4974 dirname = g_path_get_dirname (filename);
4975 replace_shadow_path (mono_domain_get (), dirname, &filename);
4976 g_free (dirname);
4978 image = mono_image_open (filename, &status);
4980 if (!image){
4981 MonoException *exc;
4983 g_free (filename);
4984 if (status == MONO_IMAGE_IMAGE_INVALID)
4985 exc = mono_get_exception_bad_image_format2 (NULL, fname);
4986 else
4987 exc = mono_get_exception_file_not_found2 (NULL, fname);
4988 mono_raise_exception (exc);
4991 res = mono_assembly_fill_assembly_name (image, &name);
4992 if (!res) {
4993 mono_image_close (image);
4994 g_free (filename);
4995 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4998 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
4999 TRUE, FALSE, TRUE);
5001 g_free (filename);
5002 mono_image_close (image);
5005 static MonoBoolean
5006 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5007 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5009 MonoBoolean result = FALSE;
5010 MonoDeclSecurityEntry entry;
5012 /* SecurityAction.RequestMinimum */
5013 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5014 *minimum = entry.blob;
5015 *minLength = entry.size;
5016 result = TRUE;
5018 /* SecurityAction.RequestOptional */
5019 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5020 *optional = entry.blob;
5021 *optLength = entry.size;
5022 result = TRUE;
5024 /* SecurityAction.RequestRefuse */
5025 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5026 *refused = entry.blob;
5027 *refLength = entry.size;
5028 result = TRUE;
5031 return result;
5034 static MonoArray*
5035 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5037 MonoArray *res;
5038 MonoClass *klass;
5039 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5040 int i, count;
5041 guint32 attrs, visibility;
5043 /* we start the count from 1 because we skip the special type <Module> */
5044 if (exportedOnly) {
5045 count = 0;
5046 for (i = 1; i < tdef->rows; ++i) {
5047 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5048 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5049 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5050 count++;
5052 } else {
5053 count = tdef->rows - 1;
5055 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5056 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5057 count = 0;
5058 for (i = 1; i < tdef->rows; ++i) {
5059 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5060 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5061 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5062 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5063 if (klass) {
5064 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5065 } else {
5066 MonoLoaderError *error;
5067 MonoException *ex;
5069 error = mono_loader_get_last_error ();
5070 g_assert (error != NULL);
5072 ex = mono_loader_error_prepare_exception (error);
5073 mono_array_setref (*exceptions, count, ex);
5075 if (mono_loader_get_last_error ())
5076 mono_loader_clear_error ();
5077 count++;
5081 return res;
5084 static MonoArray*
5085 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5087 MonoArray *res = NULL;
5088 MonoArray *exceptions = NULL;
5089 MonoImage *image = NULL;
5090 MonoTableInfo *table = NULL;
5091 MonoDomain *domain;
5092 GList *list = NULL;
5093 int i, len, ex_count;
5095 MONO_ARCH_SAVE_REGS;
5097 domain = mono_object_domain (assembly);
5099 g_assert (!assembly->assembly->dynamic);
5100 image = assembly->assembly->image;
5101 table = &image->tables [MONO_TABLE_FILE];
5102 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5104 /* Append data from all modules in the assembly */
5105 for (i = 0; i < table->rows; ++i) {
5106 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5107 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5108 if (loaded_image) {
5109 MonoArray *ex2;
5110 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5111 /* Append the new types to the end of the array */
5112 if (mono_array_length (res2) > 0) {
5113 guint32 len1, len2;
5114 MonoArray *res3, *ex3;
5116 len1 = mono_array_length (res);
5117 len2 = mono_array_length (res2);
5119 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5120 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5121 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5122 res = res3;
5124 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5125 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5126 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5127 exceptions = ex3;
5133 /* the ReflectionTypeLoadException must have all the types (Types property),
5134 * NULL replacing types which throws an exception. The LoaderException must
5135 * contain all exceptions for NULL items.
5138 len = mono_array_length (res);
5140 ex_count = 0;
5141 for (i = 0; i < len; i++) {
5142 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5143 MonoClass *klass;
5145 if (t) {
5146 klass = mono_type_get_class (t->type);
5147 if ((klass != NULL) && klass->exception_type) {
5148 /* keep the class in the list */
5149 list = g_list_append (list, klass);
5150 /* and replace Type with NULL */
5151 mono_array_setref (res, i, NULL);
5153 } else {
5154 ex_count ++;
5158 if (list || ex_count) {
5159 GList *tmp = NULL;
5160 MonoException *exc = NULL;
5161 MonoArray *exl = NULL;
5162 int j, length = g_list_length (list) + ex_count;
5164 mono_loader_clear_error ();
5166 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5167 /* Types for which mono_class_get () succeeded */
5168 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5169 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5170 mono_array_setref (exl, i, exc);
5172 /* Types for which it don't */
5173 for (j = 0; j < mono_array_length (exceptions); ++j) {
5174 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5175 if (exc) {
5176 g_assert (i < length);
5177 mono_array_setref (exl, i, exc);
5178 i ++;
5181 g_list_free (list);
5182 list = NULL;
5184 exc = mono_get_exception_reflection_type_load (res, exl);
5185 mono_loader_clear_error ();
5186 mono_raise_exception (exc);
5189 return res;
5192 static gboolean
5193 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5195 MonoAssemblyName aname;
5196 MonoDomain *domain = mono_object_domain (name);
5197 char *val;
5198 gboolean is_version_defined;
5199 gboolean is_token_defined;
5201 aname.public_key = NULL;
5202 val = mono_string_to_utf8 (assname);
5203 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5204 g_free ((guint8*) aname.public_key);
5205 g_free (val);
5206 return FALSE;
5209 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5210 FALSE, is_token_defined);
5212 mono_assembly_name_free (&aname);
5213 g_free ((guint8*) aname.public_key);
5214 g_free (val);
5216 return TRUE;
5219 static MonoReflectionType*
5220 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5222 MonoDomain *domain = mono_object_domain (module);
5223 MonoClass *klass;
5225 MONO_ARCH_SAVE_REGS;
5227 g_assert (module->image);
5229 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5230 /* These images do not have a global type */
5231 return NULL;
5233 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5234 return mono_type_get_object (domain, &klass->byval_arg);
5237 static void
5238 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5240 /*if (module->image)
5241 mono_image_close (module->image);*/
5244 static MonoString*
5245 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5247 MonoDomain *domain = mono_object_domain (module);
5249 MONO_ARCH_SAVE_REGS;
5251 g_assert (module->image);
5252 return mono_string_new (domain, module->image->guid);
5255 static gpointer
5256 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5258 #ifdef HOST_WIN32
5259 if (module->image && module->image->is_module_handle)
5260 return module->image->raw_data;
5261 #endif
5263 return (gpointer) (-1);
5266 static void
5267 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5269 if (image->dynamic) {
5270 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5271 *pe_kind = dyn->pe_kind;
5272 *machine = dyn->machine;
5274 else {
5275 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5276 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5280 static gint32
5281 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5283 return (image->md_version_major << 16) | (image->md_version_minor);
5286 static MonoArray*
5287 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5289 MonoArray *exceptions;
5290 int i;
5292 MONO_ARCH_SAVE_REGS;
5294 if (!module->image)
5295 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5296 else {
5297 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5298 for (i = 0; i < mono_array_length (exceptions); ++i) {
5299 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5300 if (ex)
5301 mono_raise_exception (ex);
5303 return res;
5307 static gboolean
5308 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5310 guint32 cols [MONO_MEMBERREF_SIZE];
5311 const char *sig;
5312 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5313 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5314 mono_metadata_decode_blob_size (sig, &sig);
5315 return (*sig != 0x6);
5318 static void
5319 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5321 if (type_args)
5322 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5323 mono_array_addr (type_args, MonoType*, 0));
5324 else
5325 context->class_inst = NULL;
5326 if (method_args)
5327 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5328 mono_array_addr (method_args, MonoType*, 0));
5329 else
5330 context->method_inst = NULL;
5333 static MonoType*
5334 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5336 MonoClass *klass;
5337 int table = mono_metadata_token_table (token);
5338 int index = mono_metadata_token_index (token);
5339 MonoGenericContext context;
5341 *error = ResolveTokenError_Other;
5343 /* Validate token */
5344 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5345 (table != MONO_TABLE_TYPESPEC)) {
5346 *error = ResolveTokenError_BadTable;
5347 return NULL;
5350 if (image->dynamic) {
5351 if (type_args || method_args)
5352 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5353 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5354 if (!klass)
5355 return NULL;
5356 return &klass->byval_arg;
5359 if ((index <= 0) || (index > image->tables [table].rows)) {
5360 *error = ResolveTokenError_OutOfRange;
5361 return NULL;
5364 init_generic_context_from_args (&context, type_args, method_args);
5365 klass = mono_class_get_full (image, token, &context);
5367 if (mono_loader_get_last_error ())
5368 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5370 if (klass)
5371 return &klass->byval_arg;
5372 else
5373 return NULL;
5376 static MonoMethod*
5377 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5379 int table = mono_metadata_token_table (token);
5380 int index = mono_metadata_token_index (token);
5381 MonoGenericContext context;
5382 MonoMethod *method;
5384 *error = ResolveTokenError_Other;
5386 /* Validate token */
5387 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5388 (table != MONO_TABLE_MEMBERREF)) {
5389 *error = ResolveTokenError_BadTable;
5390 return NULL;
5393 if (image->dynamic) {
5394 if (type_args || method_args)
5395 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5396 /* FIXME: validate memberref token type */
5397 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5400 if ((index <= 0) || (index > image->tables [table].rows)) {
5401 *error = ResolveTokenError_OutOfRange;
5402 return NULL;
5404 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5405 *error = ResolveTokenError_BadTable;
5406 return NULL;
5409 init_generic_context_from_args (&context, type_args, method_args);
5410 method = mono_get_method_full (image, token, NULL, &context);
5412 if (mono_loader_get_last_error ())
5413 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5415 return method;
5418 static MonoString*
5419 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5421 int index = mono_metadata_token_index (token);
5423 *error = ResolveTokenError_Other;
5425 /* Validate token */
5426 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5427 *error = ResolveTokenError_BadTable;
5428 return NULL;
5431 if (image->dynamic)
5432 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5434 if ((index <= 0) || (index >= image->heap_us.size)) {
5435 *error = ResolveTokenError_OutOfRange;
5436 return NULL;
5439 /* FIXME: What to do if the index points into the middle of a string ? */
5441 return mono_ldstr (mono_domain_get (), image, index);
5444 static MonoClassField*
5445 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5447 MonoClass *klass;
5448 int table = mono_metadata_token_table (token);
5449 int index = mono_metadata_token_index (token);
5450 MonoGenericContext context;
5451 MonoClassField *field;
5453 *error = ResolveTokenError_Other;
5455 /* Validate token */
5456 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5457 *error = ResolveTokenError_BadTable;
5458 return NULL;
5461 if (image->dynamic) {
5462 if (type_args || method_args)
5463 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5464 /* FIXME: validate memberref token type */
5465 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5468 if ((index <= 0) || (index > image->tables [table].rows)) {
5469 *error = ResolveTokenError_OutOfRange;
5470 return NULL;
5472 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5473 *error = ResolveTokenError_BadTable;
5474 return NULL;
5477 init_generic_context_from_args (&context, type_args, method_args);
5478 field = mono_field_from_token (image, token, &klass, &context);
5480 if (mono_loader_get_last_error ())
5481 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5483 return field;
5487 static MonoObject*
5488 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5490 int table = mono_metadata_token_table (token);
5492 *error = ResolveTokenError_Other;
5494 switch (table) {
5495 case MONO_TABLE_TYPEDEF:
5496 case MONO_TABLE_TYPEREF:
5497 case MONO_TABLE_TYPESPEC: {
5498 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5499 if (t)
5500 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5501 else
5502 return NULL;
5504 case MONO_TABLE_METHOD:
5505 case MONO_TABLE_METHODSPEC: {
5506 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5507 if (m)
5508 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5509 else
5510 return NULL;
5512 case MONO_TABLE_FIELD: {
5513 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5514 if (f)
5515 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5516 else
5517 return NULL;
5519 case MONO_TABLE_MEMBERREF:
5520 if (mono_metadata_memberref_is_method (image, token)) {
5521 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5522 if (m)
5523 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5524 else
5525 return NULL;
5527 else {
5528 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5529 if (f)
5530 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5531 else
5532 return NULL;
5534 break;
5536 default:
5537 *error = ResolveTokenError_BadTable;
5540 return NULL;
5543 static MonoArray*
5544 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5546 int table = mono_metadata_token_table (token);
5547 int idx = mono_metadata_token_index (token);
5548 MonoTableInfo *tables = image->tables;
5549 guint32 sig, len;
5550 const char *ptr;
5551 MonoArray *res;
5553 *error = ResolveTokenError_OutOfRange;
5555 /* FIXME: Support other tables ? */
5556 if (table != MONO_TABLE_STANDALONESIG)
5557 return NULL;
5559 if (image->dynamic)
5560 return NULL;
5562 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5563 return NULL;
5565 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5567 ptr = mono_metadata_blob_heap (image, sig);
5568 len = mono_metadata_decode_blob_size (ptr, &ptr);
5570 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5571 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5572 return res;
5575 static MonoReflectionType*
5576 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5578 MonoClass *klass;
5579 int isbyref = 0, rank;
5580 char *str = mono_string_to_utf8 (smodifiers);
5581 char *p;
5583 MONO_ARCH_SAVE_REGS;
5585 klass = mono_class_from_mono_type (tb->type.type);
5586 p = str;
5587 /* logic taken from mono_reflection_parse_type(): keep in sync */
5588 while (*p) {
5589 switch (*p) {
5590 case '&':
5591 if (isbyref) { /* only one level allowed by the spec */
5592 g_free (str);
5593 return NULL;
5595 isbyref = 1;
5596 p++;
5597 g_free (str);
5598 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5599 break;
5600 case '*':
5601 klass = mono_ptr_class_get (&klass->byval_arg);
5602 mono_class_init (klass);
5603 p++;
5604 break;
5605 case '[':
5606 rank = 1;
5607 p++;
5608 while (*p) {
5609 if (*p == ']')
5610 break;
5611 if (*p == ',')
5612 rank++;
5613 else if (*p != '*') { /* '*' means unknown lower bound */
5614 g_free (str);
5615 return NULL;
5617 ++p;
5619 if (*p != ']') {
5620 g_free (str);
5621 return NULL;
5623 p++;
5624 klass = mono_array_class_get (klass, rank);
5625 mono_class_init (klass);
5626 break;
5627 default:
5628 break;
5631 g_free (str);
5632 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5635 static MonoBoolean
5636 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5638 MonoType *type;
5639 MonoBoolean res;
5641 MONO_ARCH_SAVE_REGS;
5643 type = t->type;
5644 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5646 return res;
5649 static MonoReflectionType *
5650 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5652 MonoClass *klass, *aklass;
5654 MONO_ARCH_SAVE_REGS;
5656 klass = mono_class_from_mono_type (type->type);
5657 if (rank == 0) //single dimentional array
5658 aklass = mono_array_class_get (klass, 1);
5659 else
5660 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5662 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5665 static MonoReflectionType *
5666 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5668 MonoClass *klass;
5670 MONO_ARCH_SAVE_REGS;
5672 klass = mono_class_from_mono_type (type->type);
5674 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5677 static MonoReflectionType *
5678 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5680 MonoClass *pklass;
5682 MONO_ARCH_SAVE_REGS;
5684 pklass = mono_ptr_class_get (type->type);
5686 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5689 static MonoObject *
5690 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5691 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5693 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5694 MonoObject *delegate;
5695 gpointer func;
5696 MonoMethod *method = info->method;
5698 MONO_ARCH_SAVE_REGS;
5700 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5702 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5703 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5704 return NULL;
5707 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5709 if (method->dynamic) {
5710 /* Creating a trampoline would leak memory */
5711 func = mono_compile_method (method);
5712 } else {
5713 func = mono_create_ftnptr (mono_domain_get (),
5714 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5717 mono_delegate_ctor_with_method (delegate, target, func, method);
5719 return delegate;
5722 static void
5723 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5725 /* Reset the invoke impl to the default one */
5726 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5730 * Magic number to convert a time which is relative to
5731 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5733 #define EPOCH_ADJUST ((guint64)62135596800LL)
5736 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5738 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5740 #ifdef HOST_WIN32
5741 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5742 static void
5743 convert_to_absolute_date(SYSTEMTIME *date)
5745 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5746 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5747 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5748 /* from the calendar FAQ */
5749 int a = (14 - date->wMonth) / 12;
5750 int y = date->wYear - a;
5751 int m = date->wMonth + 12 * a - 2;
5752 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5754 /* d is now the day of the week for the first of the month (0 == Sunday) */
5756 int day_of_week = date->wDayOfWeek;
5758 /* set day_in_month to the first day in the month which falls on day_of_week */
5759 int day_in_month = 1 + (day_of_week - d);
5760 if (day_in_month <= 0)
5761 day_in_month += 7;
5763 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5764 date->wDay = day_in_month + (date->wDay - 1) * 7;
5765 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5766 date->wDay -= 7;
5768 #endif
5770 #ifndef HOST_WIN32
5772 * Return's the offset from GMT of a local time.
5774 * tm is a local time
5775 * t is the same local time as seconds.
5777 static int
5778 gmt_offset(struct tm *tm, time_t t)
5780 #if defined (HAVE_TM_GMTOFF)
5781 return tm->tm_gmtoff;
5782 #else
5783 struct tm g;
5784 time_t t2;
5785 g = *gmtime(&t);
5786 g.tm_isdst = tm->tm_isdst;
5787 t2 = mktime(&g);
5788 return (int)difftime(t, t2);
5789 #endif
5791 #endif
5793 * This is heavily based on zdump.c from glibc 2.2.
5795 * * data[0]: start of daylight saving time (in DateTime ticks).
5796 * * data[1]: end of daylight saving time (in DateTime ticks).
5797 * * data[2]: utcoffset (in TimeSpan ticks).
5798 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5799 * * name[0]: name of this timezone when not daylight saving.
5800 * * name[1]: name of this timezone when daylight saving.
5802 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5803 * the class library allows years between 1 and 9999.
5805 * Returns true on success and zero on failure.
5807 static guint32
5808 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5810 #ifndef HOST_WIN32
5811 MonoDomain *domain = mono_domain_get ();
5812 struct tm start, tt;
5813 time_t t;
5815 long int gmtoff;
5816 int is_daylight = 0, day;
5817 char tzone [64];
5819 MONO_ARCH_SAVE_REGS;
5821 MONO_CHECK_ARG_NULL (data);
5822 MONO_CHECK_ARG_NULL (names);
5824 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5825 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5828 * no info is better than crashing: we'll need our own tz data
5829 * to make this work properly, anyway. The range is probably
5830 * reduced to 1970 .. 2037 because that is what mktime is
5831 * guaranteed to support (we get into an infinite loop
5832 * otherwise).
5835 memset (&start, 0, sizeof (start));
5837 start.tm_mday = 1;
5838 start.tm_year = year-1900;
5840 t = mktime (&start);
5842 if ((year < 1970) || (year > 2037) || (t == -1)) {
5843 t = time (NULL);
5844 tt = *localtime (&t);
5845 strftime (tzone, sizeof (tzone), "%Z", &tt);
5846 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5847 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5848 return 1;
5851 gmtoff = gmt_offset (&start, t);
5853 /* For each day of the year, calculate the tm_gmtoff. */
5854 for (day = 0; day < 365; day++) {
5856 t += 3600*24;
5857 tt = *localtime (&t);
5859 /* Daylight saving starts or ends here. */
5860 if (gmt_offset (&tt, t) != gmtoff) {
5861 struct tm tt1;
5862 time_t t1;
5864 /* Try to find the exact hour when daylight saving starts/ends. */
5865 t1 = t;
5866 do {
5867 t1 -= 3600;
5868 tt1 = *localtime (&t1);
5869 } while (gmt_offset (&tt1, t1) != gmtoff);
5871 /* Try to find the exact minute when daylight saving starts/ends. */
5872 do {
5873 t1 += 60;
5874 tt1 = *localtime (&t1);
5875 } while (gmt_offset (&tt1, t1) == gmtoff);
5876 t1+=gmtoff;
5877 strftime (tzone, sizeof (tzone), "%Z", &tt);
5879 /* Write data, if we're already in daylight saving, we're done. */
5880 if (is_daylight) {
5881 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5882 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5883 return 1;
5884 } else {
5885 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5886 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5887 is_daylight = 1;
5890 /* This is only set once when we enter daylight saving. */
5891 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5892 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5894 gmtoff = gmt_offset (&tt, t);
5898 if (!is_daylight) {
5899 strftime (tzone, sizeof (tzone), "%Z", &tt);
5900 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5901 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5902 mono_array_set ((*data), gint64, 0, 0);
5903 mono_array_set ((*data), gint64, 1, 0);
5904 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5905 mono_array_set ((*data), gint64, 3, 0);
5908 return 1;
5909 #else
5910 MonoDomain *domain = mono_domain_get ();
5911 TIME_ZONE_INFORMATION tz_info;
5912 FILETIME ft;
5913 int i;
5914 int err, tz_id;
5916 tz_id = GetTimeZoneInformation (&tz_info);
5917 if (tz_id == TIME_ZONE_ID_INVALID)
5918 return 0;
5920 MONO_CHECK_ARG_NULL (data);
5921 MONO_CHECK_ARG_NULL (names);
5923 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
5924 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
5926 for (i = 0; i < 32; ++i)
5927 if (!tz_info.DaylightName [i])
5928 break;
5929 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
5930 for (i = 0; i < 32; ++i)
5931 if (!tz_info.StandardName [i])
5932 break;
5933 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
5935 if ((year <= 1601) || (year > 30827)) {
5937 * According to MSDN, the MS time functions can't handle dates outside
5938 * this interval.
5940 return 1;
5943 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
5944 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
5945 tz_info.StandardDate.wYear = year;
5946 convert_to_absolute_date(&tz_info.StandardDate);
5947 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
5948 //g_assert(err);
5949 if (err == 0)
5950 return 0;
5952 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5953 tz_info.DaylightDate.wYear = year;
5954 convert_to_absolute_date(&tz_info.DaylightDate);
5955 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
5956 //g_assert(err);
5957 if (err == 0)
5958 return 0;
5960 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5962 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
5963 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
5965 return 1;
5966 #endif
5969 static gpointer
5970 ves_icall_System_Object_obj_address (MonoObject *this)
5972 MONO_ARCH_SAVE_REGS;
5974 return this;
5977 /* System.Buffer */
5979 static inline gint32
5980 mono_array_get_byte_length (MonoArray *array)
5982 MonoClass *klass;
5983 int length;
5984 int i;
5986 klass = array->obj.vtable->klass;
5988 if (array->bounds == NULL)
5989 length = array->max_length;
5990 else {
5991 length = 1;
5992 for (i = 0; i < klass->rank; ++ i)
5993 length *= array->bounds [i].length;
5996 switch (klass->element_class->byval_arg.type) {
5997 case MONO_TYPE_I1:
5998 case MONO_TYPE_U1:
5999 case MONO_TYPE_BOOLEAN:
6000 return length;
6001 case MONO_TYPE_I2:
6002 case MONO_TYPE_U2:
6003 case MONO_TYPE_CHAR:
6004 return length << 1;
6005 case MONO_TYPE_I4:
6006 case MONO_TYPE_U4:
6007 case MONO_TYPE_R4:
6008 return length << 2;
6009 case MONO_TYPE_I:
6010 case MONO_TYPE_U:
6011 return length * sizeof (gpointer);
6012 case MONO_TYPE_I8:
6013 case MONO_TYPE_U8:
6014 case MONO_TYPE_R8:
6015 return length << 3;
6016 default:
6017 return -1;
6021 static gint32
6022 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6024 MONO_ARCH_SAVE_REGS;
6026 return mono_array_get_byte_length (array);
6029 static gint8
6030 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6032 MONO_ARCH_SAVE_REGS;
6034 return mono_array_get (array, gint8, idx);
6037 static void
6038 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6040 MONO_ARCH_SAVE_REGS;
6042 mono_array_set (array, gint8, idx, value);
6045 static MonoBoolean
6046 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6048 guint8 *src_buf, *dest_buf;
6050 MONO_ARCH_SAVE_REGS;
6052 /* watch out for integer overflow */
6053 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6054 return FALSE;
6056 src_buf = (guint8 *)src->vector + src_offset;
6057 dest_buf = (guint8 *)dest->vector + dest_offset;
6059 if (src != dest)
6060 memcpy (dest_buf, src_buf, count);
6061 else
6062 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6064 return TRUE;
6067 static MonoObject *
6068 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6070 MonoDomain *domain = mono_object_domain (this);
6071 MonoObject *res;
6072 MonoRealProxy *rp = ((MonoRealProxy *)this);
6073 MonoTransparentProxy *tp;
6074 MonoType *type;
6075 MonoClass *klass;
6077 MONO_ARCH_SAVE_REGS;
6079 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6080 tp = (MonoTransparentProxy*) res;
6082 MONO_OBJECT_SETREF (tp, rp, rp);
6083 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6084 klass = mono_class_from_mono_type (type);
6086 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6087 tp->remote_class = mono_remote_class (domain, class_name, klass);
6089 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6090 return res;
6093 static MonoReflectionType *
6094 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6096 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6099 /* System.Environment */
6101 MonoString*
6102 ves_icall_System_Environment_get_UserName (void)
6104 MONO_ARCH_SAVE_REGS;
6106 /* using glib is more portable */
6107 return mono_string_new (mono_domain_get (), g_get_user_name ());
6111 static MonoString *
6112 ves_icall_System_Environment_get_MachineName (void)
6114 #if defined (HOST_WIN32)
6115 gunichar2 *buf;
6116 guint32 len;
6117 MonoString *result;
6119 len = MAX_COMPUTERNAME_LENGTH + 1;
6120 buf = g_new (gunichar2, len);
6122 result = NULL;
6123 if (GetComputerName (buf, (PDWORD) &len))
6124 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6126 g_free (buf);
6127 return result;
6128 #elif !defined(DISABLE_SOCKETS)
6129 gchar buf [256];
6130 MonoString *result;
6132 if (gethostname (buf, sizeof (buf)) == 0)
6133 result = mono_string_new (mono_domain_get (), buf);
6134 else
6135 result = NULL;
6137 return result;
6138 #else
6139 return mono_string_new (mono_domain_get (), "mono");
6140 #endif
6143 static int
6144 ves_icall_System_Environment_get_Platform (void)
6146 #if defined (TARGET_WIN32)
6147 /* Win32NT */
6148 return 2;
6149 #elif defined(__MACH__)
6150 /* OSX */
6152 // For compatibility with our client code, this will be 4 for a while.
6153 // We will eventually move to 6 to match .NET, but it requires all client
6154 // code to be updated and the documentation everywhere to be updated
6155 // first.
6157 return 4;
6158 #else
6159 /* Unix */
6160 return 4;
6161 #endif
6164 static MonoString *
6165 ves_icall_System_Environment_get_NewLine (void)
6167 MONO_ARCH_SAVE_REGS;
6169 #if defined (HOST_WIN32)
6170 return mono_string_new (mono_domain_get (), "\r\n");
6171 #else
6172 return mono_string_new (mono_domain_get (), "\n");
6173 #endif
6176 static MonoString *
6177 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6179 const gchar *value;
6180 gchar *utf8_name;
6182 MONO_ARCH_SAVE_REGS;
6184 if (name == NULL)
6185 return NULL;
6187 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6188 value = g_getenv (utf8_name);
6190 g_free (utf8_name);
6192 if (value == 0)
6193 return NULL;
6195 return mono_string_new (mono_domain_get (), value);
6199 * There is no standard way to get at environ.
6201 #ifndef _MSC_VER
6202 #ifndef __MINGW32_VERSION
6203 #ifdef __APPLE__
6204 /* Apple defines this in crt_externs.h but doesn't provide that header for
6205 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6206 * in fact exist on all implementations (so far)
6208 gchar ***_NSGetEnviron(void);
6209 #define environ (*_NSGetEnviron())
6210 #else
6211 extern
6212 char **environ;
6213 #endif
6214 #endif
6215 #endif
6217 static MonoArray *
6218 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6220 #ifdef HOST_WIN32
6221 MonoArray *names;
6222 MonoDomain *domain;
6223 MonoString *str;
6224 WCHAR* env_strings;
6225 WCHAR* env_string;
6226 WCHAR* equal_str;
6227 int n = 0;
6229 env_strings = GetEnvironmentStrings();
6231 if (env_strings) {
6232 env_string = env_strings;
6233 while (*env_string != '\0') {
6234 /* weird case that MS seems to skip */
6235 if (*env_string != '=')
6236 n++;
6237 while (*env_string != '\0')
6238 env_string++;
6239 env_string++;
6243 domain = mono_domain_get ();
6244 names = mono_array_new (domain, mono_defaults.string_class, n);
6246 if (env_strings) {
6247 n = 0;
6248 env_string = env_strings;
6249 while (*env_string != '\0') {
6250 /* weird case that MS seems to skip */
6251 if (*env_string != '=') {
6252 equal_str = wcschr(env_string, '=');
6253 g_assert(equal_str);
6254 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6255 mono_array_setref (names, n, str);
6256 n++;
6258 while (*env_string != '\0')
6259 env_string++;
6260 env_string++;
6263 FreeEnvironmentStrings (env_strings);
6266 return names;
6268 #else
6269 MonoArray *names;
6270 MonoDomain *domain;
6271 MonoString *str;
6272 gchar **e, **parts;
6273 int n;
6275 MONO_ARCH_SAVE_REGS;
6277 n = 0;
6278 for (e = environ; *e != 0; ++ e)
6279 ++ n;
6281 domain = mono_domain_get ();
6282 names = mono_array_new (domain, mono_defaults.string_class, n);
6284 n = 0;
6285 for (e = environ; *e != 0; ++ e) {
6286 parts = g_strsplit (*e, "=", 2);
6287 if (*parts != 0) {
6288 str = mono_string_new (domain, *parts);
6289 mono_array_setref (names, n, str);
6292 g_strfreev (parts);
6294 ++ n;
6297 return names;
6298 #endif
6302 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6304 #if !GLIB_CHECK_VERSION(2,4,0)
6305 #define g_setenv(a,b,c) setenv(a,b,c)
6306 #define g_unsetenv(a) unsetenv(a)
6307 #endif
6309 static void
6310 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6312 MonoError error;
6313 #ifdef HOST_WIN32
6315 gunichar2 *utf16_name, *utf16_value;
6316 #else
6317 gchar *utf8_name, *utf8_value;
6318 #endif
6320 MONO_ARCH_SAVE_REGS;
6322 #ifdef HOST_WIN32
6323 utf16_name = mono_string_to_utf16 (name);
6324 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6325 SetEnvironmentVariable (utf16_name, NULL);
6326 g_free (utf16_name);
6327 return;
6330 utf16_value = mono_string_to_utf16 (value);
6332 SetEnvironmentVariable (utf16_name, utf16_value);
6334 g_free (utf16_name);
6335 g_free (utf16_value);
6336 #else
6337 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6339 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6340 g_unsetenv (utf8_name);
6341 g_free (utf8_name);
6342 return;
6345 utf8_value = mono_string_to_utf8_checked (value, &error);
6346 if (!mono_error_ok (&error)) {
6347 g_free (utf8_name);
6348 mono_error_raise_exception (&error);
6350 g_setenv (utf8_name, utf8_value, TRUE);
6352 g_free (utf8_name);
6353 g_free (utf8_value);
6354 #endif
6357 static void
6358 ves_icall_System_Environment_Exit (int result)
6360 MONO_ARCH_SAVE_REGS;
6362 mono_threads_set_shutting_down ();
6364 mono_runtime_set_shutting_down ();
6366 /* This will kill the tp threads which cannot be suspended */
6367 mono_thread_pool_cleanup ();
6369 /* Suspend all managed threads since the runtime is going away */
6370 mono_thread_suspend_all_other_threads ();
6372 mono_runtime_quit ();
6374 /* we may need to do some cleanup here... */
6375 exit (result);
6378 static MonoString*
6379 ves_icall_System_Environment_GetGacPath (void)
6381 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6384 static MonoString*
6385 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6387 #if defined (HOST_WIN32)
6388 #ifndef CSIDL_FLAG_CREATE
6389 #define CSIDL_FLAG_CREATE 0x8000
6390 #endif
6392 WCHAR path [MAX_PATH];
6393 /* Create directory if no existing */
6394 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6395 int len = 0;
6396 while (path [len])
6397 ++ len;
6398 return mono_string_new_utf16 (mono_domain_get (), path, len);
6400 #else
6401 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6402 #endif
6403 return mono_string_new (mono_domain_get (), "");
6406 static MonoArray *
6407 ves_icall_System_Environment_GetLogicalDrives (void)
6409 gunichar2 buf [128], *ptr, *dname;
6410 gunichar2 *u16;
6411 guint initial_size = 127, size = 128;
6412 gint ndrives;
6413 MonoArray *result;
6414 MonoString *drivestr;
6415 MonoDomain *domain = mono_domain_get ();
6416 gint len;
6418 MONO_ARCH_SAVE_REGS;
6420 buf [0] = '\0';
6421 ptr = buf;
6423 while (size > initial_size) {
6424 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6425 if (size > initial_size) {
6426 if (ptr != buf)
6427 g_free (ptr);
6428 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6429 initial_size = size;
6430 size++;
6434 /* Count strings */
6435 dname = ptr;
6436 ndrives = 0;
6437 do {
6438 while (*dname++);
6439 ndrives++;
6440 } while (*dname);
6442 dname = ptr;
6443 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6444 ndrives = 0;
6445 do {
6446 len = 0;
6447 u16 = dname;
6448 while (*u16) { u16++; len ++; }
6449 drivestr = mono_string_new_utf16 (domain, dname, len);
6450 mono_array_setref (result, ndrives++, drivestr);
6451 while (*dname++);
6452 } while (*dname);
6454 if (ptr != buf)
6455 g_free (ptr);
6457 return result;
6460 static MonoString *
6461 ves_icall_System_Environment_InternalGetHome (void)
6463 MONO_ARCH_SAVE_REGS;
6465 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6468 static const char *encodings [] = {
6469 (char *) 1,
6470 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6471 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6472 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6473 (char *) 2,
6474 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6475 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6476 "x_unicode_2_0_utf_7",
6477 (char *) 3,
6478 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6479 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6480 (char *) 4,
6481 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6482 "iso_10646_ucs2",
6483 (char *) 5,
6484 "unicodefffe", "utf_16be",
6485 (char *) 6,
6486 "iso_8859_1",
6487 (char *) 0
6491 * Returns the internal codepage, if the value of "int_code_page" is
6492 * 1 at entry, and we can not compute a suitable code page number,
6493 * returns the code page as a string
6495 static MonoString*
6496 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6498 const char *cset;
6499 const char *p;
6500 char *c;
6501 char *codepage = NULL;
6502 int code;
6503 int want_name = *int_code_page;
6504 int i;
6506 *int_code_page = -1;
6507 MONO_ARCH_SAVE_REGS;
6509 g_get_charset (&cset);
6510 c = codepage = strdup (cset);
6511 for (c = codepage; *c; c++){
6512 if (isascii (*c) && isalpha (*c))
6513 *c = tolower (*c);
6514 if (*c == '-')
6515 *c = '_';
6517 /* g_print ("charset: %s\n", cset); */
6519 /* handle some common aliases */
6520 p = encodings [0];
6521 code = 0;
6522 for (i = 0; p != 0; ){
6523 if ((gssize) p < 7){
6524 code = (gssize) p;
6525 p = encodings [++i];
6526 continue;
6528 if (strcmp (p, codepage) == 0){
6529 *int_code_page = code;
6530 break;
6532 p = encodings [++i];
6535 if (strstr (codepage, "utf_8") != NULL)
6536 *int_code_page |= 0x10000000;
6537 free (codepage);
6539 if (want_name && *int_code_page == -1)
6540 return mono_string_new (mono_domain_get (), cset);
6541 else
6542 return NULL;
6545 static MonoBoolean
6546 ves_icall_System_Environment_get_HasShutdownStarted (void)
6548 if (mono_runtime_is_shutting_down ())
6549 return TRUE;
6551 if (mono_domain_is_unloading (mono_domain_get ()))
6552 return TRUE;
6554 return FALSE;
6557 static void
6558 ves_icall_System_Environment_BroadcastSettingChange (void)
6560 #ifdef HOST_WIN32
6561 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6562 #endif
6565 static void
6566 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6567 MonoReflectionMethod *method,
6568 MonoArray *out_args)
6570 MONO_ARCH_SAVE_REGS;
6572 mono_message_init (mono_object_domain (this), this, method, out_args);
6575 static MonoBoolean
6576 ves_icall_IsTransparentProxy (MonoObject *proxy)
6578 MONO_ARCH_SAVE_REGS;
6580 if (!proxy)
6581 return 0;
6583 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6584 return 1;
6586 return 0;
6589 static MonoReflectionMethod *
6590 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6591 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6593 MonoClass *klass;
6594 MonoMethod *method;
6595 MonoMethod **vtable;
6596 MonoMethod *res = NULL;
6598 MONO_CHECK_ARG_NULL (rtype);
6599 MONO_CHECK_ARG_NULL (rmethod);
6601 method = rmethod->method;
6602 klass = mono_class_from_mono_type (rtype->type);
6604 if (MONO_CLASS_IS_INTERFACE (klass))
6605 return NULL;
6607 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6608 return NULL;
6610 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6611 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6612 return rmethod;
6613 else
6614 return NULL;
6617 mono_class_setup_vtable (klass);
6618 vtable = klass->vtable;
6620 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6621 gboolean variance_used = FALSE;
6622 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6623 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6624 if (offs >= 0)
6625 res = vtable [offs + method->slot];
6626 } else {
6627 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6628 return NULL;
6630 if (method->slot != -1)
6631 res = vtable [method->slot];
6634 if (!res)
6635 return NULL;
6637 return mono_method_get_object (mono_domain_get (), res, NULL);
6640 static void
6641 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6643 MonoClass *klass;
6644 MonoVTable* vtable;
6646 MONO_ARCH_SAVE_REGS;
6648 klass = mono_class_from_mono_type (type->type);
6649 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6651 if (enable) vtable->remote = 1;
6652 else vtable->remote = 0;
6655 static MonoObject *
6656 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6658 MonoClass *klass;
6659 MonoDomain *domain;
6661 MONO_ARCH_SAVE_REGS;
6663 domain = mono_object_domain (type);
6664 klass = mono_class_from_mono_type (type->type);
6666 if (klass->rank >= 1) {
6667 g_assert (klass->rank == 1);
6668 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6669 } else {
6670 /* Bypass remoting object creation check */
6671 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6675 static MonoString *
6676 ves_icall_System_IO_get_temp_path (void)
6678 MONO_ARCH_SAVE_REGS;
6680 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6683 #ifndef PLATFORM_NO_DRIVEINFO
6684 static MonoBoolean
6685 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6686 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6687 gint32 *error)
6689 gboolean result;
6690 ULARGE_INTEGER wapi_free_bytes_avail;
6691 ULARGE_INTEGER wapi_total_number_of_bytes;
6692 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6694 MONO_ARCH_SAVE_REGS;
6696 *error = ERROR_SUCCESS;
6697 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6698 &wapi_total_number_of_free_bytes);
6700 if (result) {
6701 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6702 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6703 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6704 } else {
6705 *free_bytes_avail = 0;
6706 *total_number_of_bytes = 0;
6707 *total_number_of_free_bytes = 0;
6708 *error = GetLastError ();
6711 return result;
6714 static guint32
6715 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6717 MONO_ARCH_SAVE_REGS;
6719 return GetDriveType (mono_string_chars (root_path_name));
6721 #endif
6723 static gpointer
6724 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6726 MONO_ARCH_SAVE_REGS;
6728 return mono_compile_method (method);
6731 static MonoString *
6732 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6734 MonoString *mcpath;
6735 gchar *path;
6737 MONO_ARCH_SAVE_REGS;
6739 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6741 #if defined (HOST_WIN32)
6742 /* Avoid mixing '/' and '\\' */
6744 gint i;
6745 for (i = strlen (path) - 1; i >= 0; i--)
6746 if (path [i] == '/')
6747 path [i] = '\\';
6749 #endif
6750 mcpath = mono_string_new (mono_domain_get (), path);
6751 g_free (path);
6753 return mcpath;
6756 static MonoString *
6757 get_bundled_machine_config (void)
6759 const gchar *machine_config;
6761 MONO_ARCH_SAVE_REGS;
6763 machine_config = mono_get_machine_config ();
6765 if (!machine_config)
6766 return NULL;
6768 return mono_string_new (mono_domain_get (), machine_config);
6771 static MonoString *
6772 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6774 MonoString *ipath;
6775 gchar *path;
6777 MONO_ARCH_SAVE_REGS;
6779 path = g_path_get_dirname (mono_get_config_dir ());
6781 #if defined (HOST_WIN32)
6782 /* Avoid mixing '/' and '\\' */
6784 gint i;
6785 for (i = strlen (path) - 1; i >= 0; i--)
6786 if (path [i] == '/')
6787 path [i] = '\\';
6789 #endif
6790 ipath = mono_string_new (mono_domain_get (), path);
6791 g_free (path);
6793 return ipath;
6796 static gboolean
6797 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6799 MonoPEResourceDataEntry *entry;
6800 MonoImage *image;
6802 MONO_ARCH_SAVE_REGS;
6804 if (!assembly || !result || !size)
6805 return FALSE;
6807 *result = NULL;
6808 *size = 0;
6809 image = assembly->assembly->image;
6810 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6811 if (!entry)
6812 return FALSE;
6814 *result = mono_image_rva_map (image, entry->rde_data_offset);
6815 if (!(*result)) {
6816 g_free (entry);
6817 return FALSE;
6819 *size = entry->rde_size;
6820 g_free (entry);
6821 return TRUE;
6824 static MonoBoolean
6825 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6827 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6830 static void
6831 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6833 #if defined (HOST_WIN32)
6834 OutputDebugString (mono_string_chars (message));
6835 #else
6836 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6837 #endif
6840 /* Only used for value types */
6841 static MonoObject *
6842 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6844 MonoClass *klass;
6845 MonoDomain *domain;
6847 MONO_ARCH_SAVE_REGS;
6849 domain = mono_object_domain (type);
6850 klass = mono_class_from_mono_type (type->type);
6852 if (mono_class_is_nullable (klass))
6853 /* No arguments -> null */
6854 return NULL;
6856 return mono_object_new (domain, klass);
6859 static MonoReflectionMethod *
6860 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6862 MonoClass *klass, *parent;
6863 MonoMethod *method = m->method;
6864 MonoMethod *result = NULL;
6866 MONO_ARCH_SAVE_REGS;
6868 if (method->klass == NULL)
6869 return m;
6871 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6872 MONO_CLASS_IS_INTERFACE (method->klass) ||
6873 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6874 return m;
6876 klass = method->klass;
6877 if (klass->generic_class)
6878 klass = klass->generic_class->container_class;
6880 if (definition) {
6881 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6882 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6883 mono_class_setup_vtable (parent);
6884 if (parent->vtable_size <= method->slot)
6885 break;
6886 klass = parent;
6888 } else {
6889 klass = klass->parent;
6890 if (!klass)
6891 return m;
6894 if (klass == method->klass)
6895 return m;
6897 result = klass->vtable [method->slot];
6898 if (result == NULL) {
6899 /* It is an abstract method */
6900 gpointer iter = NULL;
6901 while ((result = mono_class_get_methods (klass, &iter)))
6902 if (result->slot == method->slot)
6903 break;
6906 if (result == NULL)
6907 return m;
6909 return mono_method_get_object (mono_domain_get (), result, NULL);
6912 static MonoString*
6913 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6915 MonoMethod *method = m->method;
6917 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6918 return m->name;
6921 static void
6922 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6924 MONO_ARCH_SAVE_REGS;
6926 iter->sig = *(MonoMethodSignature**)argsp;
6928 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6929 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6931 iter->next_arg = 0;
6932 /* FIXME: it's not documented what start is exactly... */
6933 if (start) {
6934 iter->args = start;
6935 } else {
6936 iter->args = argsp + sizeof (gpointer);
6938 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6940 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6943 static MonoTypedRef
6944 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6946 guint32 i, arg_size;
6947 gint32 align;
6948 MonoTypedRef res;
6949 MONO_ARCH_SAVE_REGS;
6951 i = iter->sig->sentinelpos + iter->next_arg;
6953 g_assert (i < iter->sig->param_count);
6955 res.type = iter->sig->params [i];
6956 res.klass = mono_class_from_mono_type (res.type);
6957 res.value = iter->args;
6958 arg_size = mono_type_stack_size (res.type, &align);
6959 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
6960 if (arg_size <= sizeof (gpointer)) {
6961 int dummy;
6962 int padding = arg_size - mono_type_size (res.type, &dummy);
6963 res.value = (guint8*)res.value + padding;
6965 #endif
6966 iter->args = (char*)iter->args + arg_size;
6967 iter->next_arg++;
6969 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6971 return res;
6974 static MonoTypedRef
6975 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6977 guint32 i, arg_size;
6978 gint32 align;
6979 MonoTypedRef res;
6980 MONO_ARCH_SAVE_REGS;
6982 i = iter->sig->sentinelpos + iter->next_arg;
6984 g_assert (i < iter->sig->param_count);
6986 while (i < iter->sig->param_count) {
6987 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6988 continue;
6989 res.type = iter->sig->params [i];
6990 res.klass = mono_class_from_mono_type (res.type);
6991 /* FIXME: endianess issue... */
6992 res.value = iter->args;
6993 arg_size = mono_type_stack_size (res.type, &align);
6994 iter->args = (char*)iter->args + arg_size;
6995 iter->next_arg++;
6996 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6997 return res;
6999 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7001 res.type = NULL;
7002 res.value = NULL;
7003 res.klass = NULL;
7004 return res;
7007 static MonoType*
7008 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7010 gint i;
7011 MONO_ARCH_SAVE_REGS;
7013 i = iter->sig->sentinelpos + iter->next_arg;
7015 g_assert (i < iter->sig->param_count);
7017 return iter->sig->params [i];
7020 static MonoObject*
7021 mono_TypedReference_ToObject (MonoTypedRef tref)
7023 MONO_ARCH_SAVE_REGS;
7025 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7026 MonoObject** objp = tref.value;
7027 return *objp;
7030 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7033 static MonoObject*
7034 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7036 MONO_ARCH_SAVE_REGS;
7038 if (MONO_TYPE_IS_REFERENCE (type)) {
7039 MonoObject** objp = value;
7040 return *objp;
7043 return mono_value_box (mono_domain_get (), klass, value);
7046 static void
7047 prelink_method (MonoMethod *method)
7049 const char *exc_class, *exc_arg;
7050 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7051 return;
7052 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7053 if (exc_class) {
7054 mono_raise_exception(
7055 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7057 /* create the wrapper, too? */
7060 static void
7061 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7063 MONO_ARCH_SAVE_REGS;
7064 prelink_method (method->method);
7067 static void
7068 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7070 MonoClass *klass = mono_class_from_mono_type (type->type);
7071 MonoMethod* m;
7072 gpointer iter = NULL;
7073 MONO_ARCH_SAVE_REGS;
7075 while ((m = mono_class_get_methods (klass, &iter)))
7076 prelink_method (m);
7079 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7080 static void
7081 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7082 gint32 const **exponents,
7083 gunichar2 const **digitLowerTable,
7084 gunichar2 const **digitUpperTable,
7085 gint64 const **tenPowersList,
7086 gint32 const **decHexDigits)
7088 *mantissas = Formatter_MantissaBitsTable;
7089 *exponents = Formatter_TensExponentTable;
7090 *digitLowerTable = Formatter_DigitLowerTable;
7091 *digitUpperTable = Formatter_DigitUpperTable;
7092 *tenPowersList = Formatter_TenPowersList;
7093 *decHexDigits = Formatter_DecHexDigits;
7096 /* These parameters are "readonly" in corlib/System/Char.cs */
7097 static void
7098 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7099 guint8 const **numeric_data,
7100 gdouble const **numeric_data_values,
7101 guint16 const **to_lower_data_low,
7102 guint16 const **to_lower_data_high,
7103 guint16 const **to_upper_data_low,
7104 guint16 const **to_upper_data_high)
7106 *category_data = CategoryData;
7107 *numeric_data = NumericData;
7108 *numeric_data_values = NumericDataValues;
7109 *to_lower_data_low = ToLowerDataLow;
7110 *to_lower_data_high = ToLowerDataHigh;
7111 *to_upper_data_low = ToUpperDataLow;
7112 *to_upper_data_high = ToUpperDataHigh;
7115 static gint32
7116 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7118 return method->method->token;
7122 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7123 * and avoid useless allocations.
7125 static MonoArray*
7126 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7128 MonoArray *res;
7129 int i, count = 0;
7130 for (i = 0; i < type->num_mods; ++i) {
7131 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7132 count++;
7134 if (!count)
7135 return NULL;
7136 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7137 count = 0;
7138 for (i = 0; i < type->num_mods; ++i) {
7139 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7140 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7141 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7142 count++;
7145 return res;
7148 static MonoArray*
7149 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7151 MonoType *type = param->ClassImpl->type;
7152 MonoClass *member_class = mono_object_class (param->MemberImpl);
7153 MonoMethod *method = NULL;
7154 MonoImage *image;
7155 int pos;
7156 MonoMethodSignature *sig;
7158 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7159 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7160 method = rmethod->method;
7161 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7162 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7163 if (!(method = prop->property->get))
7164 method = prop->property->set;
7165 g_assert (method);
7166 } else {
7167 char *type_name = mono_type_get_full_name (member_class);
7168 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7169 MonoException *ex = mono_get_exception_not_supported (msg);
7170 g_free (type_name);
7171 g_free (msg);
7172 mono_raise_exception (ex);
7175 image = method->klass->image;
7176 pos = param->PositionImpl;
7177 sig = mono_method_signature (method);
7178 if (pos == -1)
7179 type = sig->ret;
7180 else
7181 type = sig->params [pos];
7183 return type_array_from_modifiers (image, type, optional);
7186 static MonoType*
7187 get_property_type (MonoProperty *prop)
7189 MonoMethodSignature *sig;
7190 if (prop->get) {
7191 sig = mono_method_signature (prop->get);
7192 return sig->ret;
7193 } else if (prop->set) {
7194 sig = mono_method_signature (prop->set);
7195 return sig->params [sig->param_count - 1];
7197 return NULL;
7200 static MonoArray*
7201 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7203 MonoType *type = get_property_type (property->property);
7204 MonoImage *image = property->klass->image;
7206 if (!type)
7207 return NULL;
7208 return type_array_from_modifiers (image, type, optional);
7212 *Construct a MonoType suited to be used to decode a constant blob object.
7214 * @type is the target type which will be constructed
7215 * @blob_type is the blob type, for example, that comes from the constant table
7216 * @real_type is the expected constructed type.
7218 static void
7219 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7221 type->type = blob_type;
7222 type->data.klass = NULL;
7223 if (blob_type == MONO_TYPE_CLASS)
7224 type->data.klass = mono_defaults.object_class;
7225 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7226 /* For enums, we need to use the base type */
7227 type->type = MONO_TYPE_VALUETYPE;
7228 type->data.klass = mono_class_from_mono_type (real_type);
7229 } else
7230 type->data.klass = mono_class_from_mono_type (real_type);
7233 static MonoObject*
7234 property_info_get_default_value (MonoReflectionProperty *property)
7236 MonoType blob_type;
7237 MonoProperty *prop = property->property;
7238 MonoType *type = get_property_type (prop);
7239 MonoDomain *domain = mono_object_domain (property);
7240 MonoTypeEnum def_type;
7241 const char *def_value;
7242 MonoObject *o;
7244 g_assert (!prop->parent->image->dynamic);
7246 mono_class_init (prop->parent);
7248 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7249 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7251 def_value = mono_class_get_property_default_value (prop, &def_type);
7253 mono_type_from_blob_type (&blob_type, def_type, type);
7254 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7256 return o;
7259 static MonoBoolean
7260 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7262 MonoCustomAttrInfo *cinfo;
7263 gboolean found;
7265 cinfo = mono_reflection_get_custom_attrs_info (obj);
7266 if (!cinfo)
7267 return FALSE;
7268 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7269 if (!cinfo->cached)
7270 mono_custom_attrs_free (cinfo);
7271 return found;
7274 static MonoArray*
7275 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7277 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7279 if (mono_loader_get_last_error ()) {
7280 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7281 g_assert_not_reached ();
7282 /* Not reached */
7283 return NULL;
7284 } else {
7285 return res;
7289 static MonoString*
7290 ves_icall_Mono_Runtime_GetDisplayName (void)
7292 char *info;
7293 MonoString *display_name;
7295 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7296 display_name = mono_string_new (mono_domain_get (), info);
7297 g_free (info);
7298 return display_name;
7301 static MonoString*
7302 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7304 MonoString *message;
7305 guint32 ret;
7306 gunichar2 buf[256];
7308 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7309 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7310 buf, 255, NULL);
7311 if (ret == 0) {
7312 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7313 } else {
7314 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7317 return message;
7320 const static guchar
7321 dbase64 [] = {
7322 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7323 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7324 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7325 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7326 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7327 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7328 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7329 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7332 static MonoArray *
7333 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7335 gint ignored;
7336 gint i;
7337 gunichar2 c;
7338 gunichar2 last, prev_last, prev2_last;
7339 gint olength;
7340 MonoArray *result;
7341 guchar *res_ptr;
7342 gint a [4], b [4];
7343 MonoException *exc;
7345 ignored = 0;
7346 last = prev_last = 0, prev2_last = 0;
7347 for (i = 0; i < ilength; i++) {
7348 c = start [i];
7349 if (c >= sizeof (dbase64)) {
7350 exc = mono_exception_from_name_msg (mono_get_corlib (),
7351 "System", "FormatException",
7352 "Invalid character found.");
7353 mono_raise_exception (exc);
7354 } else if (isspace (c)) {
7355 ignored++;
7356 } else {
7357 prev2_last = prev_last;
7358 prev_last = last;
7359 last = c;
7363 olength = ilength - ignored;
7365 if (allowWhitespaceOnly && olength == 0) {
7366 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7369 if ((olength & 3) != 0 || olength <= 0) {
7370 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7371 "FormatException", "Invalid length.");
7372 mono_raise_exception (exc);
7375 if (prev2_last == '=') {
7376 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7377 mono_raise_exception (exc);
7380 olength = (olength * 3) / 4;
7381 if (last == '=')
7382 olength--;
7384 if (prev_last == '=')
7385 olength--;
7387 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7388 res_ptr = mono_array_addr (result, guchar, 0);
7389 for (i = 0; i < ilength; ) {
7390 int k;
7392 for (k = 0; k < 4 && i < ilength;) {
7393 c = start [i++];
7394 if (isspace (c))
7395 continue;
7397 a [k] = (guchar) c;
7398 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7399 exc = mono_exception_from_name_msg (mono_get_corlib (),
7400 "System", "FormatException",
7401 "Invalid character found.");
7402 mono_raise_exception (exc);
7404 k++;
7407 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7408 if (a [2] != '=')
7409 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7410 if (a [3] != '=')
7411 *res_ptr++ = (b [2] << 6) | b [3];
7413 while (i < ilength && isspace (start [i]))
7414 i++;
7417 return result;
7420 static MonoArray *
7421 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7423 MONO_ARCH_SAVE_REGS;
7425 return base64_to_byte_array (mono_string_chars (str),
7426 mono_string_length (str), allowWhitespaceOnly);
7429 static MonoArray *
7430 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7432 MONO_ARCH_SAVE_REGS;
7434 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7435 length, FALSE);
7438 #define ICALL_TYPE(id,name,first)
7439 #define ICALL(id,name,func) Icall_ ## id,
7441 enum {
7442 #include "metadata/icall-def.h"
7443 Icall_last
7446 #undef ICALL_TYPE
7447 #undef ICALL
7448 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7449 #define ICALL(id,name,func)
7450 enum {
7451 #include "metadata/icall-def.h"
7452 Icall_type_num
7455 #undef ICALL_TYPE
7456 #undef ICALL
7457 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7458 #define ICALL(id,name,func)
7459 typedef struct {
7460 guint16 first_icall;
7461 } IcallTypeDesc;
7463 static const IcallTypeDesc
7464 icall_type_descs [] = {
7465 #include "metadata/icall-def.h"
7466 {Icall_last}
7469 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7471 #undef ICALL_TYPE
7472 #define ICALL_TYPE(id,name,first)
7473 #undef ICALL
7475 #ifdef HAVE_ARRAY_ELEM_INIT
7476 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7477 #define MSGSTRFIELD1(line) str##line
7479 static const struct msgstrtn_t {
7480 #define ICALL(id,name,func)
7481 #undef ICALL_TYPE
7482 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7483 #include "metadata/icall-def.h"
7484 #undef ICALL_TYPE
7485 } icall_type_names_str = {
7486 #define ICALL_TYPE(id,name,first) (name),
7487 #include "metadata/icall-def.h"
7488 #undef ICALL_TYPE
7490 static const guint16 icall_type_names_idx [] = {
7491 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7492 #include "metadata/icall-def.h"
7493 #undef ICALL_TYPE
7495 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7497 static const struct msgstr_t {
7498 #undef ICALL
7499 #define ICALL_TYPE(id,name,first)
7500 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7501 #include "metadata/icall-def.h"
7502 #undef ICALL
7503 } icall_names_str = {
7504 #define ICALL(id,name,func) (name),
7505 #include "metadata/icall-def.h"
7506 #undef ICALL
7508 static const guint16 icall_names_idx [] = {
7509 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7510 #include "metadata/icall-def.h"
7511 #undef ICALL
7513 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7515 #else
7517 #undef ICALL_TYPE
7518 #undef ICALL
7519 #define ICALL_TYPE(id,name,first) name,
7520 #define ICALL(id,name,func)
7521 static const char* const
7522 icall_type_names [] = {
7523 #include "metadata/icall-def.h"
7524 NULL
7527 #define icall_type_name_get(id) (icall_type_names [(id)])
7529 #undef ICALL_TYPE
7530 #undef ICALL
7531 #define ICALL_TYPE(id,name,first)
7532 #define ICALL(id,name,func) name,
7533 static const char* const
7534 icall_names [] = {
7535 #include "metadata/icall-def.h"
7536 NULL
7538 #define icall_name_get(id) icall_names [(id)]
7540 #endif /* !HAVE_ARRAY_ELEM_INIT */
7542 #undef ICALL_TYPE
7543 #undef ICALL
7544 #define ICALL_TYPE(id,name,first)
7545 #define ICALL(id,name,func) func,
7546 static const gconstpointer
7547 icall_functions [] = {
7548 #include "metadata/icall-def.h"
7549 NULL
7552 static GHashTable *icall_hash = NULL;
7553 static GHashTable *jit_icall_hash_name = NULL;
7554 static GHashTable *jit_icall_hash_addr = NULL;
7556 void
7557 mono_icall_init (void)
7559 int i = 0;
7561 /* check that tables are sorted: disable in release */
7562 if (TRUE) {
7563 int j;
7564 const char *prev_class = NULL;
7565 const char *prev_method;
7567 for (i = 0; i < Icall_type_num; ++i) {
7568 const IcallTypeDesc *desc;
7569 int num_icalls;
7570 prev_method = NULL;
7571 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7572 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7573 prev_class = icall_type_name_get (i);
7574 desc = &icall_type_descs [i];
7575 num_icalls = icall_desc_num_icalls (desc);
7576 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7577 for (j = 0; j < num_icalls; ++j) {
7578 const char *methodn = icall_name_get (desc->first_icall + j);
7579 if (prev_method && strcmp (prev_method, methodn) >= 0)
7580 g_print ("method %s should come before method %s\n", methodn, prev_method);
7581 prev_method = methodn;
7586 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7589 void
7590 mono_icall_cleanup (void)
7592 g_hash_table_destroy (icall_hash);
7593 g_hash_table_destroy (jit_icall_hash_name);
7594 g_hash_table_destroy (jit_icall_hash_addr);
7597 void
7598 mono_add_internal_call (const char *name, gconstpointer method)
7600 mono_loader_lock ();
7602 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7604 mono_loader_unlock ();
7607 #ifdef HAVE_ARRAY_ELEM_INIT
7608 static int
7609 compare_method_imap (const void *key, const void *elem)
7611 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7612 return strcmp (key, method_name);
7615 static gpointer
7616 find_method_icall (const IcallTypeDesc *imap, const char *name)
7618 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7619 if (!nameslot)
7620 return NULL;
7621 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7624 static int
7625 compare_class_imap (const void *key, const void *elem)
7627 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7628 return strcmp (key, class_name);
7631 static const IcallTypeDesc*
7632 find_class_icalls (const char *name)
7634 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7635 if (!nameslot)
7636 return NULL;
7637 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7640 #else
7641 static int
7642 compare_method_imap (const void *key, const void *elem)
7644 const char** method_name = (const char**)elem;
7645 return strcmp (key, *method_name);
7648 static gpointer
7649 find_method_icall (const IcallTypeDesc *imap, const char *name)
7651 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7652 if (!nameslot)
7653 return NULL;
7654 return (gpointer)icall_functions [(nameslot - icall_names)];
7657 static int
7658 compare_class_imap (const void *key, const void *elem)
7660 const char** class_name = (const char**)elem;
7661 return strcmp (key, *class_name);
7664 static const IcallTypeDesc*
7665 find_class_icalls (const char *name)
7667 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7668 if (!nameslot)
7669 return NULL;
7670 return &icall_type_descs [nameslot - icall_type_names];
7673 #endif
7676 * we should probably export this as an helper (handle nested types).
7677 * Returns the number of chars written in buf.
7679 static int
7680 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7682 int nspacelen, cnamelen;
7683 nspacelen = strlen (klass->name_space);
7684 cnamelen = strlen (klass->name);
7685 if (nspacelen + cnamelen + 2 > bufsize)
7686 return 0;
7687 if (nspacelen) {
7688 memcpy (buf, klass->name_space, nspacelen);
7689 buf [nspacelen ++] = '.';
7691 memcpy (buf + nspacelen, klass->name, cnamelen);
7692 buf [nspacelen + cnamelen] = 0;
7693 return nspacelen + cnamelen;
7696 gpointer
7697 mono_lookup_internal_call (MonoMethod *method)
7699 char *sigstart;
7700 char *tmpsig;
7701 char mname [2048];
7702 int typelen = 0, mlen, siglen;
7703 gpointer res;
7704 const IcallTypeDesc *imap;
7706 g_assert (method != NULL);
7708 if (method->is_inflated)
7709 method = ((MonoMethodInflated *) method)->declaring;
7711 if (method->klass->nested_in) {
7712 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7713 if (!pos)
7714 return NULL;
7716 mname [pos++] = '/';
7717 mname [pos] = 0;
7719 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7720 if (!typelen)
7721 return NULL;
7723 typelen += pos;
7724 } else {
7725 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7726 if (!typelen)
7727 return NULL;
7730 imap = find_class_icalls (mname);
7732 mname [typelen] = ':';
7733 mname [typelen + 1] = ':';
7735 mlen = strlen (method->name);
7736 memcpy (mname + typelen + 2, method->name, mlen);
7737 sigstart = mname + typelen + 2 + mlen;
7738 *sigstart = 0;
7740 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7741 siglen = strlen (tmpsig);
7742 if (typelen + mlen + siglen + 6 > sizeof (mname))
7743 return NULL;
7744 sigstart [0] = '(';
7745 memcpy (sigstart + 1, tmpsig, siglen);
7746 sigstart [siglen + 1] = ')';
7747 sigstart [siglen + 2] = 0;
7748 g_free (tmpsig);
7750 mono_loader_lock ();
7752 res = g_hash_table_lookup (icall_hash, mname);
7753 if (res) {
7754 mono_loader_unlock ();
7755 return res;
7757 /* try without signature */
7758 *sigstart = 0;
7759 res = g_hash_table_lookup (icall_hash, mname);
7760 if (res) {
7761 mono_loader_unlock ();
7762 return res;
7765 /* it wasn't found in the static call tables */
7766 if (!imap) {
7767 mono_loader_unlock ();
7768 return NULL;
7770 res = find_method_icall (imap, sigstart - mlen);
7771 if (res) {
7772 mono_loader_unlock ();
7773 return res;
7775 /* try _with_ signature */
7776 *sigstart = '(';
7777 res = find_method_icall (imap, sigstart - mlen);
7778 if (res) {
7779 mono_loader_unlock ();
7780 return res;
7783 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7784 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7785 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7786 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7787 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");
7788 g_print ("If you see other errors or faults after this message they are probably related\n");
7789 g_print ("and you need to fix your mono install first.\n");
7791 mono_loader_unlock ();
7793 return NULL;
7796 static MonoType*
7797 type_from_typename (char *typename)
7799 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7801 if (!strcmp (typename, "int"))
7802 klass = mono_defaults.int_class;
7803 else if (!strcmp (typename, "ptr"))
7804 klass = mono_defaults.int_class;
7805 else if (!strcmp (typename, "void"))
7806 klass = mono_defaults.void_class;
7807 else if (!strcmp (typename, "int32"))
7808 klass = mono_defaults.int32_class;
7809 else if (!strcmp (typename, "uint32"))
7810 klass = mono_defaults.uint32_class;
7811 else if (!strcmp (typename, "int8"))
7812 klass = mono_defaults.sbyte_class;
7813 else if (!strcmp (typename, "uint8"))
7814 klass = mono_defaults.byte_class;
7815 else if (!strcmp (typename, "int16"))
7816 klass = mono_defaults.int16_class;
7817 else if (!strcmp (typename, "uint16"))
7818 klass = mono_defaults.uint16_class;
7819 else if (!strcmp (typename, "long"))
7820 klass = mono_defaults.int64_class;
7821 else if (!strcmp (typename, "ulong"))
7822 klass = mono_defaults.uint64_class;
7823 else if (!strcmp (typename, "float"))
7824 klass = mono_defaults.single_class;
7825 else if (!strcmp (typename, "double"))
7826 klass = mono_defaults.double_class;
7827 else if (!strcmp (typename, "object"))
7828 klass = mono_defaults.object_class;
7829 else if (!strcmp (typename, "obj"))
7830 klass = mono_defaults.object_class;
7831 else if (!strcmp (typename, "string"))
7832 klass = mono_defaults.string_class;
7833 else if (!strcmp (typename, "bool"))
7834 klass = mono_defaults.boolean_class;
7835 else if (!strcmp (typename, "boolean"))
7836 klass = mono_defaults.boolean_class;
7837 else {
7838 g_error ("%s", typename);
7839 g_assert_not_reached ();
7841 return &klass->byval_arg;
7844 MonoMethodSignature*
7845 mono_create_icall_signature (const char *sigstr)
7847 gchar **parts;
7848 int i, len;
7849 gchar **tmp;
7850 MonoMethodSignature *res;
7852 mono_loader_lock ();
7853 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7854 if (res) {
7855 mono_loader_unlock ();
7856 return res;
7859 parts = g_strsplit (sigstr, " ", 256);
7861 tmp = parts;
7862 len = 0;
7863 while (*tmp) {
7864 len ++;
7865 tmp ++;
7868 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7869 res->pinvoke = 1;
7871 #ifdef HOST_WIN32
7873 * Under windows, the default pinvoke calling convention is STDCALL but
7874 * we need CDECL.
7876 res->call_convention = MONO_CALL_C;
7877 #endif
7879 res->ret = type_from_typename (parts [0]);
7880 for (i = 1; i < len; ++i) {
7881 res->params [i - 1] = type_from_typename (parts [i]);
7884 g_strfreev (parts);
7886 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7888 mono_loader_unlock ();
7890 return res;
7893 MonoJitICallInfo *
7894 mono_find_jit_icall_by_name (const char *name)
7896 MonoJitICallInfo *info;
7897 g_assert (jit_icall_hash_name);
7899 mono_loader_lock ();
7900 info = g_hash_table_lookup (jit_icall_hash_name, name);
7901 mono_loader_unlock ();
7902 return info;
7905 MonoJitICallInfo *
7906 mono_find_jit_icall_by_addr (gconstpointer addr)
7908 MonoJitICallInfo *info;
7909 g_assert (jit_icall_hash_addr);
7911 mono_loader_lock ();
7912 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7913 mono_loader_unlock ();
7915 return info;
7919 * mono_get_jit_icall_info:
7921 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7922 * caller should access it while holding the loader lock.
7924 GHashTable*
7925 mono_get_jit_icall_info (void)
7927 return jit_icall_hash_name;
7930 void
7931 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7933 mono_loader_lock ();
7934 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7935 mono_loader_unlock ();
7938 MonoJitICallInfo *
7939 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7941 MonoJitICallInfo *info;
7943 g_assert (func);
7944 g_assert (name);
7946 mono_loader_lock ();
7948 if (!jit_icall_hash_name) {
7949 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7950 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7953 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7954 g_warning ("jit icall already defined \"%s\"\n", name);
7955 g_assert_not_reached ();
7958 info = g_new0 (MonoJitICallInfo, 1);
7960 info->name = name;
7961 info->func = func;
7962 info->sig = sig;
7964 if (is_save) {
7965 info->wrapper = func;
7966 } else {
7967 info->wrapper = NULL;
7970 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7971 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7973 mono_loader_unlock ();
7974 return info;