2009-05-22 Miguel de Icaza <miguel@novell.com>
[mono/afaerber.git] / mono / metadata / icall.c
blob77d001d8db1dde84366f96b391b5758e2f7bdcfe
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 (PLATFORM_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>
76 #if defined (PLATFORM_WIN32)
77 #include <windows.h>
78 #include <shlobj.h>
79 #endif
80 #include "decimal.h"
82 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
84 static MonoArray*
85 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
87 /* This is an implementation of a growable pointer array that avoids doing memory allocations for small sizes.
88 * It works by allocating an initial small array on stack and only going to malloc'd memory if needed.
90 typedef struct {
91 void **data;
92 int size;
93 int capacity;
94 } MonoPtrArray;
96 #define MONO_PTR_ARRAY_MAX_ON_STACK (16)
98 #define mono_ptr_array_init(ARRAY, INITIAL_SIZE) do {\
99 (ARRAY).size = 0; \
100 (ARRAY).capacity = MAX (INITIAL_SIZE, MONO_PTR_ARRAY_MAX_ON_STACK); \
101 (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); \
102 } while (0)
104 #define mono_ptr_array_destroy(ARRAY) do {\
105 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
106 mono_gc_free_fixed ((ARRAY).data); \
107 } while (0)
109 #define mono_ptr_array_append(ARRAY, VALUE) do { \
110 if ((ARRAY).size >= (ARRAY).capacity) {\
111 void *__tmp = mono_gc_alloc_fixed (sizeof (void*) * (ARRAY).capacity * 2, NULL); \
112 memcpy (__tmp, (ARRAY).data, (ARRAY).capacity * sizeof (void*)); \
113 (ARRAY).data = __tmp; \
114 (ARRAY).capacity *= 2;\
116 ((ARRAY).data [(ARRAY).size++] = VALUE); \
117 } while (0)
119 #define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \
120 ((ARRAY).data [(IDX)] = VALUE); \
121 } while (0)
123 #define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)])
125 #define mono_ptr_array_size(ARRAY) ((ARRAY).size)
128 static inline MonoBoolean
129 is_generic_parameter (MonoType *type)
131 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
135 * We expect a pointer to a char, not a string
137 static gboolean
138 mono_double_ParseImpl (char *ptr, double *result)
140 gchar *endptr = NULL;
141 *result = 0.0;
143 MONO_ARCH_SAVE_REGS;
145 #ifdef __arm__
146 if (*ptr)
147 *result = strtod (ptr, &endptr);
148 #else
149 if (*ptr){
150 #ifdef _EGLIB_MAJOR
151 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
152 EnterCriticalSection (&mono_strtod_mutex);
153 *result = mono_strtod (ptr, &endptr);
154 LeaveCriticalSection (&mono_strtod_mutex);
155 #else
156 *result = mono_strtod (ptr, &endptr);
157 #endif
159 #endif
161 if (!*ptr || (endptr && *endptr))
162 return FALSE;
164 return TRUE;
167 static MonoObject *
168 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
170 MonoClass *ac;
171 MonoArray *ao;
172 gint32 esize;
173 gpointer *ea;
175 MONO_ARCH_SAVE_REGS;
177 ao = (MonoArray *)this;
178 ac = (MonoClass *)ao->obj.vtable->klass;
180 esize = mono_array_element_size (ac);
181 ea = (gpointer*)((char*)ao->vector + (pos * esize));
183 if (ac->element_class->valuetype)
184 return mono_value_box (this->vtable->domain, ac->element_class, ea);
185 else
186 return *ea;
189 static MonoObject *
190 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
192 MonoClass *ac, *ic;
193 MonoArray *ao, *io;
194 gint32 i, pos, *ind;
196 MONO_ARCH_SAVE_REGS;
198 MONO_CHECK_ARG_NULL (idxs);
200 io = (MonoArray *)idxs;
201 ic = (MonoClass *)io->obj.vtable->klass;
203 ao = (MonoArray *)this;
204 ac = (MonoClass *)ao->obj.vtable->klass;
206 g_assert (ic->rank == 1);
207 if (io->bounds != NULL || io->max_length != ac->rank)
208 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
210 ind = (gint32 *)io->vector;
212 if (ao->bounds == NULL) {
213 if (*ind < 0 || *ind >= ao->max_length)
214 mono_raise_exception (mono_get_exception_index_out_of_range ());
216 return ves_icall_System_Array_GetValueImpl (this, *ind);
219 for (i = 0; i < ac->rank; i++)
220 if ((ind [i] < ao->bounds [i].lower_bound) ||
221 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
222 mono_raise_exception (mono_get_exception_index_out_of_range ());
224 pos = ind [0] - ao->bounds [0].lower_bound;
225 for (i = 1; i < ac->rank; i++)
226 pos = pos*ao->bounds [i].length + ind [i] -
227 ao->bounds [i].lower_bound;
229 return ves_icall_System_Array_GetValueImpl (this, pos);
232 static void
233 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
235 MonoClass *ac, *vc, *ec;
236 gint32 esize, vsize;
237 gpointer *ea, *va;
238 int et, vt;
240 guint64 u64 = 0;
241 gint64 i64 = 0;
242 gdouble r64 = 0;
244 MONO_ARCH_SAVE_REGS;
246 if (value)
247 vc = value->vtable->klass;
248 else
249 vc = NULL;
251 ac = this->obj.vtable->klass;
252 ec = ac->element_class;
254 esize = mono_array_element_size (ac);
255 ea = (gpointer*)((char*)this->vector + (pos * esize));
256 va = (gpointer*)((char*)value + sizeof (MonoObject));
258 if (!value) {
259 memset (ea, 0, esize);
260 return;
263 #define NO_WIDENING_CONVERSION G_STMT_START{\
264 mono_raise_exception (mono_get_exception_argument ( \
265 "value", "not a widening conversion")); \
266 }G_STMT_END
268 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
269 if (esize < vsize + (extra)) \
270 mono_raise_exception (mono_get_exception_argument ( \
271 "value", "not a widening conversion")); \
272 }G_STMT_END
274 #define INVALID_CAST G_STMT_START{\
275 mono_raise_exception (mono_get_exception_invalid_cast ()); \
276 }G_STMT_END
278 /* Check element (destination) type. */
279 switch (ec->byval_arg.type) {
280 case MONO_TYPE_STRING:
281 switch (vc->byval_arg.type) {
282 case MONO_TYPE_STRING:
283 break;
284 default:
285 INVALID_CAST;
287 break;
288 case MONO_TYPE_BOOLEAN:
289 switch (vc->byval_arg.type) {
290 case MONO_TYPE_BOOLEAN:
291 break;
292 case MONO_TYPE_CHAR:
293 case MONO_TYPE_U1:
294 case MONO_TYPE_U2:
295 case MONO_TYPE_U4:
296 case MONO_TYPE_U8:
297 case MONO_TYPE_I1:
298 case MONO_TYPE_I2:
299 case MONO_TYPE_I4:
300 case MONO_TYPE_I8:
301 case MONO_TYPE_R4:
302 case MONO_TYPE_R8:
303 NO_WIDENING_CONVERSION;
304 default:
305 INVALID_CAST;
307 break;
310 if (!ec->valuetype) {
311 if (!mono_object_isinst (value, ec))
312 INVALID_CAST;
313 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
314 return;
317 if (mono_object_isinst (value, ec)) {
318 if (ec->has_references)
319 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
320 else
321 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
322 return;
325 if (!vc->valuetype)
326 INVALID_CAST;
328 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
330 et = ec->byval_arg.type;
331 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
332 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
334 vt = vc->byval_arg.type;
335 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
336 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
338 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
339 switch (vt) { \
340 case MONO_TYPE_U1: \
341 case MONO_TYPE_U2: \
342 case MONO_TYPE_U4: \
343 case MONO_TYPE_U8: \
344 case MONO_TYPE_CHAR: \
345 CHECK_WIDENING_CONVERSION(0); \
346 *(etype *) ea = (etype) u64; \
347 return; \
348 /* You can't assign a signed value to an unsigned array. */ \
349 case MONO_TYPE_I1: \
350 case MONO_TYPE_I2: \
351 case MONO_TYPE_I4: \
352 case MONO_TYPE_I8: \
353 /* You can't assign a floating point number to an integer array. */ \
354 case MONO_TYPE_R4: \
355 case MONO_TYPE_R8: \
356 NO_WIDENING_CONVERSION; \
358 }G_STMT_END
360 #define ASSIGN_SIGNED(etype) G_STMT_START{\
361 switch (vt) { \
362 case MONO_TYPE_I1: \
363 case MONO_TYPE_I2: \
364 case MONO_TYPE_I4: \
365 case MONO_TYPE_I8: \
366 CHECK_WIDENING_CONVERSION(0); \
367 *(etype *) ea = (etype) i64; \
368 return; \
369 /* You can assign an unsigned value to a signed array if the array's */ \
370 /* element size is larger than the value size. */ \
371 case MONO_TYPE_U1: \
372 case MONO_TYPE_U2: \
373 case MONO_TYPE_U4: \
374 case MONO_TYPE_U8: \
375 case MONO_TYPE_CHAR: \
376 CHECK_WIDENING_CONVERSION(1); \
377 *(etype *) ea = (etype) u64; \
378 return; \
379 /* You can't assign a floating point number to an integer array. */ \
380 case MONO_TYPE_R4: \
381 case MONO_TYPE_R8: \
382 NO_WIDENING_CONVERSION; \
384 }G_STMT_END
386 #define ASSIGN_REAL(etype) G_STMT_START{\
387 switch (vt) { \
388 case MONO_TYPE_R4: \
389 case MONO_TYPE_R8: \
390 CHECK_WIDENING_CONVERSION(0); \
391 *(etype *) ea = (etype) r64; \
392 return; \
393 /* All integer values fit into a floating point array, so we don't */ \
394 /* need to CHECK_WIDENING_CONVERSION here. */ \
395 case MONO_TYPE_I1: \
396 case MONO_TYPE_I2: \
397 case MONO_TYPE_I4: \
398 case MONO_TYPE_I8: \
399 *(etype *) ea = (etype) i64; \
400 return; \
401 case MONO_TYPE_U1: \
402 case MONO_TYPE_U2: \
403 case MONO_TYPE_U4: \
404 case MONO_TYPE_U8: \
405 case MONO_TYPE_CHAR: \
406 *(etype *) ea = (etype) u64; \
407 return; \
409 }G_STMT_END
411 switch (vt) {
412 case MONO_TYPE_U1:
413 u64 = *(guint8 *) va;
414 break;
415 case MONO_TYPE_U2:
416 u64 = *(guint16 *) va;
417 break;
418 case MONO_TYPE_U4:
419 u64 = *(guint32 *) va;
420 break;
421 case MONO_TYPE_U8:
422 u64 = *(guint64 *) va;
423 break;
424 case MONO_TYPE_I1:
425 i64 = *(gint8 *) va;
426 break;
427 case MONO_TYPE_I2:
428 i64 = *(gint16 *) va;
429 break;
430 case MONO_TYPE_I4:
431 i64 = *(gint32 *) va;
432 break;
433 case MONO_TYPE_I8:
434 i64 = *(gint64 *) va;
435 break;
436 case MONO_TYPE_R4:
437 r64 = *(gfloat *) va;
438 break;
439 case MONO_TYPE_R8:
440 r64 = *(gdouble *) va;
441 break;
442 case MONO_TYPE_CHAR:
443 u64 = *(guint16 *) va;
444 break;
445 case MONO_TYPE_BOOLEAN:
446 /* Boolean is only compatible with itself. */
447 switch (et) {
448 case MONO_TYPE_CHAR:
449 case MONO_TYPE_U1:
450 case MONO_TYPE_U2:
451 case MONO_TYPE_U4:
452 case MONO_TYPE_U8:
453 case MONO_TYPE_I1:
454 case MONO_TYPE_I2:
455 case MONO_TYPE_I4:
456 case MONO_TYPE_I8:
457 case MONO_TYPE_R4:
458 case MONO_TYPE_R8:
459 NO_WIDENING_CONVERSION;
460 default:
461 INVALID_CAST;
463 break;
466 /* If we can't do a direct copy, let's try a widening conversion. */
467 switch (et) {
468 case MONO_TYPE_CHAR:
469 ASSIGN_UNSIGNED (guint16);
470 case MONO_TYPE_U1:
471 ASSIGN_UNSIGNED (guint8);
472 case MONO_TYPE_U2:
473 ASSIGN_UNSIGNED (guint16);
474 case MONO_TYPE_U4:
475 ASSIGN_UNSIGNED (guint32);
476 case MONO_TYPE_U8:
477 ASSIGN_UNSIGNED (guint64);
478 case MONO_TYPE_I1:
479 ASSIGN_SIGNED (gint8);
480 case MONO_TYPE_I2:
481 ASSIGN_SIGNED (gint16);
482 case MONO_TYPE_I4:
483 ASSIGN_SIGNED (gint32);
484 case MONO_TYPE_I8:
485 ASSIGN_SIGNED (gint64);
486 case MONO_TYPE_R4:
487 ASSIGN_REAL (gfloat);
488 case MONO_TYPE_R8:
489 ASSIGN_REAL (gdouble);
492 INVALID_CAST;
493 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
494 return;
496 #undef INVALID_CAST
497 #undef NO_WIDENING_CONVERSION
498 #undef CHECK_WIDENING_CONVERSION
499 #undef ASSIGN_UNSIGNED
500 #undef ASSIGN_SIGNED
501 #undef ASSIGN_REAL
504 static void
505 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
506 MonoArray *idxs)
508 MonoClass *ac, *ic;
509 gint32 i, pos, *ind;
511 MONO_ARCH_SAVE_REGS;
513 MONO_CHECK_ARG_NULL (idxs);
515 ic = idxs->obj.vtable->klass;
516 ac = this->obj.vtable->klass;
518 g_assert (ic->rank == 1);
519 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
520 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
522 ind = (gint32 *)idxs->vector;
524 if (this->bounds == NULL) {
525 if (*ind < 0 || *ind >= this->max_length)
526 mono_raise_exception (mono_get_exception_index_out_of_range ());
528 ves_icall_System_Array_SetValueImpl (this, value, *ind);
529 return;
532 for (i = 0; i < ac->rank; i++)
533 if ((ind [i] < this->bounds [i].lower_bound) ||
534 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
535 mono_raise_exception (mono_get_exception_index_out_of_range ());
537 pos = ind [0] - this->bounds [0].lower_bound;
538 for (i = 1; i < ac->rank; i++)
539 pos = pos * this->bounds [i].length + ind [i] -
540 this->bounds [i].lower_bound;
542 ves_icall_System_Array_SetValueImpl (this, value, pos);
545 static MonoArray *
546 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
548 MonoClass *aklass;
549 MonoArray *array;
550 mono_array_size_t *sizes, i;
551 gboolean bounded = FALSE;
553 MONO_ARCH_SAVE_REGS;
555 MONO_CHECK_ARG_NULL (type);
556 MONO_CHECK_ARG_NULL (lengths);
558 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
559 if (bounds)
560 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
562 for (i = 0; i < mono_array_length (lengths); i++)
563 if (mono_array_get (lengths, gint32, i) < 0)
564 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
566 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
567 /* vectors are not the same as one dimensional arrays with no-zero bounds */
568 bounded = TRUE;
569 else
570 bounded = FALSE;
572 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
574 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
575 for (i = 0; i < aklass->rank; ++i) {
576 sizes [i] = mono_array_get (lengths, guint32, i);
577 if (bounds)
578 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
579 else
580 sizes [i + aklass->rank] = 0;
583 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
585 return array;
588 static MonoArray *
589 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
591 MonoClass *aklass;
592 MonoArray *array;
593 mono_array_size_t *sizes, i;
594 gboolean bounded = FALSE;
596 MONO_ARCH_SAVE_REGS;
598 MONO_CHECK_ARG_NULL (type);
599 MONO_CHECK_ARG_NULL (lengths);
601 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
602 if (bounds)
603 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
605 for (i = 0; i < mono_array_length (lengths); i++)
606 if ((mono_array_get (lengths, gint64, i) < 0) ||
607 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
608 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
610 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
611 /* vectors are not the same as one dimensional arrays with no-zero bounds */
612 bounded = TRUE;
613 else
614 bounded = FALSE;
616 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
618 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
619 for (i = 0; i < aklass->rank; ++i) {
620 sizes [i] = mono_array_get (lengths, guint64, i);
621 if (bounds)
622 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
623 else
624 sizes [i + aklass->rank] = 0;
627 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
629 return array;
632 static gint32
633 ves_icall_System_Array_GetRank (MonoObject *this)
635 MONO_ARCH_SAVE_REGS;
637 return this->vtable->klass->rank;
640 static gint32
641 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
643 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
644 mono_array_size_t length;
646 MONO_ARCH_SAVE_REGS;
648 if ((dimension < 0) || (dimension >= rank))
649 mono_raise_exception (mono_get_exception_index_out_of_range ());
651 if (this->bounds == NULL)
652 length = this->max_length;
653 else
654 length = this->bounds [dimension].length;
656 #ifdef MONO_BIG_ARRAYS
657 if (length > G_MAXINT32)
658 mono_raise_exception (mono_get_exception_overflow ());
659 #endif
660 return length;
663 static gint64
664 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
666 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
668 MONO_ARCH_SAVE_REGS;
670 if ((dimension < 0) || (dimension >= rank))
671 mono_raise_exception (mono_get_exception_index_out_of_range ());
673 if (this->bounds == NULL)
674 return this->max_length;
676 return this->bounds [dimension].length;
679 static gint32
680 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
682 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
684 MONO_ARCH_SAVE_REGS;
686 if ((dimension < 0) || (dimension >= rank))
687 mono_raise_exception (mono_get_exception_index_out_of_range ());
689 if (this->bounds == NULL)
690 return 0;
692 return this->bounds [dimension].lower_bound;
695 static void
696 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
698 int sz = mono_array_element_size (mono_object_class (arr));
699 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
702 static gboolean
703 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
705 int element_size;
706 void * dest_addr;
707 void * source_addr;
708 MonoClass *src_class;
709 MonoClass *dest_class;
710 int i;
712 MONO_ARCH_SAVE_REGS;
714 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
715 return FALSE;
717 if (source->bounds || dest->bounds)
718 return FALSE;
720 if ((dest_idx + length > mono_array_length (dest)) ||
721 (source_idx + length > mono_array_length (source)))
722 return FALSE;
724 src_class = source->obj.vtable->klass->element_class;
725 dest_class = dest->obj.vtable->klass->element_class;
728 * Handle common cases.
731 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
732 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
733 int has_refs = dest_class->has_references;
734 for (i = source_idx; i < source_idx + length; ++i) {
735 MonoObject *elem = mono_array_get (source, MonoObject*, i);
736 if (elem && !mono_object_isinst (elem, dest_class))
737 return FALSE;
740 element_size = mono_array_element_size (dest->obj.vtable->klass);
741 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
742 for (i = 0; i < length; ++i) {
743 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
744 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
745 if (!elem)
746 continue;
747 if (has_refs)
748 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
749 else
750 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
752 return TRUE;
755 /* Check if we're copying a char[] <==> (u)short[] */
756 if (src_class != dest_class) {
757 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
758 return FALSE;
760 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
762 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
763 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
764 for (i = source_idx; i < source_idx + length; ++i) {
765 MonoObject *elem = mono_array_get (source, MonoObject*, i);
766 if (elem && !mono_object_isinst (elem, dest_class))
767 return FALSE;
769 else
770 return FALSE;
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
778 } else {
779 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
780 memmove (dest_addr, source_addr, element_size * length);
782 } else {
783 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
786 return TRUE;
789 static void
790 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
792 MonoClass *ac;
793 MonoArray *ao;
794 gint32 esize;
795 gpointer *ea;
797 MONO_ARCH_SAVE_REGS;
799 ao = (MonoArray *)this;
800 ac = (MonoClass *)ao->obj.vtable->klass;
802 esize = mono_array_element_size (ac);
803 ea = (gpointer*)((char*)ao->vector + (pos * esize));
805 memcpy (value, ea, esize);
808 static void
809 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
811 MonoClass *ac;
812 MonoArray *ao;
813 gint32 esize;
814 gpointer *ea;
816 MONO_ARCH_SAVE_REGS;
818 ao = (MonoArray *)this;
819 ac = (MonoClass *)ao->obj.vtable->klass;
821 esize = mono_array_element_size (ac);
822 ea = (gpointer*)((char*)ao->vector + (pos * esize));
824 memcpy (ea, value, esize);
827 static void
828 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
830 MonoClass *klass = array->obj.vtable->klass;
831 guint32 size = mono_array_element_size (klass);
832 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
833 int align;
834 const char *field_data;
836 if (MONO_TYPE_IS_REFERENCE (type) ||
837 (type->type == MONO_TYPE_VALUETYPE &&
838 (!mono_type_get_class (type) ||
839 mono_type_get_class (type)->has_references))) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array containing references");
842 mono_raise_exception (exc);
845 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
846 MonoException *exc = mono_get_exception_argument("field_handle",
847 "Field doesn't have an RVA");
848 mono_raise_exception (exc);
851 size *= array->max_length;
852 field_data = mono_field_get_data (field_handle);
854 if (size > mono_type_size (field_handle->type, &align)) {
855 MonoException *exc = mono_get_exception_argument("field_handle",
856 "Field not large enough to fill array");
857 mono_raise_exception (exc);
860 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
861 #define SWAP(n) {\
862 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
863 guint ## n *src = (guint ## n *) field_data; \
864 guint ## n *end = (guint ## n *)((char*)src + size); \
866 for (; src < end; data++, src++) { \
867 *data = read ## n (src); \
871 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
873 switch (type->type) {
874 case MONO_TYPE_CHAR:
875 case MONO_TYPE_I2:
876 case MONO_TYPE_U2:
877 SWAP (16);
878 break;
879 case MONO_TYPE_I4:
880 case MONO_TYPE_U4:
881 case MONO_TYPE_R4:
882 SWAP (32);
883 break;
884 case MONO_TYPE_I8:
885 case MONO_TYPE_U8:
886 case MONO_TYPE_R8:
887 SWAP (64);
888 break;
889 default:
890 memcpy (mono_array_addr (array, char, 0), field_data, size);
891 break;
893 #else
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
895 #ifdef ARM_FPU_FPA
896 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
897 gint i;
898 double tmp;
899 double *data = (double*)mono_array_addr (array, double, 0);
901 for (i = 0; i < size; i++, data++) {
902 readr8 (data, &tmp);
903 *data = tmp;
906 #endif
907 #endif
910 static gint
911 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
913 MONO_ARCH_SAVE_REGS;
915 return offsetof (MonoString, chars);
918 static MonoObject *
919 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
921 MONO_ARCH_SAVE_REGS;
923 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
924 return obj;
925 else
926 return mono_object_clone (obj);
929 static void
930 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
932 MonoClass *klass;
934 MONO_ARCH_SAVE_REGS;
936 MONO_CHECK_ARG_NULL (handle);
938 klass = mono_class_from_mono_type (handle);
939 MONO_CHECK_ARG (handle, klass);
941 /* This will call the type constructor */
942 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
945 static void
946 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
948 MONO_ARCH_SAVE_REGS;
950 mono_image_check_for_module_cctor (image);
951 if (image->has_module_cctor) {
952 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
953 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), module_klass));
957 static MonoObject *
958 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
960 MONO_ARCH_SAVE_REGS;
962 return mono_object_clone (this);
965 static gint32
966 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
968 MonoClass *klass;
969 MonoObject **values = NULL;
970 MonoObject *o;
971 int count = 0;
972 gint32 result = 0;
973 MonoClassField* field;
974 gpointer iter;
976 MONO_ARCH_SAVE_REGS;
978 klass = mono_object_class (this);
980 if (mono_class_num_fields (klass) == 0)
981 return mono_object_hash (this);
984 * Compute the starting value of the hashcode for fields of primitive
985 * types, and return the remaining fields in an array to the managed side.
986 * This way, we can avoid costly reflection operations in managed code.
988 iter = NULL;
989 while ((field = mono_class_get_fields (klass, &iter))) {
990 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
991 continue;
992 if (mono_field_is_deleted (field))
993 continue;
994 /* FIXME: Add more types */
995 switch (field->type->type) {
996 case MONO_TYPE_I4:
997 result ^= *(gint32*)((guint8*)this + field->offset);
998 break;
999 case MONO_TYPE_STRING: {
1000 MonoString *s;
1001 s = *(MonoString**)((guint8*)this + field->offset);
1002 if (s != NULL)
1003 result ^= mono_string_hash (s);
1004 break;
1006 default:
1007 if (!values)
1008 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1009 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1010 values [count++] = o;
1014 if (values) {
1015 int i;
1016 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
1017 for (i = 0; i < count; ++i)
1018 mono_array_setref (*fields, i, values [i]);
1019 } else {
1020 *fields = NULL;
1022 return result;
1025 static MonoBoolean
1026 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1028 MonoClass *klass;
1029 MonoObject **values = NULL;
1030 MonoObject *o;
1031 MonoClassField* field;
1032 gpointer iter;
1033 int count = 0;
1035 MONO_ARCH_SAVE_REGS;
1037 MONO_CHECK_ARG_NULL (that);
1039 if (this->vtable != that->vtable)
1040 return FALSE;
1042 klass = mono_object_class (this);
1044 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1045 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1048 * Do the comparison for fields of primitive type and return a result if
1049 * possible. Otherwise, return the remaining fields in an array to the
1050 * managed side. This way, we can avoid costly reflection operations in
1051 * managed code.
1053 *fields = NULL;
1054 iter = NULL;
1055 while ((field = mono_class_get_fields (klass, &iter))) {
1056 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1057 continue;
1058 if (mono_field_is_deleted (field))
1059 continue;
1060 /* FIXME: Add more types */
1061 switch (field->type->type) {
1062 case MONO_TYPE_U1:
1063 case MONO_TYPE_I1:
1064 case MONO_TYPE_BOOLEAN:
1065 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1066 return FALSE;
1067 break;
1068 case MONO_TYPE_U2:
1069 case MONO_TYPE_I2:
1070 case MONO_TYPE_CHAR:
1071 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1072 return FALSE;
1073 break;
1074 case MONO_TYPE_U4:
1075 case MONO_TYPE_I4:
1076 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1077 return FALSE;
1078 break;
1079 case MONO_TYPE_U8:
1080 case MONO_TYPE_I8:
1081 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1082 return FALSE;
1083 break;
1084 case MONO_TYPE_R4:
1085 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1086 return FALSE;
1087 break;
1088 case MONO_TYPE_R8:
1089 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1090 return FALSE;
1091 break;
1094 case MONO_TYPE_STRING: {
1095 MonoString *s1, *s2;
1096 guint32 s1len, s2len;
1097 s1 = *(MonoString**)((guint8*)this + field->offset);
1098 s2 = *(MonoString**)((guint8*)that + field->offset);
1099 if (s1 == s2)
1100 break;
1101 if ((s1 == NULL) || (s2 == NULL))
1102 return FALSE;
1103 s1len = mono_string_length (s1);
1104 s2len = mono_string_length (s2);
1105 if (s1len != s2len)
1106 return FALSE;
1108 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1109 return FALSE;
1110 break;
1112 default:
1113 if (!values)
1114 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1115 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1116 values [count++] = o;
1117 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1118 values [count++] = o;
1121 if (klass->enumtype)
1122 /* enums only have one non-static field */
1123 break;
1126 if (values) {
1127 int i;
1128 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
1129 for (i = 0; i < count; ++i)
1130 mono_array_setref (*fields, i, values [i]);
1131 return FALSE;
1132 } else {
1133 return TRUE;
1137 static MonoReflectionType *
1138 ves_icall_System_Object_GetType (MonoObject *obj)
1140 MONO_ARCH_SAVE_REGS;
1142 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1143 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1144 else
1145 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1148 static void
1149 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1151 MONO_ARCH_SAVE_REGS;
1153 mtype->type = &obj->vtable->klass->byval_arg;
1154 g_assert (mtype->type->type);
1157 static gint32
1158 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1160 MONO_ARCH_SAVE_REGS;
1162 MONO_CHECK_ARG_NULL (obj);
1164 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1167 static gint32
1168 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1169 MonoReflectionMethod *method,
1170 MonoArray *opt_param_types)
1172 MONO_ARCH_SAVE_REGS;
1174 MONO_CHECK_ARG_NULL (method);
1176 return mono_image_create_method_token (
1177 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1180 static void
1181 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1183 MONO_ARCH_SAVE_REGS;
1185 mono_image_create_pefile (mb, file);
1188 static void
1189 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1191 MONO_ARCH_SAVE_REGS;
1193 mono_image_build_metadata (mb);
1196 static void
1197 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1199 MONO_ARCH_SAVE_REGS;
1201 mono_image_register_token (mb->dynamic_image, token, obj);
1204 static gboolean
1205 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1207 MonoMethod **dest = data;
1209 /* skip unmanaged frames */
1210 if (!managed)
1211 return FALSE;
1213 if (m == *dest) {
1214 *dest = NULL;
1215 return FALSE;
1217 if (!(*dest)) {
1218 *dest = m;
1219 return TRUE;
1221 return FALSE;
1224 static gboolean
1225 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1227 MonoMethod **dest = data;
1229 /* skip unmanaged frames */
1230 if (!managed)
1231 return FALSE;
1233 if (!(*dest)) {
1234 if (!strcmp (m->klass->name_space, "System.Reflection"))
1235 return FALSE;
1236 *dest = m;
1237 return TRUE;
1239 return FALSE;
1242 static gboolean
1243 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1245 MonoMethod **dest = data;
1247 /* skip unmanaged frames */
1248 if (!managed)
1249 return FALSE;
1251 if (m->wrapper_type != MONO_WRAPPER_NONE)
1252 return FALSE;
1254 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1255 return FALSE;
1257 if (m == *dest) {
1258 *dest = NULL;
1259 return FALSE;
1261 if (!(*dest)) {
1262 *dest = m;
1263 return TRUE;
1265 return FALSE;
1268 static MonoReflectionType *
1269 type_from_name (const char *str, MonoBoolean ignoreCase)
1271 MonoType *type = NULL;
1272 MonoAssembly *assembly = NULL;
1273 MonoTypeNameParse info;
1274 char *temp_str = g_strdup (str);
1275 gboolean type_resolve = FALSE;
1277 MONO_ARCH_SAVE_REGS;
1279 /* mono_reflection_parse_type() mangles the string */
1280 if (!mono_reflection_parse_type (temp_str, &info)) {
1281 mono_reflection_free_type_info (&info);
1282 g_free (temp_str);
1283 return NULL;
1286 if (info.assembly.name) {
1287 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1288 } else {
1289 MonoMethod *m = mono_method_get_last_managed ();
1290 MonoMethod *dest = m;
1292 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1293 if (!dest)
1294 dest = m;
1297 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1298 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1299 * to crash. This only seems to happen in some strange remoting
1300 * scenarios and I was unable to figure out what's happening there.
1301 * Dec 10, 2005 - Martin.
1304 if (dest)
1305 assembly = dest->klass->image->assembly;
1306 else {
1307 g_warning (G_STRLOC);
1311 if (assembly)
1312 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1314 if (!info.assembly.name && !type) /* try mscorlib */
1315 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1317 mono_reflection_free_type_info (&info);
1318 g_free (temp_str);
1320 if (!type)
1321 return NULL;
1323 return mono_type_get_object (mono_domain_get (), type);
1326 #ifdef UNUSED
1327 MonoReflectionType *
1328 mono_type_get (const char *str)
1330 char *copy = g_strdup (str);
1331 MonoReflectionType *type = type_from_name (copy, FALSE);
1333 g_free (copy);
1334 return type;
1336 #endif
1338 static MonoReflectionType*
1339 ves_icall_type_from_name (MonoString *name,
1340 MonoBoolean throwOnError,
1341 MonoBoolean ignoreCase)
1343 char *str = mono_string_to_utf8 (name);
1344 MonoReflectionType *type;
1346 type = type_from_name (str, ignoreCase);
1347 g_free (str);
1348 if (type == NULL){
1349 MonoException *e = NULL;
1351 if (throwOnError)
1352 e = mono_get_exception_type_load (name, NULL);
1354 mono_loader_clear_error ();
1355 if (e != NULL)
1356 mono_raise_exception (e);
1359 return type;
1363 static MonoReflectionType*
1364 ves_icall_type_from_handle (MonoType *handle)
1366 MonoDomain *domain = mono_domain_get ();
1367 MonoClass *klass = mono_class_from_mono_type (handle);
1369 MONO_ARCH_SAVE_REGS;
1371 mono_class_init (klass);
1372 return mono_type_get_object (domain, handle);
1375 static MonoBoolean
1376 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1378 MONO_ARCH_SAVE_REGS;
1380 if (c && type->type && c->type)
1381 return mono_metadata_type_equal (type->type, c->type);
1382 else
1383 return (type == c) ? TRUE : FALSE;
1386 /* System.TypeCode */
1387 typedef enum {
1388 TYPECODE_EMPTY,
1389 TYPECODE_OBJECT,
1390 TYPECODE_DBNULL,
1391 TYPECODE_BOOLEAN,
1392 TYPECODE_CHAR,
1393 TYPECODE_SBYTE,
1394 TYPECODE_BYTE,
1395 TYPECODE_INT16,
1396 TYPECODE_UINT16,
1397 TYPECODE_INT32,
1398 TYPECODE_UINT32,
1399 TYPECODE_INT64,
1400 TYPECODE_UINT64,
1401 TYPECODE_SINGLE,
1402 TYPECODE_DOUBLE,
1403 TYPECODE_DECIMAL,
1404 TYPECODE_DATETIME,
1405 TYPECODE_STRING = 18
1406 } TypeCode;
1408 static guint32
1409 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1411 int t = type->type->type;
1413 MONO_ARCH_SAVE_REGS;
1415 if (type->type->byref)
1416 return TYPECODE_OBJECT;
1418 handle_enum:
1419 switch (t) {
1420 case MONO_TYPE_VOID:
1421 return TYPECODE_OBJECT;
1422 case MONO_TYPE_BOOLEAN:
1423 return TYPECODE_BOOLEAN;
1424 case MONO_TYPE_U1:
1425 return TYPECODE_BYTE;
1426 case MONO_TYPE_I1:
1427 return TYPECODE_SBYTE;
1428 case MONO_TYPE_U2:
1429 return TYPECODE_UINT16;
1430 case MONO_TYPE_I2:
1431 return TYPECODE_INT16;
1432 case MONO_TYPE_CHAR:
1433 return TYPECODE_CHAR;
1434 case MONO_TYPE_PTR:
1435 case MONO_TYPE_U:
1436 case MONO_TYPE_I:
1437 return TYPECODE_OBJECT;
1438 case MONO_TYPE_U4:
1439 return TYPECODE_UINT32;
1440 case MONO_TYPE_I4:
1441 return TYPECODE_INT32;
1442 case MONO_TYPE_U8:
1443 return TYPECODE_UINT64;
1444 case MONO_TYPE_I8:
1445 return TYPECODE_INT64;
1446 case MONO_TYPE_R4:
1447 return TYPECODE_SINGLE;
1448 case MONO_TYPE_R8:
1449 return TYPECODE_DOUBLE;
1450 case MONO_TYPE_VALUETYPE:
1451 if (type->type->data.klass->enumtype) {
1452 t = mono_class_enum_basetype (type->type->data.klass)->type;
1453 goto handle_enum;
1454 } else {
1455 MonoClass *k = type->type->data.klass;
1456 if (strcmp (k->name_space, "System") == 0) {
1457 if (strcmp (k->name, "Decimal") == 0)
1458 return TYPECODE_DECIMAL;
1459 else if (strcmp (k->name, "DateTime") == 0)
1460 return TYPECODE_DATETIME;
1463 return TYPECODE_OBJECT;
1464 case MONO_TYPE_STRING:
1465 return TYPECODE_STRING;
1466 case MONO_TYPE_SZARRAY:
1467 case MONO_TYPE_ARRAY:
1468 case MONO_TYPE_OBJECT:
1469 case MONO_TYPE_VAR:
1470 case MONO_TYPE_MVAR:
1471 case MONO_TYPE_TYPEDBYREF:
1472 return TYPECODE_OBJECT;
1473 case MONO_TYPE_CLASS:
1475 MonoClass *k = type->type->data.klass;
1476 if (strcmp (k->name_space, "System") == 0) {
1477 if (strcmp (k->name, "DBNull") == 0)
1478 return TYPECODE_DBNULL;
1481 return TYPECODE_OBJECT;
1482 case MONO_TYPE_GENERICINST:
1483 return TYPECODE_OBJECT;
1484 default:
1485 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1487 return 0;
1490 static guint32
1491 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1493 MonoDomain *domain;
1494 MonoClass *klass;
1495 MonoClass *klassc;
1497 MONO_ARCH_SAVE_REGS;
1499 g_assert (type != NULL);
1501 domain = ((MonoObject *)type)->vtable->domain;
1503 if (!c) /* FIXME: dont know what do do here */
1504 return 0;
1506 klass = mono_class_from_mono_type (type->type);
1507 klassc = mono_class_from_mono_type (c->type);
1509 if (type->type->byref)
1510 return klassc == mono_defaults.object_class;
1512 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1515 static guint32
1516 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1518 MonoDomain *domain;
1519 MonoClass *klass;
1520 MonoClass *klassc;
1522 MONO_ARCH_SAVE_REGS;
1524 g_assert (type != NULL);
1526 domain = ((MonoObject *)type)->vtable->domain;
1528 klass = mono_class_from_mono_type (type->type);
1529 klassc = mono_class_from_mono_type (c->type);
1531 if (type->type->byref && !c->type->byref)
1532 return FALSE;
1534 return mono_class_is_assignable_from (klass, klassc);
1537 static guint32
1538 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1540 MonoClass *klass = mono_class_from_mono_type (type->type);
1541 return mono_object_isinst (obj, klass) != NULL;
1544 static guint32
1545 ves_icall_get_attributes (MonoReflectionType *type)
1547 MonoClass *klass = mono_class_from_mono_type (type->type);
1549 MONO_ARCH_SAVE_REGS;
1551 return klass->flags;
1554 static MonoReflectionMarshal*
1555 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1557 MonoClass *klass = field->field->parent;
1558 MonoMarshalType *info;
1559 int i;
1561 if (klass->generic_container ||
1562 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1563 return NULL;
1565 info = mono_marshal_load_type_info (klass);
1567 for (i = 0; i < info->num_fields; ++i) {
1568 if (info->fields [i].field == field->field) {
1569 if (!info->fields [i].mspec)
1570 return NULL;
1571 else
1572 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1576 return NULL;
1579 static MonoReflectionField*
1580 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoClass *klass)
1582 g_assert (handle);
1584 if (!klass)
1585 klass = handle->parent;
1587 /* FIXME: check that handle is a field of klass or of a parent: return null
1588 * and throw the exception in managed code.
1590 return mono_field_get_object (mono_domain_get (), klass, handle);
1593 static MonoReflectionField*
1594 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1596 MONO_ARCH_SAVE_REGS;
1598 g_assert (handle);
1600 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1603 static MonoArray*
1604 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1606 MonoType *type = field->field->type;
1608 return type_array_from_modifiers (field->field->parent->image, type, optional);
1611 static void
1612 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1614 MonoDomain *domain = mono_domain_get ();
1615 MonoMethodSignature* sig;
1616 MONO_ARCH_SAVE_REGS;
1618 sig = mono_method_signature (method);
1619 if (!sig) {
1620 g_assert (mono_loader_get_last_error ());
1621 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1624 info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
1625 info->ret = mono_type_get_object (domain, sig->ret);
1626 info->attrs = method->flags;
1627 info->implattrs = method->iflags;
1628 if (sig->call_convention == MONO_CALL_DEFAULT)
1629 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1630 else {
1631 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1632 info->callconv = 2;
1633 else
1634 info->callconv = 1;
1636 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1639 static MonoArray*
1640 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1642 MonoDomain *domain = mono_domain_get ();
1644 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1647 static MonoReflectionMarshal*
1648 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1650 MonoDomain *domain = mono_domain_get ();
1651 MonoReflectionMarshal* res = NULL;
1652 MonoMarshalSpec **mspecs;
1653 int i;
1655 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1656 mono_method_get_marshal_info (method, mspecs);
1658 if (mspecs [0])
1659 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1661 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1662 if (mspecs [i])
1663 mono_metadata_free_marshal_spec (mspecs [i]);
1664 g_free (mspecs);
1666 return res;
1669 static gint32
1670 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1672 return field->field->offset - sizeof (MonoObject);
1675 static MonoReflectionType*
1676 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1678 MonoClass *parent;
1679 MONO_ARCH_SAVE_REGS;
1681 parent = declaring? field->field->parent: field->klass;
1683 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1686 static MonoObject *
1687 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1689 MonoObject *o;
1690 MonoClassField *cf = field->field;
1691 MonoClass *klass;
1692 MonoVTable *vtable;
1693 MonoType *t;
1694 MonoDomain *domain = mono_object_domain (field);
1695 gchar *v;
1696 gboolean is_static = FALSE;
1697 gboolean is_ref = FALSE;
1699 MONO_ARCH_SAVE_REGS;
1701 if (field->klass->image->assembly->ref_only)
1702 mono_raise_exception (mono_get_exception_invalid_operation (
1703 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1705 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1706 mono_security_core_clr_ensure_reflection_access_field (cf);
1708 mono_class_init (field->klass);
1710 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1711 is_static = TRUE;
1713 if (obj && !is_static) {
1714 /* Check that the field belongs to the object */
1715 gboolean found = FALSE;
1716 MonoClass *k;
1718 for (k = obj->vtable->klass; k; k = k->parent) {
1719 if (k == cf->parent) {
1720 found = TRUE;
1721 break;
1725 if (!found) {
1726 char *msg = g_strdup_printf ("Field '%s' defined on type '%s' is not a field on the target object which is of type '%s'.", mono_field_get_name (cf), cf->parent->name, obj->vtable->klass->name);
1727 MonoException *ex = mono_get_exception_argument (NULL, msg);
1728 g_free (msg);
1729 mono_raise_exception (ex);
1733 t = mono_type_get_underlying_type (cf->type);
1734 switch (t->type) {
1735 case MONO_TYPE_STRING:
1736 case MONO_TYPE_OBJECT:
1737 case MONO_TYPE_CLASS:
1738 case MONO_TYPE_ARRAY:
1739 case MONO_TYPE_SZARRAY:
1740 is_ref = TRUE;
1741 break;
1742 case MONO_TYPE_U1:
1743 case MONO_TYPE_I1:
1744 case MONO_TYPE_BOOLEAN:
1745 case MONO_TYPE_U2:
1746 case MONO_TYPE_I2:
1747 case MONO_TYPE_CHAR:
1748 case MONO_TYPE_U:
1749 case MONO_TYPE_I:
1750 case MONO_TYPE_U4:
1751 case MONO_TYPE_I4:
1752 case MONO_TYPE_R4:
1753 case MONO_TYPE_U8:
1754 case MONO_TYPE_I8:
1755 case MONO_TYPE_R8:
1756 case MONO_TYPE_VALUETYPE:
1757 is_ref = t->byref;
1758 break;
1759 case MONO_TYPE_GENERICINST:
1760 if (mono_type_generic_inst_is_valuetype (t)) {
1761 is_ref = t->byref;
1762 } else {
1763 is_ref = TRUE;
1765 break;
1766 default:
1767 g_error ("type 0x%x not handled in "
1768 "ves_icall_Monofield_GetValue", t->type);
1769 return NULL;
1772 vtable = NULL;
1773 if (is_static) {
1774 vtable = mono_class_vtable (domain, cf->parent);
1775 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1776 mono_runtime_class_init (vtable);
1779 if (is_ref) {
1780 if (is_static) {
1781 mono_field_static_get_value (vtable, cf, &o);
1782 } else {
1783 mono_field_get_value (obj, cf, &o);
1785 return o;
1788 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1789 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1790 guint8 *buf;
1792 /* Convert the Nullable structure into a boxed vtype */
1793 if (is_static)
1794 buf = (guint8*)vtable->data + cf->offset;
1795 else
1796 buf = (guint8*)obj + cf->offset;
1798 return mono_nullable_box (buf, nklass);
1801 /* boxed value type */
1802 klass = mono_class_from_mono_type (cf->type);
1803 o = mono_object_new (domain, klass);
1804 v = ((gchar *) o) + sizeof (MonoObject);
1805 if (is_static) {
1806 mono_field_static_get_value (vtable, cf, v);
1807 } else {
1808 mono_field_get_value (obj, cf, v);
1811 return o;
1814 static void
1815 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1817 MonoClassField *cf = field->field;
1818 gchar *v;
1820 MONO_ARCH_SAVE_REGS;
1822 if (field->klass->image->assembly->ref_only)
1823 mono_raise_exception (mono_get_exception_invalid_operation (
1824 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1826 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1827 mono_security_core_clr_ensure_reflection_access_field (cf);
1829 v = (gchar *) value;
1830 if (!cf->type->byref) {
1831 switch (cf->type->type) {
1832 case MONO_TYPE_U1:
1833 case MONO_TYPE_I1:
1834 case MONO_TYPE_BOOLEAN:
1835 case MONO_TYPE_U2:
1836 case MONO_TYPE_I2:
1837 case MONO_TYPE_CHAR:
1838 case MONO_TYPE_U:
1839 case MONO_TYPE_I:
1840 case MONO_TYPE_U4:
1841 case MONO_TYPE_I4:
1842 case MONO_TYPE_R4:
1843 case MONO_TYPE_U8:
1844 case MONO_TYPE_I8:
1845 case MONO_TYPE_R8:
1846 case MONO_TYPE_VALUETYPE:
1847 if (v != NULL)
1848 v += sizeof (MonoObject);
1849 break;
1850 case MONO_TYPE_STRING:
1851 case MONO_TYPE_OBJECT:
1852 case MONO_TYPE_CLASS:
1853 case MONO_TYPE_ARRAY:
1854 case MONO_TYPE_SZARRAY:
1855 /* Do nothing */
1856 break;
1857 case MONO_TYPE_GENERICINST: {
1858 MonoGenericClass *gclass = cf->type->data.generic_class;
1859 g_assert (!gclass->context.class_inst->is_open);
1861 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1862 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1863 MonoObject *nullable;
1866 * Convert the boxed vtype into a Nullable structure.
1867 * This is complicated by the fact that Nullables have
1868 * a variable structure.
1870 nullable = mono_object_new (mono_domain_get (), nklass);
1872 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1874 v = mono_object_unbox (nullable);
1876 else
1877 if (gclass->container_class->valuetype && (v != NULL))
1878 v += sizeof (MonoObject);
1879 break;
1881 default:
1882 g_error ("type 0x%x not handled in "
1883 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1884 return;
1888 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1889 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1890 if (!vtable->initialized)
1891 mono_runtime_class_init (vtable);
1892 mono_field_static_set_value (vtable, cf, v);
1893 } else {
1894 mono_field_set_value (obj, cf, v);
1898 static MonoObject *
1899 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1901 MonoObject *o = NULL;
1902 MonoClassField *field = this->field;
1903 MonoClass *klass;
1904 MonoDomain *domain = mono_object_domain (this);
1905 gchar *v;
1906 MonoTypeEnum def_type;
1907 const char *def_value;
1909 MONO_ARCH_SAVE_REGS;
1911 mono_class_init (field->parent);
1913 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1914 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1916 if (field->parent->image->dynamic) {
1917 /* FIXME: */
1918 g_assert_not_reached ();
1921 def_value = mono_class_get_field_default_value (field, &def_type);
1923 switch (def_type) {
1924 case MONO_TYPE_U1:
1925 case MONO_TYPE_I1:
1926 case MONO_TYPE_BOOLEAN:
1927 case MONO_TYPE_U2:
1928 case MONO_TYPE_I2:
1929 case MONO_TYPE_CHAR:
1930 case MONO_TYPE_U:
1931 case MONO_TYPE_I:
1932 case MONO_TYPE_U4:
1933 case MONO_TYPE_I4:
1934 case MONO_TYPE_R4:
1935 case MONO_TYPE_U8:
1936 case MONO_TYPE_I8:
1937 case MONO_TYPE_R8: {
1938 MonoType *t;
1940 /* boxed value type */
1941 t = g_new0 (MonoType, 1);
1942 t->type = def_type;
1943 klass = mono_class_from_mono_type (t);
1944 g_free (t);
1945 o = mono_object_new (domain, klass);
1946 v = ((gchar *) o) + sizeof (MonoObject);
1947 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1948 break;
1950 case MONO_TYPE_STRING:
1951 case MONO_TYPE_CLASS:
1952 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1953 break;
1954 default:
1955 g_assert_not_reached ();
1958 return o;
1961 static MonoReflectionType*
1962 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1964 MonoMethod *method = rmethod->method.method;
1966 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1969 /* From MonoProperty.cs */
1970 typedef enum {
1971 PInfo_Attributes = 1,
1972 PInfo_GetMethod = 1 << 1,
1973 PInfo_SetMethod = 1 << 2,
1974 PInfo_ReflectedType = 1 << 3,
1975 PInfo_DeclaringType = 1 << 4,
1976 PInfo_Name = 1 << 5
1977 } PInfo;
1979 static void
1980 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1982 MonoDomain *domain = mono_object_domain (property);
1984 MONO_ARCH_SAVE_REGS;
1986 if ((req_info & PInfo_ReflectedType) != 0)
1987 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1988 else if ((req_info & PInfo_DeclaringType) != 0)
1989 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1991 if ((req_info & PInfo_Name) != 0)
1992 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1994 if ((req_info & PInfo_Attributes) != 0)
1995 info->attrs = property->property->attrs;
1997 if ((req_info & PInfo_GetMethod) != 0)
1998 MONO_STRUCT_SETREF (info, get, property->property->get ?
1999 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2001 if ((req_info & PInfo_SetMethod) != 0)
2002 MONO_STRUCT_SETREF (info, set, property->property->set ?
2003 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2005 * There may be other methods defined for properties, though, it seems they are not exposed
2006 * in the reflection API
2010 static void
2011 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2013 MonoDomain *domain = mono_object_domain (event);
2015 MONO_ARCH_SAVE_REGS;
2017 info->reflected_type = mono_type_get_object (domain, &event->klass->byval_arg);
2018 info->declaring_type = mono_type_get_object (domain, &event->event->parent->byval_arg);
2020 info->name = mono_string_new (domain, event->event->name);
2021 info->attrs = event->event->attrs;
2022 info->add_method = event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL;
2023 info->remove_method = event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL;
2024 info->raise_method = event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL;
2026 if (event->event->other) {
2027 int i, n = 0;
2028 while (event->event->other [n])
2029 n++;
2030 info->other_methods = mono_array_new (domain, mono_defaults.method_info_class, n);
2032 for (i = 0; i < n; i++)
2033 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2037 static MonoArray*
2038 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2040 MonoDomain *domain = mono_object_domain (type);
2041 MonoArray *intf;
2042 GPtrArray *ifaces = NULL;
2043 int i;
2044 MonoClass *class = mono_class_from_mono_type (type->type);
2045 MonoClass *parent;
2046 MonoBitSet *slots;
2047 MonoGenericContext *context = NULL;
2049 MONO_ARCH_SAVE_REGS;
2051 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2052 context = mono_class_get_context (class);
2053 class = class->generic_class->container_class;
2056 mono_class_setup_vtable (class);
2058 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2060 for (parent = class; parent; parent = parent->parent) {
2061 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
2062 if (tmp_ifaces) {
2063 for (i = 0; i < tmp_ifaces->len; ++i) {
2064 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2066 if (mono_bitset_test (slots, ic->interface_id))
2067 continue;
2069 mono_bitset_set (slots, ic->interface_id);
2070 if (ifaces == NULL)
2071 ifaces = g_ptr_array_new ();
2072 g_ptr_array_add (ifaces, ic);
2074 g_ptr_array_free (tmp_ifaces, TRUE);
2077 mono_bitset_free (slots);
2079 if (!ifaces)
2080 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2082 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2083 for (i = 0; i < ifaces->len; ++i) {
2084 MonoClass *ic = g_ptr_array_index (ifaces, i);
2085 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2086 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2087 inflated = ret = mono_class_inflate_generic_type (ret, context);
2089 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2090 if (inflated)
2091 mono_metadata_free_type (inflated);
2093 g_ptr_array_free (ifaces, TRUE);
2095 return intf;
2098 static void
2099 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2101 MonoClass *class = mono_class_from_mono_type (type->type);
2102 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2103 MonoReflectionMethod *member;
2104 MonoMethod* method;
2105 gpointer iter;
2106 int i = 0, len, ioffset;
2107 MonoDomain *domain;
2109 MONO_ARCH_SAVE_REGS;
2111 mono_class_setup_vtable (class);
2113 /* type doesn't implement iface: the exception is thrown in managed code */
2114 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2115 return;
2117 len = mono_class_num_methods (iclass);
2118 ioffset = mono_class_interface_offset (class, iclass);
2119 domain = mono_object_domain (type);
2120 *targets = mono_array_new (domain, mono_defaults.method_info_class, len);
2121 *methods = mono_array_new (domain, mono_defaults.method_info_class, len);
2122 iter = NULL;
2123 iter = NULL;
2124 while ((method = mono_class_get_methods (iclass, &iter))) {
2125 member = mono_method_get_object (domain, method, iclass);
2126 mono_array_setref (*methods, i, member);
2127 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2128 mono_array_setref (*targets, i, member);
2130 i ++;
2134 static void
2135 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2137 MonoClass *klass = mono_class_from_mono_type (type->type);
2139 if (klass->image->dynamic) {
2140 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2141 *packing = tb->packing_size;
2142 *size = tb->class_size;
2143 } else {
2144 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2148 static MonoReflectionType*
2149 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2151 MonoClass *class;
2153 MONO_ARCH_SAVE_REGS;
2155 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2156 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2158 class = mono_class_from_mono_type (type->type);
2160 // GetElementType should only return a type for:
2161 // Array Pointer PassedByRef
2162 if (type->type->byref)
2163 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2164 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2165 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2166 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2167 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2168 else
2169 return NULL;
2172 static MonoReflectionType*
2173 ves_icall_get_type_parent (MonoReflectionType *type)
2175 MonoClass *class = mono_class_from_mono_type (type->type);
2177 MONO_ARCH_SAVE_REGS;
2179 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2182 static MonoBoolean
2183 ves_icall_type_ispointer (MonoReflectionType *type)
2185 MONO_ARCH_SAVE_REGS;
2187 return type->type->type == MONO_TYPE_PTR;
2190 static MonoBoolean
2191 ves_icall_type_isprimitive (MonoReflectionType *type)
2193 MONO_ARCH_SAVE_REGS;
2195 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)));
2198 static MonoBoolean
2199 ves_icall_type_isbyref (MonoReflectionType *type)
2201 MONO_ARCH_SAVE_REGS;
2203 return type->type->byref;
2206 static MonoBoolean
2207 ves_icall_type_iscomobject (MonoReflectionType *type)
2209 MonoClass *klass = mono_class_from_mono_type (type->type);
2210 MONO_ARCH_SAVE_REGS;
2212 return (klass && klass->is_com_object);
2215 static MonoReflectionModule*
2216 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2218 MonoClass *class = mono_class_from_mono_type (type->type);
2220 MONO_ARCH_SAVE_REGS;
2222 return mono_module_get_object (mono_object_domain (type), class->image);
2225 static MonoReflectionAssembly*
2226 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2228 MonoDomain *domain = mono_domain_get ();
2229 MonoClass *class = mono_class_from_mono_type (type->type);
2231 MONO_ARCH_SAVE_REGS;
2233 return mono_assembly_get_object (domain, class->image->assembly);
2236 static MonoReflectionType*
2237 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2239 MonoDomain *domain = mono_domain_get ();
2240 MonoClass *class;
2242 MONO_ARCH_SAVE_REGS;
2244 if (type->type->byref)
2245 return NULL;
2246 if (type->type->type == MONO_TYPE_VAR)
2247 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2248 else if (type->type->type == MONO_TYPE_MVAR)
2249 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2250 else
2251 class = mono_class_from_mono_type (type->type)->nested_in;
2253 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2256 static MonoReflectionType*
2257 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2259 MonoDomain *domain = mono_domain_get ();
2260 MonoClass *class = mono_class_from_mono_type (type->type);
2262 MONO_ARCH_SAVE_REGS;
2264 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2265 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2266 else if (class->element_class)
2267 return mono_type_get_object (domain, &class->element_class->byval_arg);
2268 else
2269 return NULL;
2272 static MonoString*
2273 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2275 MonoDomain *domain = mono_domain_get ();
2276 MonoClass *class = mono_class_from_mono_type (type->type);
2278 MONO_ARCH_SAVE_REGS;
2280 if (type->type->byref) {
2281 char *n = g_strdup_printf ("%s&", class->name);
2282 MonoString *res = mono_string_new (domain, n);
2284 g_free (n);
2286 return res;
2287 } else {
2288 return mono_string_new (domain, class->name);
2292 static MonoString*
2293 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2295 MonoDomain *domain = mono_domain_get ();
2296 MonoClass *class = mono_class_from_mono_type (type->type);
2298 MONO_ARCH_SAVE_REGS;
2300 while (class->nested_in)
2301 class = class->nested_in;
2303 if (class->name_space [0] == '\0')
2304 return NULL;
2305 else
2306 return mono_string_new (domain, class->name_space);
2309 static gint32
2310 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2312 MonoClass *class = mono_class_from_mono_type (type->type);
2314 MONO_ARCH_SAVE_REGS;
2316 return class->rank;
2319 static MonoArray*
2320 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2322 MonoArray *res;
2323 MonoClass *klass, *pklass;
2324 MonoDomain *domain = mono_object_domain (type);
2325 MonoVTable *array_vtable = mono_class_vtable (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1));
2326 int i;
2327 MONO_ARCH_SAVE_REGS;
2329 klass = mono_class_from_mono_type (type->type);
2331 if (klass->generic_container) {
2332 MonoGenericContainer *container = klass->generic_container;
2333 res = mono_array_new_specific (array_vtable, container->type_argc);
2334 for (i = 0; i < container->type_argc; ++i) {
2335 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2336 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2338 } else if (klass->generic_class) {
2339 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2340 res = mono_array_new_specific (array_vtable, inst->type_argc);
2341 for (i = 0; i < inst->type_argc; ++i)
2342 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2343 } else {
2344 res = mono_array_new_specific (array_vtable, 0);
2346 return res;
2349 static gboolean
2350 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2352 MonoClass *klass;
2353 MONO_ARCH_SAVE_REGS;
2355 if (!IS_MONOTYPE (type))
2356 return FALSE;
2358 if (type->type->byref)
2359 return FALSE;
2361 klass = mono_class_from_mono_type (type->type);
2363 return klass->generic_container != NULL;
2366 static MonoReflectionType*
2367 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2369 MonoClass *klass;
2370 MONO_ARCH_SAVE_REGS;
2372 if (type->type->byref)
2373 return NULL;
2375 klass = mono_class_from_mono_type (type->type);
2376 if (klass->generic_container) {
2377 return type; /* check this one */
2379 if (klass->generic_class) {
2380 MonoClass *generic_class = klass->generic_class->container_class;
2382 if (generic_class->wastypebuilder && generic_class->reflection_info)
2383 return generic_class->reflection_info;
2384 else
2385 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2387 return NULL;
2390 static MonoReflectionType*
2391 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2393 MonoType *geninst, **types;
2394 int i, count;
2396 MONO_ARCH_SAVE_REGS;
2398 count = mono_array_length (type_array);
2399 types = g_new0 (MonoType *, count);
2401 for (i = 0; i < count; i++) {
2402 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2403 types [i] = t->type;
2406 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2407 g_free (types);
2408 if (!geninst)
2409 return NULL;
2411 return mono_type_get_object (mono_object_domain (type), geninst);
2414 static gboolean
2415 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2417 MonoClass *klass;
2418 MONO_ARCH_SAVE_REGS;
2420 if (type->type->byref)
2421 return FALSE;
2423 klass = mono_class_from_mono_type (type->type);
2424 return klass->generic_class != NULL;
2427 static gboolean
2428 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2430 MonoClass *klass;
2431 MONO_ARCH_SAVE_REGS;
2433 if (!IS_MONOTYPE (type))
2434 return FALSE;
2436 if (type->type->byref)
2437 return FALSE;
2439 klass = mono_class_from_mono_type (type->type);
2440 return klass->generic_class != NULL || klass->generic_container != NULL;
2443 static gint32
2444 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2446 MONO_ARCH_SAVE_REGS;
2448 if (!IS_MONOTYPE (type))
2449 return -1;
2451 if (is_generic_parameter (type->type))
2452 return mono_type_get_generic_param_num (type->type);
2453 return -1;
2456 static GenericParameterAttributes
2457 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2459 MONO_ARCH_SAVE_REGS;
2461 g_assert (IS_MONOTYPE (type));
2462 g_assert (is_generic_parameter (type->type));
2463 return mono_generic_param_info (type->type->data.generic_param)->flags;
2466 static MonoArray *
2467 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2469 MonoGenericParamInfo *param_info;
2470 MonoDomain *domain;
2471 MonoClass **ptr;
2472 MonoArray *res;
2473 int i, count;
2475 MONO_ARCH_SAVE_REGS;
2477 g_assert (IS_MONOTYPE (type));
2479 domain = mono_object_domain (type);
2480 param_info = mono_generic_param_info (type->type->data.generic_param);
2481 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2484 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2485 for (i = 0; i < count; i++)
2486 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2489 return res;
2492 static MonoBoolean
2493 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2495 MONO_ARCH_SAVE_REGS;
2496 return is_generic_parameter (type->type);
2499 static MonoBoolean
2500 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2502 MONO_ARCH_SAVE_REGS;
2503 return is_generic_parameter (tb->type.type);
2506 static void
2507 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2508 MonoReflectionType *t)
2510 enumtype->type = t->type;
2513 static MonoReflectionType*
2514 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2516 MonoDynamicGenericClass *gclass;
2517 MonoReflectionType *parent = NULL, *res;
2518 MonoDomain *domain;
2519 MonoType *inflated;
2520 MonoClass *klass;
2523 MONO_ARCH_SAVE_REGS;
2525 g_assert (type->type.type->data.generic_class->is_dynamic);
2526 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2528 domain = mono_object_domain (type);
2529 klass = mono_class_from_mono_type (type->generic_type->type.type);
2531 if (!klass->generic_class && !klass->generic_container)
2532 return NULL;
2534 parent = monotype_cast (type->generic_type->parent);
2536 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2537 return NULL;
2539 inflated = mono_class_inflate_generic_type (
2540 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2542 res = mono_type_get_object (domain, inflated);
2543 mono_metadata_free_type (inflated);
2544 return res;
2547 static MonoArray*
2548 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2550 static MonoClass *System_Reflection_MonoGenericClass;
2551 MonoGenericClass *gclass;
2552 MonoReflectionTypeBuilder *tb = NULL;
2553 MonoClass *klass = NULL;
2554 MonoDomain *domain;
2555 MonoArray *res;
2556 int icount, i;
2558 MONO_ARCH_SAVE_REGS;
2560 if (!System_Reflection_MonoGenericClass) {
2561 System_Reflection_MonoGenericClass = mono_class_from_name (
2562 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2563 g_assert (System_Reflection_MonoGenericClass);
2566 domain = mono_object_domain (type);
2568 gclass = type->type.type->data.generic_class;
2569 g_assert (gclass->is_dynamic);
2571 tb = type->generic_type;
2572 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2574 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2576 for (i = 0; i < icount; i++) {
2577 MonoReflectionType *iface;
2578 MonoType *it;
2580 if (tb) {
2581 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2582 it = iface->type;
2583 } else
2584 it = &klass->interfaces [i]->byval_arg;
2586 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2588 iface = mono_type_get_object (domain, it);
2589 mono_array_setref (res, i, iface);
2590 mono_metadata_free_type (it);
2593 return res;
2596 static MonoReflectionMethod*
2597 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2598 MonoReflectionMethod* generic)
2600 MonoGenericClass *gclass;
2601 MonoDynamicGenericClass *dgclass;
2602 MonoDomain *domain;
2603 int i;
2605 MONO_ARCH_SAVE_REGS;
2607 gclass = type->type.type->data.generic_class;
2608 g_assert (gclass->is_dynamic);
2610 dgclass = (MonoDynamicGenericClass *) gclass;
2612 domain = mono_object_domain (type);
2614 for (i = 0; i < dgclass->count_methods; i++)
2615 if (generic->method->token == dgclass->methods [i]->token)
2616 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2618 return NULL;
2621 static MonoReflectionMethod*
2622 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2623 MonoReflectionMethod* generic)
2625 MonoGenericClass *gclass;
2626 MonoDynamicGenericClass *dgclass;
2627 MonoDomain *domain;
2628 int i;
2630 MONO_ARCH_SAVE_REGS;
2632 gclass = type->type.type->data.generic_class;
2633 g_assert (gclass->is_dynamic);
2635 dgclass = (MonoDynamicGenericClass *) gclass;
2637 domain = mono_object_domain (type);
2639 for (i = 0; i < dgclass->count_ctors; i++)
2640 if (generic->method->token == dgclass->ctors [i]->token)
2641 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2643 return NULL;
2647 static MonoReflectionField*
2648 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2649 MonoString* generic_name)
2651 MonoGenericClass *gclass;
2652 MonoDynamicGenericClass *dgclass;
2653 MonoDomain *domain;
2654 MonoClass *refclass;
2655 char *utf8_name = mono_string_to_utf8 (generic_name);
2656 int i;
2658 MONO_ARCH_SAVE_REGS;
2660 gclass = type->type.type->data.generic_class;
2661 g_assert (gclass->is_dynamic);
2663 dgclass = (MonoDynamicGenericClass *) gclass;
2665 refclass = mono_class_from_mono_type (type->type.type);
2667 domain = mono_object_domain (type);
2669 for (i = 0; i < dgclass->count_fields; i++)
2670 if (strcmp (utf8_name, mono_field_get_name (&dgclass->fields [i])) == 0) {
2671 g_free (utf8_name);
2672 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2675 g_free (utf8_name);
2677 return NULL;
2681 static MonoReflectionMethod*
2682 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2683 MonoReflectionMethod* generic)
2685 MonoDomain *domain;
2686 MonoClass *klass;
2687 MonoMethod *method;
2688 gpointer iter;
2690 MONO_ARCH_SAVE_REGS;
2692 domain = ((MonoObject *)type)->vtable->domain;
2694 klass = mono_class_from_mono_type (type->type);
2696 iter = NULL;
2697 while ((method = mono_class_get_methods (klass, &iter))) {
2698 if (method->token == generic->method->token)
2699 return mono_method_get_object (domain, method, klass);
2702 return NULL;
2705 static MonoArray*
2706 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2707 MonoReflectionType *reflected_type)
2709 MonoGenericClass *gclass;
2710 MonoDynamicGenericClass *dgclass;
2711 MonoDomain *domain;
2712 MonoClass *refclass;
2713 MonoArray *res;
2714 int i;
2716 MONO_ARCH_SAVE_REGS;
2718 gclass = type->type.type->data.generic_class;
2719 g_assert (gclass->is_dynamic);
2720 dgclass = (MonoDynamicGenericClass *) gclass;
2722 refclass = mono_class_from_mono_type (reflected_type->type);
2724 domain = mono_object_domain (type);
2725 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2727 for (i = 0; i < dgclass->count_methods; i++)
2728 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2730 return res;
2733 static MonoArray*
2734 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2735 MonoReflectionType *reflected_type)
2737 static MonoClass *System_Reflection_ConstructorInfo;
2738 MonoGenericClass *gclass;
2739 MonoDynamicGenericClass *dgclass;
2740 MonoDomain *domain;
2741 MonoClass *refclass;
2742 MonoArray *res;
2743 int i;
2745 MONO_ARCH_SAVE_REGS;
2747 if (!System_Reflection_ConstructorInfo)
2748 System_Reflection_ConstructorInfo = mono_class_from_name (
2749 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2751 gclass = type->type.type->data.generic_class;
2752 g_assert (gclass->is_dynamic);
2753 dgclass = (MonoDynamicGenericClass *) gclass;
2755 refclass = mono_class_from_mono_type (reflected_type->type);
2757 domain = mono_object_domain (type);
2758 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2760 for (i = 0; i < dgclass->count_ctors; i++)
2761 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2763 return res;
2766 static MonoArray*
2767 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2768 MonoReflectionType *reflected_type)
2770 MonoGenericClass *gclass;
2771 MonoDynamicGenericClass *dgclass;
2772 MonoDomain *domain;
2773 MonoClass *refclass;
2774 MonoArray *res;
2775 int i;
2777 MONO_ARCH_SAVE_REGS;
2779 gclass = type->type.type->data.generic_class;
2780 g_assert (gclass->is_dynamic);
2781 dgclass = (MonoDynamicGenericClass *) gclass;
2783 refclass = mono_class_from_mono_type (reflected_type->type);
2785 domain = mono_object_domain (type);
2786 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2788 for (i = 0; i < dgclass->count_fields; i++)
2789 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2791 return res;
2794 static MonoArray*
2795 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2796 MonoReflectionType *reflected_type)
2798 static MonoClass *System_Reflection_PropertyInfo;
2799 MonoGenericClass *gclass;
2800 MonoDynamicGenericClass *dgclass;
2801 MonoDomain *domain;
2802 MonoClass *refclass;
2803 MonoArray *res;
2804 int i;
2806 MONO_ARCH_SAVE_REGS;
2808 if (!System_Reflection_PropertyInfo)
2809 System_Reflection_PropertyInfo = mono_class_from_name (
2810 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2812 gclass = type->type.type->data.generic_class;
2813 g_assert (gclass->is_dynamic);
2814 dgclass = (MonoDynamicGenericClass *) gclass;
2816 refclass = mono_class_from_mono_type (reflected_type->type);
2818 domain = mono_object_domain (type);
2819 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2821 for (i = 0; i < dgclass->count_properties; i++)
2822 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2824 return res;
2827 static MonoArray*
2828 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2829 MonoReflectionType *reflected_type)
2831 static MonoClass *System_Reflection_EventInfo;
2832 MonoGenericClass *gclass;
2833 MonoDynamicGenericClass *dgclass;
2834 MonoDomain *domain;
2835 MonoClass *refclass;
2836 MonoArray *res;
2837 int i;
2839 MONO_ARCH_SAVE_REGS;
2841 if (!System_Reflection_EventInfo)
2842 System_Reflection_EventInfo = mono_class_from_name (
2843 mono_defaults.corlib, "System.Reflection", "EventInfo");
2845 gclass = type->type.type->data.generic_class;
2846 g_assert (gclass->is_dynamic);
2847 dgclass = (MonoDynamicGenericClass *) gclass;
2849 refclass = mono_class_from_mono_type (reflected_type->type);
2851 domain = mono_object_domain (type);
2852 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2854 for (i = 0; i < dgclass->count_events; i++)
2855 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2857 return res;
2860 static MonoReflectionType*
2861 ves_icall_MonoGenericClass_InflateType (MonoReflectionGenericClass *type,
2862 MonoReflectionType *target)
2864 MonoType *res_type;
2865 MonoClass *gklass;
2866 MonoReflectionType *res;
2868 MONO_ARCH_SAVE_REGS;
2870 gklass = mono_class_from_mono_type (type->type.type);
2871 res_type = mono_class_inflate_generic_type (target->type, mono_class_get_context (gklass));
2872 res = mono_type_get_object (mono_object_domain (type), res_type);
2873 mono_metadata_free_type (res_type);
2874 return res;
2877 static MonoReflectionMethod *
2878 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2880 MonoMethod *method;
2881 MonoClass *klass;
2883 MONO_ARCH_SAVE_REGS;
2885 if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2886 return NULL;
2888 method = mono_type_get_generic_param_owner (type->type)->owner.method;
2889 g_assert (method);
2890 klass = mono_class_from_mono_type (type->type);
2891 return mono_method_get_object (mono_object_domain (type), method, klass);
2894 static MonoReflectionDllImportAttribute*
2895 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2897 static MonoClass *DllImportAttributeClass = NULL;
2898 MonoDomain *domain = mono_domain_get ();
2899 MonoReflectionDllImportAttribute *attr;
2900 MonoImage *image = method->klass->image;
2901 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2902 MonoTableInfo *tables = image->tables;
2903 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2904 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2905 guint32 im_cols [MONO_IMPLMAP_SIZE];
2906 guint32 scope_token;
2907 const char *import = NULL;
2908 const char *scope = NULL;
2909 guint32 flags;
2911 if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2912 return NULL;
2914 if (!DllImportAttributeClass) {
2915 DllImportAttributeClass =
2916 mono_class_from_name (mono_defaults.corlib,
2917 "System.Runtime.InteropServices", "DllImportAttribute");
2918 g_assert (DllImportAttributeClass);
2921 if (method->klass->image->dynamic) {
2922 MonoReflectionMethodAux *method_aux =
2923 g_hash_table_lookup (
2924 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2925 if (method_aux) {
2926 import = method_aux->dllentry;
2927 scope = method_aux->dll;
2930 else {
2931 if (piinfo->implmap_idx) {
2932 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2934 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2935 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2936 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2937 scope = mono_metadata_string_heap (image, scope_token);
2940 flags = piinfo->piflags;
2942 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2944 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2945 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2946 attr->call_conv = (flags & 0x700) >> 8;
2947 attr->charset = ((flags & 0x6) >> 1) + 1;
2948 if (attr->charset == 1)
2949 attr->charset = 2;
2950 attr->exact_spelling = (flags & 0x1) != 0;
2951 attr->set_last_error = (flags & 0x40) != 0;
2952 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2953 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2954 attr->preserve_sig = FALSE;
2956 return attr;
2959 static MonoReflectionMethod *
2960 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2962 MonoMethodInflated *imethod;
2963 MonoMethod *result;
2965 MONO_ARCH_SAVE_REGS;
2967 if (method->method->is_generic)
2968 return method;
2970 if (!method->method->is_inflated)
2971 return NULL;
2973 imethod = (MonoMethodInflated *) method->method;
2975 result = imethod->declaring;
2976 /* Not a generic method. */
2977 if (!result->is_generic)
2978 return NULL;
2980 if (method->method->klass->image->dynamic) {
2981 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2982 MonoReflectionMethod *res;
2985 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2986 * the dynamic case as well ?
2988 mono_loader_lock ();
2989 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2990 mono_loader_unlock ();
2992 if (res)
2993 return res;
2996 if (imethod->context.class_inst) {
2997 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2998 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
3001 return mono_method_get_object (mono_object_domain (method), result, NULL);
3004 static gboolean
3005 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3007 MONO_ARCH_SAVE_REGS;
3009 return mono_method_signature (method->method)->generic_param_count != 0;
3012 static gboolean
3013 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3015 MONO_ARCH_SAVE_REGS;
3017 return method->method->is_generic;
3020 static MonoArray*
3021 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3023 MonoArray *res;
3024 MonoDomain *domain;
3025 int count, i;
3026 MONO_ARCH_SAVE_REGS;
3028 domain = mono_object_domain (method);
3030 if (method->method->is_inflated) {
3031 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3033 if (inst) {
3034 count = inst->type_argc;
3035 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3037 for (i = 0; i < count; i++)
3038 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
3040 return res;
3044 count = mono_method_signature (method->method)->generic_param_count;
3045 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3047 for (i = 0; i < count; i++) {
3048 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3049 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3050 MonoClass *pklass = mono_class_from_generic_parameter (
3051 param, method->method->klass->image, TRUE);
3052 mono_array_setref (res, i,
3053 mono_type_get_object (domain, &pklass->byval_arg));
3056 return res;
3059 static MonoObject *
3060 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
3063 * Invoke from reflection is supposed to always be a virtual call (the API
3064 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3065 * greater flexibility.
3067 MonoMethod *m = method->method;
3068 int pcount;
3069 void *obj = this;
3071 MONO_ARCH_SAVE_REGS;
3073 *exc = NULL;
3075 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
3076 mono_security_core_clr_ensure_reflection_access_method (m);
3078 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3079 if (this) {
3080 if (!mono_object_isinst (this, m->klass)) {
3081 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type.");
3082 return NULL;
3084 m = mono_object_get_virtual_method (this, m);
3085 /* must pass the pointer to the value for valuetype methods */
3086 if (m->klass->valuetype)
3087 obj = mono_object_unbox (this);
3088 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3089 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target.");
3090 return NULL;
3094 pcount = params? mono_array_length (params): 0;
3095 if (pcount != mono_method_signature (m)->param_count) {
3096 *exc = mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException");
3097 return NULL;
3100 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
3101 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class.");
3102 return NULL;
3105 if (m->klass->image->assembly->ref_only) {
3106 *exc = mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api.");
3107 return NULL;
3110 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3111 int i;
3112 mono_array_size_t *lengths;
3113 mono_array_size_t *lower_bounds;
3114 pcount = mono_array_length (params);
3115 lengths = alloca (sizeof (mono_array_size_t) * pcount);
3116 for (i = 0; i < pcount; ++i)
3117 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3119 if (m->klass->rank == pcount) {
3120 /* Only lengths provided. */
3121 lower_bounds = NULL;
3122 } else {
3123 g_assert (pcount == (m->klass->rank * 2));
3124 /* lower bounds are first. */
3125 lower_bounds = lengths;
3126 lengths += m->klass->rank;
3129 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
3131 return mono_runtime_invoke_array (m, obj, params, NULL);
3134 static MonoObject *
3135 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
3137 MonoDomain *domain = mono_object_domain (method);
3138 MonoMethod *m = method->method;
3139 MonoMethodSignature *sig = mono_method_signature (m);
3140 MonoArray *out_args;
3141 MonoObject *result;
3142 int i, j, outarg_count = 0;
3144 MONO_ARCH_SAVE_REGS;
3146 if (m->klass == mono_defaults.object_class) {
3148 if (!strcmp (m->name, "FieldGetter")) {
3149 MonoClass *k = this->vtable->klass;
3150 MonoString *name;
3151 char *str;
3153 /* If this is a proxy, then it must be a CBO */
3154 if (k == mono_defaults.transparent_proxy_class) {
3155 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3156 this = tp->rp->unwrapped_server;
3157 g_assert (this);
3158 k = this->vtable->klass;
3161 name = mono_array_get (params, MonoString *, 1);
3162 str = mono_string_to_utf8 (name);
3164 do {
3165 MonoClassField* field = mono_class_get_field_from_name (k, str);
3166 if (field) {
3167 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3168 if (field_klass->valuetype)
3169 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
3170 else
3171 result = *((gpointer *)((char *)this + field->offset));
3173 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3174 *outArgs = out_args;
3175 mono_array_setref (out_args, 0, result);
3176 g_free (str);
3177 return NULL;
3179 k = k->parent;
3180 } while (k);
3182 g_free (str);
3183 g_assert_not_reached ();
3185 } else if (!strcmp (m->name, "FieldSetter")) {
3186 MonoClass *k = this->vtable->klass;
3187 MonoString *name;
3188 guint32 size;
3189 gint32 align;
3190 char *str;
3192 /* If this is a proxy, then it must be a CBO */
3193 if (k == mono_defaults.transparent_proxy_class) {
3194 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3195 this = tp->rp->unwrapped_server;
3196 g_assert (this);
3197 k = this->vtable->klass;
3200 name = mono_array_get (params, MonoString *, 1);
3201 str = mono_string_to_utf8 (name);
3203 do {
3204 MonoClassField* field = mono_class_get_field_from_name (k, str);
3205 if (field) {
3206 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3207 MonoObject *val = mono_array_get (params, gpointer, 2);
3209 if (field_klass->valuetype) {
3210 size = mono_type_size (field->type, &align);
3211 #ifdef HAVE_SGEN_GC
3212 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3213 #endif
3214 memcpy ((char *)this + field->offset,
3215 ((char *)val) + sizeof (MonoObject), size);
3216 } else {
3217 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
3220 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3221 *outArgs = out_args;
3223 g_free (str);
3224 return NULL;
3227 k = k->parent;
3228 } while (k);
3230 g_free (str);
3231 g_assert_not_reached ();
3236 for (i = 0; i < mono_array_length (params); i++) {
3237 if (sig->params [i]->byref)
3238 outarg_count++;
3241 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3243 /* handle constructors only for objects already allocated */
3244 if (!strcmp (method->method->name, ".ctor"))
3245 g_assert (this);
3247 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3248 g_assert (!method->method->klass->valuetype);
3249 result = mono_runtime_invoke_array (method->method, this, params, NULL);
3251 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3252 if (sig->params [i]->byref) {
3253 gpointer arg;
3254 arg = mono_array_get (params, gpointer, i);
3255 mono_array_setref (out_args, j, arg);
3256 j++;
3260 *outArgs = out_args;
3262 return result;
3265 static guint64
3266 read_enum_value (char *mem, int type)
3268 switch (type) {
3269 case MONO_TYPE_U1:
3270 return *(guint8*)mem;
3271 case MONO_TYPE_I1:
3272 return *(gint8*)mem;
3273 case MONO_TYPE_U2:
3274 return *(guint16*)mem;
3275 case MONO_TYPE_I2:
3276 return *(gint16*)mem;
3277 case MONO_TYPE_U4:
3278 return *(guint32*)mem;
3279 case MONO_TYPE_I4:
3280 return *(gint32*)mem;
3281 case MONO_TYPE_U8:
3282 return *(guint64*)mem;
3283 case MONO_TYPE_I8:
3284 return *(gint64*)mem;
3285 default:
3286 g_assert_not_reached ();
3288 return 0;
3291 static void
3292 write_enum_value (char *mem, int type, guint64 value)
3294 switch (type) {
3295 case MONO_TYPE_U1:
3296 case MONO_TYPE_I1: {
3297 guint8 *p = (guint8*)mem;
3298 *p = value;
3299 break;
3301 case MONO_TYPE_U2:
3302 case MONO_TYPE_I2: {
3303 guint16 *p = (void*)mem;
3304 *p = value;
3305 break;
3307 case MONO_TYPE_U4:
3308 case MONO_TYPE_I4: {
3309 guint32 *p = (void*)mem;
3310 *p = value;
3311 break;
3313 case MONO_TYPE_U8:
3314 case MONO_TYPE_I8: {
3315 guint64 *p = (void*)mem;
3316 *p = value;
3317 break;
3319 default:
3320 g_assert_not_reached ();
3322 return;
3325 static MonoObject *
3326 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3328 MonoDomain *domain;
3329 MonoClass *enumc, *objc;
3330 MonoObject *res;
3331 guint64 val;
3333 MONO_ARCH_SAVE_REGS;
3335 MONO_CHECK_ARG_NULL (enumType);
3336 MONO_CHECK_ARG_NULL (value);
3338 domain = mono_object_domain (enumType);
3339 enumc = mono_class_from_mono_type (enumType->type);
3340 objc = value->vtable->klass;
3342 if (!enumc->enumtype)
3343 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3344 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3345 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."));
3347 res = mono_object_new (domain, enumc);
3348 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3349 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3351 return res;
3354 static MonoObject *
3355 ves_icall_System_Enum_get_value (MonoObject *this)
3357 MonoObject *res;
3358 MonoClass *enumc;
3359 gpointer dst;
3360 gpointer src;
3361 int size;
3363 MONO_ARCH_SAVE_REGS;
3365 if (!this)
3366 return NULL;
3368 g_assert (this->vtable->klass->enumtype);
3370 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3371 res = mono_object_new (mono_object_domain (this), enumc);
3372 dst = (char *)res + sizeof (MonoObject);
3373 src = (char *)this + sizeof (MonoObject);
3374 size = mono_class_value_size (enumc, NULL);
3376 memcpy (dst, src, size);
3378 return res;
3381 static MonoReflectionType *
3382 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3384 MONO_ARCH_SAVE_REGS;
3386 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3389 static int
3390 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3392 gpointer tdata = (char *)this + sizeof (MonoObject);
3393 gpointer odata = (char *)other + sizeof (MonoObject);
3394 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3395 g_assert (basetype);
3397 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3398 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3399 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3400 if (me == other) \
3401 return 0; \
3402 return me > other ? 1 : -1; \
3403 } while (0)
3405 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3406 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3407 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3408 if (me == other) \
3409 return 0; \
3410 return me - other; \
3411 } while (0)
3413 switch (basetype->type) {
3414 case MONO_TYPE_U1:
3415 COMPARE_ENUM_VALUES (guint8);
3416 case MONO_TYPE_I1:
3417 COMPARE_ENUM_VALUES (gint8);
3418 case MONO_TYPE_CHAR:
3419 case MONO_TYPE_U2:
3420 COMPARE_ENUM_VALUES_RANGE (guint16);
3421 case MONO_TYPE_I2:
3422 COMPARE_ENUM_VALUES (gint16);
3423 case MONO_TYPE_U4:
3424 COMPARE_ENUM_VALUES (guint32);
3425 case MONO_TYPE_I4:
3426 COMPARE_ENUM_VALUES (gint32);
3427 case MONO_TYPE_U8:
3428 COMPARE_ENUM_VALUES (guint64);
3429 case MONO_TYPE_I8:
3430 COMPARE_ENUM_VALUES (gint64);
3431 default:
3432 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3434 #undef COMPARE_ENUM_VALUES_RANGE
3435 #undef COMPARE_ENUM_VALUES
3436 return 0;
3439 static int
3440 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3442 gpointer data = (char *)this + sizeof (MonoObject);
3443 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3444 g_assert (basetype);
3446 switch (basetype->type) {
3447 case MONO_TYPE_I1:
3448 return *((gint8*)data);
3449 case MONO_TYPE_U1:
3450 return *((guint8*)data);
3451 case MONO_TYPE_CHAR:
3452 case MONO_TYPE_U2:
3453 return *((guint16*)data);
3455 case MONO_TYPE_I2:
3456 return *((gint16*)data);
3457 case MONO_TYPE_U4:
3458 return *((guint32*)data);
3459 case MONO_TYPE_I4:
3460 return *((gint32*)data);
3461 case MONO_TYPE_U8:
3462 case MONO_TYPE_I8: {
3463 gint64 value = *((gint64*)data);
3464 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3466 default:
3467 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3469 return 0;
3472 static void
3473 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3475 MonoDomain *domain = mono_object_domain (type);
3476 MonoClass *enumc = mono_class_from_mono_type (type->type);
3477 guint j = 0, nvalues, crow;
3478 gpointer iter;
3479 MonoClassField *field;
3481 MONO_ARCH_SAVE_REGS;
3483 info->utype = mono_type_get_object (domain, mono_class_enum_basetype (enumc));
3484 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3485 info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3486 info->values = mono_array_new (domain, enumc, nvalues);
3488 crow = -1;
3489 iter = NULL;
3490 while ((field = mono_class_get_fields (enumc, &iter))) {
3491 const char *p;
3492 int len;
3493 MonoTypeEnum def_type;
3495 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3496 continue;
3497 if (mono_field_is_deleted (field))
3498 continue;
3499 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3501 p = mono_class_get_field_default_value (field, &def_type);
3502 len = mono_metadata_decode_blob_size (p, &p);
3503 switch (mono_class_enum_basetype (enumc)->type) {
3504 case MONO_TYPE_U1:
3505 case MONO_TYPE_I1:
3506 mono_array_set (info->values, gchar, j, *p);
3507 break;
3508 case MONO_TYPE_CHAR:
3509 case MONO_TYPE_U2:
3510 case MONO_TYPE_I2:
3511 mono_array_set (info->values, gint16, j, read16 (p));
3512 break;
3513 case MONO_TYPE_U4:
3514 case MONO_TYPE_I4:
3515 mono_array_set (info->values, gint32, j, read32 (p));
3516 break;
3517 case MONO_TYPE_U8:
3518 case MONO_TYPE_I8:
3519 mono_array_set (info->values, gint64, j, read64 (p));
3520 break;
3521 default:
3522 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3524 ++j;
3528 enum {
3529 BFLAGS_IgnoreCase = 1,
3530 BFLAGS_DeclaredOnly = 2,
3531 BFLAGS_Instance = 4,
3532 BFLAGS_Static = 8,
3533 BFLAGS_Public = 0x10,
3534 BFLAGS_NonPublic = 0x20,
3535 BFLAGS_FlattenHierarchy = 0x40,
3536 BFLAGS_InvokeMethod = 0x100,
3537 BFLAGS_CreateInstance = 0x200,
3538 BFLAGS_GetField = 0x400,
3539 BFLAGS_SetField = 0x800,
3540 BFLAGS_GetProperty = 0x1000,
3541 BFLAGS_SetProperty = 0x2000,
3542 BFLAGS_ExactBinding = 0x10000,
3543 BFLAGS_SuppressChangeType = 0x20000,
3544 BFLAGS_OptionalParamBinding = 0x40000
3547 static MonoReflectionField *
3548 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3550 MonoDomain *domain;
3551 MonoClass *startklass, *klass;
3552 int match;
3553 MonoClassField *field;
3554 gpointer iter;
3555 char *utf8_name;
3556 int (*compare_func) (const char *s1, const char *s2) = NULL;
3557 domain = ((MonoObject *)type)->vtable->domain;
3558 klass = startklass = mono_class_from_mono_type (type->type);
3560 MONO_ARCH_SAVE_REGS;
3562 if (!name)
3563 mono_raise_exception (mono_get_exception_argument_null ("name"));
3564 if (type->type->byref)
3565 return NULL;
3567 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3569 handle_parent:
3570 if (klass->exception_type != MONO_EXCEPTION_NONE)
3571 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3573 iter = NULL;
3574 while ((field = mono_class_get_fields (klass, &iter))) {
3575 match = 0;
3577 if (field->type == NULL)
3578 continue;
3579 if (mono_field_is_deleted (field))
3580 continue;
3581 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3582 if (bflags & BFLAGS_Public)
3583 match++;
3584 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3585 if (bflags & BFLAGS_NonPublic) {
3586 match++;
3589 if (!match)
3590 continue;
3591 match = 0;
3592 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3593 if (bflags & BFLAGS_Static)
3594 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3595 match++;
3596 } else {
3597 if (bflags & BFLAGS_Instance)
3598 match++;
3601 if (!match)
3602 continue;
3604 utf8_name = mono_string_to_utf8 (name);
3606 if (compare_func (mono_field_get_name (field), utf8_name)) {
3607 g_free (utf8_name);
3608 continue;
3610 g_free (utf8_name);
3612 return mono_field_get_object (domain, klass, field);
3614 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3615 goto handle_parent;
3617 return NULL;
3620 static MonoArray*
3621 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3623 MonoDomain *domain;
3624 MonoClass *startklass, *klass, *refklass;
3625 MonoArray *res;
3626 MonoObject *member;
3627 int i, match;
3628 gpointer iter;
3629 MonoClassField *field;
3630 MonoPtrArray tmp_array;
3632 MONO_ARCH_SAVE_REGS;
3634 domain = ((MonoObject *)type)->vtable->domain;
3635 if (type->type->byref)
3636 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3637 klass = startklass = mono_class_from_mono_type (type->type);
3638 refklass = mono_class_from_mono_type (reftype->type);
3640 mono_ptr_array_init (tmp_array, 2);
3642 handle_parent:
3643 if (klass->exception_type != MONO_EXCEPTION_NONE)
3644 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3646 iter = NULL;
3647 while ((field = mono_class_get_fields (klass, &iter))) {
3648 match = 0;
3649 if (mono_field_is_deleted (field))
3650 continue;
3651 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3652 if (bflags & BFLAGS_Public)
3653 match++;
3654 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3655 if (bflags & BFLAGS_NonPublic) {
3656 match++;
3659 if (!match)
3660 continue;
3661 match = 0;
3662 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3663 if (bflags & BFLAGS_Static)
3664 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3665 match++;
3666 } else {
3667 if (bflags & BFLAGS_Instance)
3668 match++;
3671 if (!match)
3672 continue;
3673 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3674 mono_ptr_array_append (tmp_array, member);
3676 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3677 goto handle_parent;
3679 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3681 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3682 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3684 mono_ptr_array_destroy (tmp_array);
3686 return res;
3689 static gboolean
3690 method_nonpublic (MonoMethod* method, gboolean start_klass)
3692 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3693 case METHOD_ATTRIBUTE_ASSEM:
3694 return (start_klass || mono_defaults.generic_ilist_class);
3695 case METHOD_ATTRIBUTE_PRIVATE:
3696 return start_klass;
3697 case METHOD_ATTRIBUTE_PUBLIC:
3698 return FALSE;
3699 default:
3700 return TRUE;
3704 static MonoArray*
3705 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3707 static MonoClass *MethodInfo_array;
3708 MonoDomain *domain;
3709 MonoClass *startklass, *klass, *refklass;
3710 MonoArray *res;
3711 MonoMethod *method;
3712 gpointer iter;
3713 MonoObject *member;
3714 int i, len, match, nslots;
3715 guint32 method_slots_default [8];
3716 guint32 *method_slots;
3717 gchar *mname = NULL;
3718 int (*compare_func) (const char *s1, const char *s2) = NULL;
3719 MonoVTable *array_vtable;
3720 MonoPtrArray tmp_array;
3722 MONO_ARCH_SAVE_REGS;
3724 mono_ptr_array_init (tmp_array, 4);
3726 if (!MethodInfo_array) {
3727 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3728 mono_memory_barrier ();
3729 MethodInfo_array = klass;
3732 domain = ((MonoObject *)type)->vtable->domain;
3733 array_vtable = mono_class_vtable (domain, MethodInfo_array);
3734 if (type->type->byref)
3735 return mono_array_new_specific (array_vtable, 0);
3736 klass = startklass = mono_class_from_mono_type (type->type);
3737 refklass = mono_class_from_mono_type (reftype->type);
3738 len = 0;
3739 if (name != NULL) {
3740 mname = mono_string_to_utf8 (name);
3741 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3744 /* An optimization for calls made from Delegate:CreateDelegate () */
3745 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3746 method = mono_get_delegate_invoke (klass);
3748 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3750 res = mono_array_new_specific (array_vtable, 1);
3751 mono_array_setref (res, 0, member);
3752 g_free (mname);
3753 return res;
3756 mono_class_setup_vtable (klass);
3758 if (is_generic_parameter (type->type))
3759 nslots = klass->parent->vtable_size;
3760 else
3761 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3762 if (nslots >= sizeof (method_slots_default) * 8) {
3763 method_slots = g_new0 (guint32, nslots / 32 + 1);
3764 } else {
3765 method_slots = method_slots_default;
3766 memset (method_slots, 0, sizeof (method_slots_default));
3768 handle_parent:
3769 mono_class_setup_vtable (klass);
3770 if (klass->exception_type != MONO_EXCEPTION_NONE)
3771 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3773 iter = NULL;
3774 while ((method = mono_class_get_methods (klass, &iter))) {
3775 match = 0;
3776 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3777 continue;
3778 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3779 if (bflags & BFLAGS_Public)
3780 match++;
3781 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3782 match++;
3784 if (!match)
3785 continue;
3786 match = 0;
3787 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3788 if (bflags & BFLAGS_Static)
3789 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3790 match++;
3791 } else {
3792 if (bflags & BFLAGS_Instance)
3793 match++;
3796 if (!match)
3797 continue;
3799 if (name != NULL) {
3800 if (compare_func (mname, method->name))
3801 continue;
3804 match = 0;
3805 if (method->slot != -1) {
3806 g_assert (method->slot < nslots);
3807 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3808 continue;
3809 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3812 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3814 mono_ptr_array_append (tmp_array, member);
3816 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3817 goto handle_parent;
3819 g_free (mname);
3820 if (method_slots != method_slots_default)
3821 g_free (method_slots);
3823 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3825 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3826 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3828 mono_ptr_array_destroy (tmp_array);
3829 return res;
3832 static MonoArray*
3833 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3835 MonoDomain *domain;
3836 static MonoClass *System_Reflection_ConstructorInfo;
3837 MonoClass *startklass, *klass, *refklass;
3838 MonoArray *res;
3839 MonoMethod *method;
3840 MonoObject *member;
3841 int i, match;
3842 gpointer iter = NULL;
3843 MonoPtrArray tmp_array;
3845 MONO_ARCH_SAVE_REGS;
3847 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3849 domain = ((MonoObject *)type)->vtable->domain;
3850 if (type->type->byref)
3851 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3852 klass = startklass = mono_class_from_mono_type (type->type);
3853 refklass = mono_class_from_mono_type (reftype->type);
3855 if (klass->exception_type != MONO_EXCEPTION_NONE)
3856 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3858 if (!System_Reflection_ConstructorInfo)
3859 System_Reflection_ConstructorInfo = mono_class_from_name (
3860 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3862 iter = NULL;
3863 while ((method = mono_class_get_methods (klass, &iter))) {
3864 match = 0;
3865 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3866 continue;
3867 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3868 if (bflags & BFLAGS_Public)
3869 match++;
3870 } else {
3871 if (bflags & BFLAGS_NonPublic)
3872 match++;
3874 if (!match)
3875 continue;
3876 match = 0;
3877 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3878 if (bflags & BFLAGS_Static)
3879 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3880 match++;
3881 } else {
3882 if (bflags & BFLAGS_Instance)
3883 match++;
3886 if (!match)
3887 continue;
3888 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3890 mono_ptr_array_append (tmp_array, member);
3893 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3895 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3896 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3898 mono_ptr_array_destroy (tmp_array);
3900 return res;
3903 static guint
3904 property_hash (gconstpointer data)
3906 MonoProperty *prop = (MonoProperty*)data;
3908 return g_str_hash (prop->name);
3911 static gboolean
3912 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3914 // Properties are hide-by-name-and-signature
3915 if (!g_str_equal (prop1->name, prop2->name))
3916 return FALSE;
3918 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3919 return FALSE;
3920 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3921 return FALSE;
3922 return TRUE;
3925 static gboolean
3926 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3928 if (!accessor)
3929 return FALSE;
3931 return method_nonpublic (accessor, start_klass);
3934 static MonoArray*
3935 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3937 MonoDomain *domain;
3938 static MonoClass *System_Reflection_PropertyInfo;
3939 MonoClass *startklass, *klass;
3940 MonoArray *res;
3941 MonoMethod *method;
3942 MonoProperty *prop;
3943 int i, match;
3944 guint32 flags;
3945 gchar *propname = NULL;
3946 int (*compare_func) (const char *s1, const char *s2) = NULL;
3947 gpointer iter;
3948 GHashTable *properties;
3949 MonoPtrArray tmp_array;
3951 MONO_ARCH_SAVE_REGS;
3953 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3955 if (!System_Reflection_PropertyInfo)
3956 System_Reflection_PropertyInfo = mono_class_from_name (
3957 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3959 domain = ((MonoObject *)type)->vtable->domain;
3960 if (type->type->byref)
3961 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3962 klass = startklass = mono_class_from_mono_type (type->type);
3963 if (name != NULL) {
3964 propname = mono_string_to_utf8 (name);
3965 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3968 mono_class_setup_vtable (klass);
3970 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3971 handle_parent:
3972 mono_class_setup_vtable (klass);
3973 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3974 g_hash_table_destroy (properties);
3975 if (name != NULL)
3976 g_free (propname);
3977 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3980 iter = NULL;
3981 while ((prop = mono_class_get_properties (klass, &iter))) {
3982 match = 0;
3983 method = prop->get;
3984 if (!method)
3985 method = prop->set;
3986 if (method)
3987 flags = method->flags;
3988 else
3989 flags = 0;
3990 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3991 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3992 if (bflags & BFLAGS_Public)
3993 match++;
3994 } else if (bflags & BFLAGS_NonPublic) {
3995 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3996 property_accessor_nonpublic(prop->set, startklass == klass)) {
3997 match++;
4000 if (!match)
4001 continue;
4002 match = 0;
4003 if (flags & METHOD_ATTRIBUTE_STATIC) {
4004 if (bflags & BFLAGS_Static)
4005 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4006 match++;
4007 } else {
4008 if (bflags & BFLAGS_Instance)
4009 match++;
4012 if (!match)
4013 continue;
4014 match = 0;
4016 if (name != NULL) {
4017 if (compare_func (propname, prop->name))
4018 continue;
4021 if (g_hash_table_lookup (properties, prop))
4022 continue;
4024 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4026 g_hash_table_insert (properties, prop, prop);
4028 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4029 goto handle_parent;
4031 g_hash_table_destroy (properties);
4032 g_free (propname);
4034 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4035 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4036 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4038 mono_ptr_array_destroy (tmp_array);
4040 return res;
4043 static MonoReflectionEvent *
4044 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
4046 MonoDomain *domain;
4047 MonoClass *klass, *startklass;
4048 gpointer iter;
4049 MonoEvent *event;
4050 MonoMethod *method;
4051 gchar *event_name;
4053 MONO_ARCH_SAVE_REGS;
4055 event_name = mono_string_to_utf8 (name);
4056 if (type->type->byref)
4057 return NULL;
4058 klass = startklass = mono_class_from_mono_type (type->type);
4059 domain = mono_object_domain (type);
4061 handle_parent:
4062 if (klass->exception_type != MONO_EXCEPTION_NONE)
4063 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4065 iter = NULL;
4066 while ((event = mono_class_get_events (klass, &iter))) {
4067 if (strcmp (event->name, event_name))
4068 continue;
4070 method = event->add;
4071 if (!method)
4072 method = event->remove;
4073 if (!method)
4074 method = event->raise;
4075 if (method) {
4076 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4077 if (!(bflags & BFLAGS_Public))
4078 continue;
4079 } else {
4080 if (!(bflags & BFLAGS_NonPublic))
4081 continue;
4082 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4083 continue;
4086 else
4087 if (!(bflags & BFLAGS_NonPublic))
4088 continue;
4090 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4091 if (!(bflags & BFLAGS_Static))
4092 continue;
4093 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4094 continue;
4095 } else {
4096 if (!(bflags & BFLAGS_Instance))
4097 continue;
4100 g_free (event_name);
4101 return mono_event_get_object (domain, startklass, event);
4104 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4105 goto handle_parent;
4107 g_free (event_name);
4108 return NULL;
4111 static MonoArray*
4112 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4114 MonoDomain *domain;
4115 static MonoClass *System_Reflection_EventInfo;
4116 MonoClass *startklass, *klass;
4117 MonoArray *res;
4118 MonoMethod *method;
4119 MonoEvent *event;
4120 int i, match;
4121 gpointer iter;
4123 MonoPtrArray tmp_array;
4125 MONO_ARCH_SAVE_REGS;
4127 mono_ptr_array_init (tmp_array, 4);
4129 if (!System_Reflection_EventInfo)
4130 System_Reflection_EventInfo = mono_class_from_name (
4131 mono_defaults.corlib, "System.Reflection", "EventInfo");
4133 domain = mono_object_domain (type);
4134 if (type->type->byref)
4135 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4136 klass = startklass = mono_class_from_mono_type (type->type);
4138 handle_parent:
4139 if (klass->exception_type != MONO_EXCEPTION_NONE)
4140 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4142 iter = NULL;
4143 while ((event = mono_class_get_events (klass, &iter))) {
4144 match = 0;
4145 method = event->add;
4146 if (!method)
4147 method = event->remove;
4148 if (!method)
4149 method = event->raise;
4150 if (method) {
4151 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4152 if (bflags & BFLAGS_Public)
4153 match++;
4154 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4155 if (bflags & BFLAGS_NonPublic)
4156 match++;
4159 else
4160 if (bflags & BFLAGS_NonPublic)
4161 match ++;
4162 if (!match)
4163 continue;
4164 match = 0;
4165 if (method) {
4166 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4167 if (bflags & BFLAGS_Static)
4168 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4169 match++;
4170 } else {
4171 if (bflags & BFLAGS_Instance)
4172 match++;
4175 else
4176 if (bflags & BFLAGS_Instance)
4177 match ++;
4178 if (!match)
4179 continue;
4180 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4182 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4183 goto handle_parent;
4185 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4187 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4188 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4190 mono_ptr_array_destroy (tmp_array);
4192 return res;
4195 static MonoReflectionType *
4196 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4198 MonoDomain *domain;
4199 MonoClass *klass;
4200 MonoClass *nested;
4201 char *str;
4202 gpointer iter;
4204 MONO_ARCH_SAVE_REGS;
4206 domain = ((MonoObject *)type)->vtable->domain;
4207 if (type->type->byref)
4208 return NULL;
4209 klass = mono_class_from_mono_type (type->type);
4210 str = mono_string_to_utf8 (name);
4212 handle_parent:
4213 if (klass->exception_type != MONO_EXCEPTION_NONE)
4214 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4217 * If a nested type is generic, return its generic type definition.
4218 * Note that this means that the return value is essentially a
4219 * nested type of the generic type definition of @klass.
4221 * A note in MSDN claims that a generic type definition can have
4222 * nested types that aren't generic. In any case, the container of that
4223 * nested type would be the generic type definition.
4225 if (klass->generic_class)
4226 klass = klass->generic_class->container_class;
4228 iter = NULL;
4229 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4230 int match = 0;
4231 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4232 if (bflags & BFLAGS_Public)
4233 match++;
4234 } else {
4235 if (bflags & BFLAGS_NonPublic)
4236 match++;
4238 if (!match)
4239 continue;
4240 if (strcmp (nested->name, str) == 0){
4241 g_free (str);
4242 return mono_type_get_object (domain, &nested->byval_arg);
4245 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4246 goto handle_parent;
4247 g_free (str);
4248 return NULL;
4251 static MonoArray*
4252 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4254 MonoDomain *domain;
4255 MonoClass *klass;
4256 MonoArray *res;
4257 MonoObject *member;
4258 int i, match;
4259 MonoClass *nested;
4260 gpointer iter;
4261 MonoPtrArray tmp_array;
4263 MONO_ARCH_SAVE_REGS;
4265 domain = ((MonoObject *)type)->vtable->domain;
4266 if (type->type->byref)
4267 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4268 klass = mono_class_from_mono_type (type->type);
4269 if (klass->exception_type != MONO_EXCEPTION_NONE)
4270 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4273 * If a nested type is generic, return its generic type definition.
4274 * Note that this means that the return value is essentially the set
4275 * of nested types of the generic type definition of @klass.
4277 * A note in MSDN claims that a generic type definition can have
4278 * nested types that aren't generic. In any case, the container of that
4279 * nested type would be the generic type definition.
4281 if (klass->generic_class)
4282 klass = klass->generic_class->container_class;
4284 mono_ptr_array_init (tmp_array, 1);
4285 iter = NULL;
4286 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4287 match = 0;
4288 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4289 if (bflags & BFLAGS_Public)
4290 match++;
4291 } else {
4292 if (bflags & BFLAGS_NonPublic)
4293 match++;
4295 if (!match)
4296 continue;
4297 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4298 mono_ptr_array_append (tmp_array, member);
4301 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4303 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4304 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4306 mono_ptr_array_destroy (tmp_array);
4308 return res;
4311 static MonoReflectionType*
4312 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4314 gchar *str;
4315 MonoType *type = NULL;
4316 MonoTypeNameParse info;
4317 gboolean type_resolve;
4319 MONO_ARCH_SAVE_REGS;
4321 /* On MS.NET, this does not fire a TypeResolve event */
4322 type_resolve = TRUE;
4323 str = mono_string_to_utf8 (name);
4324 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4325 if (!mono_reflection_parse_type (str, &info)) {
4326 g_free (str);
4327 mono_reflection_free_type_info (&info);
4328 if (throwOnError) /* uhm: this is a parse error, though... */
4329 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4330 /*g_print ("failed parse\n");*/
4331 return NULL;
4334 if (info.assembly.name) {
4335 g_free (str);
4336 mono_reflection_free_type_info (&info);
4337 if (throwOnError) {
4338 /* 1.0 and 2.0 throw different exceptions */
4339 if (mono_defaults.generic_ilist_class)
4340 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4341 else
4342 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4344 return NULL;
4347 if (module != NULL) {
4348 if (module->image)
4349 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4350 else
4351 type = NULL;
4353 else
4354 if (assembly->assembly->dynamic) {
4355 /* Enumerate all modules */
4356 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4357 int i;
4359 type = NULL;
4360 if (abuilder->modules) {
4361 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4362 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4363 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4364 if (type)
4365 break;
4369 if (!type && abuilder->loaded_modules) {
4370 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4371 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4372 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4373 if (type)
4374 break;
4378 else
4379 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4380 g_free (str);
4381 mono_reflection_free_type_info (&info);
4382 if (!type) {
4383 MonoException *e = NULL;
4385 if (throwOnError)
4386 e = mono_get_exception_type_load (name, NULL);
4388 mono_loader_clear_error ();
4390 if (e != NULL)
4391 mono_raise_exception (e);
4393 return NULL;
4396 if (type->type == MONO_TYPE_CLASS) {
4397 MonoClass *klass = mono_type_get_class (type);
4399 if (mono_is_security_manager_active () && !klass->exception_type)
4400 /* Some security problems are detected during generic vtable construction */
4401 mono_class_setup_vtable (klass);
4402 /* need to report exceptions ? */
4403 if (throwOnError && klass->exception_type) {
4404 /* report SecurityException (or others) that occured when loading the assembly */
4405 MonoException *exc = mono_class_get_exception_for_failure (klass);
4406 mono_loader_clear_error ();
4407 mono_raise_exception (exc);
4408 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4409 return NULL;
4413 /* g_print ("got it\n"); */
4414 return mono_type_get_object (mono_object_domain (assembly), type);
4417 static gboolean
4418 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4420 gchar *content;
4421 gchar *shadow_ini_file;
4422 gsize len;
4424 /* Check for shadow-copied assembly */
4425 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4426 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4427 content = NULL;
4428 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4429 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4430 if (content) {
4431 g_free (content);
4432 content = NULL;
4435 g_free (shadow_ini_file);
4436 if (content != NULL) {
4437 if (*filename)
4438 g_free (*filename);
4439 *filename = content;
4440 return TRUE;
4443 return FALSE;
4446 static MonoString *
4447 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4449 MonoDomain *domain = mono_object_domain (assembly);
4450 MonoAssembly *mass = assembly->assembly;
4451 MonoString *res = NULL;
4452 gchar *uri;
4453 gchar *absolute;
4454 gchar *dirname;
4456 MONO_ARCH_SAVE_REGS;
4458 if (g_path_is_absolute (mass->image->name)) {
4459 absolute = g_strdup (mass->image->name);
4460 dirname = g_path_get_dirname (absolute);
4461 } else {
4462 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4463 dirname = g_strdup (mass->basedir);
4466 replace_shadow_path (domain, dirname, &absolute);
4467 g_free (dirname);
4468 #if PLATFORM_WIN32
4470 gint i;
4471 for (i = strlen (absolute) - 1; i >= 0; i--)
4472 if (absolute [i] == '\\')
4473 absolute [i] = '/';
4475 #endif
4476 if (escaped) {
4477 uri = g_filename_to_uri (absolute, NULL, NULL);
4478 } else {
4479 const char *prepend = "file://";
4480 #if PLATFORM_WIN32
4481 if (*absolute == '/' && *(absolute + 1) == '/') {
4482 prepend = "file:";
4483 } else {
4484 prepend = "file:///";
4486 #endif
4487 uri = g_strconcat (prepend, absolute, NULL);
4490 if (uri) {
4491 res = mono_string_new (domain, uri);
4492 g_free (uri);
4494 g_free (absolute);
4495 return res;
4498 static MonoBoolean
4499 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4501 MonoAssembly *mass = assembly->assembly;
4503 MONO_ARCH_SAVE_REGS;
4505 return mass->in_gac;
4508 static MonoReflectionAssembly*
4509 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4511 gchar *name;
4512 MonoAssembly *res;
4513 MonoImageOpenStatus status;
4515 MONO_ARCH_SAVE_REGS;
4517 name = mono_string_to_utf8 (mname);
4518 res = mono_assembly_load_with_partial_name (name, &status);
4520 g_free (name);
4522 if (res == NULL)
4523 return NULL;
4524 return mono_assembly_get_object (mono_domain_get (), res);
4527 static MonoString *
4528 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4530 MonoDomain *domain = mono_object_domain (assembly);
4531 MonoString *res;
4533 MONO_ARCH_SAVE_REGS;
4535 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4537 return res;
4540 static MonoBoolean
4541 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4543 MONO_ARCH_SAVE_REGS;
4545 return assembly->assembly->ref_only;
4548 static MonoString *
4549 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4551 MonoDomain *domain = mono_object_domain (assembly);
4553 MONO_ARCH_SAVE_REGS;
4555 return mono_string_new (domain, assembly->assembly->image->version);
4558 static MonoReflectionMethod*
4559 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4561 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4563 MONO_ARCH_SAVE_REGS;
4565 if (!token)
4566 return NULL;
4567 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4570 static MonoReflectionModule*
4571 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4573 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4576 static MonoArray*
4577 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4579 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4580 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4581 int i;
4582 const char *val;
4584 MONO_ARCH_SAVE_REGS;
4586 for (i = 0; i < table->rows; ++i) {
4587 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4588 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4590 return result;
4593 static MonoObject*
4594 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4596 static MonoClass *System_Version = NULL;
4597 static MonoMethod *create_version = NULL;
4598 MonoObject *result;
4599 gpointer args [4];
4601 if (!System_Version) {
4602 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4603 g_assert (System_Version);
4606 if (!create_version) {
4607 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4608 create_version = mono_method_desc_search_in_class (desc, System_Version);
4609 g_assert (create_version);
4610 mono_method_desc_free (desc);
4613 args [0] = &major;
4614 args [1] = &minor;
4615 args [2] = &build;
4616 args [3] = &revision;
4617 result = mono_object_new (domain, System_Version);
4618 mono_runtime_invoke (create_version, result, args, NULL);
4620 return result;
4623 static MonoArray*
4624 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4626 static MonoClass *System_Reflection_AssemblyName;
4627 MonoArray *result;
4628 MonoDomain *domain = mono_object_domain (assembly);
4629 int i, count = 0;
4630 static MonoMethod *create_culture = NULL;
4631 MonoImage *image = assembly->assembly->image;
4632 MonoTableInfo *t;
4634 MONO_ARCH_SAVE_REGS;
4636 if (!System_Reflection_AssemblyName)
4637 System_Reflection_AssemblyName = mono_class_from_name (
4638 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4640 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4641 count = t->rows;
4643 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4645 if (count > 0 && !create_culture) {
4646 MonoMethodDesc *desc = mono_method_desc_new (
4647 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4648 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4649 g_assert (create_culture);
4650 mono_method_desc_free (desc);
4653 for (i = 0; i < count; i++) {
4654 MonoReflectionAssemblyName *aname;
4655 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4657 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4659 aname = (MonoReflectionAssemblyName *) mono_object_new (
4660 domain, System_Reflection_AssemblyName);
4662 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4664 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4665 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4666 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4667 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4668 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4669 aname->versioncompat = 1; /* SameMachine (default) */
4670 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4671 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4673 if (create_culture) {
4674 gpointer args [2];
4675 MonoBoolean assembly_ref = 1;
4676 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4677 args [1] = &assembly_ref;
4678 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4681 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4682 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4683 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4685 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4686 /* public key token isn't copied - the class library will
4687 automatically generate it from the public key if required */
4688 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4689 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4690 } else {
4691 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4692 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4694 } else {
4695 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4698 /* note: this function doesn't return the codebase on purpose (i.e. it can
4699 be used under partial trust as path information isn't present). */
4701 mono_array_setref (result, i, aname);
4703 return result;
4706 typedef struct {
4707 MonoArray *res;
4708 int idx;
4709 } NameSpaceInfo;
4711 static void
4712 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4714 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4716 mono_array_setref (info->res, info->idx, name);
4717 info->idx++;
4720 static MonoArray*
4721 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4723 MonoImage *img = assembly->assembly->image;
4724 MonoArray *res;
4725 NameSpaceInfo info;
4727 MONO_ARCH_SAVE_REGS;
4729 if (!img->name_cache)
4730 mono_image_init_name_cache (img);
4732 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4733 info.res = res;
4734 info.idx = 0;
4735 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4737 return res;
4740 /* move this in some file in mono/util/ */
4741 static char *
4742 g_concat_dir_and_file (const char *dir, const char *file)
4744 g_return_val_if_fail (dir != NULL, NULL);
4745 g_return_val_if_fail (file != NULL, NULL);
4748 * If the directory name doesn't have a / on the end, we need
4749 * to add one so we get a proper path to the file
4751 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4752 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4753 else
4754 return g_strconcat (dir, file, NULL);
4757 static void *
4758 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4760 char *n = mono_string_to_utf8 (name);
4761 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4762 guint32 i;
4763 guint32 cols [MONO_MANIFEST_SIZE];
4764 guint32 impl, file_idx;
4765 const char *val;
4766 MonoImage *module;
4768 MONO_ARCH_SAVE_REGS;
4770 for (i = 0; i < table->rows; ++i) {
4771 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4772 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4773 if (strcmp (val, n) == 0)
4774 break;
4776 g_free (n);
4777 if (i == table->rows)
4778 return NULL;
4779 /* FIXME */
4780 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4781 if (impl) {
4783 * this code should only be called after obtaining the
4784 * ResourceInfo and handling the other cases.
4786 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4787 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4789 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4790 if (!module)
4791 return NULL;
4793 else
4794 module = assembly->assembly->image;
4796 *ref_module = mono_module_get_object (mono_domain_get (), module);
4798 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4801 static gboolean
4802 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4804 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4805 int i;
4806 guint32 cols [MONO_MANIFEST_SIZE];
4807 guint32 file_cols [MONO_FILE_SIZE];
4808 const char *val;
4809 char *n;
4811 MONO_ARCH_SAVE_REGS;
4813 n = mono_string_to_utf8 (name);
4814 for (i = 0; i < table->rows; ++i) {
4815 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4816 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4817 if (strcmp (val, n) == 0)
4818 break;
4820 g_free (n);
4821 if (i == table->rows)
4822 return FALSE;
4824 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4825 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4827 else {
4828 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4829 case MONO_IMPLEMENTATION_FILE:
4830 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4831 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4832 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4833 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4834 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4835 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4836 info->location = 0;
4837 else
4838 info->location = RESOURCE_LOCATION_EMBEDDED;
4839 break;
4841 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4842 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4843 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4844 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4845 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4846 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4847 g_free (msg);
4848 mono_raise_exception (ex);
4850 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4852 /* Obtain info recursively */
4853 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4854 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4855 break;
4857 case MONO_IMPLEMENTATION_EXP_TYPE:
4858 g_assert_not_reached ();
4859 break;
4863 return TRUE;
4866 static MonoObject*
4867 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4869 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4870 MonoArray *result = NULL;
4871 int i, count;
4872 const char *val;
4873 char *n;
4875 MONO_ARCH_SAVE_REGS;
4877 /* check hash if needed */
4878 if (name) {
4879 n = mono_string_to_utf8 (name);
4880 for (i = 0; i < table->rows; ++i) {
4881 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4882 if (strcmp (val, n) == 0) {
4883 MonoString *fn;
4884 g_free (n);
4885 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4886 fn = mono_string_new (mono_object_domain (assembly), n);
4887 g_free (n);
4888 return (MonoObject*)fn;
4891 g_free (n);
4892 return NULL;
4895 count = 0;
4896 for (i = 0; i < table->rows; ++i) {
4897 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4898 count ++;
4901 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4903 count = 0;
4904 for (i = 0; i < table->rows; ++i) {
4905 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4906 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4907 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4908 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4909 g_free (n);
4910 count ++;
4913 return (MonoObject*)result;
4916 static MonoArray*
4917 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4919 MonoDomain *domain = mono_domain_get();
4920 MonoArray *res;
4921 MonoClass *klass;
4922 int i, j, file_count = 0;
4923 MonoImage **modules;
4924 guint32 module_count, real_module_count;
4925 MonoTableInfo *table;
4926 guint32 cols [MONO_FILE_SIZE];
4927 MonoImage *image = assembly->assembly->image;
4929 g_assert (image != NULL);
4930 g_assert (!assembly->assembly->dynamic);
4932 table = &image->tables [MONO_TABLE_FILE];
4933 file_count = table->rows;
4935 modules = image->modules;
4936 module_count = image->module_count;
4938 real_module_count = 0;
4939 for (i = 0; i < module_count; ++i)
4940 if (modules [i])
4941 real_module_count ++;
4943 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4944 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4946 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4947 j = 1;
4948 for (i = 0; i < module_count; ++i)
4949 if (modules [i]) {
4950 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4951 ++j;
4954 for (i = 0; i < file_count; ++i, ++j) {
4955 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4956 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4957 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4958 else {
4959 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4960 if (!m) {
4961 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4962 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4964 mono_array_setref (res, j, mono_module_get_object (domain, m));
4968 return res;
4971 static MonoReflectionMethod*
4972 ves_icall_GetCurrentMethod (void)
4974 MonoMethod *m = mono_method_get_last_managed ();
4976 MONO_ARCH_SAVE_REGS;
4978 return mono_method_get_object (mono_domain_get (), m, NULL);
4982 static MonoMethod*
4983 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4985 int offset = -1, i;
4986 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4987 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4988 //method is inflated, we should inflate it on the other class
4989 MonoGenericContext ctx;
4990 ctx.method_inst = inflated->context.method_inst;
4991 ctx.class_inst = inflated->context.class_inst;
4992 if (klass->generic_class)
4993 ctx.class_inst = klass->generic_class->context.class_inst;
4994 else if (klass->generic_container)
4995 ctx.class_inst = klass->generic_container->context.class_inst;
4996 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4999 mono_class_setup_methods (method->klass);
5000 for (i = 0; i < method->klass->method.count; ++i) {
5001 if (method->klass->methods [i] == method) {
5002 offset = i;
5003 break;
5006 mono_class_setup_methods (klass);
5007 g_assert (offset >= 0 && offset < klass->method.count);
5008 return klass->methods [offset];
5011 static MonoReflectionMethod*
5012 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5014 MonoClass *klass;
5015 if (type) {
5016 klass = mono_class_from_mono_type (type);
5017 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5018 return NULL;
5019 if (method->klass != klass)
5020 method = mono_method_get_equivalent_method (method, klass);
5021 } else
5022 klass = method->klass;
5023 return mono_method_get_object (mono_domain_get (), method, klass);
5026 static MonoReflectionMethod*
5027 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
5029 return mono_method_get_object (mono_domain_get (), method, NULL);
5032 static MonoReflectionMethodBody*
5033 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5035 return mono_method_body_get_object (mono_domain_get (), method);
5038 static MonoReflectionAssembly*
5039 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5041 MonoMethod *dest = NULL;
5043 MONO_ARCH_SAVE_REGS;
5045 mono_stack_walk_no_il (get_executing, &dest);
5046 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5050 static MonoReflectionAssembly*
5051 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5053 MonoDomain* domain = mono_domain_get ();
5055 MONO_ARCH_SAVE_REGS;
5057 if (!domain->entry_assembly)
5058 return NULL;
5060 return mono_assembly_get_object (domain, domain->entry_assembly);
5063 static MonoReflectionAssembly*
5064 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5066 MonoMethod *m;
5067 MonoMethod *dest;
5069 MONO_ARCH_SAVE_REGS;
5071 dest = NULL;
5072 mono_stack_walk_no_il (get_executing, &dest);
5073 m = dest;
5074 mono_stack_walk_no_il (get_caller, &dest);
5075 if (!dest)
5076 dest = m;
5077 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5080 static MonoString *
5081 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5082 gboolean assembly_qualified)
5084 MonoDomain *domain = mono_object_domain (object);
5085 MonoTypeNameFormat format;
5086 MonoString *res;
5087 gchar *name;
5089 MONO_ARCH_SAVE_REGS;
5090 if (full_name)
5091 format = assembly_qualified ?
5092 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5093 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5094 else
5095 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5097 name = mono_type_get_name_full (object->type, format);
5098 if (!name)
5099 return NULL;
5101 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5102 g_free (name);
5103 return NULL;
5106 res = mono_string_new (domain, name);
5107 g_free (name);
5109 return res;
5112 static void
5113 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5115 static MonoMethod *create_culture = NULL;
5116 gpointer args [2];
5117 guint32 pkey_len;
5118 const char *pkey_ptr;
5119 gchar *codebase;
5120 MonoBoolean assembly_ref = 0;
5122 MONO_ARCH_SAVE_REGS;
5124 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5125 aname->major = name->major;
5126 aname->minor = name->minor;
5127 aname->build = name->build;
5128 aname->flags = name->flags;
5129 aname->revision = name->revision;
5130 aname->hashalg = name->hash_alg;
5131 aname->versioncompat = 1; /* SameMachine (default) */
5133 if (by_default_version)
5134 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5136 codebase = NULL;
5137 if (absolute != NULL && *absolute != '\0') {
5138 const gchar *prepend = "file://";
5139 gchar *result;
5141 codebase = g_strdup (absolute);
5143 #if PLATFORM_WIN32
5145 gint i;
5146 for (i = strlen (codebase) - 1; i >= 0; i--)
5147 if (codebase [i] == '\\')
5148 codebase [i] = '/';
5150 if (*codebase == '/' && *(codebase + 1) == '/') {
5151 prepend = "file:";
5152 } else {
5153 prepend = "file:///";
5156 #endif
5157 result = g_strconcat (prepend, codebase, NULL);
5158 g_free (codebase);
5159 codebase = result;
5162 if (codebase) {
5163 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5164 g_free (codebase);
5167 if (!create_culture) {
5168 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5169 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5170 g_assert (create_culture);
5171 mono_method_desc_free (desc);
5174 if (name->culture) {
5175 args [0] = mono_string_new (domain, name->culture);
5176 args [1] = &assembly_ref;
5177 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5180 if (name->public_key) {
5181 pkey_ptr = (char*)name->public_key;
5182 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5184 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5185 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5186 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5187 } else if (default_publickey) {
5188 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5189 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5192 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5193 if (name->public_key_token [0]) {
5194 int i, j;
5195 char *p;
5197 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5198 p = mono_array_addr (aname->keyToken, char, 0);
5200 for (i = 0, j = 0; i < 8; i++) {
5201 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5202 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5203 p++;
5205 } else if (default_token) {
5206 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5210 static MonoString *
5211 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5213 MonoDomain *domain = mono_object_domain (assembly);
5214 MonoAssembly *mass = assembly->assembly;
5215 MonoString *res;
5216 gchar *name;
5218 name = g_strdup_printf (
5219 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5220 mass->aname.name,
5221 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5222 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5223 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5224 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5226 res = mono_string_new (domain, name);
5227 g_free (name);
5229 return res;
5232 static void
5233 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5235 gchar *absolute;
5236 MonoAssembly *mass = assembly->assembly;
5238 MONO_ARCH_SAVE_REGS;
5240 if (g_path_is_absolute (mass->image->name)) {
5241 fill_reflection_assembly_name (mono_object_domain (assembly),
5242 aname, &mass->aname, mass->image->name, TRUE,
5243 TRUE, mono_framework_version () >= 2);
5244 return;
5246 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5248 fill_reflection_assembly_name (mono_object_domain (assembly),
5249 aname, &mass->aname, absolute, TRUE, TRUE,
5250 mono_framework_version () >= 2);
5252 g_free (absolute);
5255 static void
5256 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5258 char *filename;
5259 MonoImageOpenStatus status = MONO_IMAGE_OK;
5260 gboolean res;
5261 MonoImage *image;
5262 MonoAssemblyName name;
5263 char *dirname
5265 MONO_ARCH_SAVE_REGS;
5267 filename = mono_string_to_utf8 (fname);
5269 dirname = g_path_get_dirname (filename);
5270 replace_shadow_path (mono_domain_get (), dirname, &filename);
5271 g_free (dirname);
5273 image = mono_image_open (filename, &status);
5275 if (!image){
5276 MonoException *exc;
5278 g_free (filename);
5279 if (status == MONO_IMAGE_IMAGE_INVALID)
5280 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5281 else
5282 exc = mono_get_exception_file_not_found2 (NULL, fname);
5283 mono_raise_exception (exc);
5286 res = mono_assembly_fill_assembly_name (image, &name);
5287 if (!res) {
5288 mono_image_close (image);
5289 g_free (filename);
5290 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5293 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5294 TRUE, mono_framework_version () == 1,
5295 mono_framework_version () >= 2);
5297 g_free (filename);
5298 mono_image_close (image);
5301 static MonoBoolean
5302 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5303 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5305 MonoBoolean result = FALSE;
5306 MonoDeclSecurityEntry entry;
5308 /* SecurityAction.RequestMinimum */
5309 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5310 *minimum = entry.blob;
5311 *minLength = entry.size;
5312 result = TRUE;
5314 /* SecurityAction.RequestOptional */
5315 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5316 *optional = entry.blob;
5317 *optLength = entry.size;
5318 result = TRUE;
5320 /* SecurityAction.RequestRefuse */
5321 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5322 *refused = entry.blob;
5323 *refLength = entry.size;
5324 result = TRUE;
5327 return result;
5330 static MonoArray*
5331 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5333 MonoArray *res;
5334 MonoClass *klass;
5335 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5336 int i, count;
5337 guint32 attrs, visibility;
5339 /* we start the count from 1 because we skip the special type <Module> */
5340 if (exportedOnly) {
5341 count = 0;
5342 for (i = 1; i < tdef->rows; ++i) {
5343 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5344 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5345 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5346 count++;
5348 } else {
5349 count = tdef->rows - 1;
5351 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5352 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5353 count = 0;
5354 for (i = 1; i < tdef->rows; ++i) {
5355 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5356 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5357 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5358 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5359 if (klass) {
5360 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5361 } else {
5362 MonoLoaderError *error;
5363 MonoException *ex;
5365 error = mono_loader_get_last_error ();
5366 g_assert (error != NULL);
5368 ex = mono_loader_error_prepare_exception (error);
5369 mono_array_setref (*exceptions, count, ex);
5371 if (mono_loader_get_last_error ())
5372 mono_loader_clear_error ();
5373 count++;
5377 return res;
5380 static MonoArray*
5381 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5383 MonoArray *res = NULL;
5384 MonoArray *exceptions = NULL;
5385 MonoImage *image = NULL;
5386 MonoTableInfo *table = NULL;
5387 MonoDomain *domain;
5388 GList *list = NULL;
5389 int i, len, ex_count;
5391 MONO_ARCH_SAVE_REGS;
5393 domain = mono_object_domain (assembly);
5395 g_assert (!assembly->assembly->dynamic);
5396 image = assembly->assembly->image;
5397 table = &image->tables [MONO_TABLE_FILE];
5398 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5400 /* Append data from all modules in the assembly */
5401 for (i = 0; i < table->rows; ++i) {
5402 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5403 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5404 if (loaded_image) {
5405 MonoArray *ex2;
5406 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5407 /* Append the new types to the end of the array */
5408 if (mono_array_length (res2) > 0) {
5409 guint32 len1, len2;
5410 MonoArray *res3, *ex3;
5412 len1 = mono_array_length (res);
5413 len2 = mono_array_length (res2);
5415 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5416 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5417 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5418 res = res3;
5420 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5421 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5422 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5423 exceptions = ex3;
5429 /* the ReflectionTypeLoadException must have all the types (Types property),
5430 * NULL replacing types which throws an exception. The LoaderException must
5431 * contain all exceptions for NULL items.
5434 len = mono_array_length (res);
5436 ex_count = 0;
5437 for (i = 0; i < len; i++) {
5438 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5439 MonoClass *klass;
5441 if (t) {
5442 klass = mono_type_get_class (t->type);
5443 if ((klass != NULL) && klass->exception_type) {
5444 /* keep the class in the list */
5445 list = g_list_append (list, klass);
5446 /* and replace Type with NULL */
5447 mono_array_setref (res, i, NULL);
5449 } else {
5450 ex_count ++;
5454 if (list || ex_count) {
5455 GList *tmp = NULL;
5456 MonoException *exc = NULL;
5457 MonoArray *exl = NULL;
5458 int j, length = g_list_length (list) + ex_count;
5460 mono_loader_clear_error ();
5462 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5463 /* Types for which mono_class_get () succeeded */
5464 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5465 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5466 mono_array_setref (exl, i, exc);
5468 /* Types for which it don't */
5469 for (j = 0; j < mono_array_length (exceptions); ++j) {
5470 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5471 if (exc) {
5472 g_assert (i < length);
5473 mono_array_setref (exl, i, exc);
5474 i ++;
5477 g_list_free (list);
5478 list = NULL;
5480 exc = mono_get_exception_reflection_type_load (res, exl);
5481 mono_loader_clear_error ();
5482 mono_raise_exception (exc);
5485 return res;
5488 static gboolean
5489 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5491 MonoAssemblyName aname;
5492 MonoDomain *domain = mono_object_domain (name);
5493 char *val;
5494 gboolean is_version_defined;
5495 gboolean is_token_defined;
5497 aname.public_key = NULL;
5498 val = mono_string_to_utf8 (assname);
5499 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5500 g_free ((guint8*) aname.public_key);
5501 g_free (val);
5502 return FALSE;
5505 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5506 FALSE, is_token_defined);
5508 mono_assembly_name_free (&aname);
5509 g_free ((guint8*) aname.public_key);
5510 g_free (val);
5512 return TRUE;
5515 static MonoReflectionType*
5516 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5518 MonoDomain *domain = mono_object_domain (module);
5519 MonoClass *klass;
5521 MONO_ARCH_SAVE_REGS;
5523 g_assert (module->image);
5525 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5526 /* These images do not have a global type */
5527 return NULL;
5529 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5530 return mono_type_get_object (domain, &klass->byval_arg);
5533 static void
5534 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5536 /*if (module->image)
5537 mono_image_close (module->image);*/
5540 static MonoString*
5541 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5543 MonoDomain *domain = mono_object_domain (module);
5545 MONO_ARCH_SAVE_REGS;
5547 g_assert (module->image);
5548 return mono_string_new (domain, module->image->guid);
5551 static gpointer
5552 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5554 #ifdef PLATFORM_WIN32
5555 if (module->image && module->image->is_module_handle)
5556 return module->image->raw_data;
5557 #endif
5559 return (gpointer) (-1);
5562 static void
5563 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5565 if (image->dynamic) {
5566 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5567 *pe_kind = dyn->pe_kind;
5568 *machine = dyn->machine;
5570 else {
5571 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5572 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5576 static gint32
5577 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5579 return (image->md_version_major << 16) | (image->md_version_minor);
5582 static MonoArray*
5583 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5585 MonoArray *exceptions;
5586 int i;
5588 MONO_ARCH_SAVE_REGS;
5590 if (!module->image)
5591 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5592 else {
5593 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5594 for (i = 0; i < mono_array_length (exceptions); ++i) {
5595 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5596 if (ex)
5597 mono_raise_exception (ex);
5599 return res;
5603 static gboolean
5604 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5606 guint32 cols [MONO_MEMBERREF_SIZE];
5607 const char *sig;
5608 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5609 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5610 mono_metadata_decode_blob_size (sig, &sig);
5611 return (*sig != 0x6);
5614 static void
5615 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5617 if (type_args)
5618 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5619 mono_array_addr (type_args, MonoType*, 0));
5620 else
5621 context->class_inst = NULL;
5622 if (method_args)
5623 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5624 mono_array_addr (method_args, MonoType*, 0));
5625 else
5626 context->method_inst = NULL;
5629 static MonoType*
5630 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5632 MonoClass *klass;
5633 int table = mono_metadata_token_table (token);
5634 int index = mono_metadata_token_index (token);
5635 MonoGenericContext context;
5637 *error = ResolveTokenError_Other;
5639 /* Validate token */
5640 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5641 (table != MONO_TABLE_TYPESPEC)) {
5642 *error = ResolveTokenError_BadTable;
5643 return NULL;
5646 if (image->dynamic) {
5647 if (type_args || method_args)
5648 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5649 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5650 if (!klass)
5651 return NULL;
5652 return &klass->byval_arg;
5655 if ((index <= 0) || (index > image->tables [table].rows)) {
5656 *error = ResolveTokenError_OutOfRange;
5657 return NULL;
5660 init_generic_context_from_args (&context, type_args, method_args);
5661 klass = mono_class_get_full (image, token, &context);
5663 if (mono_loader_get_last_error ())
5664 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5666 if (klass)
5667 return &klass->byval_arg;
5668 else
5669 return NULL;
5672 static MonoMethod*
5673 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5675 int table = mono_metadata_token_table (token);
5676 int index = mono_metadata_token_index (token);
5677 MonoGenericContext context;
5678 MonoMethod *method;
5680 *error = ResolveTokenError_Other;
5682 /* Validate token */
5683 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5684 (table != MONO_TABLE_MEMBERREF)) {
5685 *error = ResolveTokenError_BadTable;
5686 return NULL;
5689 if (image->dynamic) {
5690 if (type_args || method_args)
5691 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5692 /* FIXME: validate memberref token type */
5693 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5696 if ((index <= 0) || (index > image->tables [table].rows)) {
5697 *error = ResolveTokenError_OutOfRange;
5698 return NULL;
5700 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5701 *error = ResolveTokenError_BadTable;
5702 return NULL;
5705 init_generic_context_from_args (&context, type_args, method_args);
5706 method = mono_get_method_full (image, token, NULL, &context);
5708 if (mono_loader_get_last_error ())
5709 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5711 return method;
5714 static MonoString*
5715 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5717 int index = mono_metadata_token_index (token);
5719 *error = ResolveTokenError_Other;
5721 /* Validate token */
5722 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5723 *error = ResolveTokenError_BadTable;
5724 return NULL;
5727 if (image->dynamic)
5728 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5730 if ((index <= 0) || (index >= image->heap_us.size)) {
5731 *error = ResolveTokenError_OutOfRange;
5732 return NULL;
5735 /* FIXME: What to do if the index points into the middle of a string ? */
5737 return mono_ldstr (mono_domain_get (), image, index);
5740 static MonoClassField*
5741 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5743 MonoClass *klass;
5744 int table = mono_metadata_token_table (token);
5745 int index = mono_metadata_token_index (token);
5746 MonoGenericContext context;
5747 MonoClassField *field;
5749 *error = ResolveTokenError_Other;
5751 /* Validate token */
5752 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5753 *error = ResolveTokenError_BadTable;
5754 return NULL;
5757 if (image->dynamic) {
5758 if (type_args || method_args)
5759 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5760 /* FIXME: validate memberref token type */
5761 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5764 if ((index <= 0) || (index > image->tables [table].rows)) {
5765 *error = ResolveTokenError_OutOfRange;
5766 return NULL;
5768 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5769 *error = ResolveTokenError_BadTable;
5770 return NULL;
5773 init_generic_context_from_args (&context, type_args, method_args);
5774 field = mono_field_from_token (image, token, &klass, &context);
5776 if (mono_loader_get_last_error ())
5777 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5779 return field;
5783 static MonoObject*
5784 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5786 int table = mono_metadata_token_table (token);
5788 *error = ResolveTokenError_Other;
5790 switch (table) {
5791 case MONO_TABLE_TYPEDEF:
5792 case MONO_TABLE_TYPEREF:
5793 case MONO_TABLE_TYPESPEC: {
5794 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5795 if (t)
5796 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5797 else
5798 return NULL;
5800 case MONO_TABLE_METHOD:
5801 case MONO_TABLE_METHODSPEC: {
5802 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5803 if (m)
5804 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5805 else
5806 return NULL;
5808 case MONO_TABLE_FIELD: {
5809 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5810 if (f)
5811 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5812 else
5813 return NULL;
5815 case MONO_TABLE_MEMBERREF:
5816 if (mono_metadata_memberref_is_method (image, token)) {
5817 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5818 if (m)
5819 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5820 else
5821 return NULL;
5823 else {
5824 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5825 if (f)
5826 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5827 else
5828 return NULL;
5830 break;
5832 default:
5833 *error = ResolveTokenError_BadTable;
5836 return NULL;
5839 static MonoArray*
5840 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5842 int table = mono_metadata_token_table (token);
5843 int idx = mono_metadata_token_index (token);
5844 MonoTableInfo *tables = image->tables;
5845 guint32 sig, len;
5846 const char *ptr;
5847 MonoArray *res;
5849 *error = ResolveTokenError_OutOfRange;
5851 /* FIXME: Support other tables ? */
5852 if (table != MONO_TABLE_STANDALONESIG)
5853 return NULL;
5855 if (image->dynamic)
5856 return NULL;
5858 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5859 return NULL;
5861 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5863 ptr = mono_metadata_blob_heap (image, sig);
5864 len = mono_metadata_decode_blob_size (ptr, &ptr);
5866 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5867 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5868 return res;
5871 static MonoReflectionType*
5872 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5874 MonoClass *klass;
5875 int isbyref = 0, rank;
5876 char *str = mono_string_to_utf8 (smodifiers);
5877 char *p;
5879 MONO_ARCH_SAVE_REGS;
5881 klass = mono_class_from_mono_type (tb->type.type);
5882 p = str;
5883 /* logic taken from mono_reflection_parse_type(): keep in sync */
5884 while (*p) {
5885 switch (*p) {
5886 case '&':
5887 if (isbyref) { /* only one level allowed by the spec */
5888 g_free (str);
5889 return NULL;
5891 isbyref = 1;
5892 p++;
5893 g_free (str);
5894 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5895 break;
5896 case '*':
5897 klass = mono_ptr_class_get (&klass->byval_arg);
5898 mono_class_init (klass);
5899 p++;
5900 break;
5901 case '[':
5902 rank = 1;
5903 p++;
5904 while (*p) {
5905 if (*p == ']')
5906 break;
5907 if (*p == ',')
5908 rank++;
5909 else if (*p != '*') { /* '*' means unknown lower bound */
5910 g_free (str);
5911 return NULL;
5913 ++p;
5915 if (*p != ']') {
5916 g_free (str);
5917 return NULL;
5919 p++;
5920 klass = mono_array_class_get (klass, rank);
5921 mono_class_init (klass);
5922 break;
5923 default:
5924 break;
5927 g_free (str);
5928 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5931 static MonoBoolean
5932 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5934 MonoType *type;
5935 MonoBoolean res;
5937 MONO_ARCH_SAVE_REGS;
5939 type = t->type;
5940 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5942 return res;
5945 static MonoReflectionType *
5946 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5948 MonoClass *klass, *aklass;
5950 MONO_ARCH_SAVE_REGS;
5952 klass = mono_class_from_mono_type (type->type);
5953 aklass = mono_array_class_get (klass, rank);
5955 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5958 static MonoReflectionType *
5959 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5961 MonoClass *klass;
5963 MONO_ARCH_SAVE_REGS;
5965 klass = mono_class_from_mono_type (type->type);
5967 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5970 static MonoReflectionType *
5971 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5973 MonoClass *pklass;
5975 MONO_ARCH_SAVE_REGS;
5977 pklass = mono_ptr_class_get (type->type);
5979 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5982 static MonoObject *
5983 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5984 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5986 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5987 MonoObject *delegate;
5988 gpointer func;
5989 MonoMethod *method = info->method;
5991 MONO_ARCH_SAVE_REGS;
5993 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5995 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5996 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5997 return NULL;
6000 delegate = mono_object_new (mono_object_domain (type), delegate_class);
6002 if (mono_method_needs_static_rgctx_invoke (method, FALSE)) {
6003 method = mono_marshal_get_static_rgctx_invoke (method);
6004 func = mono_compile_method (method);
6005 } else if (method->dynamic) {
6006 /* Creating a trampoline would leak memory */
6007 func = mono_compile_method (method);
6008 } else {
6009 func = mono_create_ftnptr (mono_domain_get (),
6010 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6013 mono_delegate_ctor_with_method (delegate, target, func, method);
6015 return delegate;
6018 static void
6019 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
6021 /* Reset the invoke impl to the default one */
6022 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
6026 * Magic number to convert a time which is relative to
6027 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
6029 #define EPOCH_ADJUST ((guint64)62135596800LL)
6032 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
6034 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
6036 #ifdef PLATFORM_WIN32
6037 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
6038 static void
6039 convert_to_absolute_date(SYSTEMTIME *date)
6041 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
6042 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6043 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6044 /* from the calendar FAQ */
6045 int a = (14 - date->wMonth) / 12;
6046 int y = date->wYear - a;
6047 int m = date->wMonth + 12 * a - 2;
6048 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
6050 /* d is now the day of the week for the first of the month (0 == Sunday) */
6052 int day_of_week = date->wDayOfWeek;
6054 /* set day_in_month to the first day in the month which falls on day_of_week */
6055 int day_in_month = 1 + (day_of_week - d);
6056 if (day_in_month <= 0)
6057 day_in_month += 7;
6059 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
6060 date->wDay = day_in_month + (date->wDay - 1) * 7;
6061 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6062 date->wDay -= 7;
6064 #endif
6066 #ifndef PLATFORM_WIN32
6068 * Return's the offset from GMT of a local time.
6070 * tm is a local time
6071 * t is the same local time as seconds.
6073 static int
6074 gmt_offset(struct tm *tm, time_t t)
6076 #if defined (HAVE_TM_GMTOFF)
6077 return tm->tm_gmtoff;
6078 #else
6079 struct tm g;
6080 time_t t2;
6081 g = *gmtime(&t);
6082 g.tm_isdst = tm->tm_isdst;
6083 t2 = mktime(&g);
6084 return (int)difftime(t, t2);
6085 #endif
6087 #endif
6089 * This is heavily based on zdump.c from glibc 2.2.
6091 * * data[0]: start of daylight saving time (in DateTime ticks).
6092 * * data[1]: end of daylight saving time (in DateTime ticks).
6093 * * data[2]: utcoffset (in TimeSpan ticks).
6094 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
6095 * * name[0]: name of this timezone when not daylight saving.
6096 * * name[1]: name of this timezone when daylight saving.
6098 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6099 * the class library allows years between 1 and 9999.
6101 * Returns true on success and zero on failure.
6103 static guint32
6104 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6106 #ifndef PLATFORM_WIN32
6107 MonoDomain *domain = mono_domain_get ();
6108 struct tm start, tt;
6109 time_t t;
6111 long int gmtoff;
6112 int is_daylight = 0, day;
6113 char tzone [64];
6115 MONO_ARCH_SAVE_REGS;
6117 MONO_CHECK_ARG_NULL (data);
6118 MONO_CHECK_ARG_NULL (names);
6120 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6121 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6124 * no info is better than crashing: we'll need our own tz data
6125 * to make this work properly, anyway. The range is probably
6126 * reduced to 1970 .. 2037 because that is what mktime is
6127 * guaranteed to support (we get into an infinite loop
6128 * otherwise).
6131 memset (&start, 0, sizeof (start));
6133 start.tm_mday = 1;
6134 start.tm_year = year-1900;
6136 t = mktime (&start);
6138 if ((year < 1970) || (year > 2037) || (t == -1)) {
6139 t = time (NULL);
6140 tt = *localtime (&t);
6141 strftime (tzone, sizeof (tzone), "%Z", &tt);
6142 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6143 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6144 return 1;
6147 gmtoff = gmt_offset (&start, t);
6149 /* For each day of the year, calculate the tm_gmtoff. */
6150 for (day = 0; day < 365; day++) {
6152 t += 3600*24;
6153 tt = *localtime (&t);
6155 /* Daylight saving starts or ends here. */
6156 if (gmt_offset (&tt, t) != gmtoff) {
6157 struct tm tt1;
6158 time_t t1;
6160 /* Try to find the exact hour when daylight saving starts/ends. */
6161 t1 = t;
6162 do {
6163 t1 -= 3600;
6164 tt1 = *localtime (&t1);
6165 } while (gmt_offset (&tt1, t1) != gmtoff);
6167 /* Try to find the exact minute when daylight saving starts/ends. */
6168 do {
6169 t1 += 60;
6170 tt1 = *localtime (&t1);
6171 } while (gmt_offset (&tt1, t1) == gmtoff);
6172 t1+=gmtoff;
6173 strftime (tzone, sizeof (tzone), "%Z", &tt);
6175 /* Write data, if we're already in daylight saving, we're done. */
6176 if (is_daylight) {
6177 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6178 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6179 return 1;
6180 } else {
6181 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6182 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6183 is_daylight = 1;
6186 /* This is only set once when we enter daylight saving. */
6187 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6188 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6190 gmtoff = gmt_offset (&tt, t);
6194 if (!is_daylight) {
6195 strftime (tzone, sizeof (tzone), "%Z", &tt);
6196 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6197 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6198 mono_array_set ((*data), gint64, 0, 0);
6199 mono_array_set ((*data), gint64, 1, 0);
6200 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6201 mono_array_set ((*data), gint64, 3, 0);
6204 return 1;
6205 #else
6206 MonoDomain *domain = mono_domain_get ();
6207 TIME_ZONE_INFORMATION tz_info;
6208 FILETIME ft;
6209 int i;
6210 int err, tz_id;
6212 tz_id = GetTimeZoneInformation (&tz_info);
6213 if (tz_id == TIME_ZONE_ID_INVALID)
6214 return 0;
6216 MONO_CHECK_ARG_NULL (data);
6217 MONO_CHECK_ARG_NULL (names);
6219 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6220 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6222 for (i = 0; i < 32; ++i)
6223 if (!tz_info.DaylightName [i])
6224 break;
6225 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6226 for (i = 0; i < 32; ++i)
6227 if (!tz_info.StandardName [i])
6228 break;
6229 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6231 if ((year <= 1601) || (year > 30827)) {
6233 * According to MSDN, the MS time functions can't handle dates outside
6234 * this interval.
6236 return 1;
6239 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6240 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6241 tz_info.StandardDate.wYear = year;
6242 convert_to_absolute_date(&tz_info.StandardDate);
6243 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6244 //g_assert(err);
6245 if (err == 0)
6246 return 0;
6248 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6249 tz_info.DaylightDate.wYear = year;
6250 convert_to_absolute_date(&tz_info.DaylightDate);
6251 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6252 //g_assert(err);
6253 if (err == 0)
6254 return 0;
6256 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6258 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6259 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6261 return 1;
6262 #endif
6265 static gpointer
6266 ves_icall_System_Object_obj_address (MonoObject *this)
6268 MONO_ARCH_SAVE_REGS;
6270 return this;
6273 /* System.Buffer */
6275 static inline gint32
6276 mono_array_get_byte_length (MonoArray *array)
6278 MonoClass *klass;
6279 int length;
6280 int i;
6282 klass = array->obj.vtable->klass;
6284 if (array->bounds == NULL)
6285 length = array->max_length;
6286 else {
6287 length = 1;
6288 for (i = 0; i < klass->rank; ++ i)
6289 length *= array->bounds [i].length;
6292 switch (klass->element_class->byval_arg.type) {
6293 case MONO_TYPE_I1:
6294 case MONO_TYPE_U1:
6295 case MONO_TYPE_BOOLEAN:
6296 return length;
6297 case MONO_TYPE_I2:
6298 case MONO_TYPE_U2:
6299 case MONO_TYPE_CHAR:
6300 return length << 1;
6301 case MONO_TYPE_I4:
6302 case MONO_TYPE_U4:
6303 case MONO_TYPE_R4:
6304 return length << 2;
6305 case MONO_TYPE_I:
6306 case MONO_TYPE_U:
6307 return length * sizeof (gpointer);
6308 case MONO_TYPE_I8:
6309 case MONO_TYPE_U8:
6310 case MONO_TYPE_R8:
6311 return length << 3;
6312 default:
6313 return -1;
6317 static gint32
6318 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6320 MONO_ARCH_SAVE_REGS;
6322 return mono_array_get_byte_length (array);
6325 static gint8
6326 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6328 MONO_ARCH_SAVE_REGS;
6330 return mono_array_get (array, gint8, idx);
6333 static void
6334 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6336 MONO_ARCH_SAVE_REGS;
6338 mono_array_set (array, gint8, idx, value);
6341 static MonoBoolean
6342 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6344 guint8 *src_buf, *dest_buf;
6346 MONO_ARCH_SAVE_REGS;
6348 /* watch out for integer overflow */
6349 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6350 return FALSE;
6352 src_buf = (guint8 *)src->vector + src_offset;
6353 dest_buf = (guint8 *)dest->vector + dest_offset;
6355 if (src != dest)
6356 memcpy (dest_buf, src_buf, count);
6357 else
6358 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6360 return TRUE;
6363 static MonoObject *
6364 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6366 MonoDomain *domain = mono_object_domain (this);
6367 MonoObject *res;
6368 MonoRealProxy *rp = ((MonoRealProxy *)this);
6369 MonoTransparentProxy *tp;
6370 MonoType *type;
6371 MonoClass *klass;
6373 MONO_ARCH_SAVE_REGS;
6375 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6376 tp = (MonoTransparentProxy*) res;
6378 MONO_OBJECT_SETREF (tp, rp, rp);
6379 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6380 klass = mono_class_from_mono_type (type);
6382 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6383 tp->remote_class = mono_remote_class (domain, class_name, klass);
6385 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6386 return res;
6389 static MonoReflectionType *
6390 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6392 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6395 /* System.Environment */
6397 MonoString*
6398 ves_icall_System_Environment_get_UserName (void)
6400 MONO_ARCH_SAVE_REGS;
6402 /* using glib is more portable */
6403 return mono_string_new (mono_domain_get (), g_get_user_name ());
6407 static MonoString *
6408 ves_icall_System_Environment_get_MachineName (void)
6410 #if defined (PLATFORM_WIN32)
6411 gunichar2 *buf;
6412 guint32 len;
6413 MonoString *result;
6415 len = MAX_COMPUTERNAME_LENGTH + 1;
6416 buf = g_new (gunichar2, len);
6418 result = NULL;
6419 if (GetComputerName (buf, (PDWORD) &len))
6420 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6422 g_free (buf);
6423 return result;
6424 #elif !defined(DISABLE_SOCKETS)
6425 gchar buf [256];
6426 MonoString *result;
6428 if (gethostname (buf, sizeof (buf)) == 0)
6429 result = mono_string_new (mono_domain_get (), buf);
6430 else
6431 result = NULL;
6433 return result;
6434 #else
6435 return mono_string_new (mono_domain_get (), "mono");
6436 #endif
6439 static int
6440 ves_icall_System_Environment_get_Platform (void)
6442 #if defined (PLATFORM_WIN32)
6443 /* Win32NT */
6444 return 2;
6445 #elif defined(__MACH__)
6446 /* OSX */
6447 if (mono_framework_version () < 2)
6448 return 128;
6451 // For compatibility with our client code, this will be 4 for a while.
6452 // We will eventually move to 6 to match .NET, but it requires all client
6453 // code to be updated and the documentation everywhere to be updated
6454 // first.
6456 return 4;
6457 #else
6458 /* Unix */
6459 if (mono_framework_version () < 2)
6460 return 128;
6461 return 4;
6462 #endif
6465 static MonoString *
6466 ves_icall_System_Environment_get_NewLine (void)
6468 MONO_ARCH_SAVE_REGS;
6470 #if defined (PLATFORM_WIN32)
6471 return mono_string_new (mono_domain_get (), "\r\n");
6472 #else
6473 return mono_string_new (mono_domain_get (), "\n");
6474 #endif
6477 static MonoString *
6478 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6480 const gchar *value;
6481 gchar *utf8_name;
6483 MONO_ARCH_SAVE_REGS;
6485 if (name == NULL)
6486 return NULL;
6488 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6489 value = g_getenv (utf8_name);
6491 g_free (utf8_name);
6493 if (value == 0)
6494 return NULL;
6496 return mono_string_new (mono_domain_get (), value);
6500 * There is no standard way to get at environ.
6502 #ifndef _MSC_VER
6503 #ifndef __MINGW32_VERSION
6504 #ifdef __APPLE__
6505 /* Apple defines this in crt_externs.h but doesn't provide that header for
6506 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6507 * in fact exist on all implementations (so far)
6509 gchar ***_NSGetEnviron();
6510 #define environ (*_NSGetEnviron())
6511 #else
6512 extern
6513 char **environ;
6514 #endif
6515 #endif
6516 #endif
6518 static MonoArray *
6519 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6521 #ifdef PLATFORM_WIN32
6522 MonoArray *names;
6523 MonoDomain *domain;
6524 MonoString *str;
6525 WCHAR* env_strings;
6526 WCHAR* env_string;
6527 WCHAR* equal_str;
6528 int n = 0;
6530 env_strings = GetEnvironmentStrings();
6532 if (env_strings) {
6533 env_string = env_strings;
6534 while (*env_string != '\0') {
6535 /* weird case that MS seems to skip */
6536 if (*env_string != '=')
6537 n++;
6538 while (*env_string != '\0')
6539 env_string++;
6540 env_string++;
6544 domain = mono_domain_get ();
6545 names = mono_array_new (domain, mono_defaults.string_class, n);
6547 if (env_strings) {
6548 n = 0;
6549 env_string = env_strings;
6550 while (*env_string != '\0') {
6551 /* weird case that MS seems to skip */
6552 if (*env_string != '=') {
6553 equal_str = wcschr(env_string, '=');
6554 g_assert(equal_str);
6555 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6556 mono_array_setref (names, n, str);
6557 n++;
6559 while (*env_string != '\0')
6560 env_string++;
6561 env_string++;
6564 FreeEnvironmentStrings (env_strings);
6567 return names;
6569 #else
6570 MonoArray *names;
6571 MonoDomain *domain;
6572 MonoString *str;
6573 gchar **e, **parts;
6574 int n;
6576 MONO_ARCH_SAVE_REGS;
6578 n = 0;
6579 for (e = environ; *e != 0; ++ e)
6580 ++ n;
6582 domain = mono_domain_get ();
6583 names = mono_array_new (domain, mono_defaults.string_class, n);
6585 n = 0;
6586 for (e = environ; *e != 0; ++ e) {
6587 parts = g_strsplit (*e, "=", 2);
6588 if (*parts != 0) {
6589 str = mono_string_new (domain, *parts);
6590 mono_array_setref (names, n, str);
6593 g_strfreev (parts);
6595 ++ n;
6598 return names;
6599 #endif
6603 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6605 #if !GLIB_CHECK_VERSION(2,4,0)
6606 #define g_setenv(a,b,c) setenv(a,b,c)
6607 #define g_unsetenv(a) unsetenv(a)
6608 #endif
6610 static void
6611 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6613 #ifdef PLATFORM_WIN32
6614 gunichar2 *utf16_name, *utf16_value;
6615 #else
6616 gchar *utf8_name, *utf8_value;
6617 #endif
6619 MONO_ARCH_SAVE_REGS;
6621 #ifdef PLATFORM_WIN32
6622 utf16_name = mono_string_to_utf16 (name);
6623 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6624 SetEnvironmentVariable (utf16_name, NULL);
6625 g_free (utf16_name);
6626 return;
6629 utf16_value = mono_string_to_utf16 (value);
6631 SetEnvironmentVariable (utf16_name, utf16_value);
6633 g_free (utf16_name);
6634 g_free (utf16_value);
6635 #else
6636 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6638 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6639 g_unsetenv (utf8_name);
6640 g_free (utf8_name);
6641 return;
6644 utf8_value = mono_string_to_utf8 (value);
6645 g_setenv (utf8_name, utf8_value, TRUE);
6647 g_free (utf8_name);
6648 g_free (utf8_value);
6649 #endif
6652 static void
6653 ves_icall_System_Environment_Exit (int result)
6655 MONO_ARCH_SAVE_REGS;
6657 mono_threads_set_shutting_down ();
6659 mono_runtime_set_shutting_down ();
6661 /* Suspend all managed threads since the runtime is going away */
6662 mono_thread_suspend_all_other_threads ();
6664 mono_runtime_quit ();
6666 /* we may need to do some cleanup here... */
6667 exit (result);
6670 static MonoString*
6671 ves_icall_System_Environment_GetGacPath (void)
6673 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6676 static MonoString*
6677 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6679 #if defined (PLATFORM_WIN32)
6680 #ifndef CSIDL_FLAG_CREATE
6681 #define CSIDL_FLAG_CREATE 0x8000
6682 #endif
6684 WCHAR path [MAX_PATH];
6685 /* Create directory if no existing */
6686 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6687 int len = 0;
6688 while (path [len])
6689 ++ len;
6690 return mono_string_new_utf16 (mono_domain_get (), path, len);
6692 #else
6693 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6694 #endif
6695 return mono_string_new (mono_domain_get (), "");
6698 static MonoArray *
6699 ves_icall_System_Environment_GetLogicalDrives (void)
6701 gunichar2 buf [128], *ptr, *dname;
6702 gunichar2 *u16;
6703 guint initial_size = 127, size = 128;
6704 gint ndrives;
6705 MonoArray *result;
6706 MonoString *drivestr;
6707 MonoDomain *domain = mono_domain_get ();
6708 gint len;
6710 MONO_ARCH_SAVE_REGS;
6712 buf [0] = '\0';
6713 ptr = buf;
6715 while (size > initial_size) {
6716 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6717 if (size > initial_size) {
6718 if (ptr != buf)
6719 g_free (ptr);
6720 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6721 initial_size = size;
6722 size++;
6726 /* Count strings */
6727 dname = ptr;
6728 ndrives = 0;
6729 do {
6730 while (*dname++);
6731 ndrives++;
6732 } while (*dname);
6734 dname = ptr;
6735 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6736 ndrives = 0;
6737 do {
6738 len = 0;
6739 u16 = dname;
6740 while (*u16) { u16++; len ++; }
6741 drivestr = mono_string_new_utf16 (domain, dname, len);
6742 mono_array_setref (result, ndrives++, drivestr);
6743 while (*dname++);
6744 } while (*dname);
6746 if (ptr != buf)
6747 g_free (ptr);
6749 return result;
6752 static MonoString *
6753 ves_icall_System_Environment_InternalGetHome (void)
6755 MONO_ARCH_SAVE_REGS;
6757 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6760 static const char *encodings [] = {
6761 (char *) 1,
6762 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6763 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6764 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6765 (char *) 2,
6766 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6767 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6768 "x_unicode_2_0_utf_7",
6769 (char *) 3,
6770 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6771 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6772 (char *) 4,
6773 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6774 "iso_10646_ucs2",
6775 (char *) 5,
6776 "unicodefffe", "utf_16be",
6777 (char *) 6,
6778 "iso_8859_1",
6779 (char *) 0
6783 * Returns the internal codepage, if the value of "int_code_page" is
6784 * 1 at entry, and we can not compute a suitable code page number,
6785 * returns the code page as a string
6787 static MonoString*
6788 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6790 const char *cset;
6791 const char *p;
6792 char *c;
6793 char *codepage = NULL;
6794 int code;
6795 int want_name = *int_code_page;
6796 int i;
6798 *int_code_page = -1;
6799 MONO_ARCH_SAVE_REGS;
6801 g_get_charset (&cset);
6802 c = codepage = strdup (cset);
6803 for (c = codepage; *c; c++){
6804 if (isascii (*c) && isalpha (*c))
6805 *c = tolower (*c);
6806 if (*c == '-')
6807 *c = '_';
6809 /* g_print ("charset: %s\n", cset); */
6811 /* handle some common aliases */
6812 p = encodings [0];
6813 code = 0;
6814 for (i = 0; p != 0; ){
6815 if ((gssize) p < 7){
6816 code = (gssize) p;
6817 p = encodings [++i];
6818 continue;
6820 if (strcmp (p, codepage) == 0){
6821 *int_code_page = code;
6822 break;
6824 p = encodings [++i];
6827 if (strstr (codepage, "utf_8") != NULL)
6828 *int_code_page |= 0x10000000;
6829 free (codepage);
6831 if (want_name && *int_code_page == -1)
6832 return mono_string_new (mono_domain_get (), cset);
6833 else
6834 return NULL;
6837 static MonoBoolean
6838 ves_icall_System_Environment_get_HasShutdownStarted (void)
6840 if (mono_runtime_is_shutting_down ())
6841 return TRUE;
6843 if (mono_domain_is_unloading (mono_domain_get ()))
6844 return TRUE;
6846 return FALSE;
6849 static void
6850 ves_icall_System_Environment_BroadcastSettingChange (void)
6852 #ifdef PLATFORM_WIN32
6853 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6854 #endif
6857 static void
6858 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6859 MonoReflectionMethod *method,
6860 MonoArray *out_args)
6862 MONO_ARCH_SAVE_REGS;
6864 mono_message_init (mono_object_domain (this), this, method, out_args);
6867 static MonoBoolean
6868 ves_icall_IsTransparentProxy (MonoObject *proxy)
6870 MONO_ARCH_SAVE_REGS;
6872 if (!proxy)
6873 return 0;
6875 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6876 return 1;
6878 return 0;
6881 static MonoReflectionMethod *
6882 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6883 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6885 MonoClass *klass;
6886 MonoMethod *method;
6887 MonoMethod **vtable;
6888 MonoMethod *res = NULL;
6890 MONO_CHECK_ARG_NULL (rtype);
6891 MONO_CHECK_ARG_NULL (rmethod);
6893 method = rmethod->method;
6894 klass = mono_class_from_mono_type (rtype->type);
6896 if (MONO_CLASS_IS_INTERFACE (klass))
6897 return NULL;
6899 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6900 return NULL;
6902 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6903 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6904 return rmethod;
6905 else
6906 return NULL;
6909 mono_class_setup_vtable (klass);
6910 vtable = klass->vtable;
6912 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6913 int offs = mono_class_interface_offset (klass, method->klass);
6914 if (offs >= 0)
6915 res = vtable [offs + method->slot];
6916 } else {
6917 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6918 return NULL;
6920 if (method->slot != -1)
6921 res = vtable [method->slot];
6924 if (!res)
6925 return NULL;
6927 return mono_method_get_object (mono_domain_get (), res, NULL);
6930 static void
6931 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6933 MonoClass *klass;
6934 MonoVTable* vtable;
6936 MONO_ARCH_SAVE_REGS;
6938 klass = mono_class_from_mono_type (type->type);
6939 vtable = mono_class_vtable (mono_domain_get (), klass);
6941 if (enable) vtable->remote = 1;
6942 else vtable->remote = 0;
6945 static MonoObject *
6946 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6948 MonoClass *klass;
6949 MonoDomain *domain;
6951 MONO_ARCH_SAVE_REGS;
6953 domain = mono_object_domain (type);
6954 klass = mono_class_from_mono_type (type->type);
6956 if (klass->rank >= 1) {
6957 g_assert (klass->rank == 1);
6958 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6959 } else {
6960 /* Bypass remoting object creation check */
6961 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6965 static MonoString *
6966 ves_icall_System_IO_get_temp_path (void)
6968 MONO_ARCH_SAVE_REGS;
6970 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6973 #ifndef PLATFORM_NO_DRIVEINFO
6974 static MonoBoolean
6975 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6976 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6977 gint32 *error)
6979 gboolean result;
6980 ULARGE_INTEGER wapi_free_bytes_avail;
6981 ULARGE_INTEGER wapi_total_number_of_bytes;
6982 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6984 MONO_ARCH_SAVE_REGS;
6986 *error = ERROR_SUCCESS;
6987 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6988 &wapi_total_number_of_free_bytes);
6990 if (result) {
6991 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6992 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6993 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6994 } else {
6995 *free_bytes_avail = 0;
6996 *total_number_of_bytes = 0;
6997 *total_number_of_free_bytes = 0;
6998 *error = GetLastError ();
7001 return result;
7004 static guint32
7005 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7007 MONO_ARCH_SAVE_REGS;
7009 return GetDriveType (mono_string_chars (root_path_name));
7011 #endif
7013 static gpointer
7014 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
7016 MONO_ARCH_SAVE_REGS;
7018 return mono_compile_method (method);
7021 static MonoString *
7022 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7024 MonoString *mcpath;
7025 gchar *path;
7027 MONO_ARCH_SAVE_REGS;
7029 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7031 #if defined (PLATFORM_WIN32)
7032 /* Avoid mixing '/' and '\\' */
7034 gint i;
7035 for (i = strlen (path) - 1; i >= 0; i--)
7036 if (path [i] == '/')
7037 path [i] = '\\';
7039 #endif
7040 mcpath = mono_string_new (mono_domain_get (), path);
7041 g_free (path);
7043 return mcpath;
7046 static MonoString *
7047 get_bundled_machine_config (void)
7049 const gchar *machine_config;
7051 MONO_ARCH_SAVE_REGS;
7053 machine_config = mono_get_machine_config ();
7055 if (!machine_config)
7056 return NULL;
7058 return mono_string_new (mono_domain_get (), machine_config);
7061 static MonoString *
7062 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7064 MonoString *ipath;
7065 gchar *path;
7067 MONO_ARCH_SAVE_REGS;
7069 path = g_path_get_dirname (mono_get_config_dir ());
7071 #if defined (PLATFORM_WIN32)
7072 /* Avoid mixing '/' and '\\' */
7074 gint i;
7075 for (i = strlen (path) - 1; i >= 0; i--)
7076 if (path [i] == '/')
7077 path [i] = '\\';
7079 #endif
7080 ipath = mono_string_new (mono_domain_get (), path);
7081 g_free (path);
7083 return ipath;
7086 static gboolean
7087 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7089 MonoPEResourceDataEntry *entry;
7090 MonoImage *image;
7092 MONO_ARCH_SAVE_REGS;
7094 if (!assembly || !result || !size)
7095 return FALSE;
7097 *result = NULL;
7098 *size = 0;
7099 image = assembly->assembly->image;
7100 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7101 if (!entry)
7102 return FALSE;
7104 *result = mono_image_rva_map (image, entry->rde_data_offset);
7105 if (!(*result)) {
7106 g_free (entry);
7107 return FALSE;
7109 *size = entry->rde_size;
7110 g_free (entry);
7111 return TRUE;
7114 static MonoBoolean
7115 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7117 return mono_debug_using_mono_debugger ();
7120 static void
7121 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7123 #if defined (PLATFORM_WIN32)
7124 OutputDebugString (mono_string_chars (message));
7125 #else
7126 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7127 #endif
7130 /* Only used for value types */
7131 static MonoObject *
7132 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7134 MonoClass *klass;
7135 MonoDomain *domain;
7137 MONO_ARCH_SAVE_REGS;
7139 domain = mono_object_domain (type);
7140 klass = mono_class_from_mono_type (type->type);
7142 if (mono_class_is_nullable (klass))
7143 /* No arguments -> null */
7144 return NULL;
7146 return mono_object_new (domain, klass);
7149 static MonoReflectionMethod *
7150 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7152 MonoClass *klass, *parent;
7153 MonoMethod *method = m->method;
7154 MonoMethod *result = NULL;
7156 MONO_ARCH_SAVE_REGS;
7158 if (method->klass == NULL)
7159 return m;
7161 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7162 MONO_CLASS_IS_INTERFACE (method->klass) ||
7163 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7164 return m;
7166 klass = method->klass;
7167 if (klass->generic_class)
7168 klass = klass->generic_class->container_class;
7170 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7171 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7172 mono_class_setup_vtable (parent);
7173 if (parent->vtable_size <= method->slot)
7174 break;
7175 klass = parent;
7178 if (klass == method->klass)
7179 return m;
7181 result = klass->vtable [method->slot];
7182 if (result == NULL) {
7183 /* It is an abstract method */
7184 gpointer iter = NULL;
7185 while ((result = mono_class_get_methods (klass, &iter)))
7186 if (result->slot == method->slot)
7187 break;
7190 if (result == NULL)
7191 return m;
7193 return mono_method_get_object (mono_domain_get (), result, NULL);
7196 static MonoString*
7197 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7199 MonoMethod *method = m->method;
7201 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7202 return m->name;
7205 static void
7206 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7208 MONO_ARCH_SAVE_REGS;
7210 iter->sig = *(MonoMethodSignature**)argsp;
7212 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7213 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7215 iter->next_arg = 0;
7216 /* FIXME: it's not documented what start is exactly... */
7217 if (start) {
7218 iter->args = start;
7219 } else {
7220 iter->args = argsp + sizeof (gpointer);
7221 #ifndef MONO_ARCH_REGPARMS
7223 guint32 i, arg_size;
7224 gint32 align;
7225 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7226 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7227 iter->args = (char*)iter->args + arg_size;
7230 #endif
7232 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7234 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7237 static MonoTypedRef
7238 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7240 guint32 i, arg_size;
7241 gint32 align;
7242 MonoTypedRef res;
7243 MONO_ARCH_SAVE_REGS;
7245 i = iter->sig->sentinelpos + iter->next_arg;
7247 g_assert (i < iter->sig->param_count);
7249 res.type = iter->sig->params [i];
7250 res.klass = mono_class_from_mono_type (res.type);
7251 res.value = iter->args;
7252 arg_size = mono_type_stack_size (res.type, &align);
7253 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7254 if (arg_size <= sizeof (gpointer)) {
7255 int dummy;
7256 int padding = arg_size - mono_type_size (res.type, &dummy);
7257 res.value = (guint8*)res.value + padding;
7259 #endif
7260 iter->args = (char*)iter->args + arg_size;
7261 iter->next_arg++;
7263 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7265 return res;
7268 static MonoTypedRef
7269 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7271 guint32 i, arg_size;
7272 gint32 align;
7273 MonoTypedRef res;
7274 MONO_ARCH_SAVE_REGS;
7276 i = iter->sig->sentinelpos + iter->next_arg;
7278 g_assert (i < iter->sig->param_count);
7280 while (i < iter->sig->param_count) {
7281 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7282 continue;
7283 res.type = iter->sig->params [i];
7284 res.klass = mono_class_from_mono_type (res.type);
7285 /* FIXME: endianess issue... */
7286 res.value = iter->args;
7287 arg_size = mono_type_stack_size (res.type, &align);
7288 iter->args = (char*)iter->args + arg_size;
7289 iter->next_arg++;
7290 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7291 return res;
7293 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7295 res.type = NULL;
7296 res.value = NULL;
7297 res.klass = NULL;
7298 return res;
7301 static MonoType*
7302 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7304 gint i;
7305 MONO_ARCH_SAVE_REGS;
7307 i = iter->sig->sentinelpos + iter->next_arg;
7309 g_assert (i < iter->sig->param_count);
7311 return iter->sig->params [i];
7314 static MonoObject*
7315 mono_TypedReference_ToObject (MonoTypedRef tref)
7317 MONO_ARCH_SAVE_REGS;
7319 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7320 MonoObject** objp = tref.value;
7321 return *objp;
7324 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7327 static MonoObject*
7328 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7330 MONO_ARCH_SAVE_REGS;
7332 if (MONO_TYPE_IS_REFERENCE (type)) {
7333 MonoObject** objp = value;
7334 return *objp;
7337 return mono_value_box (mono_domain_get (), klass, value);
7340 static void
7341 prelink_method (MonoMethod *method)
7343 const char *exc_class, *exc_arg;
7344 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7345 return;
7346 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7347 if (exc_class) {
7348 mono_raise_exception(
7349 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7351 /* create the wrapper, too? */
7354 static void
7355 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7357 MONO_ARCH_SAVE_REGS;
7358 prelink_method (method->method);
7361 static void
7362 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7364 MonoClass *klass = mono_class_from_mono_type (type->type);
7365 MonoMethod* m;
7366 gpointer iter = NULL;
7367 MONO_ARCH_SAVE_REGS;
7369 while ((m = mono_class_get_methods (klass, &iter)))
7370 prelink_method (m);
7373 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7374 static void
7375 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7376 gint32 const **exponents,
7377 gunichar2 const **digitLowerTable,
7378 gunichar2 const **digitUpperTable,
7379 gint64 const **tenPowersList,
7380 gint32 const **decHexDigits)
7382 *mantissas = Formatter_MantissaBitsTable;
7383 *exponents = Formatter_TensExponentTable;
7384 *digitLowerTable = Formatter_DigitLowerTable;
7385 *digitUpperTable = Formatter_DigitUpperTable;
7386 *tenPowersList = Formatter_TenPowersList;
7387 *decHexDigits = Formatter_DecHexDigits;
7390 /* These parameters are "readonly" in corlib/System/Char.cs */
7391 static void
7392 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7393 guint8 const **numeric_data,
7394 gdouble const **numeric_data_values,
7395 guint16 const **to_lower_data_low,
7396 guint16 const **to_lower_data_high,
7397 guint16 const **to_upper_data_low,
7398 guint16 const **to_upper_data_high)
7400 *category_data = CategoryData;
7401 *numeric_data = NumericData;
7402 *numeric_data_values = NumericDataValues;
7403 *to_lower_data_low = ToLowerDataLow;
7404 *to_lower_data_high = ToLowerDataHigh;
7405 *to_upper_data_low = ToUpperDataLow;
7406 *to_upper_data_high = ToUpperDataHigh;
7409 static gint32
7410 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7412 return method->method->token;
7416 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7417 * and avoid useless allocations.
7419 static MonoArray*
7420 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7422 MonoArray *res;
7423 int i, count = 0;
7424 for (i = 0; i < type->num_mods; ++i) {
7425 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7426 count++;
7428 if (!count)
7429 return NULL;
7430 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7431 count = 0;
7432 for (i = 0; i < type->num_mods; ++i) {
7433 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7434 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7435 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7436 count++;
7439 return res;
7442 static MonoArray*
7443 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7445 MonoType *type = param->ClassImpl->type;
7446 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7447 MonoImage *image = method->method->klass->image;
7448 int pos = param->PositionImpl;
7449 MonoMethodSignature *sig = mono_method_signature (method->method);
7450 if (pos == -1)
7451 type = sig->ret;
7452 else
7453 type = sig->params [pos];
7455 return type_array_from_modifiers (image, type, optional);
7458 static MonoType*
7459 get_property_type (MonoProperty *prop)
7461 MonoMethodSignature *sig;
7462 if (prop->get) {
7463 sig = mono_method_signature (prop->get);
7464 return sig->ret;
7465 } else if (prop->set) {
7466 sig = mono_method_signature (prop->set);
7467 return sig->params [sig->param_count - 1];
7469 return NULL;
7472 static MonoArray*
7473 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7475 MonoType *type = get_property_type (property->property);
7476 MonoImage *image = property->klass->image;
7478 if (!type)
7479 return NULL;
7480 return type_array_from_modifiers (image, type, optional);
7483 static MonoBoolean
7484 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7486 MonoCustomAttrInfo *cinfo;
7487 gboolean found;
7489 cinfo = mono_reflection_get_custom_attrs_info (obj);
7490 if (!cinfo)
7491 return FALSE;
7492 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7493 if (!cinfo->cached)
7494 mono_custom_attrs_free (cinfo);
7495 return found;
7498 static MonoArray*
7499 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7501 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7503 if (mono_loader_get_last_error ()) {
7504 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7505 g_assert_not_reached ();
7506 /* Not reached */
7507 return NULL;
7508 } else {
7509 return res;
7513 static MonoBoolean
7514 GCHandle_CheckCurrentDomain (guint32 gchandle)
7516 return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
7519 static MonoString*
7520 ves_icall_Mono_Runtime_GetDisplayName (void)
7522 static const char display_name_str [] = "Mono " VERSION;
7523 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7524 return display_name;
7527 static MonoString*
7528 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7530 MonoString *message;
7531 guint32 ret;
7532 gunichar2 buf[256];
7534 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7535 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7536 buf, 255, NULL);
7537 if (ret == 0) {
7538 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7539 } else {
7540 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7543 return message;
7546 const static guchar
7547 dbase64 [] = {
7548 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7549 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7550 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7551 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7552 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7553 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7554 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7555 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7558 static MonoArray *
7559 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7561 gint ignored;
7562 gint i;
7563 gunichar2 c;
7564 gunichar2 last, prev_last, prev2_last;
7565 gint olength;
7566 MonoArray *result;
7567 guchar *res_ptr;
7568 gint a [4], b [4];
7569 MonoException *exc;
7571 ignored = 0;
7572 last = prev_last = 0, prev2_last = 0;
7573 for (i = 0; i < ilength; i++) {
7574 c = start [i];
7575 if (c >= sizeof (dbase64)) {
7576 exc = mono_exception_from_name_msg (mono_get_corlib (),
7577 "System", "FormatException",
7578 "Invalid character found.");
7579 mono_raise_exception (exc);
7580 } else if (isspace (c)) {
7581 ignored++;
7582 } else {
7583 prev2_last = prev_last;
7584 prev_last = last;
7585 last = c;
7589 olength = ilength - ignored;
7591 if (allowWhitespaceOnly && olength == 0) {
7592 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7595 if ((olength & 3) != 0 || olength <= 0) {
7596 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7597 "FormatException", "Invalid length.");
7598 mono_raise_exception (exc);
7601 if (prev2_last == '=') {
7602 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7603 mono_raise_exception (exc);
7606 olength = (olength * 3) / 4;
7607 if (last == '=')
7608 olength--;
7610 if (prev_last == '=')
7611 olength--;
7613 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7614 res_ptr = mono_array_addr (result, guchar, 0);
7615 for (i = 0; i < ilength; ) {
7616 int k;
7618 for (k = 0; k < 4 && i < ilength;) {
7619 c = start [i++];
7620 if (isspace (c))
7621 continue;
7623 a [k] = (guchar) c;
7624 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7625 exc = mono_exception_from_name_msg (mono_get_corlib (),
7626 "System", "FormatException",
7627 "Invalid character found.");
7628 mono_raise_exception (exc);
7630 k++;
7633 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7634 if (a [2] != '=')
7635 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7636 if (a [3] != '=')
7637 *res_ptr++ = (b [2] << 6) | b [3];
7639 while (i < ilength && isspace (start [i]))
7640 i++;
7643 return result;
7646 static MonoArray *
7647 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7649 MONO_ARCH_SAVE_REGS;
7651 return base64_to_byte_array (mono_string_chars (str),
7652 mono_string_length (str), allowWhitespaceOnly);
7655 static MonoArray *
7656 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7658 MONO_ARCH_SAVE_REGS;
7660 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7661 length, FALSE);
7664 #define ICALL_TYPE(id,name,first)
7665 #define ICALL(id,name,func) Icall_ ## id,
7667 enum {
7668 #include "metadata/icall-def.h"
7669 Icall_last
7672 #undef ICALL_TYPE
7673 #undef ICALL
7674 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7675 #define ICALL(id,name,func)
7676 enum {
7677 #include "metadata/icall-def.h"
7678 Icall_type_num
7681 #undef ICALL_TYPE
7682 #undef ICALL
7683 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7684 #define ICALL(id,name,func)
7685 typedef struct {
7686 guint16 first_icall;
7687 } IcallTypeDesc;
7689 static const IcallTypeDesc
7690 icall_type_descs [] = {
7691 #include "metadata/icall-def.h"
7692 {Icall_last}
7695 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7697 #undef ICALL_TYPE
7698 #define ICALL_TYPE(id,name,first)
7699 #undef ICALL
7701 #ifdef HAVE_ARRAY_ELEM_INIT
7702 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7703 #define MSGSTRFIELD1(line) str##line
7705 static const struct msgstrtn_t {
7706 #define ICALL(id,name,func)
7707 #undef ICALL_TYPE
7708 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7709 #include "metadata/icall-def.h"
7710 #undef ICALL_TYPE
7711 } icall_type_names_str = {
7712 #define ICALL_TYPE(id,name,first) (name),
7713 #include "metadata/icall-def.h"
7714 #undef ICALL_TYPE
7716 static const guint16 icall_type_names_idx [] = {
7717 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7718 #include "metadata/icall-def.h"
7719 #undef ICALL_TYPE
7721 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7723 static const struct msgstr_t {
7724 #undef ICALL
7725 #define ICALL_TYPE(id,name,first)
7726 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7727 #include "metadata/icall-def.h"
7728 #undef ICALL
7729 } icall_names_str = {
7730 #define ICALL(id,name,func) (name),
7731 #include "metadata/icall-def.h"
7732 #undef ICALL
7734 static const guint16 icall_names_idx [] = {
7735 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7736 #include "metadata/icall-def.h"
7737 #undef ICALL
7739 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7741 #else
7743 #undef ICALL_TYPE
7744 #undef ICALL
7745 #define ICALL_TYPE(id,name,first) name,
7746 #define ICALL(id,name,func)
7747 static const char* const
7748 icall_type_names [] = {
7749 #include "metadata/icall-def.h"
7750 NULL
7753 #define icall_type_name_get(id) (icall_type_names [(id)])
7755 #undef ICALL_TYPE
7756 #undef ICALL
7757 #define ICALL_TYPE(id,name,first)
7758 #define ICALL(id,name,func) name,
7759 static const char* const
7760 icall_names [] = {
7761 #include "metadata/icall-def.h"
7762 NULL
7764 #define icall_name_get(id) icall_names [(id)]
7766 #endif /* !HAVE_ARRAY_ELEM_INIT */
7768 #undef ICALL_TYPE
7769 #undef ICALL
7770 #define ICALL_TYPE(id,name,first)
7771 #define ICALL(id,name,func) func,
7772 static const gconstpointer
7773 icall_functions [] = {
7774 #include "metadata/icall-def.h"
7775 NULL
7778 static GHashTable *icall_hash = NULL;
7779 static GHashTable *jit_icall_hash_name = NULL;
7780 static GHashTable *jit_icall_hash_addr = NULL;
7782 void
7783 mono_icall_init (void)
7785 int i = 0;
7787 /* check that tables are sorted: disable in release */
7788 if (TRUE) {
7789 int j;
7790 const char *prev_class = NULL;
7791 const char *prev_method;
7793 for (i = 0; i < Icall_type_num; ++i) {
7794 const IcallTypeDesc *desc;
7795 int num_icalls;
7796 prev_method = NULL;
7797 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7798 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7799 prev_class = icall_type_name_get (i);
7800 desc = &icall_type_descs [i];
7801 num_icalls = icall_desc_num_icalls (desc);
7802 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7803 for (j = 0; j < num_icalls; ++j) {
7804 const char *methodn = icall_name_get (desc->first_icall + j);
7805 if (prev_method && strcmp (prev_method, methodn) >= 0)
7806 g_print ("method %s should come before method %s\n", methodn, prev_method);
7807 prev_method = methodn;
7812 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7815 void
7816 mono_icall_cleanup (void)
7818 g_hash_table_destroy (icall_hash);
7819 g_hash_table_destroy (jit_icall_hash_name);
7820 g_hash_table_destroy (jit_icall_hash_addr);
7823 void
7824 mono_add_internal_call (const char *name, gconstpointer method)
7826 mono_loader_lock ();
7828 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7830 mono_loader_unlock ();
7833 #ifdef HAVE_ARRAY_ELEM_INIT
7834 static int
7835 compare_method_imap (const void *key, const void *elem)
7837 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7838 return strcmp (key, method_name);
7841 static gpointer
7842 find_method_icall (const IcallTypeDesc *imap, const char *name)
7844 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7845 if (!nameslot)
7846 return NULL;
7847 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7850 static int
7851 compare_class_imap (const void *key, const void *elem)
7853 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7854 return strcmp (key, class_name);
7857 static const IcallTypeDesc*
7858 find_class_icalls (const char *name)
7860 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7861 if (!nameslot)
7862 return NULL;
7863 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7866 #else
7867 static int
7868 compare_method_imap (const void *key, const void *elem)
7870 const char** method_name = (const char**)elem;
7871 return strcmp (key, *method_name);
7874 static gpointer
7875 find_method_icall (const IcallTypeDesc *imap, const char *name)
7877 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7878 if (!nameslot)
7879 return NULL;
7880 return (gpointer)icall_functions [(nameslot - icall_names)];
7883 static int
7884 compare_class_imap (const void *key, const void *elem)
7886 const char** class_name = (const char**)elem;
7887 return strcmp (key, *class_name);
7890 static const IcallTypeDesc*
7891 find_class_icalls (const char *name)
7893 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7894 if (!nameslot)
7895 return NULL;
7896 return &icall_type_descs [nameslot - icall_type_names];
7899 #endif
7902 * we should probably export this as an helper (handle nested types).
7903 * Returns the number of chars written in buf.
7905 static int
7906 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7908 int nspacelen, cnamelen;
7909 nspacelen = strlen (klass->name_space);
7910 cnamelen = strlen (klass->name);
7911 if (nspacelen + cnamelen + 2 > bufsize)
7912 return 0;
7913 if (nspacelen) {
7914 memcpy (buf, klass->name_space, nspacelen);
7915 buf [nspacelen ++] = '.';
7917 memcpy (buf + nspacelen, klass->name, cnamelen);
7918 buf [nspacelen + cnamelen] = 0;
7919 return nspacelen + cnamelen;
7922 gpointer
7923 mono_lookup_internal_call (MonoMethod *method)
7925 char *sigstart;
7926 char *tmpsig;
7927 char mname [2048];
7928 int typelen = 0, mlen, siglen;
7929 gpointer res;
7930 const IcallTypeDesc *imap;
7932 g_assert (method != NULL);
7934 if (method->is_inflated)
7935 method = ((MonoMethodInflated *) method)->declaring;
7937 if (method->klass->nested_in) {
7938 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7939 if (!pos)
7940 return NULL;
7942 mname [pos++] = '/';
7943 mname [pos] = 0;
7945 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7946 if (!typelen)
7947 return NULL;
7949 typelen += pos;
7950 } else {
7951 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7952 if (!typelen)
7953 return NULL;
7956 imap = find_class_icalls (mname);
7958 mname [typelen] = ':';
7959 mname [typelen + 1] = ':';
7961 mlen = strlen (method->name);
7962 memcpy (mname + typelen + 2, method->name, mlen);
7963 sigstart = mname + typelen + 2 + mlen;
7964 *sigstart = 0;
7966 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7967 siglen = strlen (tmpsig);
7968 if (typelen + mlen + siglen + 6 > sizeof (mname))
7969 return NULL;
7970 sigstart [0] = '(';
7971 memcpy (sigstart + 1, tmpsig, siglen);
7972 sigstart [siglen + 1] = ')';
7973 sigstart [siglen + 2] = 0;
7974 g_free (tmpsig);
7976 mono_loader_lock ();
7978 res = g_hash_table_lookup (icall_hash, mname);
7979 if (res) {
7980 mono_loader_unlock ();
7981 return res;
7983 /* try without signature */
7984 *sigstart = 0;
7985 res = g_hash_table_lookup (icall_hash, mname);
7986 if (res) {
7987 mono_loader_unlock ();
7988 return res;
7991 /* it wasn't found in the static call tables */
7992 if (!imap) {
7993 mono_loader_unlock ();
7994 return NULL;
7996 res = find_method_icall (imap, sigstart - mlen);
7997 if (res) {
7998 mono_loader_unlock ();
7999 return res;
8001 /* try _with_ signature */
8002 *sigstart = '(';
8003 res = find_method_icall (imap, sigstart - mlen);
8004 if (res) {
8005 mono_loader_unlock ();
8006 return res;
8009 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8010 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8011 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8012 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8013 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");
8014 g_print ("If you see other errors or faults after this message they are probably related\n");
8015 g_print ("and you need to fix your mono install first.\n");
8017 mono_loader_unlock ();
8019 return NULL;
8022 static MonoType*
8023 type_from_typename (char *typename)
8025 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8027 if (!strcmp (typename, "int"))
8028 klass = mono_defaults.int_class;
8029 else if (!strcmp (typename, "ptr"))
8030 klass = mono_defaults.int_class;
8031 else if (!strcmp (typename, "void"))
8032 klass = mono_defaults.void_class;
8033 else if (!strcmp (typename, "int32"))
8034 klass = mono_defaults.int32_class;
8035 else if (!strcmp (typename, "uint32"))
8036 klass = mono_defaults.uint32_class;
8037 else if (!strcmp (typename, "int8"))
8038 klass = mono_defaults.sbyte_class;
8039 else if (!strcmp (typename, "uint8"))
8040 klass = mono_defaults.byte_class;
8041 else if (!strcmp (typename, "int16"))
8042 klass = mono_defaults.int16_class;
8043 else if (!strcmp (typename, "uint16"))
8044 klass = mono_defaults.uint16_class;
8045 else if (!strcmp (typename, "long"))
8046 klass = mono_defaults.int64_class;
8047 else if (!strcmp (typename, "ulong"))
8048 klass = mono_defaults.uint64_class;
8049 else if (!strcmp (typename, "float"))
8050 klass = mono_defaults.single_class;
8051 else if (!strcmp (typename, "double"))
8052 klass = mono_defaults.double_class;
8053 else if (!strcmp (typename, "object"))
8054 klass = mono_defaults.object_class;
8055 else if (!strcmp (typename, "obj"))
8056 klass = mono_defaults.object_class;
8057 else if (!strcmp (typename, "string"))
8058 klass = mono_defaults.string_class;
8059 else if (!strcmp (typename, "bool"))
8060 klass = mono_defaults.boolean_class;
8061 else if (!strcmp (typename, "boolean"))
8062 klass = mono_defaults.boolean_class;
8063 else {
8064 g_error ("%s", typename);
8065 g_assert_not_reached ();
8067 return &klass->byval_arg;
8070 MonoMethodSignature*
8071 mono_create_icall_signature (const char *sigstr)
8073 gchar **parts;
8074 int i, len;
8075 gchar **tmp;
8076 MonoMethodSignature *res;
8078 mono_loader_lock ();
8079 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8080 if (res) {
8081 mono_loader_unlock ();
8082 return res;
8085 parts = g_strsplit (sigstr, " ", 256);
8087 tmp = parts;
8088 len = 0;
8089 while (*tmp) {
8090 len ++;
8091 tmp ++;
8094 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8095 res->pinvoke = 1;
8097 #ifdef PLATFORM_WIN32
8099 * Under windows, the default pinvoke calling convention is STDCALL but
8100 * we need CDECL.
8102 res->call_convention = MONO_CALL_C;
8103 #endif
8105 res->ret = type_from_typename (parts [0]);
8106 for (i = 1; i < len; ++i) {
8107 res->params [i - 1] = type_from_typename (parts [i]);
8110 g_strfreev (parts);
8112 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8114 mono_loader_unlock ();
8116 return res;
8119 MonoJitICallInfo *
8120 mono_find_jit_icall_by_name (const char *name)
8122 MonoJitICallInfo *info;
8123 g_assert (jit_icall_hash_name);
8125 mono_loader_lock ();
8126 info = g_hash_table_lookup (jit_icall_hash_name, name);
8127 mono_loader_unlock ();
8128 return info;
8131 MonoJitICallInfo *
8132 mono_find_jit_icall_by_addr (gconstpointer addr)
8134 MonoJitICallInfo *info;
8135 g_assert (jit_icall_hash_addr);
8137 mono_loader_lock ();
8138 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8139 mono_loader_unlock ();
8141 return info;
8145 * mono_get_jit_icall_info:
8147 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8148 * caller should access it while holding the loader lock.
8150 GHashTable*
8151 mono_get_jit_icall_info (void)
8153 return jit_icall_hash_name;
8156 void
8157 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8159 mono_loader_lock ();
8160 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8161 mono_loader_unlock ();
8164 MonoJitICallInfo *
8165 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8167 MonoJitICallInfo *info;
8169 g_assert (func);
8170 g_assert (name);
8172 mono_loader_lock ();
8174 if (!jit_icall_hash_name) {
8175 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8176 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8179 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8180 g_warning ("jit icall already defined \"%s\"\n", name);
8181 g_assert_not_reached ();
8184 info = g_new0 (MonoJitICallInfo, 1);
8186 info->name = name;
8187 info->func = func;
8188 info->sig = sig;
8190 if (is_save) {
8191 info->wrapper = func;
8192 } else {
8193 info->wrapper = NULL;
8196 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8197 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8199 mono_loader_unlock ();
8200 return info;