2010-06-21 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / icall.c
blob6c7154370155a60136909ed5f1372f759299c16a
1 /*
2 * icall.c:
4 * Authors:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 #include <config.h>
14 #include <glib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <ctype.h>
18 #ifdef HAVE_ALLOCA_H
19 #include <alloca.h>
20 #endif
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #if defined (HOST_WIN32)
28 #include <stdlib.h>
29 #endif
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/metadata/mono-ptr-array.h>
71 #include <mono/io-layer/io-layer.h>
72 #include <mono/utils/strtod.h>
73 #include <mono/utils/monobitset.h>
74 #include <mono/utils/mono-time.h>
75 #include <mono/utils/mono-proclib.h>
76 #include <mono/utils/mono-string.h>
77 #include <mono/utils/mono-error-internals.h>
78 #include <mono/utils/mono-mmap.h>
80 #if defined (HOST_WIN32)
81 #include <windows.h>
82 #include <shlobj.h>
83 #endif
84 #include "decimal.h"
86 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
88 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
90 static MonoArray*
91 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
93 static inline MonoBoolean
94 is_generic_parameter (MonoType *type)
96 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
99 static void
100 mono_class_init_or_throw (MonoClass *klass)
102 if (!mono_class_init (klass))
103 mono_raise_exception (mono_class_get_exception_for_failure (klass));
107 * We expect a pointer to a char, not a string
109 static gboolean
110 mono_double_ParseImpl (char *ptr, double *result)
112 gchar *endptr = NULL;
113 *result = 0.0;
115 MONO_ARCH_SAVE_REGS;
117 #ifdef __arm__
118 if (*ptr)
119 *result = strtod (ptr, &endptr);
120 #else
121 if (*ptr){
122 #ifdef _EGLIB_MAJOR
123 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
124 EnterCriticalSection (&mono_strtod_mutex);
125 *result = mono_strtod (ptr, &endptr);
126 LeaveCriticalSection (&mono_strtod_mutex);
127 #else
128 *result = mono_strtod (ptr, &endptr);
129 #endif
131 #endif
133 if (!*ptr || (endptr && *endptr))
134 return FALSE;
136 return TRUE;
139 static MonoObject *
140 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
142 MonoClass *ac;
143 MonoArray *ao;
144 gint32 esize;
145 gpointer *ea;
147 MONO_ARCH_SAVE_REGS;
149 ao = (MonoArray *)this;
150 ac = (MonoClass *)ao->obj.vtable->klass;
152 esize = mono_array_element_size (ac);
153 ea = (gpointer*)((char*)ao->vector + (pos * esize));
155 if (ac->element_class->valuetype)
156 return mono_value_box (this->vtable->domain, ac->element_class, ea);
157 else
158 return *ea;
161 static MonoObject *
162 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
164 MonoClass *ac, *ic;
165 MonoArray *ao, *io;
166 gint32 i, pos, *ind;
168 MONO_ARCH_SAVE_REGS;
170 MONO_CHECK_ARG_NULL (idxs);
172 io = (MonoArray *)idxs;
173 ic = (MonoClass *)io->obj.vtable->klass;
175 ao = (MonoArray *)this;
176 ac = (MonoClass *)ao->obj.vtable->klass;
178 g_assert (ic->rank == 1);
179 if (io->bounds != NULL || io->max_length != ac->rank)
180 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
182 ind = (gint32 *)io->vector;
184 if (ao->bounds == NULL) {
185 if (*ind < 0 || *ind >= ao->max_length)
186 mono_raise_exception (mono_get_exception_index_out_of_range ());
188 return ves_icall_System_Array_GetValueImpl (this, *ind);
191 for (i = 0; i < ac->rank; i++)
192 if ((ind [i] < ao->bounds [i].lower_bound) ||
193 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
194 mono_raise_exception (mono_get_exception_index_out_of_range ());
196 pos = ind [0] - ao->bounds [0].lower_bound;
197 for (i = 1; i < ac->rank; i++)
198 pos = pos*ao->bounds [i].length + ind [i] -
199 ao->bounds [i].lower_bound;
201 return ves_icall_System_Array_GetValueImpl (this, pos);
204 static void
205 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
207 MonoClass *ac, *vc, *ec;
208 gint32 esize, vsize;
209 gpointer *ea, *va;
210 int et, vt;
212 guint64 u64 = 0;
213 gint64 i64 = 0;
214 gdouble r64 = 0;
216 MONO_ARCH_SAVE_REGS;
218 if (value)
219 vc = value->vtable->klass;
220 else
221 vc = NULL;
223 ac = this->obj.vtable->klass;
224 ec = ac->element_class;
226 esize = mono_array_element_size (ac);
227 ea = (gpointer*)((char*)this->vector + (pos * esize));
228 va = (gpointer*)((char*)value + sizeof (MonoObject));
230 if (mono_class_is_nullable (ec)) {
231 mono_nullable_init ((guint8*)ea, value, ec);
232 return;
235 if (!value) {
236 memset (ea, 0, esize);
237 return;
240 #define NO_WIDENING_CONVERSION G_STMT_START{\
241 mono_raise_exception (mono_get_exception_argument ( \
242 "value", "not a widening conversion")); \
243 }G_STMT_END
245 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
246 if (esize < vsize + (extra)) \
247 mono_raise_exception (mono_get_exception_argument ( \
248 "value", "not a widening conversion")); \
249 }G_STMT_END
251 #define INVALID_CAST G_STMT_START{\
252 mono_raise_exception (mono_get_exception_invalid_cast ()); \
253 }G_STMT_END
255 /* Check element (destination) type. */
256 switch (ec->byval_arg.type) {
257 case MONO_TYPE_STRING:
258 switch (vc->byval_arg.type) {
259 case MONO_TYPE_STRING:
260 break;
261 default:
262 INVALID_CAST;
264 break;
265 case MONO_TYPE_BOOLEAN:
266 switch (vc->byval_arg.type) {
267 case MONO_TYPE_BOOLEAN:
268 break;
269 case MONO_TYPE_CHAR:
270 case MONO_TYPE_U1:
271 case MONO_TYPE_U2:
272 case MONO_TYPE_U4:
273 case MONO_TYPE_U8:
274 case MONO_TYPE_I1:
275 case MONO_TYPE_I2:
276 case MONO_TYPE_I4:
277 case MONO_TYPE_I8:
278 case MONO_TYPE_R4:
279 case MONO_TYPE_R8:
280 NO_WIDENING_CONVERSION;
281 default:
282 INVALID_CAST;
284 break;
287 if (!ec->valuetype) {
288 if (!mono_object_isinst (value, ec))
289 INVALID_CAST;
290 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
291 return;
294 if (mono_object_isinst (value, ec)) {
295 if (ec->has_references)
296 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
297 else
298 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
299 return;
302 if (!vc->valuetype)
303 INVALID_CAST;
305 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
307 et = ec->byval_arg.type;
308 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
309 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
311 vt = vc->byval_arg.type;
312 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
313 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
315 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
316 switch (vt) { \
317 case MONO_TYPE_U1: \
318 case MONO_TYPE_U2: \
319 case MONO_TYPE_U4: \
320 case MONO_TYPE_U8: \
321 case MONO_TYPE_CHAR: \
322 CHECK_WIDENING_CONVERSION(0); \
323 *(etype *) ea = (etype) u64; \
324 return; \
325 /* You can't assign a signed value to an unsigned array. */ \
326 case MONO_TYPE_I1: \
327 case MONO_TYPE_I2: \
328 case MONO_TYPE_I4: \
329 case MONO_TYPE_I8: \
330 /* You can't assign a floating point number to an integer array. */ \
331 case MONO_TYPE_R4: \
332 case MONO_TYPE_R8: \
333 NO_WIDENING_CONVERSION; \
335 }G_STMT_END
337 #define ASSIGN_SIGNED(etype) G_STMT_START{\
338 switch (vt) { \
339 case MONO_TYPE_I1: \
340 case MONO_TYPE_I2: \
341 case MONO_TYPE_I4: \
342 case MONO_TYPE_I8: \
343 CHECK_WIDENING_CONVERSION(0); \
344 *(etype *) ea = (etype) i64; \
345 return; \
346 /* You can assign an unsigned value to a signed array if the array's */ \
347 /* element size is larger than the value size. */ \
348 case MONO_TYPE_U1: \
349 case MONO_TYPE_U2: \
350 case MONO_TYPE_U4: \
351 case MONO_TYPE_U8: \
352 case MONO_TYPE_CHAR: \
353 CHECK_WIDENING_CONVERSION(1); \
354 *(etype *) ea = (etype) u64; \
355 return; \
356 /* You can't assign a floating point number to an integer array. */ \
357 case MONO_TYPE_R4: \
358 case MONO_TYPE_R8: \
359 NO_WIDENING_CONVERSION; \
361 }G_STMT_END
363 #define ASSIGN_REAL(etype) G_STMT_START{\
364 switch (vt) { \
365 case MONO_TYPE_R4: \
366 case MONO_TYPE_R8: \
367 CHECK_WIDENING_CONVERSION(0); \
368 *(etype *) ea = (etype) r64; \
369 return; \
370 /* All integer values fit into a floating point array, so we don't */ \
371 /* need to CHECK_WIDENING_CONVERSION here. */ \
372 case MONO_TYPE_I1: \
373 case MONO_TYPE_I2: \
374 case MONO_TYPE_I4: \
375 case MONO_TYPE_I8: \
376 *(etype *) ea = (etype) i64; \
377 return; \
378 case MONO_TYPE_U1: \
379 case MONO_TYPE_U2: \
380 case MONO_TYPE_U4: \
381 case MONO_TYPE_U8: \
382 case MONO_TYPE_CHAR: \
383 *(etype *) ea = (etype) u64; \
384 return; \
386 }G_STMT_END
388 switch (vt) {
389 case MONO_TYPE_U1:
390 u64 = *(guint8 *) va;
391 break;
392 case MONO_TYPE_U2:
393 u64 = *(guint16 *) va;
394 break;
395 case MONO_TYPE_U4:
396 u64 = *(guint32 *) va;
397 break;
398 case MONO_TYPE_U8:
399 u64 = *(guint64 *) va;
400 break;
401 case MONO_TYPE_I1:
402 i64 = *(gint8 *) va;
403 break;
404 case MONO_TYPE_I2:
405 i64 = *(gint16 *) va;
406 break;
407 case MONO_TYPE_I4:
408 i64 = *(gint32 *) va;
409 break;
410 case MONO_TYPE_I8:
411 i64 = *(gint64 *) va;
412 break;
413 case MONO_TYPE_R4:
414 r64 = *(gfloat *) va;
415 break;
416 case MONO_TYPE_R8:
417 r64 = *(gdouble *) va;
418 break;
419 case MONO_TYPE_CHAR:
420 u64 = *(guint16 *) va;
421 break;
422 case MONO_TYPE_BOOLEAN:
423 /* Boolean is only compatible with itself. */
424 switch (et) {
425 case MONO_TYPE_CHAR:
426 case MONO_TYPE_U1:
427 case MONO_TYPE_U2:
428 case MONO_TYPE_U4:
429 case MONO_TYPE_U8:
430 case MONO_TYPE_I1:
431 case MONO_TYPE_I2:
432 case MONO_TYPE_I4:
433 case MONO_TYPE_I8:
434 case MONO_TYPE_R4:
435 case MONO_TYPE_R8:
436 NO_WIDENING_CONVERSION;
437 default:
438 INVALID_CAST;
440 break;
443 /* If we can't do a direct copy, let's try a widening conversion. */
444 switch (et) {
445 case MONO_TYPE_CHAR:
446 ASSIGN_UNSIGNED (guint16);
447 case MONO_TYPE_U1:
448 ASSIGN_UNSIGNED (guint8);
449 case MONO_TYPE_U2:
450 ASSIGN_UNSIGNED (guint16);
451 case MONO_TYPE_U4:
452 ASSIGN_UNSIGNED (guint32);
453 case MONO_TYPE_U8:
454 ASSIGN_UNSIGNED (guint64);
455 case MONO_TYPE_I1:
456 ASSIGN_SIGNED (gint8);
457 case MONO_TYPE_I2:
458 ASSIGN_SIGNED (gint16);
459 case MONO_TYPE_I4:
460 ASSIGN_SIGNED (gint32);
461 case MONO_TYPE_I8:
462 ASSIGN_SIGNED (gint64);
463 case MONO_TYPE_R4:
464 ASSIGN_REAL (gfloat);
465 case MONO_TYPE_R8:
466 ASSIGN_REAL (gdouble);
469 INVALID_CAST;
470 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
471 return;
473 #undef INVALID_CAST
474 #undef NO_WIDENING_CONVERSION
475 #undef CHECK_WIDENING_CONVERSION
476 #undef ASSIGN_UNSIGNED
477 #undef ASSIGN_SIGNED
478 #undef ASSIGN_REAL
481 static void
482 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
483 MonoArray *idxs)
485 MonoClass *ac, *ic;
486 gint32 i, pos, *ind;
488 MONO_ARCH_SAVE_REGS;
490 MONO_CHECK_ARG_NULL (idxs);
492 ic = idxs->obj.vtable->klass;
493 ac = this->obj.vtable->klass;
495 g_assert (ic->rank == 1);
496 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
497 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
499 ind = (gint32 *)idxs->vector;
501 if (this->bounds == NULL) {
502 if (*ind < 0 || *ind >= this->max_length)
503 mono_raise_exception (mono_get_exception_index_out_of_range ());
505 ves_icall_System_Array_SetValueImpl (this, value, *ind);
506 return;
509 for (i = 0; i < ac->rank; i++)
510 if ((ind [i] < this->bounds [i].lower_bound) ||
511 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
512 mono_raise_exception (mono_get_exception_index_out_of_range ());
514 pos = ind [0] - this->bounds [0].lower_bound;
515 for (i = 1; i < ac->rank; i++)
516 pos = pos * this->bounds [i].length + ind [i] -
517 this->bounds [i].lower_bound;
519 ves_icall_System_Array_SetValueImpl (this, value, pos);
522 static MonoArray *
523 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
525 MonoClass *aklass, *klass;
526 MonoArray *array;
527 uintptr_t *sizes, i;
528 gboolean bounded = FALSE;
530 MONO_ARCH_SAVE_REGS;
532 MONO_CHECK_ARG_NULL (type);
533 MONO_CHECK_ARG_NULL (lengths);
535 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
536 if (bounds)
537 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
539 for (i = 0; i < mono_array_length (lengths); i++)
540 if (mono_array_get (lengths, gint32, i) < 0)
541 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
543 klass = mono_class_from_mono_type (type->type);
544 mono_class_init_or_throw (klass);
546 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
547 /* vectors are not the same as one dimensional arrays with no-zero bounds */
548 bounded = TRUE;
549 else
550 bounded = FALSE;
552 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
554 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
555 for (i = 0; i < aklass->rank; ++i) {
556 sizes [i] = mono_array_get (lengths, guint32, i);
557 if (bounds)
558 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
559 else
560 sizes [i + aklass->rank] = 0;
563 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
565 return array;
568 static MonoArray *
569 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
571 MonoClass *aklass, *klass;
572 MonoArray *array;
573 uintptr_t *sizes, i;
574 gboolean bounded = FALSE;
576 MONO_ARCH_SAVE_REGS;
578 MONO_CHECK_ARG_NULL (type);
579 MONO_CHECK_ARG_NULL (lengths);
581 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
582 if (bounds)
583 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
585 for (i = 0; i < mono_array_length (lengths); i++)
586 if ((mono_array_get (lengths, gint64, i) < 0) ||
587 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
588 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
590 klass = mono_class_from_mono_type (type->type);
591 mono_class_init_or_throw (klass);
593 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
594 /* vectors are not the same as one dimensional arrays with no-zero bounds */
595 bounded = TRUE;
596 else
597 bounded = FALSE;
599 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
601 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
602 for (i = 0; i < aklass->rank; ++i) {
603 sizes [i] = mono_array_get (lengths, guint64, i);
604 if (bounds)
605 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
606 else
607 sizes [i + aklass->rank] = 0;
610 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
612 return array;
615 static gint32
616 ves_icall_System_Array_GetRank (MonoObject *this)
618 MONO_ARCH_SAVE_REGS;
620 return this->vtable->klass->rank;
623 static gint32
624 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
626 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
627 uintptr_t length;
629 MONO_ARCH_SAVE_REGS;
631 if ((dimension < 0) || (dimension >= rank))
632 mono_raise_exception (mono_get_exception_index_out_of_range ());
634 if (this->bounds == NULL)
635 length = this->max_length;
636 else
637 length = this->bounds [dimension].length;
639 #ifdef MONO_BIG_ARRAYS
640 if (length > G_MAXINT32)
641 mono_raise_exception (mono_get_exception_overflow ());
642 #endif
643 return length;
646 static gint64
647 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
649 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
651 MONO_ARCH_SAVE_REGS;
653 if ((dimension < 0) || (dimension >= rank))
654 mono_raise_exception (mono_get_exception_index_out_of_range ());
656 if (this->bounds == NULL)
657 return this->max_length;
659 return this->bounds [dimension].length;
662 static gint32
663 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
665 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
667 MONO_ARCH_SAVE_REGS;
669 if ((dimension < 0) || (dimension >= rank))
670 mono_raise_exception (mono_get_exception_index_out_of_range ());
672 if (this->bounds == NULL)
673 return 0;
675 return this->bounds [dimension].lower_bound;
678 static void
679 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
681 int sz = mono_array_element_size (mono_object_class (arr));
682 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
685 static gboolean
686 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
688 int element_size;
689 void * dest_addr;
690 void * source_addr;
691 MonoClass *src_class;
692 MonoClass *dest_class;
693 int i;
695 MONO_ARCH_SAVE_REGS;
697 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
698 return FALSE;
700 if (source->bounds || dest->bounds)
701 return FALSE;
703 /* there's no integer overflow since mono_array_length returns an unsigned integer */
704 if ((dest_idx + length > mono_array_length (dest)) ||
705 (source_idx + length > mono_array_length (source)))
706 return FALSE;
708 src_class = source->obj.vtable->klass->element_class;
709 dest_class = dest->obj.vtable->klass->element_class;
712 * Handle common cases.
715 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
716 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
717 int has_refs = dest_class->has_references;
718 for (i = source_idx; i < source_idx + length; ++i) {
719 MonoObject *elem = mono_array_get (source, MonoObject*, i);
720 if (elem && !mono_object_isinst (elem, dest_class))
721 return FALSE;
724 element_size = mono_array_element_size (dest->obj.vtable->klass);
725 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
726 for (i = 0; i < length; ++i) {
727 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
728 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
729 if (!elem)
730 continue;
731 if (has_refs)
732 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
733 else
734 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
736 return TRUE;
739 /* Check if we're copying a char[] <==> (u)short[] */
740 if (src_class != dest_class) {
741 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
742 return FALSE;
744 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
746 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
747 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
748 for (i = source_idx; i < source_idx + length; ++i) {
749 MonoObject *elem = mono_array_get (source, MonoObject*, i);
750 if (elem && !mono_object_isinst (elem, dest_class))
751 return FALSE;
753 else
754 return FALSE;
757 if (dest_class->valuetype) {
758 element_size = mono_array_element_size (source->obj.vtable->klass);
759 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
760 if (dest_class->has_references) {
761 mono_value_copy_array (dest, dest_idx, source_addr, length);
762 } else {
763 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
764 memmove (dest_addr, source_addr, element_size * length);
766 } else {
767 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
770 return TRUE;
773 static void
774 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
776 MonoClass *ac;
777 MonoArray *ao;
778 gint32 esize;
779 gpointer *ea;
781 MONO_ARCH_SAVE_REGS;
783 ao = (MonoArray *)this;
784 ac = (MonoClass *)ao->obj.vtable->klass;
786 esize = mono_array_element_size (ac);
787 ea = (gpointer*)((char*)ao->vector + (pos * esize));
789 memcpy (value, ea, esize);
792 static void
793 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
795 MonoClass *ac, *ec;
796 MonoArray *ao;
797 gint32 esize;
798 gpointer *ea;
800 MONO_ARCH_SAVE_REGS;
802 ao = (MonoArray *)this;
803 ac = (MonoClass *)ao->obj.vtable->klass;
804 ec = ac->element_class;
806 esize = mono_array_element_size (ac);
807 ea = (gpointer*)((char*)ao->vector + (pos * esize));
809 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
810 g_assert (esize == sizeof (gpointer));
811 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
812 } else {
813 g_assert (ec->inited);
814 g_assert (esize == mono_class_value_size (ec, NULL));
815 if (ec->has_references)
816 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
817 else
818 memcpy (ea, value, esize);
822 static void
823 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
825 MonoClass *klass = array->obj.vtable->klass;
826 guint32 size = mono_array_element_size (klass);
827 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
828 int align;
829 const char *field_data;
831 if (MONO_TYPE_IS_REFERENCE (type) ||
832 (type->type == MONO_TYPE_VALUETYPE &&
833 (!mono_type_get_class (type) ||
834 mono_type_get_class (type)->has_references))) {
835 MonoException *exc = mono_get_exception_argument("array",
836 "Cannot initialize array containing references");
837 mono_raise_exception (exc);
840 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
841 MonoException *exc = mono_get_exception_argument("field_handle",
842 "Field doesn't have an RVA");
843 mono_raise_exception (exc);
846 size *= array->max_length;
847 field_data = mono_field_get_data (field_handle);
849 if (size > mono_type_size (field_handle->type, &align)) {
850 MonoException *exc = mono_get_exception_argument("field_handle",
851 "Field not large enough to fill array");
852 mono_raise_exception (exc);
855 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
856 #define SWAP(n) {\
857 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
858 guint ## n *src = (guint ## n *) field_data; \
859 guint ## n *end = (guint ## n *)((char*)src + size); \
861 for (; src < end; data++, src++) { \
862 *data = read ## n (src); \
866 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
868 switch (type->type) {
869 case MONO_TYPE_CHAR:
870 case MONO_TYPE_I2:
871 case MONO_TYPE_U2:
872 SWAP (16);
873 break;
874 case MONO_TYPE_I4:
875 case MONO_TYPE_U4:
876 case MONO_TYPE_R4:
877 SWAP (32);
878 break;
879 case MONO_TYPE_I8:
880 case MONO_TYPE_U8:
881 case MONO_TYPE_R8:
882 SWAP (64);
883 break;
884 default:
885 memcpy (mono_array_addr (array, char, 0), field_data, size);
886 break;
888 #else
889 memcpy (mono_array_addr (array, char, 0), field_data, size);
890 #ifdef ARM_FPU_FPA
891 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
892 gint i;
893 double tmp;
894 double *data = (double*)mono_array_addr (array, double, 0);
896 for (i = 0; i < size; i++, data++) {
897 readr8 (data, &tmp);
898 *data = tmp;
901 #endif
902 #endif
905 static gint
906 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
908 MONO_ARCH_SAVE_REGS;
910 return offsetof (MonoString, chars);
913 static MonoObject *
914 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
916 MONO_ARCH_SAVE_REGS;
918 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
919 return obj;
920 else
921 return mono_object_clone (obj);
924 static void
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
927 MonoClass *klass;
928 MonoVTable *vtable;
930 MONO_CHECK_ARG_NULL (handle);
932 klass = mono_class_from_mono_type (handle);
933 MONO_CHECK_ARG (handle, klass);
935 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
937 /* This will call the type constructor */
938 mono_runtime_class_init (vtable);
941 static void
942 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
944 MONO_ARCH_SAVE_REGS;
946 mono_image_check_for_module_cctor (image);
947 if (image->has_module_cctor) {
948 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
949 /*It's fine to raise the exception here*/
950 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
954 static MonoBoolean
955 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
957 guint8 *stack_addr;
958 guint8 *current;
959 size_t stack_size;
960 /* later make this configurable and per-arch */
961 int min_size = 4096 * 4 * sizeof (void*);
962 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
963 /* if we have no info we are optimistic and assume there is enough room */
964 if (!stack_addr)
965 return TRUE;
966 current = (guint8 *)&stack_addr;
967 if (current > stack_addr) {
968 if ((current - stack_addr) < min_size)
969 return FALSE;
970 } else {
971 if (current - (stack_addr - stack_size) < min_size)
972 return FALSE;
974 return TRUE;
977 static MonoObject *
978 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
980 MONO_ARCH_SAVE_REGS;
982 return mono_object_clone (this);
985 static gint32
986 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
988 MonoClass *klass;
989 MonoObject **values = NULL;
990 MonoObject *o;
991 int count = 0;
992 gint32 result = 0;
993 MonoClassField* field;
994 gpointer iter;
996 MONO_ARCH_SAVE_REGS;
998 klass = mono_object_class (this);
1000 if (mono_class_num_fields (klass) == 0)
1001 return mono_object_hash (this);
1004 * Compute the starting value of the hashcode for fields of primitive
1005 * types, and return the remaining fields in an array to the managed side.
1006 * This way, we can avoid costly reflection operations in managed code.
1008 iter = NULL;
1009 while ((field = mono_class_get_fields (klass, &iter))) {
1010 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1011 continue;
1012 if (mono_field_is_deleted (field))
1013 continue;
1014 /* FIXME: Add more types */
1015 switch (field->type->type) {
1016 case MONO_TYPE_I4:
1017 result ^= *(gint32*)((guint8*)this + field->offset);
1018 break;
1019 case MONO_TYPE_STRING: {
1020 MonoString *s;
1021 s = *(MonoString**)((guint8*)this + field->offset);
1022 if (s != NULL)
1023 result ^= mono_string_hash (s);
1024 break;
1026 default:
1027 if (!values)
1028 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1029 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1030 values [count++] = o;
1034 if (values) {
1035 int i;
1036 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1037 for (i = 0; i < count; ++i)
1038 mono_array_setref (*fields, i, values [i]);
1039 } else {
1040 *fields = NULL;
1042 return result;
1045 static MonoBoolean
1046 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1048 MonoClass *klass;
1049 MonoObject **values = NULL;
1050 MonoObject *o;
1051 MonoClassField* field;
1052 gpointer iter;
1053 int count = 0;
1055 MONO_ARCH_SAVE_REGS;
1057 MONO_CHECK_ARG_NULL (that);
1059 if (this->vtable != that->vtable)
1060 return FALSE;
1062 klass = mono_object_class (this);
1064 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1065 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1068 * Do the comparison for fields of primitive type and return a result if
1069 * possible. Otherwise, return the remaining fields in an array to the
1070 * managed side. This way, we can avoid costly reflection operations in
1071 * managed code.
1073 *fields = NULL;
1074 iter = NULL;
1075 while ((field = mono_class_get_fields (klass, &iter))) {
1076 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1077 continue;
1078 if (mono_field_is_deleted (field))
1079 continue;
1080 /* FIXME: Add more types */
1081 switch (field->type->type) {
1082 case MONO_TYPE_U1:
1083 case MONO_TYPE_I1:
1084 case MONO_TYPE_BOOLEAN:
1085 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1086 return FALSE;
1087 break;
1088 case MONO_TYPE_U2:
1089 case MONO_TYPE_I2:
1090 case MONO_TYPE_CHAR:
1091 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1092 return FALSE;
1093 break;
1094 case MONO_TYPE_U4:
1095 case MONO_TYPE_I4:
1096 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1097 return FALSE;
1098 break;
1099 case MONO_TYPE_U8:
1100 case MONO_TYPE_I8:
1101 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1102 return FALSE;
1103 break;
1104 case MONO_TYPE_R4:
1105 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1106 return FALSE;
1107 break;
1108 case MONO_TYPE_R8:
1109 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1110 return FALSE;
1111 break;
1114 case MONO_TYPE_STRING: {
1115 MonoString *s1, *s2;
1116 guint32 s1len, s2len;
1117 s1 = *(MonoString**)((guint8*)this + field->offset);
1118 s2 = *(MonoString**)((guint8*)that + field->offset);
1119 if (s1 == s2)
1120 break;
1121 if ((s1 == NULL) || (s2 == NULL))
1122 return FALSE;
1123 s1len = mono_string_length (s1);
1124 s2len = mono_string_length (s2);
1125 if (s1len != s2len)
1126 return FALSE;
1128 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1129 return FALSE;
1130 break;
1132 default:
1133 if (!values)
1134 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1135 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1136 values [count++] = o;
1137 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1138 values [count++] = o;
1141 if (klass->enumtype)
1142 /* enums only have one non-static field */
1143 break;
1146 if (values) {
1147 int i;
1148 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1149 for (i = 0; i < count; ++i)
1150 mono_array_setref (*fields, i, values [i]);
1151 return FALSE;
1152 } else {
1153 return TRUE;
1157 static MonoReflectionType *
1158 ves_icall_System_Object_GetType (MonoObject *obj)
1160 MONO_ARCH_SAVE_REGS;
1162 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1163 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1164 else
1165 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1168 static void
1169 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1171 MONO_ARCH_SAVE_REGS;
1173 mtype->type = &obj->vtable->klass->byval_arg;
1174 g_assert (mtype->type->type);
1177 static gint32
1178 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1180 MONO_ARCH_SAVE_REGS;
1182 MONO_CHECK_ARG_NULL (obj);
1184 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1187 static gint32
1188 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1189 MonoReflectionMethod *method,
1190 MonoArray *opt_param_types)
1192 MONO_ARCH_SAVE_REGS;
1194 MONO_CHECK_ARG_NULL (method);
1196 return mono_image_create_method_token (
1197 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1200 static void
1201 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1203 MONO_ARCH_SAVE_REGS;
1205 mono_image_create_pefile (mb, file);
1208 static void
1209 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1211 MONO_ARCH_SAVE_REGS;
1213 mono_image_build_metadata (mb);
1216 static void
1217 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1219 MONO_ARCH_SAVE_REGS;
1221 mono_image_register_token (mb->dynamic_image, token, obj);
1224 static gboolean
1225 get_caller (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 (m == *dest) {
1234 *dest = NULL;
1235 return FALSE;
1237 if (!(*dest)) {
1238 *dest = m;
1239 return TRUE;
1241 return FALSE;
1244 static gboolean
1245 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1247 MonoMethod **dest = data;
1249 /* skip unmanaged frames */
1250 if (!managed)
1251 return FALSE;
1253 if (!(*dest)) {
1254 if (!strcmp (m->klass->name_space, "System.Reflection"))
1255 return FALSE;
1256 *dest = m;
1257 return TRUE;
1259 return FALSE;
1262 static gboolean
1263 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1265 MonoMethod **dest = data;
1267 /* skip unmanaged frames */
1268 if (!managed)
1269 return FALSE;
1271 if (m->wrapper_type != MONO_WRAPPER_NONE)
1272 return FALSE;
1274 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1275 return FALSE;
1277 if (m == *dest) {
1278 *dest = NULL;
1279 return FALSE;
1281 if (!(*dest)) {
1282 *dest = m;
1283 return TRUE;
1285 return FALSE;
1288 static MonoReflectionType *
1289 type_from_name (const char *str, MonoBoolean ignoreCase)
1291 MonoType *type = NULL;
1292 MonoAssembly *assembly = NULL;
1293 MonoTypeNameParse info;
1294 char *temp_str = g_strdup (str);
1295 gboolean type_resolve = FALSE;
1297 MONO_ARCH_SAVE_REGS;
1299 /* mono_reflection_parse_type() mangles the string */
1300 if (!mono_reflection_parse_type (temp_str, &info)) {
1301 mono_reflection_free_type_info (&info);
1302 g_free (temp_str);
1303 return NULL;
1306 if (info.assembly.name) {
1307 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1308 } else {
1309 MonoMethod *m = mono_method_get_last_managed ();
1310 MonoMethod *dest = m;
1312 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1313 if (!dest)
1314 dest = m;
1317 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1318 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1319 * to crash. This only seems to happen in some strange remoting
1320 * scenarios and I was unable to figure out what's happening there.
1321 * Dec 10, 2005 - Martin.
1324 if (dest) {
1325 assembly = dest->klass->image->assembly;
1326 type_resolve = TRUE;
1327 } else {
1328 g_warning (G_STRLOC);
1332 if (assembly) {
1333 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1334 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1337 if (!info.assembly.name && !type) /* try mscorlib */
1338 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1340 if (assembly && !type && type_resolve) {
1341 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1342 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1345 mono_reflection_free_type_info (&info);
1346 g_free (temp_str);
1348 if (!type)
1349 return NULL;
1351 return mono_type_get_object (mono_domain_get (), type);
1354 #ifdef UNUSED
1355 MonoReflectionType *
1356 mono_type_get (const char *str)
1358 char *copy = g_strdup (str);
1359 MonoReflectionType *type = type_from_name (copy, FALSE);
1361 g_free (copy);
1362 return type;
1364 #endif
1366 static MonoReflectionType*
1367 ves_icall_type_from_name (MonoString *name,
1368 MonoBoolean throwOnError,
1369 MonoBoolean ignoreCase)
1371 char *str = mono_string_to_utf8 (name);
1372 MonoReflectionType *type;
1374 type = type_from_name (str, ignoreCase);
1375 g_free (str);
1376 if (type == NULL){
1377 MonoException *e = NULL;
1379 if (throwOnError)
1380 e = mono_get_exception_type_load (name, NULL);
1382 mono_loader_clear_error ();
1383 if (e != NULL)
1384 mono_raise_exception (e);
1387 return type;
1391 static MonoReflectionType*
1392 ves_icall_type_from_handle (MonoType *handle)
1394 MonoDomain *domain = mono_domain_get ();
1396 MONO_ARCH_SAVE_REGS;
1398 return mono_type_get_object (domain, handle);
1401 static MonoBoolean
1402 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1404 MONO_ARCH_SAVE_REGS;
1406 if (c && type->type && c->type)
1407 return mono_metadata_type_equal (type->type, c->type);
1408 else
1409 return (type == c) ? TRUE : FALSE;
1412 /* System.TypeCode */
1413 typedef enum {
1414 TYPECODE_EMPTY,
1415 TYPECODE_OBJECT,
1416 TYPECODE_DBNULL,
1417 TYPECODE_BOOLEAN,
1418 TYPECODE_CHAR,
1419 TYPECODE_SBYTE,
1420 TYPECODE_BYTE,
1421 TYPECODE_INT16,
1422 TYPECODE_UINT16,
1423 TYPECODE_INT32,
1424 TYPECODE_UINT32,
1425 TYPECODE_INT64,
1426 TYPECODE_UINT64,
1427 TYPECODE_SINGLE,
1428 TYPECODE_DOUBLE,
1429 TYPECODE_DECIMAL,
1430 TYPECODE_DATETIME,
1431 TYPECODE_STRING = 18
1432 } TypeCode;
1434 static guint32
1435 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1437 int t = type->type->type;
1439 MONO_ARCH_SAVE_REGS;
1441 if (type->type->byref)
1442 return TYPECODE_OBJECT;
1444 handle_enum:
1445 switch (t) {
1446 case MONO_TYPE_VOID:
1447 return TYPECODE_OBJECT;
1448 case MONO_TYPE_BOOLEAN:
1449 return TYPECODE_BOOLEAN;
1450 case MONO_TYPE_U1:
1451 return TYPECODE_BYTE;
1452 case MONO_TYPE_I1:
1453 return TYPECODE_SBYTE;
1454 case MONO_TYPE_U2:
1455 return TYPECODE_UINT16;
1456 case MONO_TYPE_I2:
1457 return TYPECODE_INT16;
1458 case MONO_TYPE_CHAR:
1459 return TYPECODE_CHAR;
1460 case MONO_TYPE_PTR:
1461 case MONO_TYPE_U:
1462 case MONO_TYPE_I:
1463 return TYPECODE_OBJECT;
1464 case MONO_TYPE_U4:
1465 return TYPECODE_UINT32;
1466 case MONO_TYPE_I4:
1467 return TYPECODE_INT32;
1468 case MONO_TYPE_U8:
1469 return TYPECODE_UINT64;
1470 case MONO_TYPE_I8:
1471 return TYPECODE_INT64;
1472 case MONO_TYPE_R4:
1473 return TYPECODE_SINGLE;
1474 case MONO_TYPE_R8:
1475 return TYPECODE_DOUBLE;
1476 case MONO_TYPE_VALUETYPE:
1477 if (type->type->data.klass->enumtype) {
1478 t = mono_class_enum_basetype (type->type->data.klass)->type;
1479 goto handle_enum;
1480 } else {
1481 MonoClass *k = type->type->data.klass;
1482 if (strcmp (k->name_space, "System") == 0) {
1483 if (strcmp (k->name, "Decimal") == 0)
1484 return TYPECODE_DECIMAL;
1485 else if (strcmp (k->name, "DateTime") == 0)
1486 return TYPECODE_DATETIME;
1489 return TYPECODE_OBJECT;
1490 case MONO_TYPE_STRING:
1491 return TYPECODE_STRING;
1492 case MONO_TYPE_SZARRAY:
1493 case MONO_TYPE_ARRAY:
1494 case MONO_TYPE_OBJECT:
1495 case MONO_TYPE_VAR:
1496 case MONO_TYPE_MVAR:
1497 case MONO_TYPE_TYPEDBYREF:
1498 return TYPECODE_OBJECT;
1499 case MONO_TYPE_CLASS:
1501 MonoClass *k = type->type->data.klass;
1502 if (strcmp (k->name_space, "System") == 0) {
1503 if (strcmp (k->name, "DBNull") == 0)
1504 return TYPECODE_DBNULL;
1507 return TYPECODE_OBJECT;
1508 case MONO_TYPE_GENERICINST:
1509 return TYPECODE_OBJECT;
1510 default:
1511 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1513 return 0;
1516 static guint32
1517 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1519 MonoDomain *domain;
1520 MonoClass *klass;
1521 MonoClass *klassc;
1523 MONO_ARCH_SAVE_REGS;
1525 g_assert (type != NULL);
1527 domain = ((MonoObject *)type)->vtable->domain;
1529 if (!c) /* FIXME: dont know what do do here */
1530 return 0;
1532 klass = mono_class_from_mono_type (type->type);
1533 klassc = mono_class_from_mono_type (c->type);
1535 /* Interface check requires a more complex setup so we
1536 * only do for them. Otherwise we simply avoid mono_class_init.
1538 if (check_interfaces) {
1539 mono_class_init_or_throw (klass);
1540 mono_class_init_or_throw (klassc);
1541 } else if (!klass->supertypes || !klassc->supertypes) {
1542 mono_loader_lock ();
1543 mono_class_setup_supertypes (klass);
1544 mono_class_setup_supertypes (klassc);
1545 mono_loader_unlock ();
1548 if (type->type->byref)
1549 return klassc == mono_defaults.object_class;
1551 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1554 static gboolean
1555 mono_type_is_primitive (MonoType *type)
1557 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1558 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1561 static MonoType*
1562 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1564 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1565 return mono_class_enum_basetype (type->data.klass);
1566 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1567 return mono_class_enum_basetype (type->data.generic_class->container_class);
1568 return type;
1571 static guint32
1572 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1574 MonoDomain *domain;
1575 MonoClass *klass;
1576 MonoClass *klassc;
1578 MONO_ARCH_SAVE_REGS;
1580 g_assert (type != NULL);
1582 domain = ((MonoObject *)type)->vtable->domain;
1584 klass = mono_class_from_mono_type (type->type);
1585 klassc = mono_class_from_mono_type (c->type);
1587 mono_class_init_or_throw (klass);
1588 mono_class_init_or_throw (klassc);
1590 if (type->type->byref ^ c->type->byref)
1591 return FALSE;
1593 if (type->type->byref) {
1594 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1595 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1597 klass = mono_class_from_mono_type (t);
1598 klassc = mono_class_from_mono_type (ot);
1600 if (mono_type_is_primitive (t)) {
1601 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1602 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1603 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1604 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1605 return t->type == ot->type;
1606 } else {
1607 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1608 return FALSE;
1610 if (klass->valuetype)
1611 return klass == klassc;
1612 return klass->valuetype == klassc->valuetype;
1615 return mono_class_is_assignable_from (klass, klassc);
1618 static guint32
1619 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1621 MonoClass *klass = mono_class_from_mono_type (type->type);
1622 mono_class_init_or_throw (klass);
1623 return mono_object_isinst (obj, klass) != NULL;
1626 static guint32
1627 ves_icall_get_attributes (MonoReflectionType *type)
1629 MonoClass *klass = mono_class_from_mono_type (type->type);
1630 return klass->flags;
1633 static MonoReflectionMarshal*
1634 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1636 MonoClass *klass = field->field->parent;
1637 MonoMarshalType *info;
1638 int i;
1640 if (klass->generic_container ||
1641 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1642 return NULL;
1644 info = mono_marshal_load_type_info (klass);
1646 for (i = 0; i < info->num_fields; ++i) {
1647 if (info->fields [i].field == field->field) {
1648 if (!info->fields [i].mspec)
1649 return NULL;
1650 else
1651 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1655 return NULL;
1658 static MonoReflectionField*
1659 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1661 gboolean found = FALSE;
1662 MonoClass *klass;
1663 MonoClass *k;
1665 g_assert (handle);
1667 if (!type) {
1668 klass = handle->parent;
1669 } else {
1670 klass = mono_class_from_mono_type (type);
1672 /* Check that the field belongs to the class */
1673 for (k = klass; k; k = k->parent) {
1674 if (k == handle->parent) {
1675 found = TRUE;
1676 break;
1680 if (!found)
1681 /* The managed code will throw the exception */
1682 return NULL;
1685 return mono_field_get_object (mono_domain_get (), klass, handle);
1688 static MonoArray*
1689 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1691 MonoType *type = field->field->type;
1693 return type_array_from_modifiers (field->field->parent->image, type, optional);
1696 static void
1697 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1699 MonoDomain *domain = mono_domain_get ();
1700 MonoMethodSignature* sig;
1701 MONO_ARCH_SAVE_REGS;
1703 sig = mono_method_signature (method);
1704 if (!sig) {
1705 g_assert (mono_loader_get_last_error ());
1706 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1709 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1710 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1711 info->attrs = method->flags;
1712 info->implattrs = method->iflags;
1713 if (sig->call_convention == MONO_CALL_DEFAULT)
1714 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1715 else {
1716 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1717 info->callconv = 2;
1718 else
1719 info->callconv = 1;
1721 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1724 static MonoArray*
1725 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1727 MonoDomain *domain = mono_domain_get ();
1729 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1732 static MonoReflectionMarshal*
1733 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1735 MonoDomain *domain = mono_domain_get ();
1736 MonoReflectionMarshal* res = NULL;
1737 MonoMarshalSpec **mspecs;
1738 int i;
1740 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1741 mono_method_get_marshal_info (method, mspecs);
1743 if (mspecs [0])
1744 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1746 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1747 if (mspecs [i])
1748 mono_metadata_free_marshal_spec (mspecs [i]);
1749 g_free (mspecs);
1751 return res;
1754 static gint32
1755 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1757 return field->field->offset - sizeof (MonoObject);
1760 static MonoReflectionType*
1761 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1763 MonoClass *parent;
1764 MONO_ARCH_SAVE_REGS;
1766 parent = declaring? field->field->parent: field->klass;
1768 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1771 static MonoObject *
1772 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1774 MonoClass *fklass = field->klass;
1775 MonoClassField *cf = field->field;
1776 MonoDomain *domain = mono_object_domain (field);
1778 if (fklass->image->assembly->ref_only)
1779 mono_raise_exception (mono_get_exception_invalid_operation (
1780 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1782 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1783 mono_security_core_clr_ensure_reflection_access_field (cf);
1785 return mono_field_get_value_object (domain, cf, obj);
1788 static void
1789 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1791 MonoClassField *cf = field->field;
1792 gchar *v;
1794 MONO_ARCH_SAVE_REGS;
1796 if (field->klass->image->assembly->ref_only)
1797 mono_raise_exception (mono_get_exception_invalid_operation (
1798 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1800 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1801 mono_security_core_clr_ensure_reflection_access_field (cf);
1803 v = (gchar *) value;
1804 if (!cf->type->byref) {
1805 switch (cf->type->type) {
1806 case MONO_TYPE_U1:
1807 case MONO_TYPE_I1:
1808 case MONO_TYPE_BOOLEAN:
1809 case MONO_TYPE_U2:
1810 case MONO_TYPE_I2:
1811 case MONO_TYPE_CHAR:
1812 case MONO_TYPE_U:
1813 case MONO_TYPE_I:
1814 case MONO_TYPE_U4:
1815 case MONO_TYPE_I4:
1816 case MONO_TYPE_R4:
1817 case MONO_TYPE_U8:
1818 case MONO_TYPE_I8:
1819 case MONO_TYPE_R8:
1820 case MONO_TYPE_VALUETYPE:
1821 if (v != NULL)
1822 v += sizeof (MonoObject);
1823 break;
1824 case MONO_TYPE_STRING:
1825 case MONO_TYPE_OBJECT:
1826 case MONO_TYPE_CLASS:
1827 case MONO_TYPE_ARRAY:
1828 case MONO_TYPE_SZARRAY:
1829 /* Do nothing */
1830 break;
1831 case MONO_TYPE_GENERICINST: {
1832 MonoGenericClass *gclass = cf->type->data.generic_class;
1833 g_assert (!gclass->context.class_inst->is_open);
1835 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1836 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1837 MonoObject *nullable;
1840 * Convert the boxed vtype into a Nullable structure.
1841 * This is complicated by the fact that Nullables have
1842 * a variable structure.
1844 nullable = mono_object_new (mono_domain_get (), nklass);
1846 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1848 v = mono_object_unbox (nullable);
1850 else
1851 if (gclass->container_class->valuetype && (v != NULL))
1852 v += sizeof (MonoObject);
1853 break;
1855 default:
1856 g_error ("type 0x%x not handled in "
1857 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1858 return;
1862 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1863 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1864 if (!vtable->initialized)
1865 mono_runtime_class_init (vtable);
1866 mono_field_static_set_value (vtable, cf, v);
1867 } else {
1868 mono_field_set_value (obj, cf, v);
1872 static MonoObject *
1873 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1875 MonoObject *o = NULL;
1876 MonoClassField *field = this->field;
1877 MonoClass *klass;
1878 MonoDomain *domain = mono_object_domain (this);
1879 gchar *v;
1880 MonoTypeEnum def_type;
1881 const char *def_value;
1883 MONO_ARCH_SAVE_REGS;
1885 mono_class_init (field->parent);
1887 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1888 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1890 if (field->parent->image->dynamic) {
1891 /* FIXME: */
1892 g_assert_not_reached ();
1895 def_value = mono_class_get_field_default_value (field, &def_type);
1897 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1898 switch (def_type) {
1899 case MONO_TYPE_U1:
1900 case MONO_TYPE_I1:
1901 case MONO_TYPE_BOOLEAN:
1902 case MONO_TYPE_U2:
1903 case MONO_TYPE_I2:
1904 case MONO_TYPE_CHAR:
1905 case MONO_TYPE_U:
1906 case MONO_TYPE_I:
1907 case MONO_TYPE_U4:
1908 case MONO_TYPE_I4:
1909 case MONO_TYPE_R4:
1910 case MONO_TYPE_U8:
1911 case MONO_TYPE_I8:
1912 case MONO_TYPE_R8: {
1913 MonoType *t;
1915 /* boxed value type */
1916 t = g_new0 (MonoType, 1);
1917 t->type = def_type;
1918 klass = mono_class_from_mono_type (t);
1919 g_free (t);
1920 o = mono_object_new (domain, klass);
1921 v = ((gchar *) o) + sizeof (MonoObject);
1922 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1923 break;
1925 case MONO_TYPE_STRING:
1926 case MONO_TYPE_CLASS:
1927 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1928 break;
1929 default:
1930 g_assert_not_reached ();
1933 return o;
1936 static MonoReflectionType*
1937 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1939 MonoMethod *method = rmethod->method.method;
1941 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1944 /* From MonoProperty.cs */
1945 typedef enum {
1946 PInfo_Attributes = 1,
1947 PInfo_GetMethod = 1 << 1,
1948 PInfo_SetMethod = 1 << 2,
1949 PInfo_ReflectedType = 1 << 3,
1950 PInfo_DeclaringType = 1 << 4,
1951 PInfo_Name = 1 << 5
1952 } PInfo;
1954 static void
1955 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1957 MonoDomain *domain = mono_object_domain (property);
1959 MONO_ARCH_SAVE_REGS;
1961 if ((req_info & PInfo_ReflectedType) != 0)
1962 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1963 else if ((req_info & PInfo_DeclaringType) != 0)
1964 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1966 if ((req_info & PInfo_Name) != 0)
1967 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1969 if ((req_info & PInfo_Attributes) != 0)
1970 info->attrs = property->property->attrs;
1972 if ((req_info & PInfo_GetMethod) != 0)
1973 MONO_STRUCT_SETREF (info, get, property->property->get ?
1974 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1976 if ((req_info & PInfo_SetMethod) != 0)
1977 MONO_STRUCT_SETREF (info, set, property->property->set ?
1978 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1980 * There may be other methods defined for properties, though, it seems they are not exposed
1981 * in the reflection API
1985 static void
1986 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1988 MonoDomain *domain = mono_object_domain (event);
1990 MONO_ARCH_SAVE_REGS;
1992 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
1993 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
1995 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
1996 info->attrs = event->event->attrs;
1997 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
1998 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
1999 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2001 #ifndef MONO_SMALL_CONFIG
2002 if (event->event->other) {
2003 int i, n = 0;
2004 while (event->event->other [n])
2005 n++;
2006 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2008 for (i = 0; i < n; i++)
2009 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2011 #endif
2014 static void
2015 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2017 int i;
2018 MonoClass *ic;
2020 mono_class_setup_interfaces (klass, error);
2021 if (!mono_error_ok (error))
2022 return;
2024 for (i = 0; i < klass->interface_count; i++) {
2025 ic = klass->interfaces [i];
2026 g_hash_table_insert (ifaces, ic, ic);
2028 collect_interfaces (ic, ifaces, error);
2029 if (!mono_error_ok (error))
2030 return;
2034 typedef struct {
2035 MonoArray *iface_array;
2036 MonoGenericContext *context;
2037 MonoError *error;
2038 MonoDomain *domain;
2039 int next_idx;
2040 } FillIfaceArrayData;
2042 static void
2043 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2045 FillIfaceArrayData *data = user_data;
2046 MonoClass *ic = key;
2047 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2049 if (!mono_error_ok (data->error))
2050 return;
2052 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2053 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2054 if (!mono_error_ok (data->error))
2055 return;
2058 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2060 if (inflated)
2061 mono_metadata_free_type (inflated);
2064 static MonoArray*
2065 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2067 MonoError error;
2068 MonoClass *class = mono_class_from_mono_type (type->type);
2069 MonoClass *parent;
2070 FillIfaceArrayData data = { 0 };
2071 int len;
2073 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2075 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2076 data.context = mono_class_get_context (class);
2077 class = class->generic_class->container_class;
2080 for (parent = class; parent; parent = parent->parent) {
2081 mono_class_setup_interfaces (parent, &error);
2082 if (!mono_error_ok (&error))
2083 goto fail;
2084 collect_interfaces (parent, iface_hash, &error);
2085 if (!mono_error_ok (&error))
2086 goto fail;
2089 data.error = &error;
2090 data.domain = mono_object_domain (type);
2092 len = g_hash_table_size (iface_hash);
2093 if (len == 0)
2094 return mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2096 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2097 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2098 if (!mono_error_ok (&error))
2099 goto fail;
2101 g_hash_table_destroy (iface_hash);
2102 return data.iface_array;
2104 fail:
2105 g_hash_table_destroy (iface_hash);
2106 mono_error_raise_exception (&error);
2107 return NULL;
2110 static void
2111 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2113 gboolean variance_used;
2114 MonoClass *class = mono_class_from_mono_type (type->type);
2115 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2116 MonoReflectionMethod *member;
2117 MonoMethod* method;
2118 gpointer iter;
2119 int i = 0, len, ioffset;
2120 MonoDomain *domain;
2122 MONO_ARCH_SAVE_REGS;
2123 mono_class_init_or_throw (class);
2124 mono_class_init_or_throw (iclass);
2126 mono_class_setup_vtable (class);
2128 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2129 if (ioffset == -1)
2130 return;
2132 len = mono_class_num_methods (iclass);
2133 domain = mono_object_domain (type);
2134 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2135 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2136 iter = NULL;
2137 while ((method = mono_class_get_methods (iclass, &iter))) {
2138 member = mono_method_get_object (domain, method, iclass);
2139 mono_array_setref (*methods, i, member);
2140 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2141 mono_array_setref (*targets, i, member);
2143 i ++;
2147 static void
2148 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2150 MonoClass *klass = mono_class_from_mono_type (type->type);
2151 mono_class_init_or_throw (klass);
2153 if (klass->image->dynamic) {
2154 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2155 *packing = tb->packing_size;
2156 *size = tb->class_size;
2157 } else {
2158 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2162 static MonoReflectionType*
2163 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2165 MonoClass *class;
2167 MONO_ARCH_SAVE_REGS;
2169 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2170 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2172 class = mono_class_from_mono_type (type->type);
2173 mono_class_init_or_throw (class);
2175 // GetElementType should only return a type for:
2176 // Array Pointer PassedByRef
2177 if (type->type->byref)
2178 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2179 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2180 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2181 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2182 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2183 else
2184 return NULL;
2187 static MonoReflectionType*
2188 ves_icall_get_type_parent (MonoReflectionType *type)
2190 MonoClass *class = mono_class_from_mono_type (type->type);
2191 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2194 static MonoBoolean
2195 ves_icall_type_ispointer (MonoReflectionType *type)
2197 MONO_ARCH_SAVE_REGS;
2199 return type->type->type == MONO_TYPE_PTR;
2202 static MonoBoolean
2203 ves_icall_type_isprimitive (MonoReflectionType *type)
2205 MONO_ARCH_SAVE_REGS;
2207 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)));
2210 static MonoBoolean
2211 ves_icall_type_isbyref (MonoReflectionType *type)
2213 MONO_ARCH_SAVE_REGS;
2215 return type->type->byref;
2218 static MonoBoolean
2219 ves_icall_type_iscomobject (MonoReflectionType *type)
2221 MonoClass *klass = mono_class_from_mono_type (type->type);
2222 mono_class_init_or_throw (klass);
2224 return (klass && klass->is_com_object);
2227 static MonoReflectionModule*
2228 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2230 MonoClass *class = mono_class_from_mono_type (type->type);
2231 mono_class_init_or_throw (class);
2233 return mono_module_get_object (mono_object_domain (type), class->image);
2236 static MonoReflectionAssembly*
2237 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2239 MonoDomain *domain = mono_domain_get ();
2240 MonoClass *class = mono_class_from_mono_type (type->type);
2242 mono_class_init_or_throw (class);
2244 return mono_assembly_get_object (domain, class->image->assembly);
2247 static MonoReflectionType*
2248 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2250 MonoDomain *domain = mono_domain_get ();
2251 MonoClass *class;
2253 MONO_ARCH_SAVE_REGS;
2255 if (type->type->byref)
2256 return NULL;
2257 if (type->type->type == MONO_TYPE_VAR)
2258 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2259 else if (type->type->type == MONO_TYPE_MVAR)
2260 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2261 else
2262 class = mono_class_from_mono_type (type->type)->nested_in;
2264 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2267 static MonoString*
2268 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2270 MonoDomain *domain = mono_domain_get ();
2271 MonoClass *class = mono_class_from_mono_type (type->type);
2273 if (type->type->byref) {
2274 char *n = g_strdup_printf ("%s&", class->name);
2275 MonoString *res = mono_string_new (domain, n);
2277 g_free (n);
2279 return res;
2280 } else {
2281 return mono_string_new (domain, class->name);
2285 static MonoString*
2286 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2288 MonoDomain *domain = mono_domain_get ();
2289 MonoClass *class = mono_class_from_mono_type (type->type);
2291 while (class->nested_in)
2292 class = class->nested_in;
2294 if (class->name_space [0] == '\0')
2295 return NULL;
2296 else
2297 return mono_string_new (domain, class->name_space);
2300 static gint32
2301 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2303 MonoClass *class;
2305 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2306 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2308 class = mono_class_from_mono_type (type->type);
2309 mono_class_init_or_throw (class);
2311 return class->rank;
2314 static MonoArray*
2315 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2317 MonoArray *res;
2318 MonoClass *klass, *pklass;
2319 MonoDomain *domain = mono_object_domain (type);
2320 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2321 int i;
2322 MONO_ARCH_SAVE_REGS;
2324 klass = mono_class_from_mono_type (type->type);
2325 mono_class_init_or_throw (klass);
2327 if (klass->generic_container) {
2328 MonoGenericContainer *container = klass->generic_container;
2329 res = mono_array_new_specific (array_vtable, container->type_argc);
2330 for (i = 0; i < container->type_argc; ++i) {
2331 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2332 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2334 } else if (klass->generic_class) {
2335 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2336 res = mono_array_new_specific (array_vtable, inst->type_argc);
2337 for (i = 0; i < inst->type_argc; ++i)
2338 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2339 } else {
2340 res = mono_array_new_specific (array_vtable, 0);
2342 return res;
2345 static gboolean
2346 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2348 MonoClass *klass;
2349 MONO_ARCH_SAVE_REGS;
2351 if (!IS_MONOTYPE (type))
2352 return FALSE;
2354 if (type->type->byref)
2355 return FALSE;
2357 klass = mono_class_from_mono_type (type->type);
2358 return klass->generic_container != NULL;
2361 static MonoReflectionType*
2362 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2364 MonoClass *klass;
2365 MONO_ARCH_SAVE_REGS;
2367 if (type->type->byref)
2368 return NULL;
2370 klass = mono_class_from_mono_type (type->type);
2371 mono_class_init_or_throw (klass);
2373 if (klass->generic_container) {
2374 return type; /* check this one */
2376 if (klass->generic_class) {
2377 MonoClass *generic_class = klass->generic_class->container_class;
2378 gpointer tb;
2380 tb = mono_class_get_ref_info (generic_class);
2382 if (generic_class->wastypebuilder && tb)
2383 return tb;
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 g_assert (IS_MONOTYPE (type));
2397 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2399 count = mono_array_length (type_array);
2400 types = g_new0 (MonoType *, count);
2402 for (i = 0; i < count; i++) {
2403 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2404 types [i] = t->type;
2407 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2408 g_free (types);
2409 if (!geninst)
2410 return NULL;
2412 return mono_type_get_object (mono_object_domain (type), geninst);
2415 static gboolean
2416 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2418 MonoClass *klass;
2419 MONO_ARCH_SAVE_REGS;
2421 if (type->type->byref)
2422 return FALSE;
2424 klass = mono_class_from_mono_type (type->type);
2426 return klass->generic_class != NULL;
2429 static gboolean
2430 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2432 MonoClass *klass;
2433 MONO_ARCH_SAVE_REGS;
2435 if (!IS_MONOTYPE (type))
2436 return FALSE;
2438 if (type->type->byref)
2439 return FALSE;
2441 klass = mono_class_from_mono_type (type->type);
2442 return klass->generic_class != NULL || klass->generic_container != NULL;
2445 static gint32
2446 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2448 MONO_ARCH_SAVE_REGS;
2450 if (!IS_MONOTYPE (type))
2451 return -1;
2453 if (is_generic_parameter (type->type))
2454 return mono_type_get_generic_param_num (type->type);
2455 return -1;
2458 static GenericParameterAttributes
2459 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2461 MONO_ARCH_SAVE_REGS;
2463 g_assert (IS_MONOTYPE (type));
2464 g_assert (is_generic_parameter (type->type));
2465 return mono_generic_param_info (type->type->data.generic_param)->flags;
2468 static MonoArray *
2469 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2471 MonoGenericParamInfo *param_info;
2472 MonoDomain *domain;
2473 MonoClass **ptr;
2474 MonoArray *res;
2475 int i, count;
2477 MONO_ARCH_SAVE_REGS;
2479 g_assert (IS_MONOTYPE (type));
2481 domain = mono_object_domain (type);
2482 param_info = mono_generic_param_info (type->type->data.generic_param);
2483 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2486 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2487 for (i = 0; i < count; i++)
2488 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2491 return res;
2494 static MonoBoolean
2495 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2497 MONO_ARCH_SAVE_REGS;
2498 return is_generic_parameter (type->type);
2501 static MonoBoolean
2502 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2504 MONO_ARCH_SAVE_REGS;
2505 return is_generic_parameter (tb->type.type);
2508 static void
2509 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2510 MonoReflectionType *t)
2512 enumtype->type = t->type;
2515 static MonoReflectionMethod*
2516 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2517 MonoReflectionMethod* generic)
2519 MonoDomain *domain;
2520 MonoClass *klass;
2521 MonoMethod *method;
2522 gpointer iter;
2524 MONO_ARCH_SAVE_REGS;
2526 domain = ((MonoObject *)type)->vtable->domain;
2528 klass = mono_class_from_mono_type (type->type);
2529 mono_class_init_or_throw (klass);
2531 iter = NULL;
2532 while ((method = mono_class_get_methods (klass, &iter))) {
2533 if (method->token == generic->method->token)
2534 return mono_method_get_object (domain, method, klass);
2537 return NULL;
2542 static MonoReflectionMethod *
2543 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2545 MonoMethod *method;
2546 MonoType *type = ref_type->type;
2548 MONO_ARCH_SAVE_REGS;
2550 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2551 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2552 if (type->type == MONO_TYPE_VAR)
2553 return NULL;
2555 method = mono_type_get_generic_param_owner (type)->owner.method;
2556 g_assert (method);
2557 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2560 static MonoReflectionDllImportAttribute*
2561 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2563 static MonoClass *DllImportAttributeClass = NULL;
2564 MonoDomain *domain = mono_domain_get ();
2565 MonoReflectionDllImportAttribute *attr;
2566 MonoImage *image = method->klass->image;
2567 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2568 MonoTableInfo *tables = image->tables;
2569 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2570 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2571 guint32 im_cols [MONO_IMPLMAP_SIZE];
2572 guint32 scope_token;
2573 const char *import = NULL;
2574 const char *scope = NULL;
2575 guint32 flags;
2577 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2578 return NULL;
2580 if (!DllImportAttributeClass) {
2581 DllImportAttributeClass =
2582 mono_class_from_name (mono_defaults.corlib,
2583 "System.Runtime.InteropServices", "DllImportAttribute");
2584 g_assert (DllImportAttributeClass);
2587 if (method->klass->image->dynamic) {
2588 MonoReflectionMethodAux *method_aux =
2589 g_hash_table_lookup (
2590 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2591 if (method_aux) {
2592 import = method_aux->dllentry;
2593 scope = method_aux->dll;
2596 if (!import || !scope) {
2597 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2598 return NULL;
2601 else {
2602 if (piinfo->implmap_idx) {
2603 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2605 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2606 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2607 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2608 scope = mono_metadata_string_heap (image, scope_token);
2611 flags = piinfo->piflags;
2613 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2615 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2616 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2617 attr->call_conv = (flags & 0x700) >> 8;
2618 attr->charset = ((flags & 0x6) >> 1) + 1;
2619 if (attr->charset == 1)
2620 attr->charset = 2;
2621 attr->exact_spelling = (flags & 0x1) != 0;
2622 attr->set_last_error = (flags & 0x40) != 0;
2623 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2624 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2625 attr->preserve_sig = FALSE;
2627 return attr;
2630 static MonoReflectionMethod *
2631 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2633 MonoMethodInflated *imethod;
2634 MonoMethod *result;
2636 MONO_ARCH_SAVE_REGS;
2638 if (method->method->is_generic)
2639 return method;
2641 if (!method->method->is_inflated)
2642 return NULL;
2644 imethod = (MonoMethodInflated *) method->method;
2646 result = imethod->declaring;
2647 /* Not a generic method. */
2648 if (!result->is_generic)
2649 return NULL;
2651 if (method->method->klass->image->dynamic) {
2652 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2653 MonoReflectionMethod *res;
2656 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2657 * the dynamic case as well ?
2659 mono_loader_lock ();
2660 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2661 mono_loader_unlock ();
2663 if (res)
2664 return res;
2667 if (imethod->context.class_inst) {
2668 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2669 /*Generic methods gets the context of the GTD.*/
2670 if (mono_class_get_context (klass))
2671 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2674 return mono_method_get_object (mono_object_domain (method), result, NULL);
2677 static gboolean
2678 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2680 MONO_ARCH_SAVE_REGS;
2682 return mono_method_signature (method->method)->generic_param_count != 0;
2685 static gboolean
2686 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2688 MONO_ARCH_SAVE_REGS;
2690 return method->method->is_generic;
2693 static MonoArray*
2694 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2696 MonoArray *res;
2697 MonoDomain *domain;
2698 int count, i;
2699 MONO_ARCH_SAVE_REGS;
2701 domain = mono_object_domain (method);
2703 if (method->method->is_inflated) {
2704 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2706 if (inst) {
2707 count = inst->type_argc;
2708 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2710 for (i = 0; i < count; i++)
2711 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2713 return res;
2717 count = mono_method_signature (method->method)->generic_param_count;
2718 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2720 for (i = 0; i < count; i++) {
2721 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2722 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2723 MonoClass *pklass = mono_class_from_generic_parameter (
2724 param, method->method->klass->image, TRUE);
2725 mono_array_setref (res, i,
2726 mono_type_get_object (domain, &pklass->byval_arg));
2729 return res;
2732 static MonoObject *
2733 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2736 * Invoke from reflection is supposed to always be a virtual call (the API
2737 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2738 * greater flexibility.
2740 MonoMethod *m = method->method;
2741 int pcount;
2742 void *obj = this;
2744 MONO_ARCH_SAVE_REGS;
2746 *exc = NULL;
2748 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2749 mono_security_core_clr_ensure_reflection_access_method (m);
2751 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2752 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2753 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2754 return NULL;
2757 if (this) {
2758 if (!mono_object_isinst (this, m->klass)) {
2759 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2760 return NULL;
2762 m = mono_object_get_virtual_method (this, m);
2763 /* must pass the pointer to the value for valuetype methods */
2764 if (m->klass->valuetype)
2765 obj = mono_object_unbox (this);
2766 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2767 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2768 return NULL;
2772 pcount = params? mono_array_length (params): 0;
2773 if (pcount != mono_method_signature (m)->param_count) {
2774 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2775 return NULL;
2778 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2779 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2780 return NULL;
2783 if (m->klass->image->assembly->ref_only) {
2784 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2785 return NULL;
2788 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2789 int i;
2790 uintptr_t *lengths;
2791 intptr_t *lower_bounds;
2792 pcount = mono_array_length (params);
2793 lengths = alloca (sizeof (uintptr_t) * pcount);
2794 /* Note: the synthetized array .ctors have int32 as argument type */
2795 for (i = 0; i < pcount; ++i)
2796 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2798 if (m->klass->rank == pcount) {
2799 /* Only lengths provided. */
2800 lower_bounds = NULL;
2801 } else {
2802 g_assert (pcount == (m->klass->rank * 2));
2803 /* lower bounds are first. */
2804 lower_bounds = (intptr_t*)lengths;
2805 lengths += m->klass->rank;
2808 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2810 return mono_runtime_invoke_array (m, obj, params, NULL);
2813 static MonoObject *
2814 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2816 MonoDomain *domain = mono_object_domain (method);
2817 MonoMethod *m = method->method;
2818 MonoMethodSignature *sig = mono_method_signature (m);
2819 MonoArray *out_args;
2820 MonoObject *result;
2821 int i, j, outarg_count = 0;
2823 MONO_ARCH_SAVE_REGS;
2825 if (m->klass == mono_defaults.object_class) {
2827 if (!strcmp (m->name, "FieldGetter")) {
2828 MonoClass *k = this->vtable->klass;
2829 MonoString *name;
2830 char *str;
2832 /* If this is a proxy, then it must be a CBO */
2833 if (k == mono_defaults.transparent_proxy_class) {
2834 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2835 this = tp->rp->unwrapped_server;
2836 g_assert (this);
2837 k = this->vtable->klass;
2840 name = mono_array_get (params, MonoString *, 1);
2841 str = mono_string_to_utf8 (name);
2843 do {
2844 MonoClassField* field = mono_class_get_field_from_name (k, str);
2845 if (field) {
2846 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2847 if (field_klass->valuetype)
2848 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2849 else
2850 result = *((gpointer *)((char *)this + field->offset));
2852 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2853 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2854 mono_array_setref (out_args, 0, result);
2855 g_free (str);
2856 return NULL;
2858 k = k->parent;
2859 } while (k);
2861 g_free (str);
2862 g_assert_not_reached ();
2864 } else if (!strcmp (m->name, "FieldSetter")) {
2865 MonoClass *k = this->vtable->klass;
2866 MonoString *name;
2867 guint32 size;
2868 gint32 align;
2869 char *str;
2871 /* If this is a proxy, then it must be a CBO */
2872 if (k == mono_defaults.transparent_proxy_class) {
2873 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2874 this = tp->rp->unwrapped_server;
2875 g_assert (this);
2876 k = this->vtable->klass;
2879 name = mono_array_get (params, MonoString *, 1);
2880 str = mono_string_to_utf8 (name);
2882 do {
2883 MonoClassField* field = mono_class_get_field_from_name (k, str);
2884 if (field) {
2885 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2886 MonoObject *val = mono_array_get (params, gpointer, 2);
2888 if (field_klass->valuetype) {
2889 size = mono_type_size (field->type, &align);
2890 g_assert (size == mono_class_value_size (field_klass, NULL));
2891 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2892 } else {
2893 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2896 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2897 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2899 g_free (str);
2900 return NULL;
2903 k = k->parent;
2904 } while (k);
2906 g_free (str);
2907 g_assert_not_reached ();
2912 for (i = 0; i < mono_array_length (params); i++) {
2913 if (sig->params [i]->byref)
2914 outarg_count++;
2917 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2919 /* handle constructors only for objects already allocated */
2920 if (!strcmp (method->method->name, ".ctor"))
2921 g_assert (this);
2923 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2924 g_assert (!method->method->klass->valuetype);
2925 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2927 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2928 if (sig->params [i]->byref) {
2929 gpointer arg;
2930 arg = mono_array_get (params, gpointer, i);
2931 mono_array_setref (out_args, j, arg);
2932 j++;
2936 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2938 return result;
2941 static guint64
2942 read_enum_value (char *mem, int type)
2944 switch (type) {
2945 case MONO_TYPE_U1:
2946 return *(guint8*)mem;
2947 case MONO_TYPE_I1:
2948 return *(gint8*)mem;
2949 case MONO_TYPE_U2:
2950 return *(guint16*)mem;
2951 case MONO_TYPE_I2:
2952 return *(gint16*)mem;
2953 case MONO_TYPE_U4:
2954 return *(guint32*)mem;
2955 case MONO_TYPE_I4:
2956 return *(gint32*)mem;
2957 case MONO_TYPE_U8:
2958 return *(guint64*)mem;
2959 case MONO_TYPE_I8:
2960 return *(gint64*)mem;
2961 default:
2962 g_assert_not_reached ();
2964 return 0;
2967 static void
2968 write_enum_value (char *mem, int type, guint64 value)
2970 switch (type) {
2971 case MONO_TYPE_U1:
2972 case MONO_TYPE_I1: {
2973 guint8 *p = (guint8*)mem;
2974 *p = value;
2975 break;
2977 case MONO_TYPE_U2:
2978 case MONO_TYPE_I2: {
2979 guint16 *p = (void*)mem;
2980 *p = value;
2981 break;
2983 case MONO_TYPE_U4:
2984 case MONO_TYPE_I4: {
2985 guint32 *p = (void*)mem;
2986 *p = value;
2987 break;
2989 case MONO_TYPE_U8:
2990 case MONO_TYPE_I8: {
2991 guint64 *p = (void*)mem;
2992 *p = value;
2993 break;
2995 default:
2996 g_assert_not_reached ();
2998 return;
3001 static MonoObject *
3002 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3004 MonoDomain *domain;
3005 MonoClass *enumc, *objc;
3006 MonoObject *res;
3007 MonoType *etype;
3008 guint64 val;
3010 MONO_ARCH_SAVE_REGS;
3012 MONO_CHECK_ARG_NULL (enumType);
3013 MONO_CHECK_ARG_NULL (value);
3015 domain = mono_object_domain (enumType);
3016 enumc = mono_class_from_mono_type (enumType->type);
3018 mono_class_init_or_throw (enumc);
3020 objc = value->vtable->klass;
3022 if (!enumc->enumtype)
3023 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3024 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3025 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."));
3027 etype = mono_class_enum_basetype (enumc);
3028 if (!etype)
3029 /* MS throws this for typebuilders */
3030 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3032 res = mono_object_new (domain, enumc);
3033 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3034 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3036 return res;
3039 static MonoObject *
3040 ves_icall_System_Enum_get_value (MonoObject *this)
3042 MonoObject *res;
3043 MonoClass *enumc;
3044 gpointer dst;
3045 gpointer src;
3046 int size;
3048 MONO_ARCH_SAVE_REGS;
3050 if (!this)
3051 return NULL;
3053 g_assert (this->vtable->klass->enumtype);
3055 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3056 res = mono_object_new (mono_object_domain (this), enumc);
3057 dst = (char *)res + sizeof (MonoObject);
3058 src = (char *)this + sizeof (MonoObject);
3059 size = mono_class_value_size (enumc, NULL);
3061 memcpy (dst, src, size);
3063 return res;
3066 static MonoReflectionType *
3067 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3069 MonoType *etype;
3070 MonoClass *klass;
3072 MONO_ARCH_SAVE_REGS;
3074 klass = mono_class_from_mono_type (type->type);
3075 mono_class_init_or_throw (klass);
3077 etype = mono_class_enum_basetype (klass);
3078 if (!etype)
3079 /* MS throws this for typebuilders */
3080 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3082 return mono_type_get_object (mono_object_domain (type), etype);
3085 static int
3086 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3088 gpointer tdata = (char *)this + sizeof (MonoObject);
3089 gpointer odata = (char *)other + sizeof (MonoObject);
3090 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3091 g_assert (basetype);
3093 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3094 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3095 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3096 if (me == other) \
3097 return 0; \
3098 return me > other ? 1 : -1; \
3099 } while (0)
3101 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3102 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3103 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3104 if (me == other) \
3105 return 0; \
3106 return me - other; \
3107 } while (0)
3109 switch (basetype->type) {
3110 case MONO_TYPE_U1:
3111 COMPARE_ENUM_VALUES (guint8);
3112 case MONO_TYPE_I1:
3113 COMPARE_ENUM_VALUES (gint8);
3114 case MONO_TYPE_CHAR:
3115 case MONO_TYPE_U2:
3116 COMPARE_ENUM_VALUES_RANGE (guint16);
3117 case MONO_TYPE_I2:
3118 COMPARE_ENUM_VALUES (gint16);
3119 case MONO_TYPE_U4:
3120 COMPARE_ENUM_VALUES (guint32);
3121 case MONO_TYPE_I4:
3122 COMPARE_ENUM_VALUES (gint32);
3123 case MONO_TYPE_U8:
3124 COMPARE_ENUM_VALUES (guint64);
3125 case MONO_TYPE_I8:
3126 COMPARE_ENUM_VALUES (gint64);
3127 default:
3128 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3130 #undef COMPARE_ENUM_VALUES_RANGE
3131 #undef COMPARE_ENUM_VALUES
3132 return 0;
3135 static int
3136 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3138 gpointer data = (char *)this + sizeof (MonoObject);
3139 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3140 g_assert (basetype);
3142 switch (basetype->type) {
3143 case MONO_TYPE_I1:
3144 return *((gint8*)data);
3145 case MONO_TYPE_U1:
3146 return *((guint8*)data);
3147 case MONO_TYPE_CHAR:
3148 case MONO_TYPE_U2:
3149 return *((guint16*)data);
3151 case MONO_TYPE_I2:
3152 return *((gint16*)data);
3153 case MONO_TYPE_U4:
3154 return *((guint32*)data);
3155 case MONO_TYPE_I4:
3156 return *((gint32*)data);
3157 case MONO_TYPE_U8:
3158 case MONO_TYPE_I8: {
3159 gint64 value = *((gint64*)data);
3160 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3162 default:
3163 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3165 return 0;
3168 static void
3169 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3171 MonoDomain *domain = mono_object_domain (type);
3172 MonoClass *enumc = mono_class_from_mono_type (type->type);
3173 guint j = 0, nvalues, crow;
3174 gpointer iter;
3175 MonoClassField *field;
3177 MONO_ARCH_SAVE_REGS;
3179 mono_class_init_or_throw (enumc);
3181 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3182 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3183 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3184 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3186 crow = -1;
3187 iter = NULL;
3188 while ((field = mono_class_get_fields (enumc, &iter))) {
3189 const char *p;
3190 int len;
3191 MonoTypeEnum def_type;
3193 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3194 continue;
3195 if (mono_field_is_deleted (field))
3196 continue;
3197 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3199 p = mono_class_get_field_default_value (field, &def_type);
3200 len = mono_metadata_decode_blob_size (p, &p);
3201 switch (mono_class_enum_basetype (enumc)->type) {
3202 case MONO_TYPE_U1:
3203 case MONO_TYPE_I1:
3204 mono_array_set (info->values, gchar, j, *p);
3205 break;
3206 case MONO_TYPE_CHAR:
3207 case MONO_TYPE_U2:
3208 case MONO_TYPE_I2:
3209 mono_array_set (info->values, gint16, j, read16 (p));
3210 break;
3211 case MONO_TYPE_U4:
3212 case MONO_TYPE_I4:
3213 mono_array_set (info->values, gint32, j, read32 (p));
3214 break;
3215 case MONO_TYPE_U8:
3216 case MONO_TYPE_I8:
3217 mono_array_set (info->values, gint64, j, read64 (p));
3218 break;
3219 default:
3220 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3222 ++j;
3226 enum {
3227 BFLAGS_IgnoreCase = 1,
3228 BFLAGS_DeclaredOnly = 2,
3229 BFLAGS_Instance = 4,
3230 BFLAGS_Static = 8,
3231 BFLAGS_Public = 0x10,
3232 BFLAGS_NonPublic = 0x20,
3233 BFLAGS_FlattenHierarchy = 0x40,
3234 BFLAGS_InvokeMethod = 0x100,
3235 BFLAGS_CreateInstance = 0x200,
3236 BFLAGS_GetField = 0x400,
3237 BFLAGS_SetField = 0x800,
3238 BFLAGS_GetProperty = 0x1000,
3239 BFLAGS_SetProperty = 0x2000,
3240 BFLAGS_ExactBinding = 0x10000,
3241 BFLAGS_SuppressChangeType = 0x20000,
3242 BFLAGS_OptionalParamBinding = 0x40000
3245 static MonoReflectionField *
3246 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3248 MonoDomain *domain;
3249 MonoClass *startklass, *klass;
3250 int match;
3251 MonoClassField *field;
3252 gpointer iter;
3253 char *utf8_name;
3254 int (*compare_func) (const char *s1, const char *s2) = NULL;
3255 domain = ((MonoObject *)type)->vtable->domain;
3256 klass = startklass = mono_class_from_mono_type (type->type);
3257 mono_class_init_or_throw (klass);
3259 if (!name)
3260 mono_raise_exception (mono_get_exception_argument_null ("name"));
3261 if (type->type->byref)
3262 return NULL;
3264 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3266 handle_parent:
3267 if (klass->exception_type != MONO_EXCEPTION_NONE)
3268 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3270 iter = NULL;
3271 while ((field = mono_class_get_fields (klass, &iter))) {
3272 match = 0;
3274 if (field->type == NULL)
3275 continue;
3276 if (mono_field_is_deleted (field))
3277 continue;
3278 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3279 if (bflags & BFLAGS_Public)
3280 match++;
3281 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3282 if (bflags & BFLAGS_NonPublic) {
3283 match++;
3286 if (!match)
3287 continue;
3288 match = 0;
3289 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3290 if (bflags & BFLAGS_Static)
3291 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3292 match++;
3293 } else {
3294 if (bflags & BFLAGS_Instance)
3295 match++;
3298 if (!match)
3299 continue;
3301 utf8_name = mono_string_to_utf8 (name);
3303 if (compare_func (mono_field_get_name (field), utf8_name)) {
3304 g_free (utf8_name);
3305 continue;
3307 g_free (utf8_name);
3309 return mono_field_get_object (domain, klass, field);
3311 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3312 goto handle_parent;
3314 return NULL;
3317 static MonoArray*
3318 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3320 MonoDomain *domain;
3321 MonoClass *startklass, *klass, *refklass;
3322 MonoArray *res;
3323 MonoObject *member;
3324 int i, match;
3325 gpointer iter;
3326 MonoClassField *field;
3327 MonoPtrArray tmp_array;
3329 MONO_ARCH_SAVE_REGS;
3331 domain = ((MonoObject *)type)->vtable->domain;
3332 if (type->type->byref)
3333 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3334 klass = startklass = mono_class_from_mono_type (type->type);
3335 refklass = mono_class_from_mono_type (reftype->type);
3337 mono_class_init_or_throw (klass);
3338 mono_class_init_or_throw (refklass);
3340 mono_ptr_array_init (tmp_array, 2);
3342 handle_parent:
3343 if (klass->exception_type != MONO_EXCEPTION_NONE)
3344 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3346 iter = NULL;
3347 while ((field = mono_class_get_fields (klass, &iter))) {
3348 match = 0;
3349 if (mono_field_is_deleted (field))
3350 continue;
3351 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3352 if (bflags & BFLAGS_Public)
3353 match++;
3354 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3355 if (bflags & BFLAGS_NonPublic) {
3356 match++;
3359 if (!match)
3360 continue;
3361 match = 0;
3362 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3363 if (bflags & BFLAGS_Static)
3364 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3365 match++;
3366 } else {
3367 if (bflags & BFLAGS_Instance)
3368 match++;
3371 if (!match)
3372 continue;
3373 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3374 mono_ptr_array_append (tmp_array, member);
3376 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3377 goto handle_parent;
3379 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3381 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3382 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3384 mono_ptr_array_destroy (tmp_array);
3386 return res;
3389 static gboolean
3390 method_nonpublic (MonoMethod* method, gboolean start_klass)
3392 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3393 case METHOD_ATTRIBUTE_ASSEM:
3394 return (start_klass || mono_defaults.generic_ilist_class);
3395 case METHOD_ATTRIBUTE_PRIVATE:
3396 return start_klass;
3397 case METHOD_ATTRIBUTE_PUBLIC:
3398 return FALSE;
3399 default:
3400 return TRUE;
3404 static MonoArray*
3405 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3407 static MonoClass *MethodInfo_array;
3408 MonoDomain *domain;
3409 MonoClass *startklass, *klass, *refklass;
3410 MonoArray *res;
3411 MonoMethod *method;
3412 gpointer iter;
3413 MonoObject *member;
3414 int i, len, match, nslots;
3415 /*FIXME, use MonoBitSet*/
3416 guint32 method_slots_default [8];
3417 guint32 *method_slots = NULL;
3418 gchar *mname = NULL;
3419 int (*compare_func) (const char *s1, const char *s2) = NULL;
3420 MonoVTable *array_vtable;
3421 MonoException *ex;
3422 MonoPtrArray tmp_array;
3424 mono_ptr_array_init (tmp_array, 4);
3426 if (!MethodInfo_array) {
3427 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3428 mono_memory_barrier ();
3429 MethodInfo_array = klass;
3432 domain = ((MonoObject *)type)->vtable->domain;
3433 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3434 if (type->type->byref)
3435 return mono_array_new_specific (array_vtable, 0);
3436 klass = startklass = mono_class_from_mono_type (type->type);
3437 refklass = mono_class_from_mono_type (reftype->type);
3439 mono_class_init_or_throw (klass);
3440 mono_class_init_or_throw (refklass);
3442 len = 0;
3443 if (name != NULL) {
3444 mname = mono_string_to_utf8 (name);
3445 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3448 /* An optimization for calls made from Delegate:CreateDelegate () */
3449 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3450 method = mono_get_delegate_invoke (klass);
3451 if (mono_loader_get_last_error ())
3452 goto loader_error;
3454 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3456 res = mono_array_new_specific (array_vtable, 1);
3457 mono_array_setref (res, 0, member);
3458 g_free (mname);
3459 return res;
3462 mono_class_setup_vtable (klass);
3463 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3464 goto loader_error;
3466 if (is_generic_parameter (type->type))
3467 nslots = mono_class_get_vtable_size (klass->parent);
3468 else
3469 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3470 if (nslots >= sizeof (method_slots_default) * 8) {
3471 method_slots = g_new0 (guint32, nslots / 32 + 1);
3472 } else {
3473 method_slots = method_slots_default;
3474 memset (method_slots, 0, sizeof (method_slots_default));
3476 handle_parent:
3477 mono_class_setup_vtable (klass);
3478 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3479 goto loader_error;
3481 iter = NULL;
3482 while ((method = mono_class_get_methods (klass, &iter))) {
3483 match = 0;
3484 if (method->slot != -1) {
3485 g_assert (method->slot < nslots);
3486 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3487 continue;
3488 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3489 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3492 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3493 continue;
3494 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3495 if (bflags & BFLAGS_Public)
3496 match++;
3497 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3498 match++;
3500 if (!match)
3501 continue;
3502 match = 0;
3503 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3504 if (bflags & BFLAGS_Static)
3505 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3506 match++;
3507 } else {
3508 if (bflags & BFLAGS_Instance)
3509 match++;
3512 if (!match)
3513 continue;
3515 if (name != NULL) {
3516 if (compare_func (mname, method->name))
3517 continue;
3520 match = 0;
3522 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3524 mono_ptr_array_append (tmp_array, member);
3526 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3527 goto handle_parent;
3529 g_free (mname);
3530 if (method_slots != method_slots_default)
3531 g_free (method_slots);
3533 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3535 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3536 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3538 mono_ptr_array_destroy (tmp_array);
3539 return res;
3541 loader_error:
3542 g_free (mname);
3543 if (method_slots != method_slots_default)
3544 g_free (method_slots);
3545 mono_ptr_array_destroy (tmp_array);
3546 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3547 ex = mono_class_get_exception_for_failure (klass);
3548 } else {
3549 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3550 mono_loader_clear_error ();
3552 mono_raise_exception (ex);
3553 return NULL;
3556 static MonoArray*
3557 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3559 MonoDomain *domain;
3560 static MonoClass *System_Reflection_ConstructorInfo;
3561 MonoClass *startklass, *klass, *refklass;
3562 MonoArray *res;
3563 MonoMethod *method;
3564 MonoObject *member;
3565 int i, match;
3566 gpointer iter = NULL;
3567 MonoPtrArray tmp_array;
3569 MONO_ARCH_SAVE_REGS;
3571 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3573 domain = ((MonoObject *)type)->vtable->domain;
3574 if (type->type->byref)
3575 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3576 klass = startklass = mono_class_from_mono_type (type->type);
3577 refklass = mono_class_from_mono_type (reftype->type);
3579 mono_class_init_or_throw (klass);
3580 mono_class_init_or_throw (refklass);
3582 if (klass->exception_type != MONO_EXCEPTION_NONE)
3583 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3585 if (!System_Reflection_ConstructorInfo)
3586 System_Reflection_ConstructorInfo = mono_class_from_name (
3587 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3589 iter = NULL;
3590 while ((method = mono_class_get_methods (klass, &iter))) {
3591 match = 0;
3592 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3593 continue;
3594 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3595 if (bflags & BFLAGS_Public)
3596 match++;
3597 } else {
3598 if (bflags & BFLAGS_NonPublic)
3599 match++;
3601 if (!match)
3602 continue;
3603 match = 0;
3604 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3605 if (bflags & BFLAGS_Static)
3606 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3607 match++;
3608 } else {
3609 if (bflags & BFLAGS_Instance)
3610 match++;
3613 if (!match)
3614 continue;
3615 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3617 mono_ptr_array_append (tmp_array, member);
3620 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3622 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3623 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3625 mono_ptr_array_destroy (tmp_array);
3627 return res;
3630 static guint
3631 property_hash (gconstpointer data)
3633 MonoProperty *prop = (MonoProperty*)data;
3635 return g_str_hash (prop->name);
3638 static gboolean
3639 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3641 // Properties are hide-by-name-and-signature
3642 if (!g_str_equal (prop1->name, prop2->name))
3643 return FALSE;
3645 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3646 return FALSE;
3647 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3648 return FALSE;
3649 return TRUE;
3652 static gboolean
3653 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3655 if (!accessor)
3656 return FALSE;
3658 return method_nonpublic (accessor, start_klass);
3661 static MonoArray*
3662 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3664 MonoDomain *domain;
3665 static MonoClass *System_Reflection_PropertyInfo;
3666 MonoClass *startklass, *klass;
3667 MonoArray *res;
3668 MonoMethod *method;
3669 MonoProperty *prop;
3670 int i, match;
3671 guint32 flags;
3672 gchar *propname = NULL;
3673 int (*compare_func) (const char *s1, const char *s2) = NULL;
3674 gpointer iter;
3675 GHashTable *properties;
3676 MonoPtrArray tmp_array;
3678 MONO_ARCH_SAVE_REGS;
3680 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3682 if (!System_Reflection_PropertyInfo)
3683 System_Reflection_PropertyInfo = mono_class_from_name (
3684 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3686 domain = ((MonoObject *)type)->vtable->domain;
3687 if (type->type->byref)
3688 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3689 klass = startklass = mono_class_from_mono_type (type->type);
3690 mono_class_init_or_throw (klass);
3694 if (name != NULL) {
3695 propname = mono_string_to_utf8 (name);
3696 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3699 mono_class_setup_vtable (klass);
3701 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3702 handle_parent:
3703 mono_class_setup_vtable (klass);
3704 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3705 g_hash_table_destroy (properties);
3706 if (name != NULL)
3707 g_free (propname);
3708 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3711 iter = NULL;
3712 while ((prop = mono_class_get_properties (klass, &iter))) {
3713 match = 0;
3714 method = prop->get;
3715 if (!method)
3716 method = prop->set;
3717 if (method)
3718 flags = method->flags;
3719 else
3720 flags = 0;
3721 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3722 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3723 if (bflags & BFLAGS_Public)
3724 match++;
3725 } else if (bflags & BFLAGS_NonPublic) {
3726 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3727 property_accessor_nonpublic(prop->set, startklass == klass)) {
3728 match++;
3731 if (!match)
3732 continue;
3733 match = 0;
3734 if (flags & METHOD_ATTRIBUTE_STATIC) {
3735 if (bflags & BFLAGS_Static)
3736 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3737 match++;
3738 } else {
3739 if (bflags & BFLAGS_Instance)
3740 match++;
3743 if (!match)
3744 continue;
3745 match = 0;
3747 if (name != NULL) {
3748 if (compare_func (propname, prop->name))
3749 continue;
3752 if (g_hash_table_lookup (properties, prop))
3753 continue;
3755 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3757 g_hash_table_insert (properties, prop, prop);
3759 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3760 goto handle_parent;
3762 g_hash_table_destroy (properties);
3763 g_free (propname);
3765 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3766 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3767 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3769 mono_ptr_array_destroy (tmp_array);
3771 return res;
3774 static MonoReflectionEvent *
3775 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3777 MonoDomain *domain;
3778 MonoClass *klass, *startklass;
3779 gpointer iter;
3780 MonoEvent *event;
3781 MonoMethod *method;
3782 gchar *event_name;
3783 int (*compare_func) (const char *s1, const char *s2);
3785 MONO_ARCH_SAVE_REGS;
3787 event_name = mono_string_to_utf8 (name);
3788 if (type->type->byref)
3789 return NULL;
3790 klass = startklass = mono_class_from_mono_type (type->type);
3791 domain = mono_object_domain (type);
3793 mono_class_init_or_throw (klass);
3795 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3796 handle_parent:
3797 if (klass->exception_type != MONO_EXCEPTION_NONE)
3798 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3800 iter = NULL;
3801 while ((event = mono_class_get_events (klass, &iter))) {
3802 if (compare_func (event->name, event_name))
3803 continue;
3805 method = event->add;
3806 if (!method)
3807 method = event->remove;
3808 if (!method)
3809 method = event->raise;
3810 if (method) {
3811 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3812 if (!(bflags & BFLAGS_Public))
3813 continue;
3814 } else {
3815 if (!(bflags & BFLAGS_NonPublic))
3816 continue;
3817 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3818 continue;
3821 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3822 if (!(bflags & BFLAGS_Static))
3823 continue;
3824 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3825 continue;
3826 } else {
3827 if (!(bflags & BFLAGS_Instance))
3828 continue;
3830 } else
3831 if (!(bflags & BFLAGS_NonPublic))
3832 continue;
3834 g_free (event_name);
3835 return mono_event_get_object (domain, startklass, event);
3838 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3839 goto handle_parent;
3841 g_free (event_name);
3842 return NULL;
3845 static MonoArray*
3846 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3848 MonoDomain *domain;
3849 static MonoClass *System_Reflection_EventInfo;
3850 MonoClass *startklass, *klass;
3851 MonoArray *res;
3852 MonoMethod *method;
3853 MonoEvent *event;
3854 int i, match;
3855 gpointer iter;
3857 MonoPtrArray tmp_array;
3859 MONO_ARCH_SAVE_REGS;
3861 mono_ptr_array_init (tmp_array, 4);
3863 if (!System_Reflection_EventInfo)
3864 System_Reflection_EventInfo = mono_class_from_name (
3865 mono_defaults.corlib, "System.Reflection", "EventInfo");
3867 domain = mono_object_domain (type);
3868 if (type->type->byref)
3869 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3870 klass = startklass = mono_class_from_mono_type (type->type);
3871 mono_class_init_or_throw (klass);
3874 handle_parent:
3875 if (klass->exception_type != MONO_EXCEPTION_NONE)
3876 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3878 iter = NULL;
3879 while ((event = mono_class_get_events (klass, &iter))) {
3880 match = 0;
3881 method = event->add;
3882 if (!method)
3883 method = event->remove;
3884 if (!method)
3885 method = event->raise;
3886 if (method) {
3887 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3888 if (bflags & BFLAGS_Public)
3889 match++;
3890 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3891 if (bflags & BFLAGS_NonPublic)
3892 match++;
3895 else
3896 if (bflags & BFLAGS_NonPublic)
3897 match ++;
3898 if (!match)
3899 continue;
3900 match = 0;
3901 if (method) {
3902 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3903 if (bflags & BFLAGS_Static)
3904 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3905 match++;
3906 } else {
3907 if (bflags & BFLAGS_Instance)
3908 match++;
3911 else
3912 if (bflags & BFLAGS_Instance)
3913 match ++;
3914 if (!match)
3915 continue;
3916 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3918 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3919 goto handle_parent;
3921 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3923 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3924 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3926 mono_ptr_array_destroy (tmp_array);
3928 return res;
3931 static MonoReflectionType *
3932 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3934 MonoDomain *domain;
3935 MonoClass *klass;
3936 MonoClass *nested;
3937 char *str;
3938 gpointer iter;
3940 MONO_ARCH_SAVE_REGS;
3942 if (name == NULL)
3943 mono_raise_exception (mono_get_exception_argument_null ("name"));
3945 domain = ((MonoObject *)type)->vtable->domain;
3946 if (type->type->byref)
3947 return NULL;
3948 klass = mono_class_from_mono_type (type->type);
3949 mono_class_init_or_throw (klass);
3951 str = mono_string_to_utf8 (name);
3953 handle_parent:
3954 if (klass->exception_type != MONO_EXCEPTION_NONE)
3955 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3958 * If a nested type is generic, return its generic type definition.
3959 * Note that this means that the return value is essentially a
3960 * nested type of the generic type definition of @klass.
3962 * A note in MSDN claims that a generic type definition can have
3963 * nested types that aren't generic. In any case, the container of that
3964 * nested type would be the generic type definition.
3966 if (klass->generic_class)
3967 klass = klass->generic_class->container_class;
3969 iter = NULL;
3970 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3971 int match = 0;
3972 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3973 if (bflags & BFLAGS_Public)
3974 match++;
3975 } else {
3976 if (bflags & BFLAGS_NonPublic)
3977 match++;
3979 if (!match)
3980 continue;
3981 if (strcmp (nested->name, str) == 0){
3982 g_free (str);
3983 return mono_type_get_object (domain, &nested->byval_arg);
3986 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3987 goto handle_parent;
3988 g_free (str);
3989 return NULL;
3992 static MonoArray*
3993 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
3995 MonoDomain *domain;
3996 MonoClass *klass;
3997 MonoArray *res;
3998 MonoObject *member;
3999 int i, match;
4000 MonoClass *nested;
4001 gpointer iter;
4002 MonoPtrArray tmp_array;
4004 MONO_ARCH_SAVE_REGS;
4006 domain = ((MonoObject *)type)->vtable->domain;
4007 if (type->type->byref)
4008 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4009 klass = mono_class_from_mono_type (type->type);
4010 mono_class_init_or_throw (klass);
4013 * If a nested type is generic, return its generic type definition.
4014 * Note that this means that the return value is essentially the set
4015 * of nested types of the generic type definition of @klass.
4017 * A note in MSDN claims that a generic type definition can have
4018 * nested types that aren't generic. In any case, the container of that
4019 * nested type would be the generic type definition.
4021 if (klass->generic_class)
4022 klass = klass->generic_class->container_class;
4024 mono_ptr_array_init (tmp_array, 1);
4025 iter = NULL;
4026 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4027 match = 0;
4028 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4029 if (bflags & BFLAGS_Public)
4030 match++;
4031 } else {
4032 if (bflags & BFLAGS_NonPublic)
4033 match++;
4035 if (!match)
4036 continue;
4037 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4038 mono_ptr_array_append (tmp_array, member);
4041 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4043 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4044 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4046 mono_ptr_array_destroy (tmp_array);
4048 return res;
4051 static MonoReflectionType*
4052 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4054 gchar *str;
4055 MonoType *type = NULL;
4056 MonoTypeNameParse info;
4057 gboolean type_resolve;
4059 MONO_ARCH_SAVE_REGS;
4061 /* On MS.NET, this does not fire a TypeResolve event */
4062 type_resolve = TRUE;
4063 str = mono_string_to_utf8 (name);
4064 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4065 if (!mono_reflection_parse_type (str, &info)) {
4066 g_free (str);
4067 mono_reflection_free_type_info (&info);
4068 if (throwOnError) /* uhm: this is a parse error, though... */
4069 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4070 /*g_print ("failed parse\n");*/
4071 return NULL;
4074 if (info.assembly.name) {
4075 g_free (str);
4076 mono_reflection_free_type_info (&info);
4077 if (throwOnError) {
4078 /* 1.0 and 2.0 throw different exceptions */
4079 if (mono_defaults.generic_ilist_class)
4080 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4081 else
4082 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4084 return NULL;
4087 if (module != NULL) {
4088 if (module->image)
4089 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4090 else
4091 type = NULL;
4093 else
4094 if (assembly->assembly->dynamic) {
4095 /* Enumerate all modules */
4096 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4097 int i;
4099 type = NULL;
4100 if (abuilder->modules) {
4101 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4102 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4103 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4104 if (type)
4105 break;
4109 if (!type && abuilder->loaded_modules) {
4110 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4111 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4112 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4113 if (type)
4114 break;
4118 else
4119 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4120 g_free (str);
4121 mono_reflection_free_type_info (&info);
4122 if (!type) {
4123 MonoException *e = NULL;
4125 if (throwOnError)
4126 e = mono_get_exception_type_load (name, NULL);
4128 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4129 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4131 mono_loader_clear_error ();
4133 if (e != NULL)
4134 mono_raise_exception (e);
4136 return NULL;
4139 if (type->type == MONO_TYPE_CLASS) {
4140 MonoClass *klass = mono_type_get_class (type);
4142 if (mono_is_security_manager_active () && !klass->exception_type)
4143 /* Some security problems are detected during generic vtable construction */
4144 mono_class_setup_vtable (klass);
4145 /* need to report exceptions ? */
4146 if (throwOnError && klass->exception_type) {
4147 /* report SecurityException (or others) that occured when loading the assembly */
4148 MonoException *exc = mono_class_get_exception_for_failure (klass);
4149 mono_loader_clear_error ();
4150 mono_raise_exception (exc);
4151 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4152 return NULL;
4156 /* g_print ("got it\n"); */
4157 return mono_type_get_object (mono_object_domain (assembly), type);
4160 static gboolean
4161 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4163 gchar *content;
4164 gchar *shadow_ini_file;
4165 gsize len;
4167 /* Check for shadow-copied assembly */
4168 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4169 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4170 content = NULL;
4171 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4172 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4173 if (content) {
4174 g_free (content);
4175 content = NULL;
4178 g_free (shadow_ini_file);
4179 if (content != NULL) {
4180 if (*filename)
4181 g_free (*filename);
4182 *filename = content;
4183 return TRUE;
4186 return FALSE;
4189 static MonoString *
4190 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4192 MonoDomain *domain = mono_object_domain (assembly);
4193 MonoAssembly *mass = assembly->assembly;
4194 MonoString *res = NULL;
4195 gchar *uri;
4196 gchar *absolute;
4197 gchar *dirname;
4199 MONO_ARCH_SAVE_REGS;
4201 if (g_path_is_absolute (mass->image->name)) {
4202 absolute = g_strdup (mass->image->name);
4203 dirname = g_path_get_dirname (absolute);
4204 } else {
4205 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4206 dirname = g_strdup (mass->basedir);
4209 replace_shadow_path (domain, dirname, &absolute);
4210 g_free (dirname);
4211 #if HOST_WIN32
4213 gint i;
4214 for (i = strlen (absolute) - 1; i >= 0; i--)
4215 if (absolute [i] == '\\')
4216 absolute [i] = '/';
4218 #endif
4219 if (escaped) {
4220 uri = g_filename_to_uri (absolute, NULL, NULL);
4221 } else {
4222 const char *prepend = "file://";
4223 #if HOST_WIN32
4224 if (*absolute == '/' && *(absolute + 1) == '/') {
4225 prepend = "file:";
4226 } else {
4227 prepend = "file:///";
4229 #endif
4230 uri = g_strconcat (prepend, absolute, NULL);
4233 if (uri) {
4234 res = mono_string_new (domain, uri);
4235 g_free (uri);
4237 g_free (absolute);
4238 return res;
4241 static MonoBoolean
4242 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4244 MonoAssembly *mass = assembly->assembly;
4246 MONO_ARCH_SAVE_REGS;
4248 return mass->in_gac;
4251 static MonoReflectionAssembly*
4252 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4254 gchar *name;
4255 MonoAssembly *res;
4256 MonoImageOpenStatus status;
4258 MONO_ARCH_SAVE_REGS;
4260 name = mono_string_to_utf8 (mname);
4261 res = mono_assembly_load_with_partial_name (name, &status);
4263 g_free (name);
4265 if (res == NULL)
4266 return NULL;
4267 return mono_assembly_get_object (mono_domain_get (), res);
4270 static MonoString *
4271 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4273 MonoDomain *domain = mono_object_domain (assembly);
4274 MonoString *res;
4276 MONO_ARCH_SAVE_REGS;
4278 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4280 return res;
4283 static MonoBoolean
4284 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4286 MONO_ARCH_SAVE_REGS;
4288 return assembly->assembly->ref_only;
4291 static MonoString *
4292 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4294 MonoDomain *domain = mono_object_domain (assembly);
4296 MONO_ARCH_SAVE_REGS;
4298 return mono_string_new (domain, assembly->assembly->image->version);
4301 static MonoReflectionMethod*
4302 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4304 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4306 MONO_ARCH_SAVE_REGS;
4308 if (!token)
4309 return NULL;
4310 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4313 static MonoReflectionModule*
4314 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4316 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4319 static MonoArray*
4320 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4322 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4323 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4324 int i;
4325 const char *val;
4327 MONO_ARCH_SAVE_REGS;
4329 for (i = 0; i < table->rows; ++i) {
4330 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4331 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4333 return result;
4336 static MonoObject*
4337 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4339 static MonoClass *System_Version = NULL;
4340 static MonoMethod *create_version = NULL;
4341 MonoObject *result;
4342 gpointer args [4];
4344 if (!System_Version) {
4345 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4346 g_assert (System_Version);
4349 if (!create_version) {
4350 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4351 create_version = mono_method_desc_search_in_class (desc, System_Version);
4352 g_assert (create_version);
4353 mono_method_desc_free (desc);
4356 args [0] = &major;
4357 args [1] = &minor;
4358 args [2] = &build;
4359 args [3] = &revision;
4360 result = mono_object_new (domain, System_Version);
4361 mono_runtime_invoke (create_version, result, args, NULL);
4363 return result;
4366 static MonoArray*
4367 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4369 static MonoClass *System_Reflection_AssemblyName;
4370 MonoArray *result;
4371 MonoDomain *domain = mono_object_domain (assembly);
4372 int i, count = 0;
4373 static MonoMethod *create_culture = NULL;
4374 MonoImage *image = assembly->assembly->image;
4375 MonoTableInfo *t;
4377 MONO_ARCH_SAVE_REGS;
4379 if (!System_Reflection_AssemblyName)
4380 System_Reflection_AssemblyName = mono_class_from_name (
4381 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4383 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4384 count = t->rows;
4386 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4388 if (count > 0 && !create_culture) {
4389 MonoMethodDesc *desc = mono_method_desc_new (
4390 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4391 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4392 g_assert (create_culture);
4393 mono_method_desc_free (desc);
4396 for (i = 0; i < count; i++) {
4397 MonoReflectionAssemblyName *aname;
4398 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4400 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4402 aname = (MonoReflectionAssemblyName *) mono_object_new (
4403 domain, System_Reflection_AssemblyName);
4405 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4407 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4408 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4409 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4410 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4411 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4412 aname->versioncompat = 1; /* SameMachine (default) */
4413 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4414 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4416 if (create_culture) {
4417 gpointer args [2];
4418 MonoBoolean assembly_ref = 1;
4419 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4420 args [1] = &assembly_ref;
4421 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4424 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4425 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4426 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4428 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4429 /* public key token isn't copied - the class library will
4430 automatically generate it from the public key if required */
4431 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4432 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4433 } else {
4434 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4435 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4437 } else {
4438 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4441 /* note: this function doesn't return the codebase on purpose (i.e. it can
4442 be used under partial trust as path information isn't present). */
4444 mono_array_setref (result, i, aname);
4446 return result;
4449 typedef struct {
4450 MonoArray *res;
4451 int idx;
4452 } NameSpaceInfo;
4454 static void
4455 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4457 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4459 mono_array_setref (info->res, info->idx, name);
4460 info->idx++;
4463 static MonoArray*
4464 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4466 MonoImage *img = assembly->assembly->image;
4467 MonoArray *res;
4468 NameSpaceInfo info;
4469 int len;
4471 MONO_ARCH_SAVE_REGS;
4473 mono_image_lock (img);
4474 mono_image_init_name_cache (img);
4476 RETRY_LEN:
4477 len = g_hash_table_size (img->name_cache);
4478 mono_image_unlock (img);
4480 /*we can't create objects holding the image lock */
4481 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4483 mono_image_lock (img);
4484 /*len might have changed, create a new array*/
4485 if (len != g_hash_table_size (img->name_cache))
4486 goto RETRY_LEN;
4488 info.res = res;
4489 info.idx = 0;
4490 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4491 mono_image_unlock (img);
4493 return res;
4496 /* move this in some file in mono/util/ */
4497 static char *
4498 g_concat_dir_and_file (const char *dir, const char *file)
4500 g_return_val_if_fail (dir != NULL, NULL);
4501 g_return_val_if_fail (file != NULL, NULL);
4504 * If the directory name doesn't have a / on the end, we need
4505 * to add one so we get a proper path to the file
4507 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4508 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4509 else
4510 return g_strconcat (dir, file, NULL);
4513 static void *
4514 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4516 char *n = mono_string_to_utf8 (name);
4517 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4518 guint32 i;
4519 guint32 cols [MONO_MANIFEST_SIZE];
4520 guint32 impl, file_idx;
4521 const char *val;
4522 MonoImage *module;
4524 MONO_ARCH_SAVE_REGS;
4526 for (i = 0; i < table->rows; ++i) {
4527 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4528 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4529 if (strcmp (val, n) == 0)
4530 break;
4532 g_free (n);
4533 if (i == table->rows)
4534 return NULL;
4535 /* FIXME */
4536 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4537 if (impl) {
4539 * this code should only be called after obtaining the
4540 * ResourceInfo and handling the other cases.
4542 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4543 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4545 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4546 if (!module)
4547 return NULL;
4549 else
4550 module = assembly->assembly->image;
4552 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4554 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4557 static gboolean
4558 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4560 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4561 int i;
4562 guint32 cols [MONO_MANIFEST_SIZE];
4563 guint32 file_cols [MONO_FILE_SIZE];
4564 const char *val;
4565 char *n;
4567 MONO_ARCH_SAVE_REGS;
4569 n = mono_string_to_utf8 (name);
4570 for (i = 0; i < table->rows; ++i) {
4571 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4572 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4573 if (strcmp (val, n) == 0)
4574 break;
4576 g_free (n);
4577 if (i == table->rows)
4578 return FALSE;
4580 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4581 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4583 else {
4584 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4585 case MONO_IMPLEMENTATION_FILE:
4586 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4587 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4588 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4589 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4590 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4591 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4592 info->location = 0;
4593 else
4594 info->location = RESOURCE_LOCATION_EMBEDDED;
4595 break;
4597 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4598 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4599 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4600 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4601 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4602 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4603 g_free (msg);
4604 mono_raise_exception (ex);
4606 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4608 /* Obtain info recursively */
4609 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4610 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4611 break;
4613 case MONO_IMPLEMENTATION_EXP_TYPE:
4614 g_assert_not_reached ();
4615 break;
4619 return TRUE;
4622 static MonoObject*
4623 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4625 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4626 MonoArray *result = NULL;
4627 int i, count;
4628 const char *val;
4629 char *n;
4631 MONO_ARCH_SAVE_REGS;
4633 /* check hash if needed */
4634 if (name) {
4635 n = mono_string_to_utf8 (name);
4636 for (i = 0; i < table->rows; ++i) {
4637 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4638 if (strcmp (val, n) == 0) {
4639 MonoString *fn;
4640 g_free (n);
4641 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4642 fn = mono_string_new (mono_object_domain (assembly), n);
4643 g_free (n);
4644 return (MonoObject*)fn;
4647 g_free (n);
4648 return NULL;
4651 count = 0;
4652 for (i = 0; i < table->rows; ++i) {
4653 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4654 count ++;
4657 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4659 count = 0;
4660 for (i = 0; i < table->rows; ++i) {
4661 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4662 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4663 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4664 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4665 g_free (n);
4666 count ++;
4669 return (MonoObject*)result;
4672 static MonoArray*
4673 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4675 MonoDomain *domain = mono_domain_get();
4676 MonoArray *res;
4677 MonoClass *klass;
4678 int i, j, file_count = 0;
4679 MonoImage **modules;
4680 guint32 module_count, real_module_count;
4681 MonoTableInfo *table;
4682 guint32 cols [MONO_FILE_SIZE];
4683 MonoImage *image = assembly->assembly->image;
4685 g_assert (image != NULL);
4686 g_assert (!assembly->assembly->dynamic);
4688 table = &image->tables [MONO_TABLE_FILE];
4689 file_count = table->rows;
4691 modules = image->modules;
4692 module_count = image->module_count;
4694 real_module_count = 0;
4695 for (i = 0; i < module_count; ++i)
4696 if (modules [i])
4697 real_module_count ++;
4699 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4700 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4702 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4703 j = 1;
4704 for (i = 0; i < module_count; ++i)
4705 if (modules [i]) {
4706 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4707 ++j;
4710 for (i = 0; i < file_count; ++i, ++j) {
4711 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4712 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4713 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4714 else {
4715 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4716 if (!m) {
4717 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4718 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4720 mono_array_setref (res, j, mono_module_get_object (domain, m));
4724 return res;
4727 static MonoReflectionMethod*
4728 ves_icall_GetCurrentMethod (void)
4730 MonoMethod *m = mono_method_get_last_managed ();
4732 while (m->is_inflated)
4733 m = ((MonoMethodInflated*)m)->declaring;
4735 return mono_method_get_object (mono_domain_get (), m, NULL);
4739 static MonoMethod*
4740 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4742 int offset = -1, i;
4743 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4744 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4745 //method is inflated, we should inflate it on the other class
4746 MonoGenericContext ctx;
4747 ctx.method_inst = inflated->context.method_inst;
4748 ctx.class_inst = inflated->context.class_inst;
4749 if (klass->generic_class)
4750 ctx.class_inst = klass->generic_class->context.class_inst;
4751 else if (klass->generic_container)
4752 ctx.class_inst = klass->generic_container->context.class_inst;
4753 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4756 mono_class_setup_methods (method->klass);
4757 if (method->klass->exception_type)
4758 return NULL;
4759 for (i = 0; i < method->klass->method.count; ++i) {
4760 if (method->klass->methods [i] == method) {
4761 offset = i;
4762 break;
4765 mono_class_setup_methods (klass);
4766 if (klass->exception_type)
4767 return NULL;
4768 g_assert (offset >= 0 && offset < klass->method.count);
4769 return klass->methods [offset];
4772 static MonoReflectionMethod*
4773 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4775 MonoClass *klass;
4776 if (type) {
4777 klass = mono_class_from_mono_type (type);
4778 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4779 return NULL;
4780 if (method->klass != klass) {
4781 method = mono_method_get_equivalent_method (method, klass);
4782 if (!method)
4783 return NULL;
4785 } else
4786 klass = method->klass;
4787 return mono_method_get_object (mono_domain_get (), method, klass);
4790 static MonoReflectionMethod*
4791 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4793 return mono_method_get_object (mono_domain_get (), method, NULL);
4796 static MonoReflectionMethodBody*
4797 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4799 return mono_method_body_get_object (mono_domain_get (), method);
4802 static MonoReflectionAssembly*
4803 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4805 MonoMethod *dest = NULL;
4807 MONO_ARCH_SAVE_REGS;
4809 mono_stack_walk_no_il (get_executing, &dest);
4810 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4814 static MonoReflectionAssembly*
4815 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4817 MonoDomain* domain = mono_domain_get ();
4819 MONO_ARCH_SAVE_REGS;
4821 if (!domain->entry_assembly)
4822 return NULL;
4824 return mono_assembly_get_object (domain, domain->entry_assembly);
4827 static MonoReflectionAssembly*
4828 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4830 MonoMethod *m;
4831 MonoMethod *dest;
4833 MONO_ARCH_SAVE_REGS;
4835 dest = NULL;
4836 mono_stack_walk_no_il (get_executing, &dest);
4837 m = dest;
4838 mono_stack_walk_no_il (get_caller, &dest);
4839 if (!dest)
4840 dest = m;
4841 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4844 static MonoString *
4845 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4846 gboolean assembly_qualified)
4848 MonoDomain *domain = mono_object_domain (object);
4849 MonoTypeNameFormat format;
4850 MonoString *res;
4851 gchar *name;
4853 if (full_name)
4854 format = assembly_qualified ?
4855 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4856 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4857 else
4858 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4860 name = mono_type_get_name_full (object->type, format);
4861 if (!name)
4862 return NULL;
4864 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4865 g_free (name);
4866 return NULL;
4869 res = mono_string_new (domain, name);
4870 g_free (name);
4872 return res;
4875 static int
4876 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4878 MonoClass *klass = mono_class_from_mono_type (this->type);
4879 mono_class_init_or_throw (klass);
4880 return mono_security_core_clr_class_level (klass);
4883 static void
4884 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4886 static MonoMethod *create_culture = NULL;
4887 gpointer args [2];
4888 guint32 pkey_len;
4889 const char *pkey_ptr;
4890 gchar *codebase;
4891 MonoBoolean assembly_ref = 0;
4893 MONO_ARCH_SAVE_REGS;
4895 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4896 aname->major = name->major;
4897 aname->minor = name->minor;
4898 aname->build = name->build;
4899 aname->flags = name->flags;
4900 aname->revision = name->revision;
4901 aname->hashalg = name->hash_alg;
4902 aname->versioncompat = 1; /* SameMachine (default) */
4904 if (by_default_version)
4905 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4907 codebase = NULL;
4908 if (absolute != NULL && *absolute != '\0') {
4909 const gchar *prepend = "file://";
4910 gchar *result;
4912 codebase = g_strdup (absolute);
4914 #if HOST_WIN32
4916 gint i;
4917 for (i = strlen (codebase) - 1; i >= 0; i--)
4918 if (codebase [i] == '\\')
4919 codebase [i] = '/';
4921 if (*codebase == '/' && *(codebase + 1) == '/') {
4922 prepend = "file:";
4923 } else {
4924 prepend = "file:///";
4927 #endif
4928 result = g_strconcat (prepend, codebase, NULL);
4929 g_free (codebase);
4930 codebase = result;
4933 if (codebase) {
4934 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4935 g_free (codebase);
4938 if (!create_culture) {
4939 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4940 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4941 g_assert (create_culture);
4942 mono_method_desc_free (desc);
4945 if (name->culture) {
4946 args [0] = mono_string_new (domain, name->culture);
4947 args [1] = &assembly_ref;
4948 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4951 if (name->public_key) {
4952 pkey_ptr = (char*)name->public_key;
4953 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4955 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4956 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4957 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4958 } else if (default_publickey) {
4959 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4960 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4963 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4964 if (name->public_key_token [0]) {
4965 int i, j;
4966 char *p;
4968 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4969 p = mono_array_addr (aname->keyToken, char, 0);
4971 for (i = 0, j = 0; i < 8; i++) {
4972 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4973 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4974 p++;
4976 } else if (default_token) {
4977 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4981 static MonoString *
4982 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4984 MonoDomain *domain = mono_object_domain (assembly);
4985 MonoAssembly *mass = assembly->assembly;
4986 MonoString *res;
4987 gchar *name;
4989 name = g_strdup_printf (
4990 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
4991 mass->aname.name,
4992 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
4993 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
4994 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
4995 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
4997 res = mono_string_new (domain, name);
4998 g_free (name);
5000 return res;
5003 static void
5004 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5006 gchar *absolute;
5007 MonoAssembly *mass = assembly->assembly;
5009 MONO_ARCH_SAVE_REGS;
5011 if (g_path_is_absolute (mass->image->name)) {
5012 fill_reflection_assembly_name (mono_object_domain (assembly),
5013 aname, &mass->aname, mass->image->name, TRUE,
5014 TRUE, TRUE);
5015 return;
5017 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5019 fill_reflection_assembly_name (mono_object_domain (assembly),
5020 aname, &mass->aname, absolute, TRUE, TRUE,
5021 TRUE);
5023 g_free (absolute);
5026 static void
5027 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5029 char *filename;
5030 MonoImageOpenStatus status = MONO_IMAGE_OK;
5031 gboolean res;
5032 MonoImage *image;
5033 MonoAssemblyName name;
5034 char *dirname
5036 MONO_ARCH_SAVE_REGS;
5038 filename = mono_string_to_utf8 (fname);
5040 dirname = g_path_get_dirname (filename);
5041 replace_shadow_path (mono_domain_get (), dirname, &filename);
5042 g_free (dirname);
5044 image = mono_image_open (filename, &status);
5046 if (!image){
5047 MonoException *exc;
5049 g_free (filename);
5050 if (status == MONO_IMAGE_IMAGE_INVALID)
5051 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5052 else
5053 exc = mono_get_exception_file_not_found2 (NULL, fname);
5054 mono_raise_exception (exc);
5057 res = mono_assembly_fill_assembly_name (image, &name);
5058 if (!res) {
5059 mono_image_close (image);
5060 g_free (filename);
5061 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5064 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5065 TRUE, FALSE, TRUE);
5067 g_free (filename);
5068 mono_image_close (image);
5071 static MonoBoolean
5072 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5073 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5075 MonoBoolean result = FALSE;
5076 MonoDeclSecurityEntry entry;
5078 /* SecurityAction.RequestMinimum */
5079 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5080 *minimum = entry.blob;
5081 *minLength = entry.size;
5082 result = TRUE;
5084 /* SecurityAction.RequestOptional */
5085 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5086 *optional = entry.blob;
5087 *optLength = entry.size;
5088 result = TRUE;
5090 /* SecurityAction.RequestRefuse */
5091 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5092 *refused = entry.blob;
5093 *refLength = entry.size;
5094 result = TRUE;
5097 return result;
5100 static MonoArray*
5101 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5103 MonoArray *res;
5104 MonoClass *klass;
5105 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5106 int i, count;
5107 guint32 attrs, visibility;
5109 /* we start the count from 1 because we skip the special type <Module> */
5110 if (exportedOnly) {
5111 count = 0;
5112 for (i = 1; i < tdef->rows; ++i) {
5113 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5114 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5115 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5116 count++;
5118 } else {
5119 count = tdef->rows - 1;
5121 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5122 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5123 count = 0;
5124 for (i = 1; i < tdef->rows; ++i) {
5125 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5126 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5127 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5128 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5129 if (klass) {
5130 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5131 } else {
5132 MonoLoaderError *error;
5133 MonoException *ex;
5135 error = mono_loader_get_last_error ();
5136 g_assert (error != NULL);
5138 ex = mono_loader_error_prepare_exception (error);
5139 mono_array_setref (*exceptions, count, ex);
5141 if (mono_loader_get_last_error ())
5142 mono_loader_clear_error ();
5143 count++;
5147 return res;
5150 static MonoArray*
5151 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5153 MonoArray *res = NULL;
5154 MonoArray *exceptions = NULL;
5155 MonoImage *image = NULL;
5156 MonoTableInfo *table = NULL;
5157 MonoDomain *domain;
5158 GList *list = NULL;
5159 int i, len, ex_count;
5161 MONO_ARCH_SAVE_REGS;
5163 domain = mono_object_domain (assembly);
5165 g_assert (!assembly->assembly->dynamic);
5166 image = assembly->assembly->image;
5167 table = &image->tables [MONO_TABLE_FILE];
5168 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5170 /* Append data from all modules in the assembly */
5171 for (i = 0; i < table->rows; ++i) {
5172 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5173 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5174 if (loaded_image) {
5175 MonoArray *ex2;
5176 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5177 /* Append the new types to the end of the array */
5178 if (mono_array_length (res2) > 0) {
5179 guint32 len1, len2;
5180 MonoArray *res3, *ex3;
5182 len1 = mono_array_length (res);
5183 len2 = mono_array_length (res2);
5185 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5186 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5187 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5188 res = res3;
5190 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5191 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5192 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5193 exceptions = ex3;
5199 /* the ReflectionTypeLoadException must have all the types (Types property),
5200 * NULL replacing types which throws an exception. The LoaderException must
5201 * contain all exceptions for NULL items.
5204 len = mono_array_length (res);
5206 ex_count = 0;
5207 for (i = 0; i < len; i++) {
5208 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5209 MonoClass *klass;
5211 if (t) {
5212 klass = mono_type_get_class (t->type);
5213 if ((klass != NULL) && klass->exception_type) {
5214 /* keep the class in the list */
5215 list = g_list_append (list, klass);
5216 /* and replace Type with NULL */
5217 mono_array_setref (res, i, NULL);
5219 } else {
5220 ex_count ++;
5224 if (list || ex_count) {
5225 GList *tmp = NULL;
5226 MonoException *exc = NULL;
5227 MonoArray *exl = NULL;
5228 int j, length = g_list_length (list) + ex_count;
5230 mono_loader_clear_error ();
5232 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5233 /* Types for which mono_class_get () succeeded */
5234 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5235 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5236 mono_array_setref (exl, i, exc);
5238 /* Types for which it don't */
5239 for (j = 0; j < mono_array_length (exceptions); ++j) {
5240 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5241 if (exc) {
5242 g_assert (i < length);
5243 mono_array_setref (exl, i, exc);
5244 i ++;
5247 g_list_free (list);
5248 list = NULL;
5250 exc = mono_get_exception_reflection_type_load (res, exl);
5251 mono_loader_clear_error ();
5252 mono_raise_exception (exc);
5255 return res;
5258 static gboolean
5259 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5261 MonoAssemblyName aname;
5262 MonoDomain *domain = mono_object_domain (name);
5263 char *val;
5264 gboolean is_version_defined;
5265 gboolean is_token_defined;
5267 aname.public_key = NULL;
5268 val = mono_string_to_utf8 (assname);
5269 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5270 g_free ((guint8*) aname.public_key);
5271 g_free (val);
5272 return FALSE;
5275 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5276 FALSE, is_token_defined);
5278 mono_assembly_name_free (&aname);
5279 g_free ((guint8*) aname.public_key);
5280 g_free (val);
5282 return TRUE;
5285 static MonoReflectionType*
5286 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5288 MonoDomain *domain = mono_object_domain (module);
5289 MonoClass *klass;
5291 MONO_ARCH_SAVE_REGS;
5293 g_assert (module->image);
5295 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5296 /* These images do not have a global type */
5297 return NULL;
5299 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5300 return mono_type_get_object (domain, &klass->byval_arg);
5303 static void
5304 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5306 /*if (module->image)
5307 mono_image_close (module->image);*/
5310 static MonoString*
5311 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5313 MonoDomain *domain = mono_object_domain (module);
5315 MONO_ARCH_SAVE_REGS;
5317 g_assert (module->image);
5318 return mono_string_new (domain, module->image->guid);
5321 static gpointer
5322 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5324 #ifdef HOST_WIN32
5325 if (module->image && module->image->is_module_handle)
5326 return module->image->raw_data;
5327 #endif
5329 return (gpointer) (-1);
5332 static void
5333 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5335 if (image->dynamic) {
5336 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5337 *pe_kind = dyn->pe_kind;
5338 *machine = dyn->machine;
5340 else {
5341 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5342 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5346 static gint32
5347 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5349 return (image->md_version_major << 16) | (image->md_version_minor);
5352 static MonoArray*
5353 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5355 MonoArray *exceptions;
5356 int i;
5358 MONO_ARCH_SAVE_REGS;
5360 if (!module->image)
5361 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5362 else {
5363 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5364 for (i = 0; i < mono_array_length (exceptions); ++i) {
5365 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5366 if (ex)
5367 mono_raise_exception (ex);
5369 return res;
5373 static gboolean
5374 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5376 guint32 cols [MONO_MEMBERREF_SIZE];
5377 const char *sig;
5378 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5379 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5380 mono_metadata_decode_blob_size (sig, &sig);
5381 return (*sig != 0x6);
5384 static void
5385 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5387 if (type_args)
5388 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5389 mono_array_addr (type_args, MonoType*, 0));
5390 else
5391 context->class_inst = NULL;
5392 if (method_args)
5393 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5394 mono_array_addr (method_args, MonoType*, 0));
5395 else
5396 context->method_inst = NULL;
5399 static MonoType*
5400 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5402 MonoClass *klass;
5403 int table = mono_metadata_token_table (token);
5404 int index = mono_metadata_token_index (token);
5405 MonoGenericContext context;
5407 *error = ResolveTokenError_Other;
5409 /* Validate token */
5410 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5411 (table != MONO_TABLE_TYPESPEC)) {
5412 *error = ResolveTokenError_BadTable;
5413 return NULL;
5416 if (image->dynamic) {
5417 if (type_args || method_args)
5418 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5419 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5420 if (!klass)
5421 return NULL;
5422 return &klass->byval_arg;
5425 if ((index <= 0) || (index > image->tables [table].rows)) {
5426 *error = ResolveTokenError_OutOfRange;
5427 return NULL;
5430 init_generic_context_from_args (&context, type_args, method_args);
5431 klass = mono_class_get_full (image, token, &context);
5433 if (mono_loader_get_last_error ())
5434 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5436 if (klass)
5437 return &klass->byval_arg;
5438 else
5439 return NULL;
5442 static MonoMethod*
5443 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5445 int table = mono_metadata_token_table (token);
5446 int index = mono_metadata_token_index (token);
5447 MonoGenericContext context;
5448 MonoMethod *method;
5450 *error = ResolveTokenError_Other;
5452 /* Validate token */
5453 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5454 (table != MONO_TABLE_MEMBERREF)) {
5455 *error = ResolveTokenError_BadTable;
5456 return NULL;
5459 if (image->dynamic) {
5460 if (type_args || method_args)
5461 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5462 /* FIXME: validate memberref token type */
5463 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5466 if ((index <= 0) || (index > image->tables [table].rows)) {
5467 *error = ResolveTokenError_OutOfRange;
5468 return NULL;
5470 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5471 *error = ResolveTokenError_BadTable;
5472 return NULL;
5475 init_generic_context_from_args (&context, type_args, method_args);
5476 method = mono_get_method_full (image, token, NULL, &context);
5478 if (mono_loader_get_last_error ())
5479 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5481 return method;
5484 static MonoString*
5485 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5487 int index = mono_metadata_token_index (token);
5489 *error = ResolveTokenError_Other;
5491 /* Validate token */
5492 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5493 *error = ResolveTokenError_BadTable;
5494 return NULL;
5497 if (image->dynamic)
5498 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5500 if ((index <= 0) || (index >= image->heap_us.size)) {
5501 *error = ResolveTokenError_OutOfRange;
5502 return NULL;
5505 /* FIXME: What to do if the index points into the middle of a string ? */
5507 return mono_ldstr (mono_domain_get (), image, index);
5510 static MonoClassField*
5511 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5513 MonoClass *klass;
5514 int table = mono_metadata_token_table (token);
5515 int index = mono_metadata_token_index (token);
5516 MonoGenericContext context;
5517 MonoClassField *field;
5519 *error = ResolveTokenError_Other;
5521 /* Validate token */
5522 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5523 *error = ResolveTokenError_BadTable;
5524 return NULL;
5527 if (image->dynamic) {
5528 if (type_args || method_args)
5529 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5530 /* FIXME: validate memberref token type */
5531 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5534 if ((index <= 0) || (index > image->tables [table].rows)) {
5535 *error = ResolveTokenError_OutOfRange;
5536 return NULL;
5538 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5539 *error = ResolveTokenError_BadTable;
5540 return NULL;
5543 init_generic_context_from_args (&context, type_args, method_args);
5544 field = mono_field_from_token (image, token, &klass, &context);
5546 if (mono_loader_get_last_error ())
5547 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5549 return field;
5553 static MonoObject*
5554 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5556 int table = mono_metadata_token_table (token);
5558 *error = ResolveTokenError_Other;
5560 switch (table) {
5561 case MONO_TABLE_TYPEDEF:
5562 case MONO_TABLE_TYPEREF:
5563 case MONO_TABLE_TYPESPEC: {
5564 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5565 if (t)
5566 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5567 else
5568 return NULL;
5570 case MONO_TABLE_METHOD:
5571 case MONO_TABLE_METHODSPEC: {
5572 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5573 if (m)
5574 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5575 else
5576 return NULL;
5578 case MONO_TABLE_FIELD: {
5579 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5580 if (f)
5581 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5582 else
5583 return NULL;
5585 case MONO_TABLE_MEMBERREF:
5586 if (mono_metadata_memberref_is_method (image, token)) {
5587 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5588 if (m)
5589 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5590 else
5591 return NULL;
5593 else {
5594 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5595 if (f)
5596 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5597 else
5598 return NULL;
5600 break;
5602 default:
5603 *error = ResolveTokenError_BadTable;
5606 return NULL;
5609 static MonoArray*
5610 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5612 int table = mono_metadata_token_table (token);
5613 int idx = mono_metadata_token_index (token);
5614 MonoTableInfo *tables = image->tables;
5615 guint32 sig, len;
5616 const char *ptr;
5617 MonoArray *res;
5619 *error = ResolveTokenError_OutOfRange;
5621 /* FIXME: Support other tables ? */
5622 if (table != MONO_TABLE_STANDALONESIG)
5623 return NULL;
5625 if (image->dynamic)
5626 return NULL;
5628 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5629 return NULL;
5631 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5633 ptr = mono_metadata_blob_heap (image, sig);
5634 len = mono_metadata_decode_blob_size (ptr, &ptr);
5636 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5637 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5638 return res;
5641 static MonoReflectionType*
5642 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5644 MonoClass *klass;
5645 int isbyref = 0, rank;
5646 char *str = mono_string_to_utf8 (smodifiers);
5647 char *p;
5649 MONO_ARCH_SAVE_REGS;
5651 klass = mono_class_from_mono_type (tb->type.type);
5652 p = str;
5653 /* logic taken from mono_reflection_parse_type(): keep in sync */
5654 while (*p) {
5655 switch (*p) {
5656 case '&':
5657 if (isbyref) { /* only one level allowed by the spec */
5658 g_free (str);
5659 return NULL;
5661 isbyref = 1;
5662 p++;
5663 g_free (str);
5664 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5665 break;
5666 case '*':
5667 klass = mono_ptr_class_get (&klass->byval_arg);
5668 mono_class_init (klass);
5669 p++;
5670 break;
5671 case '[':
5672 rank = 1;
5673 p++;
5674 while (*p) {
5675 if (*p == ']')
5676 break;
5677 if (*p == ',')
5678 rank++;
5679 else if (*p != '*') { /* '*' means unknown lower bound */
5680 g_free (str);
5681 return NULL;
5683 ++p;
5685 if (*p != ']') {
5686 g_free (str);
5687 return NULL;
5689 p++;
5690 klass = mono_array_class_get (klass, rank);
5691 mono_class_init (klass);
5692 break;
5693 default:
5694 break;
5697 g_free (str);
5698 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5701 static MonoBoolean
5702 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5704 MonoType *type;
5705 MonoBoolean res;
5707 MONO_ARCH_SAVE_REGS;
5709 type = t->type;
5710 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5712 return res;
5715 static MonoReflectionType *
5716 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5718 MonoClass *klass, *aklass;
5720 MONO_ARCH_SAVE_REGS;
5722 klass = mono_class_from_mono_type (type->type);
5723 mono_class_init_or_throw (klass);
5725 if (rank == 0) //single dimentional array
5726 aklass = mono_array_class_get (klass, 1);
5727 else
5728 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5730 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5733 static MonoReflectionType *
5734 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5736 MonoClass *klass;
5738 MONO_ARCH_SAVE_REGS;
5740 klass = mono_class_from_mono_type (type->type);
5741 mono_class_init_or_throw (klass);
5743 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5746 static MonoReflectionType *
5747 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5749 MonoClass *pklass;
5751 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
5753 pklass = mono_ptr_class_get (type->type);
5755 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5758 static MonoObject *
5759 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5760 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5762 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5763 MonoObject *delegate;
5764 gpointer func;
5765 MonoMethod *method = info->method;
5767 MONO_ARCH_SAVE_REGS;
5769 mono_class_init_or_throw (delegate_class);
5771 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5773 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5774 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5775 return NULL;
5778 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5780 if (method->dynamic) {
5781 /* Creating a trampoline would leak memory */
5782 func = mono_compile_method (method);
5783 } else {
5784 func = mono_create_ftnptr (mono_domain_get (),
5785 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5788 mono_delegate_ctor_with_method (delegate, target, func, method);
5790 return delegate;
5793 static void
5794 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5796 /* Reset the invoke impl to the default one */
5797 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5801 * Magic number to convert a time which is relative to
5802 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5804 #define EPOCH_ADJUST ((guint64)62135596800LL)
5807 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5809 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5811 #ifdef HOST_WIN32
5812 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5813 static void
5814 convert_to_absolute_date(SYSTEMTIME *date)
5816 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5817 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5818 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5819 /* from the calendar FAQ */
5820 int a = (14 - date->wMonth) / 12;
5821 int y = date->wYear - a;
5822 int m = date->wMonth + 12 * a - 2;
5823 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5825 /* d is now the day of the week for the first of the month (0 == Sunday) */
5827 int day_of_week = date->wDayOfWeek;
5829 /* set day_in_month to the first day in the month which falls on day_of_week */
5830 int day_in_month = 1 + (day_of_week - d);
5831 if (day_in_month <= 0)
5832 day_in_month += 7;
5834 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5835 date->wDay = day_in_month + (date->wDay - 1) * 7;
5836 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5837 date->wDay -= 7;
5839 #endif
5841 #ifndef HOST_WIN32
5843 * Return's the offset from GMT of a local time.
5845 * tm is a local time
5846 * t is the same local time as seconds.
5848 static int
5849 gmt_offset(struct tm *tm, time_t t)
5851 #if defined (HAVE_TM_GMTOFF)
5852 return tm->tm_gmtoff;
5853 #else
5854 struct tm g;
5855 time_t t2;
5856 g = *gmtime(&t);
5857 g.tm_isdst = tm->tm_isdst;
5858 t2 = mktime(&g);
5859 return (int)difftime(t, t2);
5860 #endif
5862 #endif
5864 * This is heavily based on zdump.c from glibc 2.2.
5866 * * data[0]: start of daylight saving time (in DateTime ticks).
5867 * * data[1]: end of daylight saving time (in DateTime ticks).
5868 * * data[2]: utcoffset (in TimeSpan ticks).
5869 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5870 * * name[0]: name of this timezone when not daylight saving.
5871 * * name[1]: name of this timezone when daylight saving.
5873 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5874 * the class library allows years between 1 and 9999.
5876 * Returns true on success and zero on failure.
5878 static guint32
5879 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5881 #ifndef HOST_WIN32
5882 MonoDomain *domain = mono_domain_get ();
5883 struct tm start, tt;
5884 time_t t;
5886 long int gmtoff;
5887 int is_daylight = 0, day;
5888 char tzone [64];
5890 MONO_ARCH_SAVE_REGS;
5892 MONO_CHECK_ARG_NULL (data);
5893 MONO_CHECK_ARG_NULL (names);
5895 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5896 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5899 * no info is better than crashing: we'll need our own tz data
5900 * to make this work properly, anyway. The range is probably
5901 * reduced to 1970 .. 2037 because that is what mktime is
5902 * guaranteed to support (we get into an infinite loop
5903 * otherwise).
5906 memset (&start, 0, sizeof (start));
5908 start.tm_mday = 1;
5909 start.tm_year = year-1900;
5911 t = mktime (&start);
5913 if ((year < 1970) || (year > 2037) || (t == -1)) {
5914 t = time (NULL);
5915 tt = *localtime (&t);
5916 strftime (tzone, sizeof (tzone), "%Z", &tt);
5917 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5918 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5919 return 1;
5922 gmtoff = gmt_offset (&start, t);
5924 /* For each day of the year, calculate the tm_gmtoff. */
5925 for (day = 0; day < 365; day++) {
5927 t += 3600*24;
5928 tt = *localtime (&t);
5930 /* Daylight saving starts or ends here. */
5931 if (gmt_offset (&tt, t) != gmtoff) {
5932 struct tm tt1;
5933 time_t t1;
5935 /* Try to find the exact hour when daylight saving starts/ends. */
5936 t1 = t;
5937 do {
5938 t1 -= 3600;
5939 tt1 = *localtime (&t1);
5940 } while (gmt_offset (&tt1, t1) != gmtoff);
5942 /* Try to find the exact minute when daylight saving starts/ends. */
5943 do {
5944 t1 += 60;
5945 tt1 = *localtime (&t1);
5946 } while (gmt_offset (&tt1, t1) == gmtoff);
5947 t1+=gmtoff;
5948 strftime (tzone, sizeof (tzone), "%Z", &tt);
5950 /* Write data, if we're already in daylight saving, we're done. */
5951 if (is_daylight) {
5952 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5953 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5954 return 1;
5955 } else {
5956 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5957 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5958 is_daylight = 1;
5961 /* This is only set once when we enter daylight saving. */
5962 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5963 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5965 gmtoff = gmt_offset (&tt, t);
5969 if (!is_daylight) {
5970 strftime (tzone, sizeof (tzone), "%Z", &tt);
5971 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5972 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5973 mono_array_set ((*data), gint64, 0, 0);
5974 mono_array_set ((*data), gint64, 1, 0);
5975 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5976 mono_array_set ((*data), gint64, 3, 0);
5979 return 1;
5980 #else
5981 MonoDomain *domain = mono_domain_get ();
5982 TIME_ZONE_INFORMATION tz_info;
5983 FILETIME ft;
5984 int i;
5985 int err, tz_id;
5987 tz_id = GetTimeZoneInformation (&tz_info);
5988 if (tz_id == TIME_ZONE_ID_INVALID)
5989 return 0;
5991 MONO_CHECK_ARG_NULL (data);
5992 MONO_CHECK_ARG_NULL (names);
5994 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
5995 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
5997 for (i = 0; i < 32; ++i)
5998 if (!tz_info.DaylightName [i])
5999 break;
6000 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6001 for (i = 0; i < 32; ++i)
6002 if (!tz_info.StandardName [i])
6003 break;
6004 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6006 if ((year <= 1601) || (year > 30827)) {
6008 * According to MSDN, the MS time functions can't handle dates outside
6009 * this interval.
6011 return 1;
6014 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6015 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6016 tz_info.StandardDate.wYear = year;
6017 convert_to_absolute_date(&tz_info.StandardDate);
6018 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6019 //g_assert(err);
6020 if (err == 0)
6021 return 0;
6023 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6024 tz_info.DaylightDate.wYear = year;
6025 convert_to_absolute_date(&tz_info.DaylightDate);
6026 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6027 //g_assert(err);
6028 if (err == 0)
6029 return 0;
6031 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6033 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6034 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6036 return 1;
6037 #endif
6040 static gpointer
6041 ves_icall_System_Object_obj_address (MonoObject *this)
6043 MONO_ARCH_SAVE_REGS;
6045 return this;
6048 /* System.Buffer */
6050 static inline gint32
6051 mono_array_get_byte_length (MonoArray *array)
6053 MonoClass *klass;
6054 int length;
6055 int i;
6057 klass = array->obj.vtable->klass;
6059 if (array->bounds == NULL)
6060 length = array->max_length;
6061 else {
6062 length = 1;
6063 for (i = 0; i < klass->rank; ++ i)
6064 length *= array->bounds [i].length;
6067 switch (klass->element_class->byval_arg.type) {
6068 case MONO_TYPE_I1:
6069 case MONO_TYPE_U1:
6070 case MONO_TYPE_BOOLEAN:
6071 return length;
6072 case MONO_TYPE_I2:
6073 case MONO_TYPE_U2:
6074 case MONO_TYPE_CHAR:
6075 return length << 1;
6076 case MONO_TYPE_I4:
6077 case MONO_TYPE_U4:
6078 case MONO_TYPE_R4:
6079 return length << 2;
6080 case MONO_TYPE_I:
6081 case MONO_TYPE_U:
6082 return length * sizeof (gpointer);
6083 case MONO_TYPE_I8:
6084 case MONO_TYPE_U8:
6085 case MONO_TYPE_R8:
6086 return length << 3;
6087 default:
6088 return -1;
6092 static gint32
6093 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6095 MONO_ARCH_SAVE_REGS;
6097 return mono_array_get_byte_length (array);
6100 static gint8
6101 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6103 MONO_ARCH_SAVE_REGS;
6105 return mono_array_get (array, gint8, idx);
6108 static void
6109 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6111 MONO_ARCH_SAVE_REGS;
6113 mono_array_set (array, gint8, idx, value);
6116 static MonoBoolean
6117 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6119 guint8 *src_buf, *dest_buf;
6121 MONO_ARCH_SAVE_REGS;
6123 /* watch out for integer overflow */
6124 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6125 return FALSE;
6127 src_buf = (guint8 *)src->vector + src_offset;
6128 dest_buf = (guint8 *)dest->vector + dest_offset;
6130 if (src != dest)
6131 memcpy (dest_buf, src_buf, count);
6132 else
6133 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6135 return TRUE;
6138 static MonoObject *
6139 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6141 MonoDomain *domain = mono_object_domain (this);
6142 MonoObject *res;
6143 MonoRealProxy *rp = ((MonoRealProxy *)this);
6144 MonoTransparentProxy *tp;
6145 MonoType *type;
6146 MonoClass *klass;
6148 MONO_ARCH_SAVE_REGS;
6150 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6151 tp = (MonoTransparentProxy*) res;
6153 MONO_OBJECT_SETREF (tp, rp, rp);
6154 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6155 klass = mono_class_from_mono_type (type);
6157 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6158 tp->remote_class = mono_remote_class (domain, class_name, klass);
6160 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6161 return res;
6164 static MonoReflectionType *
6165 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6167 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6170 /* System.Environment */
6172 MonoString*
6173 ves_icall_System_Environment_get_UserName (void)
6175 MONO_ARCH_SAVE_REGS;
6177 /* using glib is more portable */
6178 return mono_string_new (mono_domain_get (), g_get_user_name ());
6182 static MonoString *
6183 ves_icall_System_Environment_get_MachineName (void)
6185 #if defined (HOST_WIN32)
6186 gunichar2 *buf;
6187 guint32 len;
6188 MonoString *result;
6190 len = MAX_COMPUTERNAME_LENGTH + 1;
6191 buf = g_new (gunichar2, len);
6193 result = NULL;
6194 if (GetComputerName (buf, (PDWORD) &len))
6195 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6197 g_free (buf);
6198 return result;
6199 #elif !defined(DISABLE_SOCKETS)
6200 gchar buf [256];
6201 MonoString *result;
6203 if (gethostname (buf, sizeof (buf)) == 0)
6204 result = mono_string_new (mono_domain_get (), buf);
6205 else
6206 result = NULL;
6208 return result;
6209 #else
6210 return mono_string_new (mono_domain_get (), "mono");
6211 #endif
6214 static int
6215 ves_icall_System_Environment_get_Platform (void)
6217 #if defined (TARGET_WIN32)
6218 /* Win32NT */
6219 return 2;
6220 #elif defined(__MACH__)
6221 /* OSX */
6223 // For compatibility with our client code, this will be 4 for a while.
6224 // We will eventually move to 6 to match .NET, but it requires all client
6225 // code to be updated and the documentation everywhere to be updated
6226 // first.
6228 return 4;
6229 #else
6230 /* Unix */
6231 return 4;
6232 #endif
6235 static MonoString *
6236 ves_icall_System_Environment_get_NewLine (void)
6238 MONO_ARCH_SAVE_REGS;
6240 #if defined (HOST_WIN32)
6241 return mono_string_new (mono_domain_get (), "\r\n");
6242 #else
6243 return mono_string_new (mono_domain_get (), "\n");
6244 #endif
6247 static MonoString *
6248 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6250 const gchar *value;
6251 gchar *utf8_name;
6253 MONO_ARCH_SAVE_REGS;
6255 if (name == NULL)
6256 return NULL;
6258 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6259 value = g_getenv (utf8_name);
6261 g_free (utf8_name);
6263 if (value == 0)
6264 return NULL;
6266 return mono_string_new (mono_domain_get (), value);
6270 * There is no standard way to get at environ.
6272 #ifndef _MSC_VER
6273 #ifndef __MINGW32_VERSION
6274 #ifdef __APPLE__
6275 /* Apple defines this in crt_externs.h but doesn't provide that header for
6276 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6277 * in fact exist on all implementations (so far)
6279 gchar ***_NSGetEnviron(void);
6280 #define environ (*_NSGetEnviron())
6281 #else
6282 extern
6283 char **environ;
6284 #endif
6285 #endif
6286 #endif
6288 static MonoArray *
6289 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6291 #ifdef HOST_WIN32
6292 MonoArray *names;
6293 MonoDomain *domain;
6294 MonoString *str;
6295 WCHAR* env_strings;
6296 WCHAR* env_string;
6297 WCHAR* equal_str;
6298 int n = 0;
6300 env_strings = GetEnvironmentStrings();
6302 if (env_strings) {
6303 env_string = env_strings;
6304 while (*env_string != '\0') {
6305 /* weird case that MS seems to skip */
6306 if (*env_string != '=')
6307 n++;
6308 while (*env_string != '\0')
6309 env_string++;
6310 env_string++;
6314 domain = mono_domain_get ();
6315 names = mono_array_new (domain, mono_defaults.string_class, n);
6317 if (env_strings) {
6318 n = 0;
6319 env_string = env_strings;
6320 while (*env_string != '\0') {
6321 /* weird case that MS seems to skip */
6322 if (*env_string != '=') {
6323 equal_str = wcschr(env_string, '=');
6324 g_assert(equal_str);
6325 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6326 mono_array_setref (names, n, str);
6327 n++;
6329 while (*env_string != '\0')
6330 env_string++;
6331 env_string++;
6334 FreeEnvironmentStrings (env_strings);
6337 return names;
6339 #else
6340 MonoArray *names;
6341 MonoDomain *domain;
6342 MonoString *str;
6343 gchar **e, **parts;
6344 int n;
6346 MONO_ARCH_SAVE_REGS;
6348 n = 0;
6349 for (e = environ; *e != 0; ++ e)
6350 ++ n;
6352 domain = mono_domain_get ();
6353 names = mono_array_new (domain, mono_defaults.string_class, n);
6355 n = 0;
6356 for (e = environ; *e != 0; ++ e) {
6357 parts = g_strsplit (*e, "=", 2);
6358 if (*parts != 0) {
6359 str = mono_string_new (domain, *parts);
6360 mono_array_setref (names, n, str);
6363 g_strfreev (parts);
6365 ++ n;
6368 return names;
6369 #endif
6373 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6375 #if !GLIB_CHECK_VERSION(2,4,0)
6376 #define g_setenv(a,b,c) setenv(a,b,c)
6377 #define g_unsetenv(a) unsetenv(a)
6378 #endif
6380 static void
6381 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6383 MonoError error;
6384 #ifdef HOST_WIN32
6386 gunichar2 *utf16_name, *utf16_value;
6387 #else
6388 gchar *utf8_name, *utf8_value;
6389 #endif
6391 MONO_ARCH_SAVE_REGS;
6393 #ifdef HOST_WIN32
6394 utf16_name = mono_string_to_utf16 (name);
6395 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6396 SetEnvironmentVariable (utf16_name, NULL);
6397 g_free (utf16_name);
6398 return;
6401 utf16_value = mono_string_to_utf16 (value);
6403 SetEnvironmentVariable (utf16_name, utf16_value);
6405 g_free (utf16_name);
6406 g_free (utf16_value);
6407 #else
6408 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6410 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6411 g_unsetenv (utf8_name);
6412 g_free (utf8_name);
6413 return;
6416 utf8_value = mono_string_to_utf8_checked (value, &error);
6417 if (!mono_error_ok (&error)) {
6418 g_free (utf8_name);
6419 mono_error_raise_exception (&error);
6421 g_setenv (utf8_name, utf8_value, TRUE);
6423 g_free (utf8_name);
6424 g_free (utf8_value);
6425 #endif
6428 static void
6429 ves_icall_System_Environment_Exit (int result)
6431 MONO_ARCH_SAVE_REGS;
6433 mono_threads_set_shutting_down ();
6435 mono_runtime_set_shutting_down ();
6437 /* This will kill the tp threads which cannot be suspended */
6438 mono_thread_pool_cleanup ();
6440 /* Suspend all managed threads since the runtime is going away */
6441 mono_thread_suspend_all_other_threads ();
6443 mono_runtime_quit ();
6445 /* we may need to do some cleanup here... */
6446 exit (result);
6449 static MonoString*
6450 ves_icall_System_Environment_GetGacPath (void)
6452 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6455 static MonoString*
6456 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6458 #if defined (HOST_WIN32)
6459 #ifndef CSIDL_FLAG_CREATE
6460 #define CSIDL_FLAG_CREATE 0x8000
6461 #endif
6463 WCHAR path [MAX_PATH];
6464 /* Create directory if no existing */
6465 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6466 int len = 0;
6467 while (path [len])
6468 ++ len;
6469 return mono_string_new_utf16 (mono_domain_get (), path, len);
6471 #else
6472 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6473 #endif
6474 return mono_string_new (mono_domain_get (), "");
6477 static MonoArray *
6478 ves_icall_System_Environment_GetLogicalDrives (void)
6480 gunichar2 buf [128], *ptr, *dname;
6481 gunichar2 *u16;
6482 guint initial_size = 127, size = 128;
6483 gint ndrives;
6484 MonoArray *result;
6485 MonoString *drivestr;
6486 MonoDomain *domain = mono_domain_get ();
6487 gint len;
6489 MONO_ARCH_SAVE_REGS;
6491 buf [0] = '\0';
6492 ptr = buf;
6494 while (size > initial_size) {
6495 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6496 if (size > initial_size) {
6497 if (ptr != buf)
6498 g_free (ptr);
6499 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6500 initial_size = size;
6501 size++;
6505 /* Count strings */
6506 dname = ptr;
6507 ndrives = 0;
6508 do {
6509 while (*dname++);
6510 ndrives++;
6511 } while (*dname);
6513 dname = ptr;
6514 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6515 ndrives = 0;
6516 do {
6517 len = 0;
6518 u16 = dname;
6519 while (*u16) { u16++; len ++; }
6520 drivestr = mono_string_new_utf16 (domain, dname, len);
6521 mono_array_setref (result, ndrives++, drivestr);
6522 while (*dname++);
6523 } while (*dname);
6525 if (ptr != buf)
6526 g_free (ptr);
6528 return result;
6531 static MonoString *
6532 ves_icall_System_Environment_InternalGetHome (void)
6534 MONO_ARCH_SAVE_REGS;
6536 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6539 static const char *encodings [] = {
6540 (char *) 1,
6541 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6542 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6543 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6544 (char *) 2,
6545 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6546 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6547 "x_unicode_2_0_utf_7",
6548 (char *) 3,
6549 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6550 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6551 (char *) 4,
6552 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6553 "iso_10646_ucs2",
6554 (char *) 5,
6555 "unicodefffe", "utf_16be",
6556 (char *) 6,
6557 "iso_8859_1",
6558 (char *) 0
6562 * Returns the internal codepage, if the value of "int_code_page" is
6563 * 1 at entry, and we can not compute a suitable code page number,
6564 * returns the code page as a string
6566 static MonoString*
6567 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6569 const char *cset;
6570 const char *p;
6571 char *c;
6572 char *codepage = NULL;
6573 int code;
6574 int want_name = *int_code_page;
6575 int i;
6577 *int_code_page = -1;
6578 MONO_ARCH_SAVE_REGS;
6580 g_get_charset (&cset);
6581 c = codepage = strdup (cset);
6582 for (c = codepage; *c; c++){
6583 if (isascii (*c) && isalpha (*c))
6584 *c = tolower (*c);
6585 if (*c == '-')
6586 *c = '_';
6588 /* g_print ("charset: %s\n", cset); */
6590 /* handle some common aliases */
6591 p = encodings [0];
6592 code = 0;
6593 for (i = 0; p != 0; ){
6594 if ((gssize) p < 7){
6595 code = (gssize) p;
6596 p = encodings [++i];
6597 continue;
6599 if (strcmp (p, codepage) == 0){
6600 *int_code_page = code;
6601 break;
6603 p = encodings [++i];
6606 if (strstr (codepage, "utf_8") != NULL)
6607 *int_code_page |= 0x10000000;
6608 free (codepage);
6610 if (want_name && *int_code_page == -1)
6611 return mono_string_new (mono_domain_get (), cset);
6612 else
6613 return NULL;
6616 static MonoBoolean
6617 ves_icall_System_Environment_get_HasShutdownStarted (void)
6619 if (mono_runtime_is_shutting_down ())
6620 return TRUE;
6622 if (mono_domain_is_unloading (mono_domain_get ()))
6623 return TRUE;
6625 return FALSE;
6628 static void
6629 ves_icall_System_Environment_BroadcastSettingChange (void)
6631 #ifdef HOST_WIN32
6632 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6633 #endif
6636 static void
6637 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6638 MonoReflectionMethod *method,
6639 MonoArray *out_args)
6641 MONO_ARCH_SAVE_REGS;
6643 mono_message_init (mono_object_domain (this), this, method, out_args);
6646 static MonoBoolean
6647 ves_icall_IsTransparentProxy (MonoObject *proxy)
6649 MONO_ARCH_SAVE_REGS;
6651 if (!proxy)
6652 return 0;
6654 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6655 return 1;
6657 return 0;
6660 static MonoReflectionMethod *
6661 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6662 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6664 MonoClass *klass;
6665 MonoMethod *method;
6666 MonoMethod **vtable;
6667 MonoMethod *res = NULL;
6669 MONO_CHECK_ARG_NULL (rtype);
6670 MONO_CHECK_ARG_NULL (rmethod);
6672 method = rmethod->method;
6673 klass = mono_class_from_mono_type (rtype->type);
6674 mono_class_init_or_throw (klass);
6676 if (MONO_CLASS_IS_INTERFACE (klass))
6677 return NULL;
6679 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6680 return NULL;
6682 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6683 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6684 return rmethod;
6685 else
6686 return NULL;
6689 mono_class_setup_vtable (klass);
6690 vtable = klass->vtable;
6692 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6693 gboolean variance_used = FALSE;
6694 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6695 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6696 if (offs >= 0)
6697 res = vtable [offs + method->slot];
6698 } else {
6699 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6700 return NULL;
6702 if (method->slot != -1)
6703 res = vtable [method->slot];
6706 if (!res)
6707 return NULL;
6709 return mono_method_get_object (mono_domain_get (), res, NULL);
6712 static void
6713 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6715 MonoClass *klass;
6716 MonoVTable* vtable;
6718 MONO_ARCH_SAVE_REGS;
6720 klass = mono_class_from_mono_type (type->type);
6721 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6723 if (enable) vtable->remote = 1;
6724 else vtable->remote = 0;
6727 static MonoObject *
6728 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6730 MonoClass *klass;
6731 MonoDomain *domain;
6733 MONO_ARCH_SAVE_REGS;
6735 domain = mono_object_domain (type);
6736 klass = mono_class_from_mono_type (type->type);
6737 mono_class_init_or_throw (klass);
6739 if (klass->rank >= 1) {
6740 g_assert (klass->rank == 1);
6741 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6742 } else {
6743 /* Bypass remoting object creation check */
6744 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6748 static MonoString *
6749 ves_icall_System_IO_get_temp_path (void)
6751 MONO_ARCH_SAVE_REGS;
6753 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6756 #ifndef PLATFORM_NO_DRIVEINFO
6757 static MonoBoolean
6758 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6759 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6760 gint32 *error)
6762 gboolean result;
6763 ULARGE_INTEGER wapi_free_bytes_avail;
6764 ULARGE_INTEGER wapi_total_number_of_bytes;
6765 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6767 MONO_ARCH_SAVE_REGS;
6769 *error = ERROR_SUCCESS;
6770 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6771 &wapi_total_number_of_free_bytes);
6773 if (result) {
6774 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6775 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6776 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6777 } else {
6778 *free_bytes_avail = 0;
6779 *total_number_of_bytes = 0;
6780 *total_number_of_free_bytes = 0;
6781 *error = GetLastError ();
6784 return result;
6787 static guint32
6788 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6790 MONO_ARCH_SAVE_REGS;
6792 return GetDriveType (mono_string_chars (root_path_name));
6794 #endif
6796 static gpointer
6797 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6799 MONO_ARCH_SAVE_REGS;
6801 return mono_compile_method (method);
6804 static MonoString *
6805 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6807 MonoString *mcpath;
6808 gchar *path;
6810 MONO_ARCH_SAVE_REGS;
6812 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6814 #if defined (HOST_WIN32)
6815 /* Avoid mixing '/' and '\\' */
6817 gint i;
6818 for (i = strlen (path) - 1; i >= 0; i--)
6819 if (path [i] == '/')
6820 path [i] = '\\';
6822 #endif
6823 mcpath = mono_string_new (mono_domain_get (), path);
6824 g_free (path);
6826 return mcpath;
6829 static MonoString *
6830 get_bundled_machine_config (void)
6832 const gchar *machine_config;
6834 MONO_ARCH_SAVE_REGS;
6836 machine_config = mono_get_machine_config ();
6838 if (!machine_config)
6839 return NULL;
6841 return mono_string_new (mono_domain_get (), machine_config);
6844 static MonoString *
6845 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6847 MonoString *ipath;
6848 gchar *path;
6850 MONO_ARCH_SAVE_REGS;
6852 path = g_path_get_dirname (mono_get_config_dir ());
6854 #if defined (HOST_WIN32)
6855 /* Avoid mixing '/' and '\\' */
6857 gint i;
6858 for (i = strlen (path) - 1; i >= 0; i--)
6859 if (path [i] == '/')
6860 path [i] = '\\';
6862 #endif
6863 ipath = mono_string_new (mono_domain_get (), path);
6864 g_free (path);
6866 return ipath;
6869 static gboolean
6870 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6872 MonoPEResourceDataEntry *entry;
6873 MonoImage *image;
6875 MONO_ARCH_SAVE_REGS;
6877 if (!assembly || !result || !size)
6878 return FALSE;
6880 *result = NULL;
6881 *size = 0;
6882 image = assembly->assembly->image;
6883 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6884 if (!entry)
6885 return FALSE;
6887 *result = mono_image_rva_map (image, entry->rde_data_offset);
6888 if (!(*result)) {
6889 g_free (entry);
6890 return FALSE;
6892 *size = entry->rde_size;
6893 g_free (entry);
6894 return TRUE;
6897 static MonoBoolean
6898 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6900 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6903 static void
6904 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6906 #if defined (HOST_WIN32)
6907 OutputDebugString (mono_string_chars (message));
6908 #else
6909 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6910 #endif
6913 /* Only used for value types */
6914 static MonoObject *
6915 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6917 MonoClass *klass;
6918 MonoDomain *domain;
6920 MONO_ARCH_SAVE_REGS;
6922 domain = mono_object_domain (type);
6923 klass = mono_class_from_mono_type (type->type);
6924 mono_class_init_or_throw (klass);
6926 if (mono_class_is_nullable (klass))
6927 /* No arguments -> null */
6928 return NULL;
6930 return mono_object_new (domain, klass);
6933 static MonoReflectionMethod *
6934 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6936 MonoClass *klass, *parent;
6937 MonoMethod *method = m->method;
6938 MonoMethod *result = NULL;
6940 MONO_ARCH_SAVE_REGS;
6942 if (method->klass == NULL)
6943 return m;
6945 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6946 MONO_CLASS_IS_INTERFACE (method->klass) ||
6947 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6948 return m;
6950 klass = method->klass;
6951 if (klass->generic_class)
6952 klass = klass->generic_class->container_class;
6954 if (definition) {
6955 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6956 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6957 mono_class_setup_vtable (parent);
6958 if (parent->vtable_size <= method->slot)
6959 break;
6960 klass = parent;
6962 } else {
6963 klass = klass->parent;
6964 if (!klass)
6965 return m;
6968 if (klass == method->klass)
6969 return m;
6971 result = klass->vtable [method->slot];
6972 if (result == NULL) {
6973 /* It is an abstract method */
6974 gpointer iter = NULL;
6975 while ((result = mono_class_get_methods (klass, &iter)))
6976 if (result->slot == method->slot)
6977 break;
6980 if (result == NULL)
6981 return m;
6983 return mono_method_get_object (mono_domain_get (), result, NULL);
6986 static MonoString*
6987 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6989 MonoMethod *method = m->method;
6991 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6992 return m->name;
6995 static void
6996 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6998 MONO_ARCH_SAVE_REGS;
7000 iter->sig = *(MonoMethodSignature**)argsp;
7002 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7003 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7005 iter->next_arg = 0;
7006 /* FIXME: it's not documented what start is exactly... */
7007 if (start) {
7008 iter->args = start;
7009 } else {
7010 iter->args = argsp + sizeof (gpointer);
7012 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7014 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7017 static MonoTypedRef
7018 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7020 guint32 i, arg_size;
7021 gint32 align;
7022 MonoTypedRef res;
7023 MONO_ARCH_SAVE_REGS;
7025 i = iter->sig->sentinelpos + iter->next_arg;
7027 g_assert (i < iter->sig->param_count);
7029 res.type = iter->sig->params [i];
7030 res.klass = mono_class_from_mono_type (res.type);
7031 res.value = iter->args;
7032 arg_size = mono_type_stack_size (res.type, &align);
7033 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7034 if (arg_size <= sizeof (gpointer)) {
7035 int dummy;
7036 int padding = arg_size - mono_type_size (res.type, &dummy);
7037 res.value = (guint8*)res.value + padding;
7039 #endif
7040 iter->args = (char*)iter->args + arg_size;
7041 iter->next_arg++;
7043 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7045 return res;
7048 static MonoTypedRef
7049 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7051 guint32 i, arg_size;
7052 gint32 align;
7053 MonoTypedRef res;
7054 MONO_ARCH_SAVE_REGS;
7056 i = iter->sig->sentinelpos + iter->next_arg;
7058 g_assert (i < iter->sig->param_count);
7060 while (i < iter->sig->param_count) {
7061 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7062 continue;
7063 res.type = iter->sig->params [i];
7064 res.klass = mono_class_from_mono_type (res.type);
7065 /* FIXME: endianess issue... */
7066 res.value = iter->args;
7067 arg_size = mono_type_stack_size (res.type, &align);
7068 iter->args = (char*)iter->args + arg_size;
7069 iter->next_arg++;
7070 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7071 return res;
7073 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7075 res.type = NULL;
7076 res.value = NULL;
7077 res.klass = NULL;
7078 return res;
7081 static MonoType*
7082 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7084 gint i;
7085 MONO_ARCH_SAVE_REGS;
7087 i = iter->sig->sentinelpos + iter->next_arg;
7089 g_assert (i < iter->sig->param_count);
7091 return iter->sig->params [i];
7094 static MonoObject*
7095 mono_TypedReference_ToObject (MonoTypedRef tref)
7097 MONO_ARCH_SAVE_REGS;
7099 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7100 MonoObject** objp = tref.value;
7101 return *objp;
7104 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7107 static MonoObject*
7108 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7110 MONO_ARCH_SAVE_REGS;
7112 if (MONO_TYPE_IS_REFERENCE (type)) {
7113 MonoObject** objp = value;
7114 return *objp;
7117 return mono_value_box (mono_domain_get (), klass, value);
7120 static void
7121 prelink_method (MonoMethod *method)
7123 const char *exc_class, *exc_arg;
7124 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7125 return;
7126 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7127 if (exc_class) {
7128 mono_raise_exception(
7129 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7131 /* create the wrapper, too? */
7134 static void
7135 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7137 MONO_ARCH_SAVE_REGS;
7138 prelink_method (method->method);
7141 static void
7142 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7144 MonoClass *klass = mono_class_from_mono_type (type->type);
7145 MonoMethod* m;
7146 gpointer iter = NULL;
7147 MONO_ARCH_SAVE_REGS;
7149 mono_class_init_or_throw (klass);
7151 while ((m = mono_class_get_methods (klass, &iter)))
7152 prelink_method (m);
7155 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7156 static void
7157 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7158 gint32 const **exponents,
7159 gunichar2 const **digitLowerTable,
7160 gunichar2 const **digitUpperTable,
7161 gint64 const **tenPowersList,
7162 gint32 const **decHexDigits)
7164 *mantissas = Formatter_MantissaBitsTable;
7165 *exponents = Formatter_TensExponentTable;
7166 *digitLowerTable = Formatter_DigitLowerTable;
7167 *digitUpperTable = Formatter_DigitUpperTable;
7168 *tenPowersList = Formatter_TenPowersList;
7169 *decHexDigits = Formatter_DecHexDigits;
7172 /* These parameters are "readonly" in corlib/System/Char.cs */
7173 static void
7174 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7175 guint8 const **numeric_data,
7176 gdouble const **numeric_data_values,
7177 guint16 const **to_lower_data_low,
7178 guint16 const **to_lower_data_high,
7179 guint16 const **to_upper_data_low,
7180 guint16 const **to_upper_data_high)
7182 *category_data = CategoryData;
7183 *numeric_data = NumericData;
7184 *numeric_data_values = NumericDataValues;
7185 *to_lower_data_low = ToLowerDataLow;
7186 *to_lower_data_high = ToLowerDataHigh;
7187 *to_upper_data_low = ToUpperDataLow;
7188 *to_upper_data_high = ToUpperDataHigh;
7191 static gint32
7192 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7194 return method->method->token;
7198 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7199 * and avoid useless allocations.
7201 static MonoArray*
7202 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7204 MonoArray *res;
7205 int i, count = 0;
7206 for (i = 0; i < type->num_mods; ++i) {
7207 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7208 count++;
7210 if (!count)
7211 return NULL;
7212 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7213 count = 0;
7214 for (i = 0; i < type->num_mods; ++i) {
7215 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7216 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7217 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7218 count++;
7221 return res;
7224 static MonoArray*
7225 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7227 MonoType *type = param->ClassImpl->type;
7228 MonoClass *member_class = mono_object_class (param->MemberImpl);
7229 MonoMethod *method = NULL;
7230 MonoImage *image;
7231 int pos;
7232 MonoMethodSignature *sig;
7234 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7235 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7236 method = rmethod->method;
7237 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7238 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7239 if (!(method = prop->property->get))
7240 method = prop->property->set;
7241 g_assert (method);
7242 } else {
7243 char *type_name = mono_type_get_full_name (member_class);
7244 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7245 MonoException *ex = mono_get_exception_not_supported (msg);
7246 g_free (type_name);
7247 g_free (msg);
7248 mono_raise_exception (ex);
7251 image = method->klass->image;
7252 pos = param->PositionImpl;
7253 sig = mono_method_signature (method);
7254 if (pos == -1)
7255 type = sig->ret;
7256 else
7257 type = sig->params [pos];
7259 return type_array_from_modifiers (image, type, optional);
7262 static MonoType*
7263 get_property_type (MonoProperty *prop)
7265 MonoMethodSignature *sig;
7266 if (prop->get) {
7267 sig = mono_method_signature (prop->get);
7268 return sig->ret;
7269 } else if (prop->set) {
7270 sig = mono_method_signature (prop->set);
7271 return sig->params [sig->param_count - 1];
7273 return NULL;
7276 static MonoArray*
7277 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7279 MonoType *type = get_property_type (property->property);
7280 MonoImage *image = property->klass->image;
7282 if (!type)
7283 return NULL;
7284 return type_array_from_modifiers (image, type, optional);
7288 *Construct a MonoType suited to be used to decode a constant blob object.
7290 * @type is the target type which will be constructed
7291 * @blob_type is the blob type, for example, that comes from the constant table
7292 * @real_type is the expected constructed type.
7294 static void
7295 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7297 type->type = blob_type;
7298 type->data.klass = NULL;
7299 if (blob_type == MONO_TYPE_CLASS)
7300 type->data.klass = mono_defaults.object_class;
7301 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7302 /* For enums, we need to use the base type */
7303 type->type = MONO_TYPE_VALUETYPE;
7304 type->data.klass = mono_class_from_mono_type (real_type);
7305 } else
7306 type->data.klass = mono_class_from_mono_type (real_type);
7309 static MonoObject*
7310 property_info_get_default_value (MonoReflectionProperty *property)
7312 MonoType blob_type;
7313 MonoProperty *prop = property->property;
7314 MonoType *type = get_property_type (prop);
7315 MonoDomain *domain = mono_object_domain (property);
7316 MonoTypeEnum def_type;
7317 const char *def_value;
7318 MonoObject *o;
7320 g_assert (!prop->parent->image->dynamic);
7322 mono_class_init (prop->parent);
7324 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7325 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7327 def_value = mono_class_get_property_default_value (prop, &def_type);
7329 mono_type_from_blob_type (&blob_type, def_type, type);
7330 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7332 return o;
7335 static MonoBoolean
7336 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7338 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7339 MonoCustomAttrInfo *cinfo;
7340 gboolean found;
7342 mono_class_init_or_throw (attr_class);
7344 cinfo = mono_reflection_get_custom_attrs_info (obj);
7345 if (!cinfo)
7346 return FALSE;
7347 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7348 if (!cinfo->cached)
7349 mono_custom_attrs_free (cinfo);
7350 return found;
7353 static MonoArray*
7354 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7356 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7357 MonoArray *res;
7359 if (attr_class)
7360 mono_class_init_or_throw (attr_class);
7362 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7364 if (mono_loader_get_last_error ()) {
7365 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7366 g_assert_not_reached ();
7367 /* Not reached */
7368 return NULL;
7369 } else {
7370 return res;
7374 static MonoString*
7375 ves_icall_Mono_Runtime_GetDisplayName (void)
7377 char *info;
7378 MonoString *display_name;
7380 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7381 display_name = mono_string_new (mono_domain_get (), info);
7382 g_free (info);
7383 return display_name;
7386 static MonoString*
7387 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7389 MonoString *message;
7390 guint32 ret;
7391 gunichar2 buf[256];
7393 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7394 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7395 buf, 255, NULL);
7396 if (ret == 0) {
7397 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7398 } else {
7399 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7402 return message;
7405 const static guchar
7406 dbase64 [] = {
7407 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7408 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7409 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7410 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7411 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7412 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7413 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7414 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7417 static MonoArray *
7418 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7420 gint ignored;
7421 gint i;
7422 gunichar2 c;
7423 gunichar2 last, prev_last, prev2_last;
7424 gint olength;
7425 MonoArray *result;
7426 guchar *res_ptr;
7427 gint a [4], b [4];
7428 MonoException *exc;
7430 ignored = 0;
7431 last = prev_last = 0, prev2_last = 0;
7432 for (i = 0; i < ilength; i++) {
7433 c = start [i];
7434 if (c >= sizeof (dbase64)) {
7435 exc = mono_exception_from_name_msg (mono_get_corlib (),
7436 "System", "FormatException",
7437 "Invalid character found.");
7438 mono_raise_exception (exc);
7439 } else if (isspace (c)) {
7440 ignored++;
7441 } else {
7442 prev2_last = prev_last;
7443 prev_last = last;
7444 last = c;
7448 olength = ilength - ignored;
7450 if (allowWhitespaceOnly && olength == 0) {
7451 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7454 if ((olength & 3) != 0 || olength <= 0) {
7455 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7456 "FormatException", "Invalid length.");
7457 mono_raise_exception (exc);
7460 if (prev2_last == '=') {
7461 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7462 mono_raise_exception (exc);
7465 olength = (olength * 3) / 4;
7466 if (last == '=')
7467 olength--;
7469 if (prev_last == '=')
7470 olength--;
7472 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7473 res_ptr = mono_array_addr (result, guchar, 0);
7474 for (i = 0; i < ilength; ) {
7475 int k;
7477 for (k = 0; k < 4 && i < ilength;) {
7478 c = start [i++];
7479 if (isspace (c))
7480 continue;
7482 a [k] = (guchar) c;
7483 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7484 exc = mono_exception_from_name_msg (mono_get_corlib (),
7485 "System", "FormatException",
7486 "Invalid character found.");
7487 mono_raise_exception (exc);
7489 k++;
7492 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7493 if (a [2] != '=')
7494 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7495 if (a [3] != '=')
7496 *res_ptr++ = (b [2] << 6) | b [3];
7498 while (i < ilength && isspace (start [i]))
7499 i++;
7502 return result;
7505 static MonoArray *
7506 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7508 MONO_ARCH_SAVE_REGS;
7510 return base64_to_byte_array (mono_string_chars (str),
7511 mono_string_length (str), allowWhitespaceOnly);
7514 static MonoArray *
7515 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7517 MONO_ARCH_SAVE_REGS;
7519 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7520 length, FALSE);
7523 #define ICALL_TYPE(id,name,first)
7524 #define ICALL(id,name,func) Icall_ ## id,
7526 enum {
7527 #include "metadata/icall-def.h"
7528 Icall_last
7531 #undef ICALL_TYPE
7532 #undef ICALL
7533 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7534 #define ICALL(id,name,func)
7535 enum {
7536 #include "metadata/icall-def.h"
7537 Icall_type_num
7540 #undef ICALL_TYPE
7541 #undef ICALL
7542 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7543 #define ICALL(id,name,func)
7544 typedef struct {
7545 guint16 first_icall;
7546 } IcallTypeDesc;
7548 static const IcallTypeDesc
7549 icall_type_descs [] = {
7550 #include "metadata/icall-def.h"
7551 {Icall_last}
7554 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7556 #undef ICALL_TYPE
7557 #define ICALL_TYPE(id,name,first)
7558 #undef ICALL
7560 #ifdef HAVE_ARRAY_ELEM_INIT
7561 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7562 #define MSGSTRFIELD1(line) str##line
7564 static const struct msgstrtn_t {
7565 #define ICALL(id,name,func)
7566 #undef ICALL_TYPE
7567 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7568 #include "metadata/icall-def.h"
7569 #undef ICALL_TYPE
7570 } icall_type_names_str = {
7571 #define ICALL_TYPE(id,name,first) (name),
7572 #include "metadata/icall-def.h"
7573 #undef ICALL_TYPE
7575 static const guint16 icall_type_names_idx [] = {
7576 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7577 #include "metadata/icall-def.h"
7578 #undef ICALL_TYPE
7580 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7582 static const struct msgstr_t {
7583 #undef ICALL
7584 #define ICALL_TYPE(id,name,first)
7585 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7586 #include "metadata/icall-def.h"
7587 #undef ICALL
7588 } icall_names_str = {
7589 #define ICALL(id,name,func) (name),
7590 #include "metadata/icall-def.h"
7591 #undef ICALL
7593 static const guint16 icall_names_idx [] = {
7594 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7595 #include "metadata/icall-def.h"
7596 #undef ICALL
7598 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7600 #else
7602 #undef ICALL_TYPE
7603 #undef ICALL
7604 #define ICALL_TYPE(id,name,first) name,
7605 #define ICALL(id,name,func)
7606 static const char* const
7607 icall_type_names [] = {
7608 #include "metadata/icall-def.h"
7609 NULL
7612 #define icall_type_name_get(id) (icall_type_names [(id)])
7614 #undef ICALL_TYPE
7615 #undef ICALL
7616 #define ICALL_TYPE(id,name,first)
7617 #define ICALL(id,name,func) name,
7618 static const char* const
7619 icall_names [] = {
7620 #include "metadata/icall-def.h"
7621 NULL
7623 #define icall_name_get(id) icall_names [(id)]
7625 #endif /* !HAVE_ARRAY_ELEM_INIT */
7627 #undef ICALL_TYPE
7628 #undef ICALL
7629 #define ICALL_TYPE(id,name,first)
7630 #define ICALL(id,name,func) func,
7631 static const gconstpointer
7632 icall_functions [] = {
7633 #include "metadata/icall-def.h"
7634 NULL
7637 static GHashTable *icall_hash = NULL;
7638 static GHashTable *jit_icall_hash_name = NULL;
7639 static GHashTable *jit_icall_hash_addr = NULL;
7641 void
7642 mono_icall_init (void)
7644 int i = 0;
7646 /* check that tables are sorted: disable in release */
7647 if (TRUE) {
7648 int j;
7649 const char *prev_class = NULL;
7650 const char *prev_method;
7652 for (i = 0; i < Icall_type_num; ++i) {
7653 const IcallTypeDesc *desc;
7654 int num_icalls;
7655 prev_method = NULL;
7656 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7657 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7658 prev_class = icall_type_name_get (i);
7659 desc = &icall_type_descs [i];
7660 num_icalls = icall_desc_num_icalls (desc);
7661 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7662 for (j = 0; j < num_icalls; ++j) {
7663 const char *methodn = icall_name_get (desc->first_icall + j);
7664 if (prev_method && strcmp (prev_method, methodn) >= 0)
7665 g_print ("method %s should come before method %s\n", methodn, prev_method);
7666 prev_method = methodn;
7671 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7674 void
7675 mono_icall_cleanup (void)
7677 g_hash_table_destroy (icall_hash);
7678 g_hash_table_destroy (jit_icall_hash_name);
7679 g_hash_table_destroy (jit_icall_hash_addr);
7682 void
7683 mono_add_internal_call (const char *name, gconstpointer method)
7685 mono_loader_lock ();
7687 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7689 mono_loader_unlock ();
7692 #ifdef HAVE_ARRAY_ELEM_INIT
7693 static int
7694 compare_method_imap (const void *key, const void *elem)
7696 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7697 return strcmp (key, method_name);
7700 static gpointer
7701 find_method_icall (const IcallTypeDesc *imap, const char *name)
7703 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7704 if (!nameslot)
7705 return NULL;
7706 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7709 static int
7710 compare_class_imap (const void *key, const void *elem)
7712 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7713 return strcmp (key, class_name);
7716 static const IcallTypeDesc*
7717 find_class_icalls (const char *name)
7719 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7720 if (!nameslot)
7721 return NULL;
7722 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7725 #else
7726 static int
7727 compare_method_imap (const void *key, const void *elem)
7729 const char** method_name = (const char**)elem;
7730 return strcmp (key, *method_name);
7733 static gpointer
7734 find_method_icall (const IcallTypeDesc *imap, const char *name)
7736 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7737 if (!nameslot)
7738 return NULL;
7739 return (gpointer)icall_functions [(nameslot - icall_names)];
7742 static int
7743 compare_class_imap (const void *key, const void *elem)
7745 const char** class_name = (const char**)elem;
7746 return strcmp (key, *class_name);
7749 static const IcallTypeDesc*
7750 find_class_icalls (const char *name)
7752 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7753 if (!nameslot)
7754 return NULL;
7755 return &icall_type_descs [nameslot - icall_type_names];
7758 #endif
7761 * we should probably export this as an helper (handle nested types).
7762 * Returns the number of chars written in buf.
7764 static int
7765 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7767 int nspacelen, cnamelen;
7768 nspacelen = strlen (klass->name_space);
7769 cnamelen = strlen (klass->name);
7770 if (nspacelen + cnamelen + 2 > bufsize)
7771 return 0;
7772 if (nspacelen) {
7773 memcpy (buf, klass->name_space, nspacelen);
7774 buf [nspacelen ++] = '.';
7776 memcpy (buf + nspacelen, klass->name, cnamelen);
7777 buf [nspacelen + cnamelen] = 0;
7778 return nspacelen + cnamelen;
7781 gpointer
7782 mono_lookup_internal_call (MonoMethod *method)
7784 char *sigstart;
7785 char *tmpsig;
7786 char mname [2048];
7787 int typelen = 0, mlen, siglen;
7788 gpointer res;
7789 const IcallTypeDesc *imap;
7791 g_assert (method != NULL);
7793 if (method->is_inflated)
7794 method = ((MonoMethodInflated *) method)->declaring;
7796 if (method->klass->nested_in) {
7797 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7798 if (!pos)
7799 return NULL;
7801 mname [pos++] = '/';
7802 mname [pos] = 0;
7804 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7805 if (!typelen)
7806 return NULL;
7808 typelen += pos;
7809 } else {
7810 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7811 if (!typelen)
7812 return NULL;
7815 imap = find_class_icalls (mname);
7817 mname [typelen] = ':';
7818 mname [typelen + 1] = ':';
7820 mlen = strlen (method->name);
7821 memcpy (mname + typelen + 2, method->name, mlen);
7822 sigstart = mname + typelen + 2 + mlen;
7823 *sigstart = 0;
7825 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7826 siglen = strlen (tmpsig);
7827 if (typelen + mlen + siglen + 6 > sizeof (mname))
7828 return NULL;
7829 sigstart [0] = '(';
7830 memcpy (sigstart + 1, tmpsig, siglen);
7831 sigstart [siglen + 1] = ')';
7832 sigstart [siglen + 2] = 0;
7833 g_free (tmpsig);
7835 mono_loader_lock ();
7837 res = g_hash_table_lookup (icall_hash, mname);
7838 if (res) {
7839 mono_loader_unlock ();
7840 return res;
7842 /* try without signature */
7843 *sigstart = 0;
7844 res = g_hash_table_lookup (icall_hash, mname);
7845 if (res) {
7846 mono_loader_unlock ();
7847 return res;
7850 /* it wasn't found in the static call tables */
7851 if (!imap) {
7852 mono_loader_unlock ();
7853 return NULL;
7855 res = find_method_icall (imap, sigstart - mlen);
7856 if (res) {
7857 mono_loader_unlock ();
7858 return res;
7860 /* try _with_ signature */
7861 *sigstart = '(';
7862 res = find_method_icall (imap, sigstart - mlen);
7863 if (res) {
7864 mono_loader_unlock ();
7865 return res;
7868 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7869 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7870 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7871 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7872 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");
7873 g_print ("If you see other errors or faults after this message they are probably related\n");
7874 g_print ("and you need to fix your mono install first.\n");
7876 mono_loader_unlock ();
7878 return NULL;
7881 static MonoType*
7882 type_from_typename (char *typename)
7884 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7886 if (!strcmp (typename, "int"))
7887 klass = mono_defaults.int_class;
7888 else if (!strcmp (typename, "ptr"))
7889 klass = mono_defaults.int_class;
7890 else if (!strcmp (typename, "void"))
7891 klass = mono_defaults.void_class;
7892 else if (!strcmp (typename, "int32"))
7893 klass = mono_defaults.int32_class;
7894 else if (!strcmp (typename, "uint32"))
7895 klass = mono_defaults.uint32_class;
7896 else if (!strcmp (typename, "int8"))
7897 klass = mono_defaults.sbyte_class;
7898 else if (!strcmp (typename, "uint8"))
7899 klass = mono_defaults.byte_class;
7900 else if (!strcmp (typename, "int16"))
7901 klass = mono_defaults.int16_class;
7902 else if (!strcmp (typename, "uint16"))
7903 klass = mono_defaults.uint16_class;
7904 else if (!strcmp (typename, "long"))
7905 klass = mono_defaults.int64_class;
7906 else if (!strcmp (typename, "ulong"))
7907 klass = mono_defaults.uint64_class;
7908 else if (!strcmp (typename, "float"))
7909 klass = mono_defaults.single_class;
7910 else if (!strcmp (typename, "double"))
7911 klass = mono_defaults.double_class;
7912 else if (!strcmp (typename, "object"))
7913 klass = mono_defaults.object_class;
7914 else if (!strcmp (typename, "obj"))
7915 klass = mono_defaults.object_class;
7916 else if (!strcmp (typename, "string"))
7917 klass = mono_defaults.string_class;
7918 else if (!strcmp (typename, "bool"))
7919 klass = mono_defaults.boolean_class;
7920 else if (!strcmp (typename, "boolean"))
7921 klass = mono_defaults.boolean_class;
7922 else {
7923 g_error ("%s", typename);
7924 g_assert_not_reached ();
7926 return &klass->byval_arg;
7929 MonoMethodSignature*
7930 mono_create_icall_signature (const char *sigstr)
7932 gchar **parts;
7933 int i, len;
7934 gchar **tmp;
7935 MonoMethodSignature *res;
7937 mono_loader_lock ();
7938 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7939 if (res) {
7940 mono_loader_unlock ();
7941 return res;
7944 parts = g_strsplit (sigstr, " ", 256);
7946 tmp = parts;
7947 len = 0;
7948 while (*tmp) {
7949 len ++;
7950 tmp ++;
7953 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7954 res->pinvoke = 1;
7956 #ifdef HOST_WIN32
7958 * Under windows, the default pinvoke calling convention is STDCALL but
7959 * we need CDECL.
7961 res->call_convention = MONO_CALL_C;
7962 #endif
7964 res->ret = type_from_typename (parts [0]);
7965 for (i = 1; i < len; ++i) {
7966 res->params [i - 1] = type_from_typename (parts [i]);
7969 g_strfreev (parts);
7971 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7973 mono_loader_unlock ();
7975 return res;
7978 MonoJitICallInfo *
7979 mono_find_jit_icall_by_name (const char *name)
7981 MonoJitICallInfo *info;
7982 g_assert (jit_icall_hash_name);
7984 mono_loader_lock ();
7985 info = g_hash_table_lookup (jit_icall_hash_name, name);
7986 mono_loader_unlock ();
7987 return info;
7990 MonoJitICallInfo *
7991 mono_find_jit_icall_by_addr (gconstpointer addr)
7993 MonoJitICallInfo *info;
7994 g_assert (jit_icall_hash_addr);
7996 mono_loader_lock ();
7997 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7998 mono_loader_unlock ();
8000 return info;
8004 * mono_get_jit_icall_info:
8006 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8007 * caller should access it while holding the loader lock.
8009 GHashTable*
8010 mono_get_jit_icall_info (void)
8012 return jit_icall_hash_name;
8015 void
8016 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8018 mono_loader_lock ();
8019 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8020 mono_loader_unlock ();
8023 MonoJitICallInfo *
8024 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8026 MonoJitICallInfo *info;
8028 g_assert (func);
8029 g_assert (name);
8031 mono_loader_lock ();
8033 if (!jit_icall_hash_name) {
8034 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8035 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8038 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8039 g_warning ("jit icall already defined \"%s\"\n", name);
8040 g_assert_not_reached ();
8043 info = g_new0 (MonoJitICallInfo, 1);
8045 info->name = name;
8046 info->func = func;
8047 info->sig = sig;
8049 if (is_save) {
8050 info->wrapper = func;
8051 } else {
8052 info->wrapper = NULL;
8055 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8056 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8058 mono_loader_unlock ();
8059 return info;