2009-02-16 Zoltan Varga <vargaz@gmail.com>
[mono-debugger.git] / mono / metadata / icall.c
blob61de07144c8bf75d5d3c1ad6933e0d0b602e5673
1 /*
2 * icall.c:
4 * Authors:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 #include <config.h>
14 #include <glib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <ctype.h>
18 #ifdef HAVE_ALLOCA_H
19 #include <alloca.h>
20 #endif
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #if defined (PLATFORM_WIN32)
28 #include <stdlib.h>
29 #endif
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/io-layer/io-layer.h>
71 #include <mono/utils/strtod.h>
72 #include <mono/utils/monobitset.h>
73 #include <mono/utils/mono-time.h>
74 #include <mono/utils/mono-proclib.h>
76 #if defined (PLATFORM_WIN32)
77 #include <windows.h>
78 #include <shlobj.h>
79 #endif
80 #include "decimal.h"
82 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
84 static MonoArray*
85 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
87 static inline MonoBoolean
88 is_generic_parameter (MonoType *type)
90 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
94 * We expect a pointer to a char, not a string
96 static gboolean
97 mono_double_ParseImpl (char *ptr, double *result)
99 gchar *endptr = NULL;
100 *result = 0.0;
102 MONO_ARCH_SAVE_REGS;
104 #ifdef __arm__
105 if (*ptr)
106 *result = strtod (ptr, &endptr);
107 #else
108 if (*ptr){
109 #ifdef _EGLIB_MAJOR
110 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
111 EnterCriticalSection (&mono_strtod_mutex);
112 *result = mono_strtod (ptr, &endptr);
113 LeaveCriticalSection (&mono_strtod_mutex);
114 #else
115 *result = mono_strtod (ptr, &endptr);
116 #endif
118 #endif
120 if (!*ptr || (endptr && *endptr))
121 return FALSE;
123 return TRUE;
126 static MonoObject *
127 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
129 MonoClass *ac;
130 MonoArray *ao;
131 gint32 esize;
132 gpointer *ea;
134 MONO_ARCH_SAVE_REGS;
136 ao = (MonoArray *)this;
137 ac = (MonoClass *)ao->obj.vtable->klass;
139 esize = mono_array_element_size (ac);
140 ea = (gpointer*)((char*)ao->vector + (pos * esize));
142 if (ac->element_class->valuetype)
143 return mono_value_box (this->vtable->domain, ac->element_class, ea);
144 else
145 return *ea;
148 static MonoObject *
149 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
151 MonoClass *ac, *ic;
152 MonoArray *ao, *io;
153 gint32 i, pos, *ind;
155 MONO_ARCH_SAVE_REGS;
157 MONO_CHECK_ARG_NULL (idxs);
159 io = (MonoArray *)idxs;
160 ic = (MonoClass *)io->obj.vtable->klass;
162 ao = (MonoArray *)this;
163 ac = (MonoClass *)ao->obj.vtable->klass;
165 g_assert (ic->rank == 1);
166 if (io->bounds != NULL || io->max_length != ac->rank)
167 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
169 ind = (gint32 *)io->vector;
171 if (ao->bounds == NULL) {
172 if (*ind < 0 || *ind >= ao->max_length)
173 mono_raise_exception (mono_get_exception_index_out_of_range ());
175 return ves_icall_System_Array_GetValueImpl (this, *ind);
178 for (i = 0; i < ac->rank; i++)
179 if ((ind [i] < ao->bounds [i].lower_bound) ||
180 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
181 mono_raise_exception (mono_get_exception_index_out_of_range ());
183 pos = ind [0] - ao->bounds [0].lower_bound;
184 for (i = 1; i < ac->rank; i++)
185 pos = pos*ao->bounds [i].length + ind [i] -
186 ao->bounds [i].lower_bound;
188 return ves_icall_System_Array_GetValueImpl (this, pos);
191 static void
192 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
194 MonoClass *ac, *vc, *ec;
195 gint32 esize, vsize;
196 gpointer *ea, *va;
197 int et, vt;
199 guint64 u64 = 0;
200 gint64 i64 = 0;
201 gdouble r64 = 0;
203 MONO_ARCH_SAVE_REGS;
205 if (value)
206 vc = value->vtable->klass;
207 else
208 vc = NULL;
210 ac = this->obj.vtable->klass;
211 ec = ac->element_class;
213 esize = mono_array_element_size (ac);
214 ea = (gpointer*)((char*)this->vector + (pos * esize));
215 va = (gpointer*)((char*)value + sizeof (MonoObject));
217 if (!value) {
218 memset (ea, 0, esize);
219 return;
222 #define NO_WIDENING_CONVERSION G_STMT_START{\
223 mono_raise_exception (mono_get_exception_argument ( \
224 "value", "not a widening conversion")); \
225 }G_STMT_END
227 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
228 if (esize < vsize + (extra)) \
229 mono_raise_exception (mono_get_exception_argument ( \
230 "value", "not a widening conversion")); \
231 }G_STMT_END
233 #define INVALID_CAST G_STMT_START{\
234 mono_raise_exception (mono_get_exception_invalid_cast ()); \
235 }G_STMT_END
237 /* Check element (destination) type. */
238 switch (ec->byval_arg.type) {
239 case MONO_TYPE_STRING:
240 switch (vc->byval_arg.type) {
241 case MONO_TYPE_STRING:
242 break;
243 default:
244 INVALID_CAST;
246 break;
247 case MONO_TYPE_BOOLEAN:
248 switch (vc->byval_arg.type) {
249 case MONO_TYPE_BOOLEAN:
250 break;
251 case MONO_TYPE_CHAR:
252 case MONO_TYPE_U1:
253 case MONO_TYPE_U2:
254 case MONO_TYPE_U4:
255 case MONO_TYPE_U8:
256 case MONO_TYPE_I1:
257 case MONO_TYPE_I2:
258 case MONO_TYPE_I4:
259 case MONO_TYPE_I8:
260 case MONO_TYPE_R4:
261 case MONO_TYPE_R8:
262 NO_WIDENING_CONVERSION;
263 default:
264 INVALID_CAST;
266 break;
269 if (!ec->valuetype) {
270 if (!mono_object_isinst (value, ec))
271 INVALID_CAST;
272 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
273 return;
276 if (mono_object_isinst (value, ec)) {
277 if (ec->has_references)
278 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
279 else
280 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
281 return;
284 if (!vc->valuetype)
285 INVALID_CAST;
287 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
289 et = ec->byval_arg.type;
290 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
291 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
293 vt = vc->byval_arg.type;
294 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
295 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
297 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
298 switch (vt) { \
299 case MONO_TYPE_U1: \
300 case MONO_TYPE_U2: \
301 case MONO_TYPE_U4: \
302 case MONO_TYPE_U8: \
303 case MONO_TYPE_CHAR: \
304 CHECK_WIDENING_CONVERSION(0); \
305 *(etype *) ea = (etype) u64; \
306 return; \
307 /* You can't assign a signed value to an unsigned array. */ \
308 case MONO_TYPE_I1: \
309 case MONO_TYPE_I2: \
310 case MONO_TYPE_I4: \
311 case MONO_TYPE_I8: \
312 /* You can't assign a floating point number to an integer array. */ \
313 case MONO_TYPE_R4: \
314 case MONO_TYPE_R8: \
315 NO_WIDENING_CONVERSION; \
317 }G_STMT_END
319 #define ASSIGN_SIGNED(etype) G_STMT_START{\
320 switch (vt) { \
321 case MONO_TYPE_I1: \
322 case MONO_TYPE_I2: \
323 case MONO_TYPE_I4: \
324 case MONO_TYPE_I8: \
325 CHECK_WIDENING_CONVERSION(0); \
326 *(etype *) ea = (etype) i64; \
327 return; \
328 /* You can assign an unsigned value to a signed array if the array's */ \
329 /* element size is larger than the value size. */ \
330 case MONO_TYPE_U1: \
331 case MONO_TYPE_U2: \
332 case MONO_TYPE_U4: \
333 case MONO_TYPE_U8: \
334 case MONO_TYPE_CHAR: \
335 CHECK_WIDENING_CONVERSION(1); \
336 *(etype *) ea = (etype) u64; \
337 return; \
338 /* You can't assign a floating point number to an integer array. */ \
339 case MONO_TYPE_R4: \
340 case MONO_TYPE_R8: \
341 NO_WIDENING_CONVERSION; \
343 }G_STMT_END
345 #define ASSIGN_REAL(etype) G_STMT_START{\
346 switch (vt) { \
347 case MONO_TYPE_R4: \
348 case MONO_TYPE_R8: \
349 CHECK_WIDENING_CONVERSION(0); \
350 *(etype *) ea = (etype) r64; \
351 return; \
352 /* All integer values fit into a floating point array, so we don't */ \
353 /* need to CHECK_WIDENING_CONVERSION here. */ \
354 case MONO_TYPE_I1: \
355 case MONO_TYPE_I2: \
356 case MONO_TYPE_I4: \
357 case MONO_TYPE_I8: \
358 *(etype *) ea = (etype) i64; \
359 return; \
360 case MONO_TYPE_U1: \
361 case MONO_TYPE_U2: \
362 case MONO_TYPE_U4: \
363 case MONO_TYPE_U8: \
364 case MONO_TYPE_CHAR: \
365 *(etype *) ea = (etype) u64; \
366 return; \
368 }G_STMT_END
370 switch (vt) {
371 case MONO_TYPE_U1:
372 u64 = *(guint8 *) va;
373 break;
374 case MONO_TYPE_U2:
375 u64 = *(guint16 *) va;
376 break;
377 case MONO_TYPE_U4:
378 u64 = *(guint32 *) va;
379 break;
380 case MONO_TYPE_U8:
381 u64 = *(guint64 *) va;
382 break;
383 case MONO_TYPE_I1:
384 i64 = *(gint8 *) va;
385 break;
386 case MONO_TYPE_I2:
387 i64 = *(gint16 *) va;
388 break;
389 case MONO_TYPE_I4:
390 i64 = *(gint32 *) va;
391 break;
392 case MONO_TYPE_I8:
393 i64 = *(gint64 *) va;
394 break;
395 case MONO_TYPE_R4:
396 r64 = *(gfloat *) va;
397 break;
398 case MONO_TYPE_R8:
399 r64 = *(gdouble *) va;
400 break;
401 case MONO_TYPE_CHAR:
402 u64 = *(guint16 *) va;
403 break;
404 case MONO_TYPE_BOOLEAN:
405 /* Boolean is only compatible with itself. */
406 switch (et) {
407 case MONO_TYPE_CHAR:
408 case MONO_TYPE_U1:
409 case MONO_TYPE_U2:
410 case MONO_TYPE_U4:
411 case MONO_TYPE_U8:
412 case MONO_TYPE_I1:
413 case MONO_TYPE_I2:
414 case MONO_TYPE_I4:
415 case MONO_TYPE_I8:
416 case MONO_TYPE_R4:
417 case MONO_TYPE_R8:
418 NO_WIDENING_CONVERSION;
419 default:
420 INVALID_CAST;
422 break;
425 /* If we can't do a direct copy, let's try a widening conversion. */
426 switch (et) {
427 case MONO_TYPE_CHAR:
428 ASSIGN_UNSIGNED (guint16);
429 case MONO_TYPE_U1:
430 ASSIGN_UNSIGNED (guint8);
431 case MONO_TYPE_U2:
432 ASSIGN_UNSIGNED (guint16);
433 case MONO_TYPE_U4:
434 ASSIGN_UNSIGNED (guint32);
435 case MONO_TYPE_U8:
436 ASSIGN_UNSIGNED (guint64);
437 case MONO_TYPE_I1:
438 ASSIGN_SIGNED (gint8);
439 case MONO_TYPE_I2:
440 ASSIGN_SIGNED (gint16);
441 case MONO_TYPE_I4:
442 ASSIGN_SIGNED (gint32);
443 case MONO_TYPE_I8:
444 ASSIGN_SIGNED (gint64);
445 case MONO_TYPE_R4:
446 ASSIGN_REAL (gfloat);
447 case MONO_TYPE_R8:
448 ASSIGN_REAL (gdouble);
451 INVALID_CAST;
452 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
453 return;
455 #undef INVALID_CAST
456 #undef NO_WIDENING_CONVERSION
457 #undef CHECK_WIDENING_CONVERSION
458 #undef ASSIGN_UNSIGNED
459 #undef ASSIGN_SIGNED
460 #undef ASSIGN_REAL
463 static void
464 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
465 MonoArray *idxs)
467 MonoClass *ac, *ic;
468 gint32 i, pos, *ind;
470 MONO_ARCH_SAVE_REGS;
472 MONO_CHECK_ARG_NULL (idxs);
474 ic = idxs->obj.vtable->klass;
475 ac = this->obj.vtable->klass;
477 g_assert (ic->rank == 1);
478 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
479 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
481 ind = (gint32 *)idxs->vector;
483 if (this->bounds == NULL) {
484 if (*ind < 0 || *ind >= this->max_length)
485 mono_raise_exception (mono_get_exception_index_out_of_range ());
487 ves_icall_System_Array_SetValueImpl (this, value, *ind);
488 return;
491 for (i = 0; i < ac->rank; i++)
492 if ((ind [i] < this->bounds [i].lower_bound) ||
493 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
494 mono_raise_exception (mono_get_exception_index_out_of_range ());
496 pos = ind [0] - this->bounds [0].lower_bound;
497 for (i = 1; i < ac->rank; i++)
498 pos = pos * this->bounds [i].length + ind [i] -
499 this->bounds [i].lower_bound;
501 ves_icall_System_Array_SetValueImpl (this, value, pos);
504 static MonoArray *
505 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
507 MonoClass *aklass;
508 MonoArray *array;
509 mono_array_size_t *sizes, i;
510 gboolean bounded = FALSE;
512 MONO_ARCH_SAVE_REGS;
514 MONO_CHECK_ARG_NULL (type);
515 MONO_CHECK_ARG_NULL (lengths);
517 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
518 if (bounds)
519 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
521 for (i = 0; i < mono_array_length (lengths); i++)
522 if (mono_array_get (lengths, gint32, i) < 0)
523 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
525 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
526 /* vectors are not the same as one dimensional arrays with no-zero bounds */
527 bounded = TRUE;
528 else
529 bounded = FALSE;
531 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
533 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
534 for (i = 0; i < aklass->rank; ++i) {
535 sizes [i] = mono_array_get (lengths, guint32, i);
536 if (bounds)
537 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
538 else
539 sizes [i + aklass->rank] = 0;
542 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
544 return array;
547 static MonoArray *
548 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
550 MonoClass *aklass;
551 MonoArray *array;
552 mono_array_size_t *sizes, i;
553 gboolean bounded = FALSE;
555 MONO_ARCH_SAVE_REGS;
557 MONO_CHECK_ARG_NULL (type);
558 MONO_CHECK_ARG_NULL (lengths);
560 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
561 if (bounds)
562 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
564 for (i = 0; i < mono_array_length (lengths); i++)
565 if ((mono_array_get (lengths, gint64, i) < 0) ||
566 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
567 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
569 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
570 /* vectors are not the same as one dimensional arrays with no-zero bounds */
571 bounded = TRUE;
572 else
573 bounded = FALSE;
575 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
577 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
578 for (i = 0; i < aklass->rank; ++i) {
579 sizes [i] = mono_array_get (lengths, guint64, i);
580 if (bounds)
581 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
582 else
583 sizes [i + aklass->rank] = 0;
586 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
588 return array;
591 static gint32
592 ves_icall_System_Array_GetRank (MonoObject *this)
594 MONO_ARCH_SAVE_REGS;
596 return this->vtable->klass->rank;
599 static gint32
600 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
602 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
603 mono_array_size_t length;
605 MONO_ARCH_SAVE_REGS;
607 if ((dimension < 0) || (dimension >= rank))
608 mono_raise_exception (mono_get_exception_index_out_of_range ());
610 if (this->bounds == NULL)
611 length = this->max_length;
612 else
613 length = this->bounds [dimension].length;
615 #ifdef MONO_BIG_ARRAYS
616 if (length > G_MAXINT32)
617 mono_raise_exception (mono_get_exception_overflow ());
618 #endif
619 return length;
622 static gint64
623 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
625 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
627 MONO_ARCH_SAVE_REGS;
629 if ((dimension < 0) || (dimension >= rank))
630 mono_raise_exception (mono_get_exception_index_out_of_range ());
632 if (this->bounds == NULL)
633 return this->max_length;
635 return this->bounds [dimension].length;
638 static gint32
639 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
641 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
643 MONO_ARCH_SAVE_REGS;
645 if ((dimension < 0) || (dimension >= rank))
646 mono_raise_exception (mono_get_exception_index_out_of_range ());
648 if (this->bounds == NULL)
649 return 0;
651 return this->bounds [dimension].lower_bound;
654 static void
655 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
657 int sz = mono_array_element_size (mono_object_class (arr));
658 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
661 static gboolean
662 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
664 int element_size;
665 void * dest_addr;
666 void * source_addr;
667 MonoClass *src_class;
668 MonoClass *dest_class;
669 int i;
671 MONO_ARCH_SAVE_REGS;
673 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
674 return FALSE;
676 if (source->bounds || dest->bounds)
677 return FALSE;
679 if ((dest_idx + length > mono_array_length (dest)) ||
680 (source_idx + length > mono_array_length (source)))
681 return FALSE;
683 src_class = source->obj.vtable->klass->element_class;
684 dest_class = dest->obj.vtable->klass->element_class;
687 * Handle common cases.
690 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
691 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
692 int has_refs = dest_class->has_references;
693 for (i = source_idx; i < source_idx + length; ++i) {
694 MonoObject *elem = mono_array_get (source, MonoObject*, i);
695 if (elem && !mono_object_isinst (elem, dest_class))
696 return FALSE;
699 element_size = mono_array_element_size (dest->obj.vtable->klass);
700 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
701 for (i = 0; i < length; ++i) {
702 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
703 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
704 if (!elem)
705 continue;
706 if (has_refs)
707 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
708 else
709 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
711 return TRUE;
714 /* Check if we're copying a char[] <==> (u)short[] */
715 if (src_class != dest_class) {
716 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
717 return FALSE;
719 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
721 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
722 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
723 for (i = source_idx; i < source_idx + length; ++i) {
724 MonoObject *elem = mono_array_get (source, MonoObject*, i);
725 if (elem && !mono_object_isinst (elem, dest_class))
726 return FALSE;
728 else
729 return FALSE;
732 if (dest_class->valuetype) {
733 element_size = mono_array_element_size (source->obj.vtable->klass);
734 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
735 if (dest_class->has_references) {
736 mono_value_copy_array (dest, dest_idx, source_addr, length);
737 } else {
738 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
739 memmove (dest_addr, source_addr, element_size * length);
741 } else {
742 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
745 return TRUE;
748 static void
749 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
751 MonoClass *ac;
752 MonoArray *ao;
753 gint32 esize;
754 gpointer *ea;
756 MONO_ARCH_SAVE_REGS;
758 ao = (MonoArray *)this;
759 ac = (MonoClass *)ao->obj.vtable->klass;
761 esize = mono_array_element_size (ac);
762 ea = (gpointer*)((char*)ao->vector + (pos * esize));
764 memcpy (value, ea, esize);
767 static void
768 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
770 MonoClass *ac;
771 MonoArray *ao;
772 gint32 esize;
773 gpointer *ea;
775 MONO_ARCH_SAVE_REGS;
777 ao = (MonoArray *)this;
778 ac = (MonoClass *)ao->obj.vtable->klass;
780 esize = mono_array_element_size (ac);
781 ea = (gpointer*)((char*)ao->vector + (pos * esize));
783 memcpy (ea, value, esize);
786 static void
787 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
789 MonoClass *klass = array->obj.vtable->klass;
790 guint32 size = mono_array_element_size (klass);
791 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
792 int align;
793 const char *field_data;
795 if (MONO_TYPE_IS_REFERENCE (type) ||
796 (type->type == MONO_TYPE_VALUETYPE &&
797 (!mono_type_get_class (type) ||
798 mono_type_get_class (type)->has_references))) {
799 MonoException *exc = mono_get_exception_argument("array",
800 "Cannot initialize array containing references");
801 mono_raise_exception (exc);
804 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
805 MonoException *exc = mono_get_exception_argument("field_handle",
806 "Field doesn't have an RVA");
807 mono_raise_exception (exc);
810 size *= array->max_length;
811 field_data = mono_field_get_data (field_handle);
813 if (size > mono_type_size (field_handle->type, &align)) {
814 MonoException *exc = mono_get_exception_argument("field_handle",
815 "Field not large enough to fill array");
816 mono_raise_exception (exc);
819 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
820 #define SWAP(n) {\
821 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
822 guint ## n *src = (guint ## n *) field_data; \
823 guint ## n *end = (guint ## n *)((char*)src + size); \
825 for (; src < end; data++, src++) { \
826 *data = read ## n (src); \
830 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
832 switch (type->type) {
833 case MONO_TYPE_CHAR:
834 case MONO_TYPE_I2:
835 case MONO_TYPE_U2:
836 SWAP (16);
837 break;
838 case MONO_TYPE_I4:
839 case MONO_TYPE_U4:
840 case MONO_TYPE_R4:
841 SWAP (32);
842 break;
843 case MONO_TYPE_I8:
844 case MONO_TYPE_U8:
845 case MONO_TYPE_R8:
846 SWAP (64);
847 break;
848 default:
849 memcpy (mono_array_addr (array, char, 0), field_data, size);
850 break;
852 #else
853 memcpy (mono_array_addr (array, char, 0), field_data, size);
854 #ifdef ARM_FPU_FPA
855 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
856 gint i;
857 double tmp;
858 double *data = (double*)mono_array_addr (array, double, 0);
860 for (i = 0; i < size; i++, data++) {
861 readr8 (data, &tmp);
862 *data = tmp;
865 #endif
866 #endif
869 static gint
870 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
872 MONO_ARCH_SAVE_REGS;
874 return offsetof (MonoString, chars);
877 static MonoObject *
878 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
880 MONO_ARCH_SAVE_REGS;
882 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
883 return obj;
884 else
885 return mono_object_clone (obj);
888 static void
889 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
891 MonoClass *klass;
893 MONO_ARCH_SAVE_REGS;
895 MONO_CHECK_ARG_NULL (handle);
897 klass = mono_class_from_mono_type (handle);
898 MONO_CHECK_ARG (handle, klass);
900 /* This will call the type constructor */
901 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
904 static void
905 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
907 MONO_ARCH_SAVE_REGS;
909 mono_image_check_for_module_cctor (image);
910 if (image->has_module_cctor) {
911 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
912 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), module_klass));
916 static MonoObject *
917 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
919 MONO_ARCH_SAVE_REGS;
921 return mono_object_clone (this);
924 static gint32
925 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
927 MonoClass *klass;
928 MonoObject **values = NULL;
929 MonoObject *o;
930 int count = 0;
931 gint32 result = 0;
932 MonoClassField* field;
933 gpointer iter;
935 MONO_ARCH_SAVE_REGS;
937 klass = mono_object_class (this);
939 if (mono_class_num_fields (klass) == 0)
940 return mono_object_hash (this);
943 * Compute the starting value of the hashcode for fields of primitive
944 * types, and return the remaining fields in an array to the managed side.
945 * This way, we can avoid costly reflection operations in managed code.
947 iter = NULL;
948 while ((field = mono_class_get_fields (klass, &iter))) {
949 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
950 continue;
951 if (mono_field_is_deleted (field))
952 continue;
953 /* FIXME: Add more types */
954 switch (field->type->type) {
955 case MONO_TYPE_I4:
956 result ^= *(gint32*)((guint8*)this + field->offset);
957 break;
958 case MONO_TYPE_STRING: {
959 MonoString *s;
960 s = *(MonoString**)((guint8*)this + field->offset);
961 if (s != NULL)
962 result ^= mono_string_hash (s);
963 break;
965 default:
966 if (!values)
967 values = g_newa (MonoObject*, mono_class_num_fields (klass));
968 o = mono_field_get_value_object (mono_object_domain (this), field, this);
969 values [count++] = o;
973 if (values) {
974 int i;
975 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
976 for (i = 0; i < count; ++i)
977 mono_array_setref (*fields, i, values [i]);
978 } else {
979 *fields = NULL;
981 return result;
984 static MonoBoolean
985 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
987 MonoClass *klass;
988 MonoObject **values = NULL;
989 MonoObject *o;
990 MonoClassField* field;
991 gpointer iter;
992 int count = 0;
994 MONO_ARCH_SAVE_REGS;
996 MONO_CHECK_ARG_NULL (that);
998 if (this->vtable != that->vtable)
999 return FALSE;
1001 klass = mono_object_class (this);
1003 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1004 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1007 * Do the comparison for fields of primitive type and return a result if
1008 * possible. Otherwise, return the remaining fields in an array to the
1009 * managed side. This way, we can avoid costly reflection operations in
1010 * managed code.
1012 *fields = NULL;
1013 iter = NULL;
1014 while ((field = mono_class_get_fields (klass, &iter))) {
1015 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1016 continue;
1017 if (mono_field_is_deleted (field))
1018 continue;
1019 /* FIXME: Add more types */
1020 switch (field->type->type) {
1021 case MONO_TYPE_U1:
1022 case MONO_TYPE_I1:
1023 case MONO_TYPE_BOOLEAN:
1024 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1025 return FALSE;
1026 break;
1027 case MONO_TYPE_U2:
1028 case MONO_TYPE_I2:
1029 case MONO_TYPE_CHAR:
1030 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1031 return FALSE;
1032 break;
1033 case MONO_TYPE_U4:
1034 case MONO_TYPE_I4:
1035 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1036 return FALSE;
1037 break;
1038 case MONO_TYPE_U8:
1039 case MONO_TYPE_I8:
1040 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1041 return FALSE;
1042 break;
1043 case MONO_TYPE_R4:
1044 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1045 return FALSE;
1046 break;
1047 case MONO_TYPE_R8:
1048 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1049 return FALSE;
1050 break;
1053 case MONO_TYPE_STRING: {
1054 MonoString *s1, *s2;
1055 guint32 s1len, s2len;
1056 s1 = *(MonoString**)((guint8*)this + field->offset);
1057 s2 = *(MonoString**)((guint8*)that + field->offset);
1058 if (s1 == s2)
1059 break;
1060 if ((s1 == NULL) || (s2 == NULL))
1061 return FALSE;
1062 s1len = mono_string_length (s1);
1063 s2len = mono_string_length (s2);
1064 if (s1len != s2len)
1065 return FALSE;
1067 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1068 return FALSE;
1069 break;
1071 default:
1072 if (!values)
1073 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1074 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1075 values [count++] = o;
1076 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1077 values [count++] = o;
1080 if (klass->enumtype)
1081 /* enums only have one non-static field */
1082 break;
1085 if (values) {
1086 int i;
1087 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
1088 for (i = 0; i < count; ++i)
1089 mono_array_setref (*fields, i, values [i]);
1090 return FALSE;
1091 } else {
1092 return TRUE;
1096 static MonoReflectionType *
1097 ves_icall_System_Object_GetType (MonoObject *obj)
1099 MONO_ARCH_SAVE_REGS;
1101 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1102 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1103 else
1104 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1107 static void
1108 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1110 MONO_ARCH_SAVE_REGS;
1112 mtype->type = &obj->vtable->klass->byval_arg;
1113 g_assert (mtype->type->type);
1116 static gint32
1117 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1119 MONO_ARCH_SAVE_REGS;
1121 MONO_CHECK_ARG_NULL (obj);
1123 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1126 static gint32
1127 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1128 MonoReflectionMethod *method,
1129 MonoArray *opt_param_types)
1131 MONO_ARCH_SAVE_REGS;
1133 MONO_CHECK_ARG_NULL (method);
1135 return mono_image_create_method_token (
1136 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1139 static void
1140 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1142 MONO_ARCH_SAVE_REGS;
1144 mono_image_create_pefile (mb, file);
1147 static void
1148 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1150 MONO_ARCH_SAVE_REGS;
1152 mono_image_build_metadata (mb);
1155 static void
1156 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1158 MONO_ARCH_SAVE_REGS;
1160 mono_image_register_token (mb->dynamic_image, token, obj);
1163 static gboolean
1164 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1166 MonoMethod **dest = data;
1168 /* skip unmanaged frames */
1169 if (!managed)
1170 return FALSE;
1172 if (m == *dest) {
1173 *dest = NULL;
1174 return FALSE;
1176 if (!(*dest)) {
1177 *dest = m;
1178 return TRUE;
1180 return FALSE;
1183 static gboolean
1184 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1186 MonoMethod **dest = data;
1188 /* skip unmanaged frames */
1189 if (!managed)
1190 return FALSE;
1192 if (!(*dest)) {
1193 if (!strcmp (m->klass->name_space, "System.Reflection"))
1194 return FALSE;
1195 *dest = m;
1196 return TRUE;
1198 return FALSE;
1201 static gboolean
1202 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1204 MonoMethod **dest = data;
1206 /* skip unmanaged frames */
1207 if (!managed)
1208 return FALSE;
1210 if (m->wrapper_type != MONO_WRAPPER_NONE)
1211 return FALSE;
1213 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1214 return FALSE;
1216 if (m == *dest) {
1217 *dest = NULL;
1218 return FALSE;
1220 if (!(*dest)) {
1221 *dest = m;
1222 return TRUE;
1224 return FALSE;
1227 static MonoReflectionType *
1228 type_from_name (const char *str, MonoBoolean ignoreCase)
1230 MonoType *type = NULL;
1231 MonoAssembly *assembly = NULL;
1232 MonoTypeNameParse info;
1233 char *temp_str = g_strdup (str);
1234 gboolean type_resolve = FALSE;
1236 MONO_ARCH_SAVE_REGS;
1238 /* mono_reflection_parse_type() mangles the string */
1239 if (!mono_reflection_parse_type (temp_str, &info)) {
1240 mono_reflection_free_type_info (&info);
1241 g_free (temp_str);
1242 return NULL;
1245 if (info.assembly.name) {
1246 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1247 } else {
1248 MonoMethod *m = mono_method_get_last_managed ();
1249 MonoMethod *dest = m;
1251 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1252 if (!dest)
1253 dest = m;
1256 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1257 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1258 * to crash. This only seems to happen in some strange remoting
1259 * scenarios and I was unable to figure out what's happening there.
1260 * Dec 10, 2005 - Martin.
1263 if (dest)
1264 assembly = dest->klass->image->assembly;
1265 else {
1266 g_warning (G_STRLOC);
1270 if (assembly)
1271 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1273 if (!info.assembly.name && !type) /* try mscorlib */
1274 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1276 mono_reflection_free_type_info (&info);
1277 g_free (temp_str);
1279 if (!type)
1280 return NULL;
1282 return mono_type_get_object (mono_domain_get (), type);
1285 #ifdef UNUSED
1286 MonoReflectionType *
1287 mono_type_get (const char *str)
1289 char *copy = g_strdup (str);
1290 MonoReflectionType *type = type_from_name (copy, FALSE);
1292 g_free (copy);
1293 return type;
1295 #endif
1297 static MonoReflectionType*
1298 ves_icall_type_from_name (MonoString *name,
1299 MonoBoolean throwOnError,
1300 MonoBoolean ignoreCase)
1302 char *str = mono_string_to_utf8 (name);
1303 MonoReflectionType *type;
1305 type = type_from_name (str, ignoreCase);
1306 g_free (str);
1307 if (type == NULL){
1308 MonoException *e = NULL;
1310 if (throwOnError)
1311 e = mono_get_exception_type_load (name, NULL);
1313 mono_loader_clear_error ();
1314 if (e != NULL)
1315 mono_raise_exception (e);
1318 return type;
1322 static MonoReflectionType*
1323 ves_icall_type_from_handle (MonoType *handle)
1325 MonoDomain *domain = mono_domain_get ();
1326 MonoClass *klass = mono_class_from_mono_type (handle);
1328 MONO_ARCH_SAVE_REGS;
1330 mono_class_init (klass);
1331 return mono_type_get_object (domain, handle);
1334 static MonoBoolean
1335 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1337 MONO_ARCH_SAVE_REGS;
1339 if (c && type->type && c->type)
1340 return mono_metadata_type_equal (type->type, c->type);
1341 else
1342 return (type == c) ? TRUE : FALSE;
1345 /* System.TypeCode */
1346 typedef enum {
1347 TYPECODE_EMPTY,
1348 TYPECODE_OBJECT,
1349 TYPECODE_DBNULL,
1350 TYPECODE_BOOLEAN,
1351 TYPECODE_CHAR,
1352 TYPECODE_SBYTE,
1353 TYPECODE_BYTE,
1354 TYPECODE_INT16,
1355 TYPECODE_UINT16,
1356 TYPECODE_INT32,
1357 TYPECODE_UINT32,
1358 TYPECODE_INT64,
1359 TYPECODE_UINT64,
1360 TYPECODE_SINGLE,
1361 TYPECODE_DOUBLE,
1362 TYPECODE_DECIMAL,
1363 TYPECODE_DATETIME,
1364 TYPECODE_STRING = 18
1365 } TypeCode;
1367 static guint32
1368 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1370 int t = type->type->type;
1372 MONO_ARCH_SAVE_REGS;
1374 if (type->type->byref)
1375 return TYPECODE_OBJECT;
1377 handle_enum:
1378 switch (t) {
1379 case MONO_TYPE_VOID:
1380 return TYPECODE_OBJECT;
1381 case MONO_TYPE_BOOLEAN:
1382 return TYPECODE_BOOLEAN;
1383 case MONO_TYPE_U1:
1384 return TYPECODE_BYTE;
1385 case MONO_TYPE_I1:
1386 return TYPECODE_SBYTE;
1387 case MONO_TYPE_U2:
1388 return TYPECODE_UINT16;
1389 case MONO_TYPE_I2:
1390 return TYPECODE_INT16;
1391 case MONO_TYPE_CHAR:
1392 return TYPECODE_CHAR;
1393 case MONO_TYPE_PTR:
1394 case MONO_TYPE_U:
1395 case MONO_TYPE_I:
1396 return TYPECODE_OBJECT;
1397 case MONO_TYPE_U4:
1398 return TYPECODE_UINT32;
1399 case MONO_TYPE_I4:
1400 return TYPECODE_INT32;
1401 case MONO_TYPE_U8:
1402 return TYPECODE_UINT64;
1403 case MONO_TYPE_I8:
1404 return TYPECODE_INT64;
1405 case MONO_TYPE_R4:
1406 return TYPECODE_SINGLE;
1407 case MONO_TYPE_R8:
1408 return TYPECODE_DOUBLE;
1409 case MONO_TYPE_VALUETYPE:
1410 if (type->type->data.klass->enumtype) {
1411 t = mono_class_enum_basetype (type->type->data.klass)->type;
1412 goto handle_enum;
1413 } else {
1414 MonoClass *k = type->type->data.klass;
1415 if (strcmp (k->name_space, "System") == 0) {
1416 if (strcmp (k->name, "Decimal") == 0)
1417 return TYPECODE_DECIMAL;
1418 else if (strcmp (k->name, "DateTime") == 0)
1419 return TYPECODE_DATETIME;
1422 return TYPECODE_OBJECT;
1423 case MONO_TYPE_STRING:
1424 return TYPECODE_STRING;
1425 case MONO_TYPE_SZARRAY:
1426 case MONO_TYPE_ARRAY:
1427 case MONO_TYPE_OBJECT:
1428 case MONO_TYPE_VAR:
1429 case MONO_TYPE_MVAR:
1430 case MONO_TYPE_TYPEDBYREF:
1431 return TYPECODE_OBJECT;
1432 case MONO_TYPE_CLASS:
1434 MonoClass *k = type->type->data.klass;
1435 if (strcmp (k->name_space, "System") == 0) {
1436 if (strcmp (k->name, "DBNull") == 0)
1437 return TYPECODE_DBNULL;
1440 return TYPECODE_OBJECT;
1441 case MONO_TYPE_GENERICINST:
1442 return TYPECODE_OBJECT;
1443 default:
1444 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1446 return 0;
1449 static guint32
1450 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1452 MonoDomain *domain;
1453 MonoClass *klass;
1454 MonoClass *klassc;
1456 MONO_ARCH_SAVE_REGS;
1458 g_assert (type != NULL);
1460 domain = ((MonoObject *)type)->vtable->domain;
1462 if (!c) /* FIXME: dont know what do do here */
1463 return 0;
1465 klass = mono_class_from_mono_type (type->type);
1466 klassc = mono_class_from_mono_type (c->type);
1468 if (type->type->byref)
1469 return klassc == mono_defaults.object_class;
1471 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1474 static guint32
1475 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1477 MonoDomain *domain;
1478 MonoClass *klass;
1479 MonoClass *klassc;
1481 MONO_ARCH_SAVE_REGS;
1483 g_assert (type != NULL);
1485 domain = ((MonoObject *)type)->vtable->domain;
1487 klass = mono_class_from_mono_type (type->type);
1488 klassc = mono_class_from_mono_type (c->type);
1490 if (type->type->byref && !c->type->byref)
1491 return FALSE;
1493 return mono_class_is_assignable_from (klass, klassc);
1496 static guint32
1497 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1499 MonoClass *klass = mono_class_from_mono_type (type->type);
1500 return mono_object_isinst (obj, klass) != NULL;
1503 static guint32
1504 ves_icall_get_attributes (MonoReflectionType *type)
1506 MonoClass *klass = mono_class_from_mono_type (type->type);
1508 MONO_ARCH_SAVE_REGS;
1510 return klass->flags;
1513 static MonoReflectionMarshal*
1514 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1516 MonoClass *klass = field->field->parent;
1517 MonoMarshalType *info;
1518 int i;
1520 if (klass->generic_container ||
1521 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1522 return NULL;
1524 info = mono_marshal_load_type_info (klass);
1526 for (i = 0; i < info->num_fields; ++i) {
1527 if (info->fields [i].field == field->field) {
1528 if (!info->fields [i].mspec)
1529 return NULL;
1530 else
1531 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1535 return NULL;
1538 static MonoReflectionField*
1539 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoClass *klass)
1541 g_assert (handle);
1543 if (!klass)
1544 klass = handle->parent;
1546 /* FIXME: check that handle is a field of klass or of a parent: return null
1547 * and throw the exception in managed code.
1549 return mono_field_get_object (mono_domain_get (), klass, handle);
1552 static MonoReflectionField*
1553 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1555 MONO_ARCH_SAVE_REGS;
1557 g_assert (handle);
1559 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1562 static MonoArray*
1563 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1565 MonoType *type = field->field->type;
1567 return type_array_from_modifiers (field->field->parent->image, type, optional);
1570 static void
1571 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1573 MonoDomain *domain = mono_domain_get ();
1574 MonoMethodSignature* sig;
1575 MONO_ARCH_SAVE_REGS;
1577 sig = mono_method_signature (method);
1578 if (!sig) {
1579 g_assert (mono_loader_get_last_error ());
1580 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1583 info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
1584 info->ret = mono_type_get_object (domain, sig->ret);
1585 info->attrs = method->flags;
1586 info->implattrs = method->iflags;
1587 if (sig->call_convention == MONO_CALL_DEFAULT)
1588 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1589 else {
1590 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1591 info->callconv = 2;
1592 else
1593 info->callconv = 1;
1595 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1598 static MonoArray*
1599 ves_icall_get_parameter_info (MonoMethod *method)
1601 MonoDomain *domain = mono_domain_get ();
1603 return mono_param_get_objects (domain, method);
1606 static MonoReflectionMarshal*
1607 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1609 MonoDomain *domain = mono_domain_get ();
1610 MonoReflectionMarshal* res = NULL;
1611 MonoMarshalSpec **mspecs;
1612 int i;
1614 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1615 mono_method_get_marshal_info (method, mspecs);
1617 if (mspecs [0])
1618 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1620 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1621 if (mspecs [i])
1622 mono_metadata_free_marshal_spec (mspecs [i]);
1623 g_free (mspecs);
1625 return res;
1628 static gint32
1629 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1631 return field->field->offset - sizeof (MonoObject);
1634 static MonoReflectionType*
1635 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1637 MonoClass *parent;
1638 MONO_ARCH_SAVE_REGS;
1640 parent = declaring? field->field->parent: field->klass;
1642 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1645 static MonoObject *
1646 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1648 MonoObject *o;
1649 MonoClassField *cf = field->field;
1650 MonoClass *klass;
1651 MonoVTable *vtable;
1652 MonoType *t;
1653 MonoDomain *domain = mono_object_domain (field);
1654 gchar *v;
1655 gboolean is_static = FALSE;
1656 gboolean is_ref = FALSE;
1658 MONO_ARCH_SAVE_REGS;
1660 if (field->klass->image->assembly->ref_only)
1661 mono_raise_exception (mono_get_exception_invalid_operation (
1662 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1664 mono_class_init (field->klass);
1666 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1667 is_static = TRUE;
1669 if (obj && !is_static) {
1670 /* Check that the field belongs to the object */
1671 gboolean found = FALSE;
1672 MonoClass *k;
1674 for (k = obj->vtable->klass; k; k = k->parent) {
1675 if (k == cf->parent) {
1676 found = TRUE;
1677 break;
1681 if (!found) {
1682 char *msg = g_strdup_printf ("Field '%s' defined on type '%s' is not a field on the target object which is of type '%s'.", mono_field_get_name (cf), cf->parent->name, obj->vtable->klass->name);
1683 MonoException *ex = mono_get_exception_argument (NULL, msg);
1684 g_free (msg);
1685 mono_raise_exception (ex);
1689 t = mono_type_get_underlying_type (cf->type);
1690 switch (t->type) {
1691 case MONO_TYPE_STRING:
1692 case MONO_TYPE_OBJECT:
1693 case MONO_TYPE_CLASS:
1694 case MONO_TYPE_ARRAY:
1695 case MONO_TYPE_SZARRAY:
1696 is_ref = TRUE;
1697 break;
1698 case MONO_TYPE_U1:
1699 case MONO_TYPE_I1:
1700 case MONO_TYPE_BOOLEAN:
1701 case MONO_TYPE_U2:
1702 case MONO_TYPE_I2:
1703 case MONO_TYPE_CHAR:
1704 case MONO_TYPE_U:
1705 case MONO_TYPE_I:
1706 case MONO_TYPE_U4:
1707 case MONO_TYPE_I4:
1708 case MONO_TYPE_R4:
1709 case MONO_TYPE_U8:
1710 case MONO_TYPE_I8:
1711 case MONO_TYPE_R8:
1712 case MONO_TYPE_VALUETYPE:
1713 is_ref = t->byref;
1714 break;
1715 case MONO_TYPE_GENERICINST:
1716 if (mono_type_generic_inst_is_valuetype (t)) {
1717 is_ref = t->byref;
1718 } else {
1719 is_ref = TRUE;
1721 break;
1722 default:
1723 g_error ("type 0x%x not handled in "
1724 "ves_icall_Monofield_GetValue", t->type);
1725 return NULL;
1728 vtable = NULL;
1729 if (is_static) {
1730 vtable = mono_class_vtable (domain, cf->parent);
1731 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1732 mono_runtime_class_init (vtable);
1735 if (is_ref) {
1736 if (is_static) {
1737 mono_field_static_get_value (vtable, cf, &o);
1738 } else {
1739 mono_field_get_value (obj, cf, &o);
1741 return o;
1744 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1745 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1746 guint8 *buf;
1748 /* Convert the Nullable structure into a boxed vtype */
1749 if (is_static)
1750 buf = (guint8*)vtable->data + cf->offset;
1751 else
1752 buf = (guint8*)obj + cf->offset;
1754 return mono_nullable_box (buf, nklass);
1757 /* boxed value type */
1758 klass = mono_class_from_mono_type (cf->type);
1759 o = mono_object_new (domain, klass);
1760 v = ((gchar *) o) + sizeof (MonoObject);
1761 if (is_static) {
1762 mono_field_static_get_value (vtable, cf, v);
1763 } else {
1764 mono_field_get_value (obj, cf, v);
1767 return o;
1770 static void
1771 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1773 MonoClassField *cf = field->field;
1774 gchar *v;
1776 MONO_ARCH_SAVE_REGS;
1778 if (field->klass->image->assembly->ref_only)
1779 mono_raise_exception (mono_get_exception_invalid_operation (
1780 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1782 v = (gchar *) value;
1783 if (!cf->type->byref) {
1784 switch (cf->type->type) {
1785 case MONO_TYPE_U1:
1786 case MONO_TYPE_I1:
1787 case MONO_TYPE_BOOLEAN:
1788 case MONO_TYPE_U2:
1789 case MONO_TYPE_I2:
1790 case MONO_TYPE_CHAR:
1791 case MONO_TYPE_U:
1792 case MONO_TYPE_I:
1793 case MONO_TYPE_U4:
1794 case MONO_TYPE_I4:
1795 case MONO_TYPE_R4:
1796 case MONO_TYPE_U8:
1797 case MONO_TYPE_I8:
1798 case MONO_TYPE_R8:
1799 case MONO_TYPE_VALUETYPE:
1800 if (v != NULL)
1801 v += sizeof (MonoObject);
1802 break;
1803 case MONO_TYPE_STRING:
1804 case MONO_TYPE_OBJECT:
1805 case MONO_TYPE_CLASS:
1806 case MONO_TYPE_ARRAY:
1807 case MONO_TYPE_SZARRAY:
1808 /* Do nothing */
1809 break;
1810 case MONO_TYPE_GENERICINST: {
1811 MonoGenericClass *gclass = cf->type->data.generic_class;
1812 g_assert (!gclass->context.class_inst->is_open);
1814 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1815 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1816 MonoObject *nullable;
1819 * Convert the boxed vtype into a Nullable structure.
1820 * This is complicated by the fact that Nullables have
1821 * a variable structure.
1823 nullable = mono_object_new (mono_domain_get (), nklass);
1825 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1827 v = mono_object_unbox (nullable);
1829 else
1830 if (gclass->container_class->valuetype && (v != NULL))
1831 v += sizeof (MonoObject);
1832 break;
1834 default:
1835 g_error ("type 0x%x not handled in "
1836 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1837 return;
1841 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1842 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1843 if (!vtable->initialized)
1844 mono_runtime_class_init (vtable);
1845 mono_field_static_set_value (vtable, cf, v);
1846 } else {
1847 mono_field_set_value (obj, cf, v);
1851 static MonoObject *
1852 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1854 MonoObject *o = NULL;
1855 MonoClassField *field = this->field;
1856 MonoClass *klass;
1857 MonoDomain *domain = mono_object_domain (this);
1858 gchar *v;
1859 MonoTypeEnum def_type;
1860 const char *def_value;
1862 MONO_ARCH_SAVE_REGS;
1864 mono_class_init (field->parent);
1866 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1867 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1869 if (field->parent->image->dynamic) {
1870 /* FIXME: */
1871 g_assert_not_reached ();
1874 def_value = mono_class_get_field_default_value (field, &def_type);
1876 switch (def_type) {
1877 case MONO_TYPE_U1:
1878 case MONO_TYPE_I1:
1879 case MONO_TYPE_BOOLEAN:
1880 case MONO_TYPE_U2:
1881 case MONO_TYPE_I2:
1882 case MONO_TYPE_CHAR:
1883 case MONO_TYPE_U:
1884 case MONO_TYPE_I:
1885 case MONO_TYPE_U4:
1886 case MONO_TYPE_I4:
1887 case MONO_TYPE_R4:
1888 case MONO_TYPE_U8:
1889 case MONO_TYPE_I8:
1890 case MONO_TYPE_R8: {
1891 MonoType *t;
1893 /* boxed value type */
1894 t = g_new0 (MonoType, 1);
1895 t->type = def_type;
1896 klass = mono_class_from_mono_type (t);
1897 g_free (t);
1898 o = mono_object_new (domain, klass);
1899 v = ((gchar *) o) + sizeof (MonoObject);
1900 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1901 break;
1903 case MONO_TYPE_STRING:
1904 case MONO_TYPE_CLASS:
1905 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1906 break;
1907 default:
1908 g_assert_not_reached ();
1911 return o;
1914 static MonoReflectionType*
1915 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1917 MonoMethod *method = rmethod->method.method;
1919 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1922 /* From MonoProperty.cs */
1923 typedef enum {
1924 PInfo_Attributes = 1,
1925 PInfo_GetMethod = 1 << 1,
1926 PInfo_SetMethod = 1 << 2,
1927 PInfo_ReflectedType = 1 << 3,
1928 PInfo_DeclaringType = 1 << 4,
1929 PInfo_Name = 1 << 5
1930 } PInfo;
1932 static void
1933 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1935 MonoDomain *domain = mono_object_domain (property);
1937 MONO_ARCH_SAVE_REGS;
1939 if ((req_info & PInfo_ReflectedType) != 0)
1940 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1941 else if ((req_info & PInfo_DeclaringType) != 0)
1942 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1944 if ((req_info & PInfo_Name) != 0)
1945 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1947 if ((req_info & PInfo_Attributes) != 0)
1948 info->attrs = property->property->attrs;
1950 if ((req_info & PInfo_GetMethod) != 0)
1951 MONO_STRUCT_SETREF (info, get, property->property->get ?
1952 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1954 if ((req_info & PInfo_SetMethod) != 0)
1955 MONO_STRUCT_SETREF (info, set, property->property->set ?
1956 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1958 * There may be other methods defined for properties, though, it seems they are not exposed
1959 * in the reflection API
1963 static void
1964 ves_icall_get_event_info (MonoReflectionEvent *event, MonoEventInfo *info)
1966 MonoDomain *domain = mono_object_domain (event);
1968 MONO_ARCH_SAVE_REGS;
1970 info->reflected_type = mono_type_get_object (domain, &event->klass->byval_arg);
1971 info->declaring_type = mono_type_get_object (domain, &event->event->parent->byval_arg);
1973 info->name = mono_string_new (domain, event->event->name);
1974 info->attrs = event->event->attrs;
1975 info->add_method = event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL;
1976 info->remove_method = event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL;
1977 info->raise_method = event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL;
1979 if (event->event->other) {
1980 int i, n = 0;
1981 while (event->event->other [n])
1982 n++;
1983 info->other_methods = mono_array_new (domain, mono_defaults.method_info_class, n);
1985 for (i = 0; i < n; i++)
1986 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
1990 static MonoArray*
1991 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
1993 MonoDomain *domain = mono_object_domain (type);
1994 MonoArray *intf;
1995 GPtrArray *ifaces = NULL;
1996 int i;
1997 MonoClass *class = mono_class_from_mono_type (type->type);
1998 MonoClass *parent;
1999 MonoBitSet *slots;
2000 MonoGenericContext *context = NULL;
2002 MONO_ARCH_SAVE_REGS;
2004 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2005 context = mono_class_get_context (class);
2006 class = class->generic_class->container_class;
2009 mono_class_setup_vtable (class);
2011 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2013 for (parent = class; parent; parent = parent->parent) {
2014 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
2015 if (tmp_ifaces) {
2016 for (i = 0; i < tmp_ifaces->len; ++i) {
2017 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2019 if (mono_bitset_test (slots, ic->interface_id))
2020 continue;
2022 mono_bitset_set (slots, ic->interface_id);
2023 if (ifaces == NULL)
2024 ifaces = g_ptr_array_new ();
2025 g_ptr_array_add (ifaces, ic);
2027 g_ptr_array_free (tmp_ifaces, TRUE);
2030 mono_bitset_free (slots);
2032 if (!ifaces)
2033 return mono_array_new (domain, mono_defaults.monotype_class, 0);
2035 intf = mono_array_new (domain, mono_defaults.monotype_class, ifaces->len);
2036 for (i = 0; i < ifaces->len; ++i) {
2037 MonoClass *ic = g_ptr_array_index (ifaces, i);
2038 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2039 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2040 inflated = ret = mono_class_inflate_generic_type (ret, context);
2042 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2043 if (inflated)
2044 mono_metadata_free_type (inflated);
2046 g_ptr_array_free (ifaces, TRUE);
2048 return intf;
2051 static void
2052 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2054 MonoClass *class = mono_class_from_mono_type (type->type);
2055 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2056 MonoReflectionMethod *member;
2057 MonoMethod* method;
2058 gpointer iter;
2059 int i = 0, len, ioffset;
2060 MonoDomain *domain;
2062 MONO_ARCH_SAVE_REGS;
2064 mono_class_setup_vtable (class);
2066 /* type doesn't implement iface: the exception is thrown in managed code */
2067 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2068 return;
2070 len = mono_class_num_methods (iclass);
2071 ioffset = mono_class_interface_offset (class, iclass);
2072 domain = mono_object_domain (type);
2073 *targets = mono_array_new (domain, mono_defaults.method_info_class, len);
2074 *methods = mono_array_new (domain, mono_defaults.method_info_class, len);
2075 iter = NULL;
2076 iter = NULL;
2077 while ((method = mono_class_get_methods (iclass, &iter))) {
2078 member = mono_method_get_object (domain, method, iclass);
2079 mono_array_setref (*methods, i, member);
2080 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2081 mono_array_setref (*targets, i, member);
2083 i ++;
2087 static void
2088 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2090 MonoClass *klass = mono_class_from_mono_type (type->type);
2092 if (klass->image->dynamic) {
2093 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2094 *packing = tb->packing_size;
2095 *size = tb->class_size;
2096 } else {
2097 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2101 static MonoReflectionType*
2102 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2104 MonoClass *class = mono_class_from_mono_type (type->type);
2106 MONO_ARCH_SAVE_REGS;
2108 // GetElementType should only return a type for:
2109 // Array Pointer PassedByRef
2110 if (type->type->byref)
2111 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2112 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2113 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2114 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2115 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2116 else
2117 return NULL;
2120 static MonoReflectionType*
2121 ves_icall_get_type_parent (MonoReflectionType *type)
2123 MonoClass *class = mono_class_from_mono_type (type->type);
2125 MONO_ARCH_SAVE_REGS;
2127 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2130 static MonoBoolean
2131 ves_icall_type_ispointer (MonoReflectionType *type)
2133 MONO_ARCH_SAVE_REGS;
2135 return type->type->type == MONO_TYPE_PTR;
2138 static MonoBoolean
2139 ves_icall_type_isprimitive (MonoReflectionType *type)
2141 MONO_ARCH_SAVE_REGS;
2143 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)));
2146 static MonoBoolean
2147 ves_icall_type_isbyref (MonoReflectionType *type)
2149 MONO_ARCH_SAVE_REGS;
2151 return type->type->byref;
2154 static MonoBoolean
2155 ves_icall_type_iscomobject (MonoReflectionType *type)
2157 MonoClass *klass = mono_class_from_mono_type (type->type);
2158 MONO_ARCH_SAVE_REGS;
2160 return (klass && klass->is_com_object);
2163 static MonoReflectionModule*
2164 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2166 MonoClass *class = mono_class_from_mono_type (type->type);
2168 MONO_ARCH_SAVE_REGS;
2170 return mono_module_get_object (mono_object_domain (type), class->image);
2173 static MonoReflectionAssembly*
2174 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2176 MonoDomain *domain = mono_domain_get ();
2177 MonoClass *class = mono_class_from_mono_type (type->type);
2179 MONO_ARCH_SAVE_REGS;
2181 return mono_assembly_get_object (domain, class->image->assembly);
2184 static MonoReflectionType*
2185 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2187 MonoDomain *domain = mono_domain_get ();
2188 MonoClass *class;
2190 MONO_ARCH_SAVE_REGS;
2192 if (type->type->byref)
2193 return NULL;
2194 if (type->type->type == MONO_TYPE_VAR)
2195 class = type->type->data.generic_param->owner->owner.klass;
2196 else if (type->type->type == MONO_TYPE_MVAR)
2197 class = type->type->data.generic_param->owner->owner.method->klass;
2198 else
2199 class = mono_class_from_mono_type (type->type)->nested_in;
2201 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2204 static MonoReflectionType*
2205 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2207 MonoDomain *domain = mono_domain_get ();
2208 MonoClass *class = mono_class_from_mono_type (type->type);
2210 MONO_ARCH_SAVE_REGS;
2212 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2213 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2214 else if (class->element_class)
2215 return mono_type_get_object (domain, &class->element_class->byval_arg);
2216 else
2217 return NULL;
2220 static MonoString*
2221 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2223 MonoDomain *domain = mono_domain_get ();
2224 MonoClass *class = mono_class_from_mono_type (type->type);
2226 MONO_ARCH_SAVE_REGS;
2228 if (type->type->byref) {
2229 char *n = g_strdup_printf ("%s&", class->name);
2230 MonoString *res = mono_string_new (domain, n);
2232 g_free (n);
2234 return res;
2235 } else {
2236 return mono_string_new (domain, class->name);
2240 static MonoString*
2241 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2243 MonoDomain *domain = mono_domain_get ();
2244 MonoClass *class = mono_class_from_mono_type (type->type);
2246 MONO_ARCH_SAVE_REGS;
2248 while (class->nested_in)
2249 class = class->nested_in;
2251 if (class->name_space [0] == '\0')
2252 return NULL;
2253 else
2254 return mono_string_new (domain, class->name_space);
2257 static gint32
2258 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2260 MonoClass *class = mono_class_from_mono_type (type->type);
2262 MONO_ARCH_SAVE_REGS;
2264 return class->rank;
2267 static MonoArray*
2268 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2270 MonoArray *res;
2271 MonoClass *klass, *pklass;
2272 int i;
2273 MONO_ARCH_SAVE_REGS;
2275 klass = mono_class_from_mono_type (type->type);
2277 if (klass->generic_container) {
2278 MonoGenericContainer *container = klass->generic_container;
2279 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, container->type_argc);
2280 for (i = 0; i < container->type_argc; ++i) {
2281 pklass = mono_class_from_generic_parameter (&container->type_params [i], klass->image, FALSE);
2282 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), &pklass->byval_arg));
2284 } else if (klass->generic_class) {
2285 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2286 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, inst->type_argc);
2287 for (i = 0; i < inst->type_argc; ++i)
2288 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), inst->type_argv [i]));
2289 } else {
2290 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, 0);
2292 return res;
2295 static gboolean
2296 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2298 MonoClass *klass;
2299 MONO_ARCH_SAVE_REGS;
2301 if (type->type->byref)
2302 return FALSE;
2304 klass = mono_class_from_mono_type (type->type);
2306 return klass->generic_container != NULL;
2309 static MonoReflectionType*
2310 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2312 MonoClass *klass;
2313 MONO_ARCH_SAVE_REGS;
2315 if (type->type->byref)
2316 return NULL;
2318 klass = mono_class_from_mono_type (type->type);
2319 if (klass->generic_container) {
2320 return type; /* check this one */
2322 if (klass->generic_class) {
2323 MonoClass *generic_class = klass->generic_class->container_class;
2325 if (generic_class->wastypebuilder && generic_class->reflection_info)
2326 return generic_class->reflection_info;
2327 else
2328 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2330 return NULL;
2333 static MonoReflectionType*
2334 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2336 MonoType *geninst, **types;
2337 int i, count;
2339 MONO_ARCH_SAVE_REGS;
2341 count = mono_array_length (type_array);
2342 types = g_new0 (MonoType *, count);
2344 for (i = 0; i < count; i++) {
2345 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2346 types [i] = t->type;
2349 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2350 g_free (types);
2351 if (!geninst)
2352 return NULL;
2354 return mono_type_get_object (mono_object_domain (type), geninst);
2357 static gboolean
2358 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2360 MonoClass *klass;
2361 MONO_ARCH_SAVE_REGS;
2363 if (type->type->byref)
2364 return FALSE;
2366 klass = mono_class_from_mono_type (type->type);
2367 return klass->generic_class != NULL;
2370 static gboolean
2371 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2373 MonoClass *klass;
2374 MONO_ARCH_SAVE_REGS;
2376 if (type->type->byref)
2377 return FALSE;
2379 klass = mono_class_from_mono_type (type->type);
2380 return klass->generic_class != NULL || klass->generic_container != NULL;
2383 static gint32
2384 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2386 MONO_ARCH_SAVE_REGS;
2388 if (is_generic_parameter (type->type))
2389 return type->type->data.generic_param->num;
2390 return -1;
2393 static GenericParameterAttributes
2394 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2396 MONO_ARCH_SAVE_REGS;
2397 g_assert (is_generic_parameter (type->type));
2398 return type->type->data.generic_param->flags;
2401 static MonoArray *
2402 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2404 MonoGenericParam *param;
2405 MonoDomain *domain;
2406 MonoClass **ptr;
2407 MonoArray *res;
2408 int i, count;
2410 MONO_ARCH_SAVE_REGS;
2412 domain = mono_object_domain (type);
2413 param = type->type->data.generic_param;
2414 for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
2417 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2418 for (i = 0; i < count; i++)
2419 mono_array_setref (res, i, mono_type_get_object (domain, &param->constraints [i]->byval_arg));
2422 return res;
2425 static MonoBoolean
2426 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2428 MONO_ARCH_SAVE_REGS;
2429 return is_generic_parameter (type->type);
2432 static MonoBoolean
2433 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2435 MONO_ARCH_SAVE_REGS;
2436 return is_generic_parameter (tb->type.type);
2439 static void
2440 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2441 MonoReflectionType *t)
2443 enumtype->type = t->type;
2446 static MonoReflectionType*
2447 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2449 MonoDynamicGenericClass *gclass;
2450 MonoReflectionType *parent = NULL, *res;
2451 MonoDomain *domain;
2452 MonoType *inflated;
2453 MonoClass *klass;
2456 MONO_ARCH_SAVE_REGS;
2458 g_assert (type->type.type->data.generic_class->is_dynamic);
2459 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2461 domain = mono_object_domain (type);
2462 klass = mono_class_from_mono_type (type->generic_type->type.type);
2464 if (!klass->generic_class && !klass->generic_container)
2465 return NULL;
2467 parent = type->generic_type->parent;
2469 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2470 return NULL;
2472 inflated = mono_class_inflate_generic_type (
2473 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2475 res = mono_type_get_object (domain, inflated);
2476 mono_metadata_free_type (inflated);
2477 return res;
2480 static MonoArray*
2481 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2483 static MonoClass *System_Reflection_MonoGenericClass;
2484 MonoGenericClass *gclass;
2485 MonoReflectionTypeBuilder *tb = NULL;
2486 MonoClass *klass = NULL;
2487 MonoDomain *domain;
2488 MonoArray *res;
2489 int icount, i;
2491 MONO_ARCH_SAVE_REGS;
2493 if (!System_Reflection_MonoGenericClass) {
2494 System_Reflection_MonoGenericClass = mono_class_from_name (
2495 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2496 g_assert (System_Reflection_MonoGenericClass);
2499 domain = mono_object_domain (type);
2501 gclass = type->type.type->data.generic_class;
2502 g_assert (gclass->is_dynamic);
2504 tb = type->generic_type;
2505 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2507 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2509 for (i = 0; i < icount; i++) {
2510 MonoReflectionType *iface;
2511 MonoType *it;
2513 if (tb) {
2514 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2515 it = iface->type;
2516 } else
2517 it = &klass->interfaces [i]->byval_arg;
2519 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2521 iface = mono_type_get_object (domain, it);
2522 mono_array_setref (res, i, iface);
2523 mono_metadata_free_type (it);
2526 return res;
2529 static MonoReflectionMethod*
2530 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2531 MonoReflectionMethod* generic)
2533 MonoGenericClass *gclass;
2534 MonoDynamicGenericClass *dgclass;
2535 MonoDomain *domain;
2536 int i;
2538 MONO_ARCH_SAVE_REGS;
2540 gclass = type->type.type->data.generic_class;
2541 g_assert (gclass->is_dynamic);
2543 dgclass = (MonoDynamicGenericClass *) gclass;
2545 domain = mono_object_domain (type);
2547 for (i = 0; i < dgclass->count_methods; i++)
2548 if (generic->method->token == dgclass->methods [i]->token)
2549 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2551 return NULL;
2554 static MonoReflectionMethod*
2555 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2556 MonoReflectionMethod* generic)
2558 MonoGenericClass *gclass;
2559 MonoDynamicGenericClass *dgclass;
2560 MonoDomain *domain;
2561 int i;
2563 MONO_ARCH_SAVE_REGS;
2565 gclass = type->type.type->data.generic_class;
2566 g_assert (gclass->is_dynamic);
2568 dgclass = (MonoDynamicGenericClass *) gclass;
2570 domain = mono_object_domain (type);
2572 for (i = 0; i < dgclass->count_ctors; i++)
2573 if (generic->method->token == dgclass->ctors [i]->token)
2574 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2576 return NULL;
2580 static MonoReflectionField*
2581 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2582 MonoString* generic_name)
2584 MonoGenericClass *gclass;
2585 MonoDynamicGenericClass *dgclass;
2586 MonoDomain *domain;
2587 MonoClass *refclass;
2588 char *utf8_name = mono_string_to_utf8 (generic_name);
2589 int i;
2591 MONO_ARCH_SAVE_REGS;
2593 gclass = type->type.type->data.generic_class;
2594 g_assert (gclass->is_dynamic);
2596 dgclass = (MonoDynamicGenericClass *) gclass;
2598 refclass = mono_class_from_mono_type (type->type.type);
2600 domain = mono_object_domain (type);
2602 for (i = 0; i < dgclass->count_fields; i++)
2603 if (strcmp (utf8_name, mono_field_get_name (&dgclass->fields [i])) == 0) {
2604 g_free (utf8_name);
2605 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2608 g_free (utf8_name);
2610 return NULL;
2614 static MonoReflectionMethod*
2615 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2616 MonoReflectionMethod* generic)
2618 MonoDomain *domain;
2619 MonoClass *klass;
2620 MonoMethod *method;
2621 gpointer iter;
2623 MONO_ARCH_SAVE_REGS;
2625 domain = ((MonoObject *)type)->vtable->domain;
2627 klass = mono_class_from_mono_type (type->type);
2629 iter = NULL;
2630 while ((method = mono_class_get_methods (klass, &iter))) {
2631 if (method->token == generic->method->token)
2632 return mono_method_get_object (domain, method, klass);
2635 return NULL;
2638 static MonoArray*
2639 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2640 MonoReflectionType *reflected_type)
2642 MonoGenericClass *gclass;
2643 MonoDynamicGenericClass *dgclass;
2644 MonoDomain *domain;
2645 MonoClass *refclass;
2646 MonoArray *res;
2647 int i;
2649 MONO_ARCH_SAVE_REGS;
2651 gclass = type->type.type->data.generic_class;
2652 g_assert (gclass->is_dynamic);
2653 dgclass = (MonoDynamicGenericClass *) gclass;
2655 refclass = mono_class_from_mono_type (reflected_type->type);
2657 domain = mono_object_domain (type);
2658 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2660 for (i = 0; i < dgclass->count_methods; i++)
2661 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2663 return res;
2666 static MonoArray*
2667 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2668 MonoReflectionType *reflected_type)
2670 static MonoClass *System_Reflection_ConstructorInfo;
2671 MonoGenericClass *gclass;
2672 MonoDynamicGenericClass *dgclass;
2673 MonoDomain *domain;
2674 MonoClass *refclass;
2675 MonoArray *res;
2676 int i;
2678 MONO_ARCH_SAVE_REGS;
2680 if (!System_Reflection_ConstructorInfo)
2681 System_Reflection_ConstructorInfo = mono_class_from_name (
2682 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2684 gclass = type->type.type->data.generic_class;
2685 g_assert (gclass->is_dynamic);
2686 dgclass = (MonoDynamicGenericClass *) gclass;
2688 refclass = mono_class_from_mono_type (reflected_type->type);
2690 domain = mono_object_domain (type);
2691 res = mono_array_new (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2693 for (i = 0; i < dgclass->count_ctors; i++)
2694 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2696 return res;
2699 static MonoArray*
2700 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2701 MonoReflectionType *reflected_type)
2703 MonoGenericClass *gclass;
2704 MonoDynamicGenericClass *dgclass;
2705 MonoDomain *domain;
2706 MonoClass *refclass;
2707 MonoArray *res;
2708 int i;
2710 MONO_ARCH_SAVE_REGS;
2712 gclass = type->type.type->data.generic_class;
2713 g_assert (gclass->is_dynamic);
2714 dgclass = (MonoDynamicGenericClass *) gclass;
2716 refclass = mono_class_from_mono_type (reflected_type->type);
2718 domain = mono_object_domain (type);
2719 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2721 for (i = 0; i < dgclass->count_fields; i++)
2722 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2724 return res;
2727 static MonoArray*
2728 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2729 MonoReflectionType *reflected_type)
2731 static MonoClass *System_Reflection_PropertyInfo;
2732 MonoGenericClass *gclass;
2733 MonoDynamicGenericClass *dgclass;
2734 MonoDomain *domain;
2735 MonoClass *refclass;
2736 MonoArray *res;
2737 int i;
2739 MONO_ARCH_SAVE_REGS;
2741 if (!System_Reflection_PropertyInfo)
2742 System_Reflection_PropertyInfo = mono_class_from_name (
2743 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2745 gclass = type->type.type->data.generic_class;
2746 g_assert (gclass->is_dynamic);
2747 dgclass = (MonoDynamicGenericClass *) gclass;
2749 refclass = mono_class_from_mono_type (reflected_type->type);
2751 domain = mono_object_domain (type);
2752 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2754 for (i = 0; i < dgclass->count_properties; i++)
2755 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2757 return res;
2760 static MonoArray*
2761 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2762 MonoReflectionType *reflected_type)
2764 static MonoClass *System_Reflection_EventInfo;
2765 MonoGenericClass *gclass;
2766 MonoDynamicGenericClass *dgclass;
2767 MonoDomain *domain;
2768 MonoClass *refclass;
2769 MonoArray *res;
2770 int i;
2772 MONO_ARCH_SAVE_REGS;
2774 if (!System_Reflection_EventInfo)
2775 System_Reflection_EventInfo = mono_class_from_name (
2776 mono_defaults.corlib, "System.Reflection", "EventInfo");
2778 gclass = type->type.type->data.generic_class;
2779 g_assert (gclass->is_dynamic);
2780 dgclass = (MonoDynamicGenericClass *) gclass;
2782 refclass = mono_class_from_mono_type (reflected_type->type);
2784 domain = mono_object_domain (type);
2785 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2787 for (i = 0; i < dgclass->count_events; i++)
2788 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2790 return res;
2793 static MonoReflectionType*
2794 ves_icall_MonoGenericClass_InflateType (MonoReflectionGenericClass *type,
2795 MonoReflectionType *target)
2797 MonoType *res_type;
2798 MonoClass *gklass;
2799 MonoReflectionType *res;
2801 MONO_ARCH_SAVE_REGS;
2803 gklass = mono_class_from_mono_type (type->type.type);
2804 res_type = mono_class_inflate_generic_type (target->type, mono_class_get_context (gklass));
2805 res = mono_type_get_object (mono_object_domain (type), res_type);
2806 mono_metadata_free_type (res_type);
2807 return res;
2810 static MonoReflectionMethod *
2811 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2813 MonoMethod *method;
2814 MonoClass *klass;
2816 MONO_ARCH_SAVE_REGS;
2818 if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2819 return NULL;
2821 method = type->type->data.generic_param->owner->owner.method;
2822 g_assert (method);
2823 klass = mono_class_from_mono_type (type->type);
2824 return mono_method_get_object (mono_object_domain (type), method, klass);
2827 static MonoReflectionDllImportAttribute*
2828 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2830 static MonoClass *DllImportAttributeClass = NULL;
2831 MonoDomain *domain = mono_domain_get ();
2832 MonoReflectionDllImportAttribute *attr;
2833 MonoImage *image = method->klass->image;
2834 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2835 MonoTableInfo *tables = image->tables;
2836 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2837 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2838 guint32 im_cols [MONO_IMPLMAP_SIZE];
2839 guint32 scope_token;
2840 const char *import = NULL;
2841 const char *scope = NULL;
2842 guint32 flags;
2844 if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2845 return NULL;
2847 if (!DllImportAttributeClass) {
2848 DllImportAttributeClass =
2849 mono_class_from_name (mono_defaults.corlib,
2850 "System.Runtime.InteropServices", "DllImportAttribute");
2851 g_assert (DllImportAttributeClass);
2854 if (method->klass->image->dynamic) {
2855 MonoReflectionMethodAux *method_aux =
2856 g_hash_table_lookup (
2857 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2858 if (method_aux) {
2859 import = method_aux->dllentry;
2860 scope = method_aux->dll;
2863 else {
2864 if (piinfo->implmap_idx) {
2865 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2867 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2868 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2869 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2870 scope = mono_metadata_string_heap (image, scope_token);
2873 flags = piinfo->piflags;
2875 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2877 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2878 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2879 attr->call_conv = (flags & 0x700) >> 8;
2880 attr->charset = ((flags & 0x6) >> 1) + 1;
2881 if (attr->charset == 1)
2882 attr->charset = 2;
2883 attr->exact_spelling = (flags & 0x1) != 0;
2884 attr->set_last_error = (flags & 0x40) != 0;
2885 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2886 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2887 attr->preserve_sig = FALSE;
2889 return attr;
2892 static MonoReflectionMethod *
2893 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2895 MonoMethodInflated *imethod;
2896 MonoMethod *result;
2898 MONO_ARCH_SAVE_REGS;
2900 if (method->method->is_generic)
2901 return method;
2903 if (!method->method->is_inflated)
2904 return NULL;
2906 imethod = (MonoMethodInflated *) method->method;
2908 result = imethod->declaring;
2909 /* Not a generic method. */
2910 if (!result->is_generic)
2911 return NULL;
2913 if (method->method->klass->image->dynamic) {
2914 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2915 MonoReflectionMethod *res;
2918 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2919 * the dynamic case as well ?
2921 mono_loader_lock ();
2922 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2923 mono_loader_unlock ();
2925 if (res)
2926 return res;
2929 if (imethod->context.class_inst) {
2930 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2931 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2934 return mono_method_get_object (mono_object_domain (method), result, NULL);
2937 static gboolean
2938 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2940 MONO_ARCH_SAVE_REGS;
2942 return mono_method_signature (method->method)->generic_param_count != 0;
2945 static gboolean
2946 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2948 MONO_ARCH_SAVE_REGS;
2950 return method->method->is_generic;
2953 static MonoArray*
2954 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2956 MonoArray *res;
2957 MonoDomain *domain;
2958 int count, i;
2959 MONO_ARCH_SAVE_REGS;
2961 domain = mono_object_domain (method);
2963 if (method->method->is_inflated) {
2964 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2966 if (inst) {
2967 count = inst->type_argc;
2968 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2970 for (i = 0; i < count; i++)
2971 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2973 return res;
2977 count = mono_method_signature (method->method)->generic_param_count;
2978 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2980 for (i = 0; i < count; i++) {
2981 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2982 MonoGenericParam *param = &container->type_params [i];
2983 MonoClass *pklass = mono_class_from_generic_parameter (
2984 param, method->method->klass->image, TRUE);
2985 mono_array_setref (res, i,
2986 mono_type_get_object (domain, &pklass->byval_arg));
2989 return res;
2992 static void
2993 ensure_reflection_security (void)
2995 MonoMethod *m = mono_method_get_last_managed ();
2997 while (m) {
2999 g_print ("method %s.%s.%s in image %s\n",
3000 m->klass->name_space, m->klass->name, m->name, m->klass->image->name);
3003 /* We stop at the first method which is not in
3004 System.Reflection or which is not in a platform
3005 image. */
3006 if (strcmp (m->klass->name_space, "System.Reflection") != 0 ||
3007 !mono_security_core_clr_is_platform_image (m->klass->image)) {
3008 /* If the method is transparent we throw an exception. */
3009 if (mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_TRANSPARENT ) {
3010 MonoException *ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", "Reflection called from transparent code");
3012 mono_raise_exception (ex);
3014 return;
3017 mono_stack_walk_no_il (get_caller, &m);
3021 static gboolean
3022 can_call_generic_shared_method_for_class (MonoDomain *domain, MonoMethod *method, MonoClass *class)
3024 MonoClass *method_class;
3026 if (!mono_method_is_generic_sharable_impl (method, FALSE))
3027 return FALSE;
3029 method = mono_method_get_declaring_generic_method (method);
3030 method_class = method->klass;
3031 g_assert (!method_class->generic_class);
3033 if (!mono_domain_lookup_shared_generic (domain, method))
3034 return FALSE;
3036 while (class) {
3037 if (class->generic_class)
3038 class = class->generic_class->container_class;
3039 if (method_class == class)
3040 return TRUE;
3041 class = class->parent;
3044 return FALSE;
3047 static MonoObject *
3048 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
3051 * Invoke from reflection is supposed to always be a virtual call (the API
3052 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3053 * greater flexibility.
3055 MonoMethod *m = method->method;
3056 int pcount;
3057 void *obj = this;
3059 MONO_ARCH_SAVE_REGS;
3061 *exc = NULL;
3063 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR &&
3064 mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL)
3065 ensure_reflection_security ();
3067 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3068 if (this) {
3069 if (!mono_object_isinst (this, m->klass) &&
3070 !can_call_generic_shared_method_for_class (this->vtable->domain, m, this->vtable->klass)) {
3071 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type.");
3072 return NULL;
3074 m = mono_object_get_virtual_method (this, m);
3075 /* must pass the pointer to the value for valuetype methods */
3076 if (m->klass->valuetype)
3077 obj = mono_object_unbox (this);
3078 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3079 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target.");
3080 return NULL;
3084 pcount = params? mono_array_length (params): 0;
3085 if (pcount != mono_method_signature (m)->param_count) {
3086 *exc = mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException");
3087 return NULL;
3090 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
3091 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class.");
3092 return NULL;
3095 if (m->klass->image->assembly->ref_only) {
3096 *exc = mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api.");
3097 return NULL;
3100 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3101 int i;
3102 mono_array_size_t *lengths;
3103 mono_array_size_t *lower_bounds;
3104 pcount = mono_array_length (params);
3105 lengths = alloca (sizeof (mono_array_size_t) * pcount);
3106 for (i = 0; i < pcount; ++i)
3107 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3109 if (m->klass->rank == pcount) {
3110 /* Only lengths provided. */
3111 lower_bounds = NULL;
3112 } else {
3113 g_assert (pcount == (m->klass->rank * 2));
3114 /* lower bounds are first. */
3115 lower_bounds = lengths;
3116 lengths += m->klass->rank;
3119 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
3121 return mono_runtime_invoke_array (m, obj, params, NULL);
3124 static MonoObject *
3125 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
3127 MonoDomain *domain = mono_object_domain (method);
3128 MonoMethod *m = method->method;
3129 MonoMethodSignature *sig = mono_method_signature (m);
3130 MonoArray *out_args;
3131 MonoObject *result;
3132 int i, j, outarg_count = 0;
3134 MONO_ARCH_SAVE_REGS;
3136 if (m->klass == mono_defaults.object_class) {
3138 if (!strcmp (m->name, "FieldGetter")) {
3139 MonoClass *k = this->vtable->klass;
3140 MonoString *name;
3141 char *str;
3143 /* If this is a proxy, then it must be a CBO */
3144 if (k == mono_defaults.transparent_proxy_class) {
3145 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3146 this = tp->rp->unwrapped_server;
3147 g_assert (this);
3148 k = this->vtable->klass;
3151 name = mono_array_get (params, MonoString *, 1);
3152 str = mono_string_to_utf8 (name);
3154 do {
3155 MonoClassField* field = mono_class_get_field_from_name (k, str);
3156 if (field) {
3157 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3158 if (field_klass->valuetype)
3159 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
3160 else
3161 result = *((gpointer *)((char *)this + field->offset));
3163 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3164 *outArgs = out_args;
3165 mono_array_setref (out_args, 0, result);
3166 g_free (str);
3167 return NULL;
3169 k = k->parent;
3170 } while (k);
3172 g_free (str);
3173 g_assert_not_reached ();
3175 } else if (!strcmp (m->name, "FieldSetter")) {
3176 MonoClass *k = this->vtable->klass;
3177 MonoString *name;
3178 guint32 size;
3179 gint32 align;
3180 char *str;
3182 /* If this is a proxy, then it must be a CBO */
3183 if (k == mono_defaults.transparent_proxy_class) {
3184 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3185 this = tp->rp->unwrapped_server;
3186 g_assert (this);
3187 k = this->vtable->klass;
3190 name = mono_array_get (params, MonoString *, 1);
3191 str = mono_string_to_utf8 (name);
3193 do {
3194 MonoClassField* field = mono_class_get_field_from_name (k, str);
3195 if (field) {
3196 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3197 MonoObject *val = mono_array_get (params, gpointer, 2);
3199 if (field_klass->valuetype) {
3200 size = mono_type_size (field->type, &align);
3201 #ifdef HAVE_SGEN_GC
3202 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3203 #endif
3204 memcpy ((char *)this + field->offset,
3205 ((char *)val) + sizeof (MonoObject), size);
3206 } else {
3207 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
3210 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3211 *outArgs = out_args;
3213 g_free (str);
3214 return NULL;
3217 k = k->parent;
3218 } while (k);
3220 g_free (str);
3221 g_assert_not_reached ();
3226 for (i = 0; i < mono_array_length (params); i++) {
3227 if (sig->params [i]->byref)
3228 outarg_count++;
3231 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3233 /* handle constructors only for objects already allocated */
3234 if (!strcmp (method->method->name, ".ctor"))
3235 g_assert (this);
3237 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3238 g_assert (!method->method->klass->valuetype);
3239 result = mono_runtime_invoke_array (method->method, this, params, NULL);
3241 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3242 if (sig->params [i]->byref) {
3243 gpointer arg;
3244 arg = mono_array_get (params, gpointer, i);
3245 mono_array_setref (out_args, j, arg);
3246 j++;
3250 *outArgs = out_args;
3252 return result;
3255 static guint64
3256 read_enum_value (char *mem, int type)
3258 switch (type) {
3259 case MONO_TYPE_U1:
3260 return *(guint8*)mem;
3261 case MONO_TYPE_I1:
3262 return *(gint8*)mem;
3263 case MONO_TYPE_U2:
3264 return *(guint16*)mem;
3265 case MONO_TYPE_I2:
3266 return *(gint16*)mem;
3267 case MONO_TYPE_U4:
3268 return *(guint32*)mem;
3269 case MONO_TYPE_I4:
3270 return *(gint32*)mem;
3271 case MONO_TYPE_U8:
3272 return *(guint64*)mem;
3273 case MONO_TYPE_I8:
3274 return *(gint64*)mem;
3275 default:
3276 g_assert_not_reached ();
3278 return 0;
3281 static void
3282 write_enum_value (char *mem, int type, guint64 value)
3284 switch (type) {
3285 case MONO_TYPE_U1:
3286 case MONO_TYPE_I1: {
3287 guint8 *p = (guint8*)mem;
3288 *p = value;
3289 break;
3291 case MONO_TYPE_U2:
3292 case MONO_TYPE_I2: {
3293 guint16 *p = (void*)mem;
3294 *p = value;
3295 break;
3297 case MONO_TYPE_U4:
3298 case MONO_TYPE_I4: {
3299 guint32 *p = (void*)mem;
3300 *p = value;
3301 break;
3303 case MONO_TYPE_U8:
3304 case MONO_TYPE_I8: {
3305 guint64 *p = (void*)mem;
3306 *p = value;
3307 break;
3309 default:
3310 g_assert_not_reached ();
3312 return;
3315 static MonoObject *
3316 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3318 MonoDomain *domain;
3319 MonoClass *enumc, *objc;
3320 MonoObject *res;
3321 guint64 val;
3323 MONO_ARCH_SAVE_REGS;
3325 MONO_CHECK_ARG_NULL (enumType);
3326 MONO_CHECK_ARG_NULL (value);
3328 domain = mono_object_domain (enumType);
3329 enumc = mono_class_from_mono_type (enumType->type);
3330 objc = value->vtable->klass;
3332 if (!enumc->enumtype)
3333 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3334 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3335 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."));
3337 res = mono_object_new (domain, enumc);
3338 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3339 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3341 return res;
3344 static MonoObject *
3345 ves_icall_System_Enum_get_value (MonoObject *this)
3347 MonoObject *res;
3348 MonoClass *enumc;
3349 gpointer dst;
3350 gpointer src;
3351 int size;
3353 MONO_ARCH_SAVE_REGS;
3355 if (!this)
3356 return NULL;
3358 g_assert (this->vtable->klass->enumtype);
3360 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3361 res = mono_object_new (mono_object_domain (this), enumc);
3362 dst = (char *)res + sizeof (MonoObject);
3363 src = (char *)this + sizeof (MonoObject);
3364 size = mono_class_value_size (enumc, NULL);
3366 memcpy (dst, src, size);
3368 return res;
3371 static MonoReflectionType *
3372 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3374 MONO_ARCH_SAVE_REGS;
3376 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3379 static int
3380 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3382 gpointer data = (char *)this + sizeof (MonoObject);
3383 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3384 g_assert (basetype);
3386 switch (basetype->type) {
3387 case MONO_TYPE_I1:
3388 return *((gint8*)data);
3389 case MONO_TYPE_U1:
3390 return *((guint8*)data);
3391 case MONO_TYPE_CHAR:
3392 case MONO_TYPE_U2:
3393 return *((guint16*)data);
3395 case MONO_TYPE_I2:
3396 return *((gint16*)data);
3397 case MONO_TYPE_U4:
3398 return *((guint32*)data);
3399 case MONO_TYPE_I4:
3400 return *((gint32*)data);
3401 case MONO_TYPE_U8:
3402 case MONO_TYPE_I8: {
3403 gint64 value = *((gint64*)data);
3404 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3406 default:
3407 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3409 return 0;
3412 static void
3413 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3415 MonoDomain *domain = mono_object_domain (type);
3416 MonoClass *enumc = mono_class_from_mono_type (type->type);
3417 guint j = 0, nvalues, crow;
3418 gpointer iter;
3419 MonoClassField *field;
3421 MONO_ARCH_SAVE_REGS;
3423 info->utype = mono_type_get_object (domain, mono_class_enum_basetype (enumc));
3424 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3425 info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3426 info->values = mono_array_new (domain, enumc, nvalues);
3428 crow = -1;
3429 iter = NULL;
3430 while ((field = mono_class_get_fields (enumc, &iter))) {
3431 const char *p;
3432 int len;
3433 MonoTypeEnum def_type;
3435 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3436 continue;
3437 if (mono_field_is_deleted (field))
3438 continue;
3439 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3441 p = mono_class_get_field_default_value (field, &def_type);
3442 len = mono_metadata_decode_blob_size (p, &p);
3443 switch (mono_class_enum_basetype (enumc)->type) {
3444 case MONO_TYPE_U1:
3445 case MONO_TYPE_I1:
3446 mono_array_set (info->values, gchar, j, *p);
3447 break;
3448 case MONO_TYPE_CHAR:
3449 case MONO_TYPE_U2:
3450 case MONO_TYPE_I2:
3451 mono_array_set (info->values, gint16, j, read16 (p));
3452 break;
3453 case MONO_TYPE_U4:
3454 case MONO_TYPE_I4:
3455 mono_array_set (info->values, gint32, j, read32 (p));
3456 break;
3457 case MONO_TYPE_U8:
3458 case MONO_TYPE_I8:
3459 mono_array_set (info->values, gint64, j, read64 (p));
3460 break;
3461 default:
3462 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3464 ++j;
3468 enum {
3469 BFLAGS_IgnoreCase = 1,
3470 BFLAGS_DeclaredOnly = 2,
3471 BFLAGS_Instance = 4,
3472 BFLAGS_Static = 8,
3473 BFLAGS_Public = 0x10,
3474 BFLAGS_NonPublic = 0x20,
3475 BFLAGS_FlattenHierarchy = 0x40,
3476 BFLAGS_InvokeMethod = 0x100,
3477 BFLAGS_CreateInstance = 0x200,
3478 BFLAGS_GetField = 0x400,
3479 BFLAGS_SetField = 0x800,
3480 BFLAGS_GetProperty = 0x1000,
3481 BFLAGS_SetProperty = 0x2000,
3482 BFLAGS_ExactBinding = 0x10000,
3483 BFLAGS_SuppressChangeType = 0x20000,
3484 BFLAGS_OptionalParamBinding = 0x40000
3487 static MonoReflectionField *
3488 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3490 MonoDomain *domain;
3491 MonoClass *startklass, *klass;
3492 int match;
3493 MonoClassField *field;
3494 gpointer iter;
3495 char *utf8_name;
3496 int (*compare_func) (const char *s1, const char *s2) = NULL;
3497 domain = ((MonoObject *)type)->vtable->domain;
3498 klass = startklass = mono_class_from_mono_type (type->type);
3500 MONO_ARCH_SAVE_REGS;
3502 if (!name)
3503 mono_raise_exception (mono_get_exception_argument_null ("name"));
3504 if (type->type->byref)
3505 return NULL;
3507 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3509 handle_parent:
3510 if (klass->exception_type != MONO_EXCEPTION_NONE)
3511 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3513 iter = NULL;
3514 while ((field = mono_class_get_fields (klass, &iter))) {
3515 match = 0;
3517 if (field->type == NULL)
3518 continue;
3519 if (mono_field_is_deleted (field))
3520 continue;
3521 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3522 if (bflags & BFLAGS_Public)
3523 match++;
3524 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3525 if (bflags & BFLAGS_NonPublic) {
3526 match++;
3529 if (!match)
3530 continue;
3531 match = 0;
3532 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3533 if (bflags & BFLAGS_Static)
3534 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3535 match++;
3536 } else {
3537 if (bflags & BFLAGS_Instance)
3538 match++;
3541 if (!match)
3542 continue;
3544 utf8_name = mono_string_to_utf8 (name);
3546 if (compare_func (mono_field_get_name (field), utf8_name)) {
3547 g_free (utf8_name);
3548 continue;
3550 g_free (utf8_name);
3552 return mono_field_get_object (domain, klass, field);
3554 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3555 goto handle_parent;
3557 return NULL;
3560 static MonoArray*
3561 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3563 MonoDomain *domain;
3564 MonoClass *startklass, *klass, *refklass;
3565 MonoArray *res;
3566 MonoObject *member;
3567 int i, len, match;
3568 gpointer iter;
3569 MonoClassField *field;
3571 MONO_ARCH_SAVE_REGS;
3573 domain = ((MonoObject *)type)->vtable->domain;
3574 if (type->type->byref)
3575 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3576 klass = startklass = mono_class_from_mono_type (type->type);
3577 refklass = mono_class_from_mono_type (reftype->type);
3579 i = 0;
3580 len = 2;
3581 res = mono_array_new (domain, mono_defaults.field_info_class, len);
3582 handle_parent:
3583 if (klass->exception_type != MONO_EXCEPTION_NONE)
3584 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3586 iter = NULL;
3587 while ((field = mono_class_get_fields (klass, &iter))) {
3588 match = 0;
3589 if (mono_field_is_deleted (field))
3590 continue;
3591 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3592 if (bflags & BFLAGS_Public)
3593 match++;
3594 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3595 if (bflags & BFLAGS_NonPublic) {
3596 match++;
3599 if (!match)
3600 continue;
3601 match = 0;
3602 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3603 if (bflags & BFLAGS_Static)
3604 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3605 match++;
3606 } else {
3607 if (bflags & BFLAGS_Instance)
3608 match++;
3611 if (!match)
3612 continue;
3613 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3614 if (i >= len) {
3615 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, len * 2);
3616 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3617 len *= 2;
3618 res = new_res;
3620 mono_array_setref (res, i, member);
3621 ++i;
3623 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3624 goto handle_parent;
3625 if (i != len) {
3626 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, i);
3627 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3628 res = new_res;
3630 * Better solution for the new GC.
3631 * res->max_length = i;
3634 return res;
3637 static gboolean
3638 method_nonpublic (MonoMethod* method, gboolean start_klass)
3640 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3641 case METHOD_ATTRIBUTE_ASSEM:
3642 return (start_klass || mono_defaults.generic_ilist_class);
3643 case METHOD_ATTRIBUTE_PRIVATE:
3644 return start_klass;
3645 case METHOD_ATTRIBUTE_PUBLIC:
3646 return FALSE;
3647 default:
3648 return TRUE;
3652 static MonoArray*
3653 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3655 static MonoClass *MethodInfo_array;
3656 MonoDomain *domain;
3657 MonoClass *startklass, *klass, *refklass;
3658 MonoArray *res;
3659 MonoMethod *method;
3660 gpointer iter;
3661 MonoObject *member;
3662 int i, len, match, nslots;
3663 guint32 method_slots_default [8];
3664 guint32 *method_slots;
3665 gchar *mname = NULL;
3666 int (*compare_func) (const char *s1, const char *s2) = NULL;
3667 MonoVTable *array_vtable;
3669 MONO_ARCH_SAVE_REGS;
3671 if (!MethodInfo_array) {
3672 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3673 mono_memory_barrier ();
3674 MethodInfo_array = klass;
3677 domain = ((MonoObject *)type)->vtable->domain;
3678 array_vtable = mono_class_vtable (domain, MethodInfo_array);
3679 if (type->type->byref)
3680 return mono_array_new_specific (array_vtable, 0);
3681 klass = startklass = mono_class_from_mono_type (type->type);
3682 refklass = mono_class_from_mono_type (reftype->type);
3683 len = 0;
3684 if (name != NULL) {
3685 mname = mono_string_to_utf8 (name);
3686 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3689 /* An optimization for calls made from Delegate:CreateDelegate () */
3690 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3691 method = mono_get_delegate_invoke (klass);
3693 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3695 res = mono_array_new_specific (array_vtable, 1);
3696 mono_array_setref (res, 0, member);
3697 return res;
3700 mono_class_setup_vtable (klass);
3702 if (is_generic_parameter (type->type))
3703 nslots = klass->parent->vtable_size;
3704 else
3705 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3706 if (nslots >= sizeof (method_slots_default) * 8) {
3707 method_slots = g_new0 (guint32, nslots / 32 + 1);
3708 } else {
3709 method_slots = method_slots_default;
3710 memset (method_slots, 0, sizeof (method_slots_default));
3712 i = 0;
3713 len = 1;
3714 res = mono_array_new_specific (array_vtable, len);
3715 handle_parent:
3716 mono_class_setup_vtable (klass);
3717 if (klass->exception_type != MONO_EXCEPTION_NONE)
3718 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3720 iter = NULL;
3721 while ((method = mono_class_get_methods (klass, &iter))) {
3722 match = 0;
3723 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3724 continue;
3725 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3726 if (bflags & BFLAGS_Public)
3727 match++;
3728 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3729 match++;
3731 if (!match)
3732 continue;
3733 match = 0;
3734 if (method->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;
3746 if (name != NULL) {
3747 if (compare_func (mname, method->name))
3748 continue;
3751 match = 0;
3752 if (method->slot != -1) {
3753 g_assert (method->slot < nslots);
3754 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3755 continue;
3756 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3759 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3761 if (i >= len) {
3762 MonoArray *new_res = mono_array_new_specific (array_vtable, len * 2);
3763 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3764 len *= 2;
3765 res = new_res;
3767 mono_array_setref (res, i, member);
3768 ++i;
3770 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3771 goto handle_parent;
3773 g_free (mname);
3774 if (method_slots != method_slots_default)
3775 g_free (method_slots);
3776 if (i != len) {
3777 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, i);
3778 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3779 res = new_res;
3781 * Better solution for the new GC.
3782 * res->max_length = i;
3785 return res;
3788 static MonoArray*
3789 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3791 MonoDomain *domain;
3792 static MonoClass *System_Reflection_ConstructorInfo;
3793 MonoClass *startklass, *klass, *refklass;
3794 MonoArray *res;
3795 MonoMethod *method;
3796 MonoObject *member;
3797 int i, len, match;
3798 gpointer iter = NULL;
3800 MONO_ARCH_SAVE_REGS;
3802 domain = ((MonoObject *)type)->vtable->domain;
3803 if (type->type->byref)
3804 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3805 klass = startklass = mono_class_from_mono_type (type->type);
3806 refklass = mono_class_from_mono_type (reftype->type);
3808 if (klass->exception_type != MONO_EXCEPTION_NONE)
3809 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3811 if (!System_Reflection_ConstructorInfo)
3812 System_Reflection_ConstructorInfo = mono_class_from_name (
3813 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3815 i = 0;
3816 len = 2;
3817 res = mono_array_new (domain, System_Reflection_ConstructorInfo, len);
3818 iter = NULL;
3819 while ((method = mono_class_get_methods (klass, &iter))) {
3820 match = 0;
3821 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3822 continue;
3823 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3824 if (bflags & BFLAGS_Public)
3825 match++;
3826 } else {
3827 if (bflags & BFLAGS_NonPublic)
3828 match++;
3830 if (!match)
3831 continue;
3832 match = 0;
3833 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3834 if (bflags & BFLAGS_Static)
3835 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3836 match++;
3837 } else {
3838 if (bflags & BFLAGS_Instance)
3839 match++;
3842 if (!match)
3843 continue;
3844 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3846 if (i >= len) {
3847 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, len * 2);
3848 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3849 len *= 2;
3850 res = new_res;
3852 mono_array_setref (res, i, member);
3853 ++i;
3855 if (i != len) {
3856 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, i);
3857 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3858 res = new_res;
3860 * Better solution for the new GC.
3861 * res->max_length = i;
3864 return res;
3867 static guint
3868 property_hash (gconstpointer data)
3870 MonoProperty *prop = (MonoProperty*)data;
3872 return g_str_hash (prop->name);
3875 static gboolean
3876 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3878 // Properties are hide-by-name-and-signature
3879 if (!g_str_equal (prop1->name, prop2->name))
3880 return FALSE;
3882 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3883 return FALSE;
3884 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3885 return FALSE;
3886 return TRUE;
3889 static gboolean
3890 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3892 if (!accessor)
3893 return FALSE;
3895 return method_nonpublic (accessor, start_klass);
3898 static MonoArray*
3899 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3901 MonoDomain *domain;
3902 static MonoClass *System_Reflection_PropertyInfo;
3903 MonoClass *startklass, *klass;
3904 MonoArray *res;
3905 MonoMethod *method;
3906 MonoProperty *prop;
3907 int i, match;
3908 int len = 0;
3909 guint32 flags;
3910 gchar *propname = NULL;
3911 int (*compare_func) (const char *s1, const char *s2) = NULL;
3912 gpointer iter;
3913 GHashTable *properties;
3915 MONO_ARCH_SAVE_REGS;
3917 if (!System_Reflection_PropertyInfo)
3918 System_Reflection_PropertyInfo = mono_class_from_name (
3919 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3921 domain = ((MonoObject *)type)->vtable->domain;
3922 if (type->type->byref)
3923 return mono_array_new (domain, System_Reflection_PropertyInfo, 0);
3924 klass = startklass = mono_class_from_mono_type (type->type);
3925 if (name != NULL) {
3926 propname = mono_string_to_utf8 (name);
3927 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3930 mono_class_setup_vtable (klass);
3932 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3933 i = 0;
3934 len = 2;
3935 res = mono_array_new (domain, System_Reflection_PropertyInfo, len);
3936 handle_parent:
3937 mono_class_setup_vtable (klass);
3938 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3939 g_hash_table_destroy (properties);
3940 if (name != NULL)
3941 g_free (propname);
3942 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3945 iter = NULL;
3946 while ((prop = mono_class_get_properties (klass, &iter))) {
3947 match = 0;
3948 method = prop->get;
3949 if (!method)
3950 method = prop->set;
3951 if (method)
3952 flags = method->flags;
3953 else
3954 flags = 0;
3955 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3956 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3957 if (bflags & BFLAGS_Public)
3958 match++;
3959 } else if (bflags & BFLAGS_NonPublic) {
3960 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3961 property_accessor_nonpublic(prop->set, startklass == klass)) {
3962 match++;
3965 if (!match)
3966 continue;
3967 match = 0;
3968 if (flags & METHOD_ATTRIBUTE_STATIC) {
3969 if (bflags & BFLAGS_Static)
3970 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3971 match++;
3972 } else {
3973 if (bflags & BFLAGS_Instance)
3974 match++;
3977 if (!match)
3978 continue;
3979 match = 0;
3981 if (name != NULL) {
3982 if (compare_func (propname, prop->name))
3983 continue;
3986 if (g_hash_table_lookup (properties, prop))
3987 continue;
3989 if (i >= len) {
3990 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, len * 2);
3991 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3992 len *= 2;
3993 res = new_res;
3995 mono_array_setref (res, i, mono_property_get_object (domain, startklass, prop));
3996 ++i;
3998 g_hash_table_insert (properties, prop, prop);
4000 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4001 goto handle_parent;
4003 g_hash_table_destroy (properties);
4004 g_free (propname);
4005 if (i != len) {
4006 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, i);
4007 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4008 res = new_res;
4010 * Better solution for the new GC.
4011 * res->max_length = i;
4014 return res;
4017 static MonoReflectionEvent *
4018 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
4020 MonoDomain *domain;
4021 MonoClass *klass, *startklass;
4022 gpointer iter;
4023 MonoEvent *event;
4024 MonoMethod *method;
4025 gchar *event_name;
4027 MONO_ARCH_SAVE_REGS;
4029 event_name = mono_string_to_utf8 (name);
4030 if (type->type->byref)
4031 return NULL;
4032 klass = startklass = mono_class_from_mono_type (type->type);
4033 domain = mono_object_domain (type);
4035 handle_parent:
4036 if (klass->exception_type != MONO_EXCEPTION_NONE)
4037 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4039 iter = NULL;
4040 while ((event = mono_class_get_events (klass, &iter))) {
4041 if (strcmp (event->name, event_name))
4042 continue;
4044 method = event->add;
4045 if (!method)
4046 method = event->remove;
4047 if (!method)
4048 method = event->raise;
4049 if (method) {
4050 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4051 if (!(bflags & BFLAGS_Public))
4052 continue;
4053 } else {
4054 if (!(bflags & BFLAGS_NonPublic))
4055 continue;
4056 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4057 continue;
4060 else
4061 if (!(bflags & BFLAGS_NonPublic))
4062 continue;
4064 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4065 if (!(bflags & BFLAGS_Static))
4066 continue;
4067 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4068 continue;
4069 } else {
4070 if (!(bflags & BFLAGS_Instance))
4071 continue;
4074 g_free (event_name);
4075 return mono_event_get_object (domain, startklass, event);
4078 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4079 goto handle_parent;
4081 g_free (event_name);
4082 return NULL;
4085 static MonoArray*
4086 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4088 MonoDomain *domain;
4089 static MonoClass *System_Reflection_EventInfo;
4090 MonoClass *startklass, *klass;
4091 MonoArray *res;
4092 MonoMethod *method;
4093 MonoEvent *event;
4094 int i, len, match;
4095 gpointer iter;
4097 MONO_ARCH_SAVE_REGS;
4099 if (!System_Reflection_EventInfo)
4100 System_Reflection_EventInfo = mono_class_from_name (
4101 mono_defaults.corlib, "System.Reflection", "EventInfo");
4103 domain = mono_object_domain (type);
4104 if (type->type->byref)
4105 return mono_array_new (domain, System_Reflection_EventInfo, 0);
4106 klass = startklass = mono_class_from_mono_type (type->type);
4108 i = 0;
4109 len = 2;
4110 res = mono_array_new (domain, System_Reflection_EventInfo, len);
4111 handle_parent:
4112 if (klass->exception_type != MONO_EXCEPTION_NONE)
4113 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4115 iter = NULL;
4116 while ((event = mono_class_get_events (klass, &iter))) {
4117 match = 0;
4118 method = event->add;
4119 if (!method)
4120 method = event->remove;
4121 if (!method)
4122 method = event->raise;
4123 if (method) {
4124 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4125 if (bflags & BFLAGS_Public)
4126 match++;
4127 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4128 if (bflags & BFLAGS_NonPublic)
4129 match++;
4132 else
4133 if (bflags & BFLAGS_NonPublic)
4134 match ++;
4135 if (!match)
4136 continue;
4137 match = 0;
4138 if (method) {
4139 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4140 if (bflags & BFLAGS_Static)
4141 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4142 match++;
4143 } else {
4144 if (bflags & BFLAGS_Instance)
4145 match++;
4148 else
4149 if (bflags & BFLAGS_Instance)
4150 match ++;
4151 if (!match)
4152 continue;
4153 match = 0;
4154 if (i >= len) {
4155 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, len * 2);
4156 mono_array_memcpy_refs (new_res, 0, res, 0, len);
4157 len *= 2;
4158 res = new_res;
4160 mono_array_setref (res, i, mono_event_get_object (domain, startklass, event));
4161 ++i;
4163 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4164 goto handle_parent;
4165 if (i != len) {
4166 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, i);
4167 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4168 res = new_res;
4170 * Better solution for the new GC.
4171 * res->max_length = i;
4174 return res;
4177 static MonoReflectionType *
4178 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4180 MonoDomain *domain;
4181 MonoClass *klass;
4182 MonoClass *nested;
4183 char *str;
4184 gpointer iter;
4186 MONO_ARCH_SAVE_REGS;
4188 domain = ((MonoObject *)type)->vtable->domain;
4189 if (type->type->byref)
4190 return NULL;
4191 klass = mono_class_from_mono_type (type->type);
4192 str = mono_string_to_utf8 (name);
4194 handle_parent:
4195 if (klass->exception_type != MONO_EXCEPTION_NONE)
4196 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4199 * If a nested type is generic, return its generic type definition.
4200 * Note that this means that the return value is essentially a
4201 * nested type of the generic type definition of @klass.
4203 * A note in MSDN claims that a generic type definition can have
4204 * nested types that aren't generic. In any case, the container of that
4205 * nested type would be the generic type definition.
4207 if (klass->generic_class)
4208 klass = klass->generic_class->container_class;
4210 iter = NULL;
4211 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4212 int match = 0;
4213 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4214 if (bflags & BFLAGS_Public)
4215 match++;
4216 } else {
4217 if (bflags & BFLAGS_NonPublic)
4218 match++;
4220 if (!match)
4221 continue;
4222 if (strcmp (nested->name, str) == 0){
4223 g_free (str);
4224 return mono_type_get_object (domain, &nested->byval_arg);
4227 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4228 goto handle_parent;
4229 g_free (str);
4230 return NULL;
4233 static MonoArray*
4234 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4236 MonoDomain *domain;
4237 MonoClass *klass;
4238 MonoArray *res;
4239 MonoObject *member;
4240 int i, len, match;
4241 MonoClass *nested;
4242 gpointer iter;
4244 MONO_ARCH_SAVE_REGS;
4246 domain = ((MonoObject *)type)->vtable->domain;
4247 if (type->type->byref)
4248 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4249 klass = mono_class_from_mono_type (type->type);
4250 if (klass->exception_type != MONO_EXCEPTION_NONE)
4251 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4254 * If a nested type is generic, return its generic type definition.
4255 * Note that this means that the return value is essentially the set
4256 * of nested types of the generic type definition of @klass.
4258 * A note in MSDN claims that a generic type definition can have
4259 * nested types that aren't generic. In any case, the container of that
4260 * nested type would be the generic type definition.
4262 if (klass->generic_class)
4263 klass = klass->generic_class->container_class;
4265 i = 0;
4266 len = 1;
4267 res = mono_array_new (domain, mono_defaults.monotype_class, len);
4268 iter = NULL;
4269 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4270 match = 0;
4271 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4272 if (bflags & BFLAGS_Public)
4273 match++;
4274 } else {
4275 if (bflags & BFLAGS_NonPublic)
4276 match++;
4278 if (!match)
4279 continue;
4280 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4281 if (i >= len) {
4282 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, len * 2);
4283 mono_array_memcpy_refs (new_res, 0, res, 0, len);
4284 len *= 2;
4285 res = new_res;
4287 mono_array_setref (res, i, member);
4288 ++i;
4290 if (i != len) {
4291 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, i);
4292 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4293 res = new_res;
4295 * Better solution for the new GC.
4296 * res->max_length = i;
4299 return res;
4302 static MonoReflectionType*
4303 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4305 gchar *str;
4306 MonoType *type = NULL;
4307 MonoTypeNameParse info;
4308 gboolean type_resolve;
4310 MONO_ARCH_SAVE_REGS;
4312 /* On MS.NET, this does not fire a TypeResolve event */
4313 type_resolve = TRUE;
4314 str = mono_string_to_utf8 (name);
4315 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4316 if (!mono_reflection_parse_type (str, &info)) {
4317 g_free (str);
4318 mono_reflection_free_type_info (&info);
4319 if (throwOnError) /* uhm: this is a parse error, though... */
4320 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4321 /*g_print ("failed parse\n");*/
4322 return NULL;
4325 if (info.assembly.name) {
4326 g_free (str);
4327 mono_reflection_free_type_info (&info);
4328 if (throwOnError) {
4329 /* 1.0 and 2.0 throw different exceptions */
4330 if (mono_defaults.generic_ilist_class)
4331 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4332 else
4333 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4335 return NULL;
4338 if (module != NULL) {
4339 if (module->image)
4340 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4341 else
4342 type = NULL;
4344 else
4345 if (assembly->assembly->dynamic) {
4346 /* Enumerate all modules */
4347 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4348 int i;
4350 type = NULL;
4351 if (abuilder->modules) {
4352 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4353 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4354 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4355 if (type)
4356 break;
4360 if (!type && abuilder->loaded_modules) {
4361 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4362 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4363 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4364 if (type)
4365 break;
4369 else
4370 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4371 g_free (str);
4372 mono_reflection_free_type_info (&info);
4373 if (!type) {
4374 MonoException *e = NULL;
4376 if (throwOnError)
4377 e = mono_get_exception_type_load (name, NULL);
4379 mono_loader_clear_error ();
4381 if (e != NULL)
4382 mono_raise_exception (e);
4384 return NULL;
4387 if (type->type == MONO_TYPE_CLASS) {
4388 MonoClass *klass = mono_type_get_class (type);
4390 if (mono_is_security_manager_active () && !klass->exception_type)
4391 /* Some security problems are detected during generic vtable construction */
4392 mono_class_setup_vtable (klass);
4393 /* need to report exceptions ? */
4394 if (throwOnError && klass->exception_type) {
4395 /* report SecurityException (or others) that occured when loading the assembly */
4396 MonoException *exc = mono_class_get_exception_for_failure (klass);
4397 mono_loader_clear_error ();
4398 mono_raise_exception (exc);
4399 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4400 return NULL;
4404 /* g_print ("got it\n"); */
4405 return mono_type_get_object (mono_object_domain (assembly), type);
4408 static MonoString *
4409 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4411 MonoDomain *domain = mono_object_domain (assembly);
4412 MonoAssembly *mass = assembly->assembly;
4413 MonoString *res = NULL;
4414 gchar *uri;
4415 gchar *absolute;
4416 gchar *content;
4417 gchar *shadow_ini_file;
4418 gsize len;
4419 gchar *dirname;
4421 MONO_ARCH_SAVE_REGS;
4423 if (g_path_is_absolute (mass->image->name)) {
4424 absolute = g_strdup (mass->image->name);
4425 dirname = g_path_get_dirname (absolute);
4426 } else {
4427 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4428 dirname = g_strdup (mass->basedir);
4431 /* Check for shadow-copied assembly */
4432 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4433 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4434 content = NULL;
4435 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4436 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4437 if (content) {
4438 g_free (content);
4439 content = NULL;
4442 g_free (shadow_ini_file);
4443 if (content != NULL) {
4444 g_free (absolute);
4445 absolute = content;
4448 g_free (dirname);
4450 #if PLATFORM_WIN32
4452 gint i;
4453 for (i = strlen (absolute) - 1; i >= 0; i--)
4454 if (absolute [i] == '\\')
4455 absolute [i] = '/';
4457 #endif
4458 if (escaped) {
4459 uri = g_filename_to_uri (absolute, NULL, NULL);
4460 } else {
4461 const char *prepend = "file://";
4462 #if PLATFORM_WIN32
4463 if (*absolute == '/' && *(absolute + 1) == '/') {
4464 prepend = "file:";
4465 } else {
4466 prepend = "file:///";
4468 #endif
4469 uri = g_strconcat (prepend, absolute, NULL);
4472 if (uri) {
4473 res = mono_string_new (domain, uri);
4474 g_free (uri);
4476 g_free (absolute);
4477 return res;
4480 static MonoBoolean
4481 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4483 MonoAssembly *mass = assembly->assembly;
4485 MONO_ARCH_SAVE_REGS;
4487 return mass->in_gac;
4490 static MonoReflectionAssembly*
4491 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4493 gchar *name;
4494 MonoAssembly *res;
4495 MonoImageOpenStatus status;
4497 MONO_ARCH_SAVE_REGS;
4499 name = mono_string_to_utf8 (mname);
4500 res = mono_assembly_load_with_partial_name (name, &status);
4502 g_free (name);
4504 if (res == NULL)
4505 return NULL;
4506 return mono_assembly_get_object (mono_domain_get (), res);
4509 static MonoString *
4510 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4512 MonoDomain *domain = mono_object_domain (assembly);
4513 MonoString *res;
4515 MONO_ARCH_SAVE_REGS;
4517 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4519 return res;
4522 static MonoBoolean
4523 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4525 MONO_ARCH_SAVE_REGS;
4527 return assembly->assembly->ref_only;
4530 static MonoString *
4531 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4533 MonoDomain *domain = mono_object_domain (assembly);
4535 MONO_ARCH_SAVE_REGS;
4537 return mono_string_new (domain, assembly->assembly->image->version);
4540 static MonoReflectionMethod*
4541 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4543 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4545 MONO_ARCH_SAVE_REGS;
4547 if (!token)
4548 return NULL;
4549 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4552 static MonoReflectionModule*
4553 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4555 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4558 static MonoArray*
4559 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4561 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4562 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4563 int i;
4564 const char *val;
4566 MONO_ARCH_SAVE_REGS;
4568 for (i = 0; i < table->rows; ++i) {
4569 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4570 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4572 return result;
4575 static MonoObject*
4576 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4578 static MonoClass *System_Version = NULL;
4579 static MonoMethod *create_version = NULL;
4580 MonoObject *result;
4581 gpointer args [4];
4583 if (!System_Version) {
4584 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4585 g_assert (System_Version);
4588 if (!create_version) {
4589 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4590 create_version = mono_method_desc_search_in_class (desc, System_Version);
4591 g_assert (create_version);
4592 mono_method_desc_free (desc);
4595 args [0] = &major;
4596 args [1] = &minor;
4597 args [2] = &build;
4598 args [3] = &revision;
4599 result = mono_object_new (domain, System_Version);
4600 mono_runtime_invoke (create_version, result, args, NULL);
4602 return result;
4605 static MonoArray*
4606 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4608 static MonoClass *System_Reflection_AssemblyName;
4609 MonoArray *result;
4610 MonoDomain *domain = mono_object_domain (assembly);
4611 int i, count = 0;
4612 static MonoMethod *create_culture = NULL;
4613 MonoImage *image = assembly->assembly->image;
4614 MonoTableInfo *t;
4616 MONO_ARCH_SAVE_REGS;
4618 if (!System_Reflection_AssemblyName)
4619 System_Reflection_AssemblyName = mono_class_from_name (
4620 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4622 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4623 count = t->rows;
4625 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4627 if (count > 0) {
4628 MonoMethodDesc *desc = mono_method_desc_new (
4629 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4630 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4631 g_assert (create_culture);
4632 mono_method_desc_free (desc);
4635 for (i = 0; i < count; i++) {
4636 MonoReflectionAssemblyName *aname;
4637 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4639 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4641 aname = (MonoReflectionAssemblyName *) mono_object_new (
4642 domain, System_Reflection_AssemblyName);
4644 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4646 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4647 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4648 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4649 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4650 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4651 aname->versioncompat = 1; /* SameMachine (default) */
4652 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4653 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4655 if (create_culture) {
4656 gpointer args [2];
4657 MonoBoolean assembly_ref = 1;
4658 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4659 args [1] = &assembly_ref;
4660 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4663 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4664 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4665 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4667 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4668 /* public key token isn't copied - the class library will
4669 automatically generate it from the public key if required */
4670 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4671 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4672 } else {
4673 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4674 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4676 } else {
4677 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4680 /* note: this function doesn't return the codebase on purpose (i.e. it can
4681 be used under partial trust as path information isn't present). */
4683 mono_array_setref (result, i, aname);
4685 return result;
4688 typedef struct {
4689 MonoArray *res;
4690 int idx;
4691 } NameSpaceInfo;
4693 static void
4694 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4696 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4698 mono_array_setref (info->res, info->idx, name);
4699 info->idx++;
4702 static MonoArray*
4703 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4705 MonoImage *img = assembly->assembly->image;
4706 MonoArray *res;
4707 NameSpaceInfo info;
4709 MONO_ARCH_SAVE_REGS;
4711 if (!img->name_cache)
4712 mono_image_init_name_cache (img);
4714 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4715 info.res = res;
4716 info.idx = 0;
4717 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4719 return res;
4722 /* move this in some file in mono/util/ */
4723 static char *
4724 g_concat_dir_and_file (const char *dir, const char *file)
4726 g_return_val_if_fail (dir != NULL, NULL);
4727 g_return_val_if_fail (file != NULL, NULL);
4730 * If the directory name doesn't have a / on the end, we need
4731 * to add one so we get a proper path to the file
4733 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4734 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4735 else
4736 return g_strconcat (dir, file, NULL);
4739 static void *
4740 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4742 char *n = mono_string_to_utf8 (name);
4743 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4744 guint32 i;
4745 guint32 cols [MONO_MANIFEST_SIZE];
4746 guint32 impl, file_idx;
4747 const char *val;
4748 MonoImage *module;
4750 MONO_ARCH_SAVE_REGS;
4752 for (i = 0; i < table->rows; ++i) {
4753 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4754 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4755 if (strcmp (val, n) == 0)
4756 break;
4758 g_free (n);
4759 if (i == table->rows)
4760 return NULL;
4761 /* FIXME */
4762 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4763 if (impl) {
4765 * this code should only be called after obtaining the
4766 * ResourceInfo and handling the other cases.
4768 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4769 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4771 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4772 if (!module)
4773 return NULL;
4775 else
4776 module = assembly->assembly->image;
4778 *ref_module = mono_module_get_object (mono_domain_get (), module);
4780 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4783 static gboolean
4784 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4786 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4787 int i;
4788 guint32 cols [MONO_MANIFEST_SIZE];
4789 guint32 file_cols [MONO_FILE_SIZE];
4790 const char *val;
4791 char *n;
4793 MONO_ARCH_SAVE_REGS;
4795 n = mono_string_to_utf8 (name);
4796 for (i = 0; i < table->rows; ++i) {
4797 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4798 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4799 if (strcmp (val, n) == 0)
4800 break;
4802 g_free (n);
4803 if (i == table->rows)
4804 return FALSE;
4806 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4807 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4809 else {
4810 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4811 case MONO_IMPLEMENTATION_FILE:
4812 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4813 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4814 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4815 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4816 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4817 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4818 info->location = 0;
4819 else
4820 info->location = RESOURCE_LOCATION_EMBEDDED;
4821 break;
4823 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4824 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4825 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4826 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4827 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4828 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4829 g_free (msg);
4830 mono_raise_exception (ex);
4832 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4834 /* Obtain info recursively */
4835 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4836 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4837 break;
4839 case MONO_IMPLEMENTATION_EXP_TYPE:
4840 g_assert_not_reached ();
4841 break;
4845 return TRUE;
4848 static MonoObject*
4849 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4851 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4852 MonoArray *result = NULL;
4853 int i, count;
4854 const char *val;
4855 char *n;
4857 MONO_ARCH_SAVE_REGS;
4859 /* check hash if needed */
4860 if (name) {
4861 n = mono_string_to_utf8 (name);
4862 for (i = 0; i < table->rows; ++i) {
4863 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4864 if (strcmp (val, n) == 0) {
4865 MonoString *fn;
4866 g_free (n);
4867 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4868 fn = mono_string_new (mono_object_domain (assembly), n);
4869 g_free (n);
4870 return (MonoObject*)fn;
4873 g_free (n);
4874 return NULL;
4877 count = 0;
4878 for (i = 0; i < table->rows; ++i) {
4879 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4880 count ++;
4883 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4885 count = 0;
4886 for (i = 0; i < table->rows; ++i) {
4887 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4888 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4889 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4890 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4891 g_free (n);
4892 count ++;
4895 return (MonoObject*)result;
4898 static MonoArray*
4899 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4901 MonoDomain *domain = mono_domain_get();
4902 MonoArray *res;
4903 MonoClass *klass;
4904 int i, j, file_count = 0;
4905 MonoImage **modules;
4906 guint32 module_count, real_module_count;
4907 MonoTableInfo *table;
4908 guint32 cols [MONO_FILE_SIZE];
4909 MonoImage *image = assembly->assembly->image;
4911 g_assert (image != NULL);
4912 g_assert (!assembly->assembly->dynamic);
4914 table = &image->tables [MONO_TABLE_FILE];
4915 file_count = table->rows;
4917 modules = image->modules;
4918 module_count = image->module_count;
4920 real_module_count = 0;
4921 for (i = 0; i < module_count; ++i)
4922 if (modules [i])
4923 real_module_count ++;
4925 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4926 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4928 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4929 j = 1;
4930 for (i = 0; i < module_count; ++i)
4931 if (modules [i]) {
4932 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4933 ++j;
4936 for (i = 0; i < file_count; ++i, ++j) {
4937 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4938 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4939 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4940 else {
4941 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4942 if (!m) {
4943 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4944 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4946 mono_array_setref (res, j, mono_module_get_object (domain, m));
4950 return res;
4953 static MonoReflectionMethod*
4954 ves_icall_GetCurrentMethod (void)
4956 MonoMethod *m = mono_method_get_last_managed ();
4958 MONO_ARCH_SAVE_REGS;
4960 return mono_method_get_object (mono_domain_get (), m, NULL);
4964 static MonoMethod*
4965 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4967 int offset = -1, i;
4968 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4969 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4970 //method is inflated, we should inflate it on the other class
4971 MonoGenericContext ctx;
4972 ctx.method_inst = inflated->context.method_inst;
4973 ctx.class_inst = inflated->context.class_inst;
4974 if (klass->generic_class)
4975 ctx.class_inst = klass->generic_class->context.class_inst;
4976 else if (klass->generic_container)
4977 ctx.class_inst = klass->generic_container->context.class_inst;
4978 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4981 mono_class_setup_methods (method->klass);
4982 for (i = 0; i < method->klass->method.count; ++i) {
4983 if (method->klass->methods [i] == method) {
4984 offset = i;
4985 break;
4988 mono_class_setup_methods (klass);
4989 g_assert (offset >= 0 && offset < klass->method.count);
4990 return klass->methods [offset];
4993 static MonoReflectionMethod*
4994 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4996 MonoClass *klass;
4997 if (type) {
4998 klass = mono_class_from_mono_type (type);
4999 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5000 return NULL;
5001 if (method->klass != klass)
5002 method = mono_method_get_equivalent_method (method, klass);
5003 } else
5004 klass = method->klass;
5005 return mono_method_get_object (mono_domain_get (), method, klass);
5008 static MonoReflectionMethod*
5009 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
5011 return mono_method_get_object (mono_domain_get (), method, NULL);
5014 static MonoReflectionMethodBody*
5015 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5017 return mono_method_body_get_object (mono_domain_get (), method);
5020 static MonoReflectionAssembly*
5021 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5023 MonoMethod *dest = NULL;
5025 MONO_ARCH_SAVE_REGS;
5027 mono_stack_walk_no_il (get_executing, &dest);
5028 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5032 static MonoReflectionAssembly*
5033 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5035 MonoDomain* domain = mono_domain_get ();
5037 MONO_ARCH_SAVE_REGS;
5039 if (!domain->entry_assembly)
5040 return NULL;
5042 return mono_assembly_get_object (domain, domain->entry_assembly);
5045 static MonoReflectionAssembly*
5046 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5048 MonoMethod *m;
5049 MonoMethod *dest;
5051 MONO_ARCH_SAVE_REGS;
5053 dest = NULL;
5054 mono_stack_walk_no_il (get_executing, &dest);
5055 m = dest;
5056 mono_stack_walk_no_il (get_caller, &dest);
5057 if (!dest)
5058 dest = m;
5059 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5062 static MonoString *
5063 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5064 gboolean assembly_qualified)
5066 MonoDomain *domain = mono_object_domain (object);
5067 MonoTypeNameFormat format;
5068 MonoString *res;
5069 gchar *name;
5071 MONO_ARCH_SAVE_REGS;
5072 if (full_name)
5073 format = assembly_qualified ?
5074 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5075 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5076 else
5077 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5079 name = mono_type_get_name_full (object->type, format);
5080 if (!name)
5081 return NULL;
5083 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5084 g_free (name);
5085 return NULL;
5088 res = mono_string_new (domain, name);
5089 g_free (name);
5091 return res;
5094 static void
5095 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5097 static MonoMethod *create_culture = NULL;
5098 gpointer args [2];
5099 guint32 pkey_len;
5100 const char *pkey_ptr;
5101 gchar *codebase;
5102 MonoBoolean assembly_ref = 0;
5104 MONO_ARCH_SAVE_REGS;
5106 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5107 aname->major = name->major;
5108 aname->minor = name->minor;
5109 aname->build = name->build;
5110 aname->flags = name->flags;
5111 aname->revision = name->revision;
5112 aname->hashalg = name->hash_alg;
5113 aname->versioncompat = 1; /* SameMachine (default) */
5115 if (by_default_version)
5116 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5118 codebase = NULL;
5119 if (absolute != NULL && *absolute != '\0') {
5120 const gchar *prepend = "file://";
5121 gchar *result;
5123 codebase = g_strdup (absolute);
5125 #if PLATFORM_WIN32
5127 gint i;
5128 for (i = strlen (codebase) - 1; i >= 0; i--)
5129 if (codebase [i] == '\\')
5130 codebase [i] = '/';
5132 if (*codebase == '/' && *(codebase + 1) == '/') {
5133 prepend = "file:";
5134 } else {
5135 prepend = "file:///";
5138 #endif
5139 result = g_strconcat (prepend, codebase, NULL);
5140 g_free (codebase);
5141 codebase = result;
5144 if (codebase) {
5145 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5146 g_free (codebase);
5149 if (!create_culture) {
5150 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5151 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5152 g_assert (create_culture);
5153 mono_method_desc_free (desc);
5156 if (name->culture) {
5157 args [0] = mono_string_new (domain, name->culture);
5158 args [1] = &assembly_ref;
5159 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5162 if (name->public_key) {
5163 pkey_ptr = (char*)name->public_key;
5164 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5166 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5167 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5168 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5169 } else if (default_publickey) {
5170 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5171 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5174 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5175 if (name->public_key_token [0]) {
5176 int i, j;
5177 char *p;
5179 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5180 p = mono_array_addr (aname->keyToken, char, 0);
5182 for (i = 0, j = 0; i < 8; i++) {
5183 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5184 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5185 p++;
5187 } else if (default_token) {
5188 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5192 static MonoString *
5193 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5195 MonoDomain *domain = mono_object_domain (assembly);
5196 MonoAssembly *mass = assembly->assembly;
5197 MonoString *res;
5198 gchar *name;
5200 name = g_strdup_printf (
5201 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5202 mass->aname.name,
5203 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5204 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5205 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5206 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5208 res = mono_string_new (domain, name);
5209 g_free (name);
5211 return res;
5214 static void
5215 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5217 gchar *absolute;
5218 MonoAssembly *mass = assembly->assembly;
5220 MONO_ARCH_SAVE_REGS;
5222 if (g_path_is_absolute (mass->image->name)) {
5223 fill_reflection_assembly_name (mono_object_domain (assembly),
5224 aname, &mass->aname, mass->image->name, TRUE,
5225 TRUE, mono_framework_version () >= 2);
5226 return;
5228 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5230 fill_reflection_assembly_name (mono_object_domain (assembly),
5231 aname, &mass->aname, absolute, TRUE, TRUE,
5232 mono_framework_version () >= 2);
5234 g_free (absolute);
5237 static void
5238 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5240 char *filename;
5241 MonoImageOpenStatus status = MONO_IMAGE_OK;
5242 gboolean res;
5243 MonoImage *image;
5244 MonoAssemblyName name;
5246 MONO_ARCH_SAVE_REGS;
5248 filename = mono_string_to_utf8 (fname);
5250 image = mono_image_open (filename, &status);
5252 if (!image){
5253 MonoException *exc;
5255 g_free (filename);
5256 if (status == MONO_IMAGE_IMAGE_INVALID)
5257 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5258 else
5259 exc = mono_get_exception_file_not_found2 (NULL, fname);
5260 mono_raise_exception (exc);
5263 res = mono_assembly_fill_assembly_name (image, &name);
5264 if (!res) {
5265 mono_image_close (image);
5266 g_free (filename);
5267 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5270 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5271 TRUE, mono_framework_version () == 1,
5272 mono_framework_version () >= 2);
5274 g_free (filename);
5275 mono_image_close (image);
5278 static MonoBoolean
5279 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5280 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5282 MonoBoolean result = FALSE;
5283 MonoDeclSecurityEntry entry;
5285 /* SecurityAction.RequestMinimum */
5286 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5287 *minimum = entry.blob;
5288 *minLength = entry.size;
5289 result = TRUE;
5291 /* SecurityAction.RequestOptional */
5292 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5293 *optional = entry.blob;
5294 *optLength = entry.size;
5295 result = TRUE;
5297 /* SecurityAction.RequestRefuse */
5298 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5299 *refused = entry.blob;
5300 *refLength = entry.size;
5301 result = TRUE;
5304 return result;
5307 static MonoArray*
5308 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5310 MonoArray *res;
5311 MonoClass *klass;
5312 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5313 int i, count;
5314 guint32 attrs, visibility;
5316 /* we start the count from 1 because we skip the special type <Module> */
5317 if (exportedOnly) {
5318 count = 0;
5319 for (i = 1; i < tdef->rows; ++i) {
5320 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5321 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5322 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5323 count++;
5325 } else {
5326 count = tdef->rows - 1;
5328 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5329 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5330 count = 0;
5331 for (i = 1; i < tdef->rows; ++i) {
5332 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5333 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5334 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5335 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5336 if (klass) {
5337 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5338 } else {
5339 MonoLoaderError *error;
5340 MonoException *ex;
5342 error = mono_loader_get_last_error ();
5343 g_assert (error != NULL);
5345 ex = mono_loader_error_prepare_exception (error);
5346 mono_array_setref (*exceptions, count, ex);
5348 if (mono_loader_get_last_error ())
5349 mono_loader_clear_error ();
5350 count++;
5354 return res;
5357 static MonoArray*
5358 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5360 MonoArray *res = NULL;
5361 MonoArray *exceptions = NULL;
5362 MonoImage *image = NULL;
5363 MonoTableInfo *table = NULL;
5364 MonoDomain *domain;
5365 GList *list = NULL;
5366 int i, len, ex_count;
5368 MONO_ARCH_SAVE_REGS;
5370 domain = mono_object_domain (assembly);
5372 g_assert (!assembly->assembly->dynamic);
5373 image = assembly->assembly->image;
5374 table = &image->tables [MONO_TABLE_FILE];
5375 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5377 /* Append data from all modules in the assembly */
5378 for (i = 0; i < table->rows; ++i) {
5379 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5380 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5381 if (loaded_image) {
5382 MonoArray *ex2;
5383 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5384 /* Append the new types to the end of the array */
5385 if (mono_array_length (res2) > 0) {
5386 guint32 len1, len2;
5387 MonoArray *res3, *ex3;
5389 len1 = mono_array_length (res);
5390 len2 = mono_array_length (res2);
5392 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5393 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5394 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5395 res = res3;
5397 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5398 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5399 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5400 exceptions = ex3;
5406 /* the ReflectionTypeLoadException must have all the types (Types property),
5407 * NULL replacing types which throws an exception. The LoaderException must
5408 * contain all exceptions for NULL items.
5411 len = mono_array_length (res);
5413 ex_count = 0;
5414 for (i = 0; i < len; i++) {
5415 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5416 MonoClass *klass;
5418 if (t) {
5419 klass = mono_type_get_class (t->type);
5420 if ((klass != NULL) && klass->exception_type) {
5421 /* keep the class in the list */
5422 list = g_list_append (list, klass);
5423 /* and replace Type with NULL */
5424 mono_array_setref (res, i, NULL);
5426 } else {
5427 ex_count ++;
5431 if (list || ex_count) {
5432 GList *tmp = NULL;
5433 MonoException *exc = NULL;
5434 MonoArray *exl = NULL;
5435 int j, length = g_list_length (list) + ex_count;
5437 mono_loader_clear_error ();
5439 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5440 /* Types for which mono_class_get () succeeded */
5441 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5442 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5443 mono_array_setref (exl, i, exc);
5445 /* Types for which it don't */
5446 for (j = 0; j < mono_array_length (exceptions); ++j) {
5447 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5448 if (exc) {
5449 g_assert (i < length);
5450 mono_array_setref (exl, i, exc);
5451 i ++;
5454 g_list_free (list);
5455 list = NULL;
5457 exc = mono_get_exception_reflection_type_load (res, exl);
5458 mono_loader_clear_error ();
5459 mono_raise_exception (exc);
5462 return res;
5465 static gboolean
5466 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5468 MonoAssemblyName aname;
5469 MonoDomain *domain = mono_object_domain (name);
5470 char *val;
5471 gboolean is_version_defined;
5472 gboolean is_token_defined;
5474 aname.public_key = NULL;
5475 val = mono_string_to_utf8 (assname);
5476 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5477 g_free ((guint8*) aname.public_key);
5478 g_free (val);
5479 return FALSE;
5482 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5483 FALSE, is_token_defined);
5485 mono_assembly_name_free (&aname);
5486 g_free ((guint8*) aname.public_key);
5487 g_free (val);
5489 return TRUE;
5492 static MonoReflectionType*
5493 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5495 MonoDomain *domain = mono_object_domain (module);
5496 MonoClass *klass;
5498 MONO_ARCH_SAVE_REGS;
5500 g_assert (module->image);
5502 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5503 /* These images do not have a global type */
5504 return NULL;
5506 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5507 return mono_type_get_object (domain, &klass->byval_arg);
5510 static void
5511 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5513 /*if (module->image)
5514 mono_image_close (module->image);*/
5517 static MonoString*
5518 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5520 MonoDomain *domain = mono_object_domain (module);
5522 MONO_ARCH_SAVE_REGS;
5524 g_assert (module->image);
5525 return mono_string_new (domain, module->image->guid);
5528 static gpointer
5529 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5531 #ifdef PLATFORM_WIN32
5532 if (module->image && module->image->is_module_handle)
5533 return module->image->raw_data;
5534 #endif
5536 return (gpointer) (-1);
5539 static void
5540 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5542 if (image->dynamic) {
5543 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5544 *pe_kind = dyn->pe_kind;
5545 *machine = dyn->machine;
5547 else {
5548 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5549 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5553 static gint32
5554 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5556 return (image->md_version_major << 16) | (image->md_version_minor);
5559 static MonoArray*
5560 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5562 MonoArray *exceptions;
5563 int i;
5565 MONO_ARCH_SAVE_REGS;
5567 if (!module->image)
5568 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5569 else {
5570 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5571 for (i = 0; i < mono_array_length (exceptions); ++i) {
5572 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5573 if (ex)
5574 mono_raise_exception (ex);
5576 return res;
5580 static gboolean
5581 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5583 guint32 cols [MONO_MEMBERREF_SIZE];
5584 const char *sig;
5585 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5586 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5587 mono_metadata_decode_blob_size (sig, &sig);
5588 return (*sig != 0x6);
5591 static void
5592 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5594 if (type_args)
5595 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5596 mono_array_addr (type_args, MonoType*, 0));
5597 else
5598 context->class_inst = NULL;
5599 if (method_args)
5600 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5601 mono_array_addr (method_args, MonoType*, 0));
5602 else
5603 context->method_inst = NULL;
5606 static MonoType*
5607 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5609 MonoClass *klass;
5610 int table = mono_metadata_token_table (token);
5611 int index = mono_metadata_token_index (token);
5612 MonoGenericContext context;
5614 *error = ResolveTokenError_Other;
5616 /* Validate token */
5617 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5618 (table != MONO_TABLE_TYPESPEC)) {
5619 *error = ResolveTokenError_BadTable;
5620 return NULL;
5623 if (image->dynamic) {
5624 if (type_args || method_args)
5625 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5626 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5627 if (!klass)
5628 return NULL;
5629 return &klass->byval_arg;
5632 if ((index <= 0) || (index > image->tables [table].rows)) {
5633 *error = ResolveTokenError_OutOfRange;
5634 return NULL;
5637 init_generic_context_from_args (&context, type_args, method_args);
5638 klass = mono_class_get_full (image, token, &context);
5640 if (mono_loader_get_last_error ())
5641 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5643 if (klass)
5644 return &klass->byval_arg;
5645 else
5646 return NULL;
5649 static MonoMethod*
5650 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5652 int table = mono_metadata_token_table (token);
5653 int index = mono_metadata_token_index (token);
5654 MonoGenericContext context;
5655 MonoMethod *method;
5657 *error = ResolveTokenError_Other;
5659 /* Validate token */
5660 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5661 (table != MONO_TABLE_MEMBERREF)) {
5662 *error = ResolveTokenError_BadTable;
5663 return NULL;
5666 if (image->dynamic) {
5667 if (type_args || method_args)
5668 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5669 /* FIXME: validate memberref token type */
5670 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5673 if ((index <= 0) || (index > image->tables [table].rows)) {
5674 *error = ResolveTokenError_OutOfRange;
5675 return NULL;
5677 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5678 *error = ResolveTokenError_BadTable;
5679 return NULL;
5682 init_generic_context_from_args (&context, type_args, method_args);
5683 method = mono_get_method_full (image, token, NULL, &context);
5685 if (mono_loader_get_last_error ())
5686 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5688 return method;
5691 static MonoString*
5692 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5694 int index = mono_metadata_token_index (token);
5696 *error = ResolveTokenError_Other;
5698 /* Validate token */
5699 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5700 *error = ResolveTokenError_BadTable;
5701 return NULL;
5704 if (image->dynamic)
5705 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5707 if ((index <= 0) || (index >= image->heap_us.size)) {
5708 *error = ResolveTokenError_OutOfRange;
5709 return NULL;
5712 /* FIXME: What to do if the index points into the middle of a string ? */
5714 return mono_ldstr (mono_domain_get (), image, index);
5717 static MonoClassField*
5718 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5720 MonoClass *klass;
5721 int table = mono_metadata_token_table (token);
5722 int index = mono_metadata_token_index (token);
5723 MonoGenericContext context;
5724 MonoClassField *field;
5726 *error = ResolveTokenError_Other;
5728 /* Validate token */
5729 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5730 *error = ResolveTokenError_BadTable;
5731 return NULL;
5734 if (image->dynamic) {
5735 if (type_args || method_args)
5736 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5737 /* FIXME: validate memberref token type */
5738 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5741 if ((index <= 0) || (index > image->tables [table].rows)) {
5742 *error = ResolveTokenError_OutOfRange;
5743 return NULL;
5745 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5746 *error = ResolveTokenError_BadTable;
5747 return NULL;
5750 init_generic_context_from_args (&context, type_args, method_args);
5751 field = mono_field_from_token (image, token, &klass, &context);
5753 if (mono_loader_get_last_error ())
5754 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5756 return field;
5760 static MonoObject*
5761 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5763 int table = mono_metadata_token_table (token);
5765 *error = ResolveTokenError_Other;
5767 switch (table) {
5768 case MONO_TABLE_TYPEDEF:
5769 case MONO_TABLE_TYPEREF:
5770 case MONO_TABLE_TYPESPEC: {
5771 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5772 if (t)
5773 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5774 else
5775 return NULL;
5777 case MONO_TABLE_METHOD:
5778 case MONO_TABLE_METHODSPEC: {
5779 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5780 if (m)
5781 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5782 else
5783 return NULL;
5785 case MONO_TABLE_FIELD: {
5786 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5787 if (f)
5788 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5789 else
5790 return NULL;
5792 case MONO_TABLE_MEMBERREF:
5793 if (mono_metadata_memberref_is_method (image, token)) {
5794 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5795 if (m)
5796 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5797 else
5798 return NULL;
5800 else {
5801 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5802 if (f)
5803 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5804 else
5805 return NULL;
5807 break;
5809 default:
5810 *error = ResolveTokenError_BadTable;
5813 return NULL;
5816 static MonoArray*
5817 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5819 int table = mono_metadata_token_table (token);
5820 int idx = mono_metadata_token_index (token);
5821 MonoTableInfo *tables = image->tables;
5822 guint32 sig, len;
5823 const char *ptr;
5824 MonoArray *res;
5826 *error = ResolveTokenError_OutOfRange;
5828 /* FIXME: Support other tables ? */
5829 if (table != MONO_TABLE_STANDALONESIG)
5830 return NULL;
5832 if (image->dynamic)
5833 return NULL;
5835 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5836 return NULL;
5838 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5840 ptr = mono_metadata_blob_heap (image, sig);
5841 len = mono_metadata_decode_blob_size (ptr, &ptr);
5843 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5844 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5845 return res;
5848 static MonoReflectionType*
5849 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5851 MonoClass *klass;
5852 int isbyref = 0, rank;
5853 char *str = mono_string_to_utf8 (smodifiers);
5854 char *p;
5856 MONO_ARCH_SAVE_REGS;
5858 klass = mono_class_from_mono_type (tb->type.type);
5859 p = str;
5860 /* logic taken from mono_reflection_parse_type(): keep in sync */
5861 while (*p) {
5862 switch (*p) {
5863 case '&':
5864 if (isbyref) { /* only one level allowed by the spec */
5865 g_free (str);
5866 return NULL;
5868 isbyref = 1;
5869 p++;
5870 g_free (str);
5871 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5872 break;
5873 case '*':
5874 klass = mono_ptr_class_get (&klass->byval_arg);
5875 mono_class_init (klass);
5876 p++;
5877 break;
5878 case '[':
5879 rank = 1;
5880 p++;
5881 while (*p) {
5882 if (*p == ']')
5883 break;
5884 if (*p == ',')
5885 rank++;
5886 else if (*p != '*') { /* '*' means unknown lower bound */
5887 g_free (str);
5888 return NULL;
5890 ++p;
5892 if (*p != ']') {
5893 g_free (str);
5894 return NULL;
5896 p++;
5897 klass = mono_array_class_get (klass, rank);
5898 mono_class_init (klass);
5899 break;
5900 default:
5901 break;
5904 g_free (str);
5905 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5908 static MonoBoolean
5909 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5911 MonoType *type;
5912 MonoBoolean res;
5914 MONO_ARCH_SAVE_REGS;
5916 type = t->type;
5917 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5919 return res;
5922 static MonoReflectionType *
5923 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5925 MonoClass *klass, *aklass;
5927 MONO_ARCH_SAVE_REGS;
5929 klass = mono_class_from_mono_type (type->type);
5930 aklass = mono_array_class_get (klass, rank);
5932 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5935 static MonoReflectionType *
5936 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5938 MonoClass *klass;
5940 MONO_ARCH_SAVE_REGS;
5942 klass = mono_class_from_mono_type (type->type);
5944 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5947 static MonoReflectionType *
5948 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5950 MonoClass *pklass;
5952 MONO_ARCH_SAVE_REGS;
5954 pklass = mono_ptr_class_get (type->type);
5956 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5959 static MonoObject *
5960 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5961 MonoReflectionMethod *info)
5963 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5964 MonoObject *delegate;
5965 gpointer func;
5966 MonoMethod *method = info->method;
5968 MONO_ARCH_SAVE_REGS;
5970 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5972 /* FIME: We must check if target is visible to the caller under coreclr.
5973 * The check should be disabled otherwise as it shouldn't raise expection under fulltrust.
5976 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5978 if (mono_method_needs_static_rgctx_invoke (method, FALSE)) {
5979 method = mono_marshal_get_static_rgctx_invoke (method);
5980 func = mono_compile_method (method);
5981 } else if (method->dynamic) {
5982 /* Creating a trampoline would leak memory */
5983 func = mono_compile_method (method);
5984 } else {
5985 func = mono_create_ftnptr (mono_domain_get (),
5986 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5989 mono_delegate_ctor_with_method (delegate, target, func, method);
5991 return delegate;
5994 static void
5995 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5997 /* Reset the invoke impl to the default one */
5998 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
6002 * Magic number to convert a time which is relative to
6003 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
6005 #define EPOCH_ADJUST ((guint64)62135596800LL)
6008 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
6010 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
6012 #ifdef PLATFORM_WIN32
6013 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
6014 static void
6015 convert_to_absolute_date(SYSTEMTIME *date)
6017 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
6018 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6019 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6020 /* from the calendar FAQ */
6021 int a = (14 - date->wMonth) / 12;
6022 int y = date->wYear - a;
6023 int m = date->wMonth + 12 * a - 2;
6024 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
6026 /* d is now the day of the week for the first of the month (0 == Sunday) */
6028 int day_of_week = date->wDayOfWeek;
6030 /* set day_in_month to the first day in the month which falls on day_of_week */
6031 int day_in_month = 1 + (day_of_week - d);
6032 if (day_in_month <= 0)
6033 day_in_month += 7;
6035 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
6036 date->wDay = day_in_month + (date->wDay - 1) * 7;
6037 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6038 date->wDay -= 7;
6040 #endif
6042 #ifndef PLATFORM_WIN32
6044 * Return's the offset from GMT of a local time.
6046 * tm is a local time
6047 * t is the same local time as seconds.
6049 static int
6050 gmt_offset(struct tm *tm, time_t t)
6052 #if defined (HAVE_TM_GMTOFF)
6053 return tm->tm_gmtoff;
6054 #else
6055 struct tm g;
6056 time_t t2;
6057 g = *gmtime(&t);
6058 g.tm_isdst = tm->tm_isdst;
6059 t2 = mktime(&g);
6060 return (int)difftime(t, t2);
6061 #endif
6063 #endif
6065 * This is heavily based on zdump.c from glibc 2.2.
6067 * * data[0]: start of daylight saving time (in DateTime ticks).
6068 * * data[1]: end of daylight saving time (in DateTime ticks).
6069 * * data[2]: utcoffset (in TimeSpan ticks).
6070 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
6071 * * name[0]: name of this timezone when not daylight saving.
6072 * * name[1]: name of this timezone when daylight saving.
6074 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6075 * the class library allows years between 1 and 9999.
6077 * Returns true on success and zero on failure.
6079 static guint32
6080 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6082 #ifndef PLATFORM_WIN32
6083 MonoDomain *domain = mono_domain_get ();
6084 struct tm start, tt;
6085 time_t t;
6087 long int gmtoff;
6088 int is_daylight = 0, day;
6089 char tzone [64];
6091 MONO_ARCH_SAVE_REGS;
6093 MONO_CHECK_ARG_NULL (data);
6094 MONO_CHECK_ARG_NULL (names);
6096 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6097 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6100 * no info is better than crashing: we'll need our own tz data
6101 * to make this work properly, anyway. The range is probably
6102 * reduced to 1970 .. 2037 because that is what mktime is
6103 * guaranteed to support (we get into an infinite loop
6104 * otherwise).
6107 memset (&start, 0, sizeof (start));
6109 start.tm_mday = 1;
6110 start.tm_year = year-1900;
6112 t = mktime (&start);
6114 if ((year < 1970) || (year > 2037) || (t == -1)) {
6115 t = time (NULL);
6116 tt = *localtime (&t);
6117 strftime (tzone, sizeof (tzone), "%Z", &tt);
6118 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6119 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6120 return 1;
6123 gmtoff = gmt_offset (&start, t);
6125 /* For each day of the year, calculate the tm_gmtoff. */
6126 for (day = 0; day < 365; day++) {
6128 t += 3600*24;
6129 tt = *localtime (&t);
6131 /* Daylight saving starts or ends here. */
6132 if (gmt_offset (&tt, t) != gmtoff) {
6133 struct tm tt1;
6134 time_t t1;
6136 /* Try to find the exact hour when daylight saving starts/ends. */
6137 t1 = t;
6138 do {
6139 t1 -= 3600;
6140 tt1 = *localtime (&t1);
6141 } while (gmt_offset (&tt1, t1) != gmtoff);
6143 /* Try to find the exact minute when daylight saving starts/ends. */
6144 do {
6145 t1 += 60;
6146 tt1 = *localtime (&t1);
6147 } while (gmt_offset (&tt1, t1) == gmtoff);
6148 t1+=gmtoff;
6149 strftime (tzone, sizeof (tzone), "%Z", &tt);
6151 /* Write data, if we're already in daylight saving, we're done. */
6152 if (is_daylight) {
6153 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6154 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6155 return 1;
6156 } else {
6157 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6158 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6159 is_daylight = 1;
6162 /* This is only set once when we enter daylight saving. */
6163 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6164 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6166 gmtoff = gmt_offset (&tt, t);
6170 if (!is_daylight) {
6171 strftime (tzone, sizeof (tzone), "%Z", &tt);
6172 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6173 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6174 mono_array_set ((*data), gint64, 0, 0);
6175 mono_array_set ((*data), gint64, 1, 0);
6176 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6177 mono_array_set ((*data), gint64, 3, 0);
6180 return 1;
6181 #else
6182 MonoDomain *domain = mono_domain_get ();
6183 TIME_ZONE_INFORMATION tz_info;
6184 FILETIME ft;
6185 int i;
6186 int err, tz_id;
6188 tz_id = GetTimeZoneInformation (&tz_info);
6189 if (tz_id == TIME_ZONE_ID_INVALID)
6190 return 0;
6192 MONO_CHECK_ARG_NULL (data);
6193 MONO_CHECK_ARG_NULL (names);
6195 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6196 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6198 for (i = 0; i < 32; ++i)
6199 if (!tz_info.DaylightName [i])
6200 break;
6201 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6202 for (i = 0; i < 32; ++i)
6203 if (!tz_info.StandardName [i])
6204 break;
6205 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6207 if ((year <= 1601) || (year > 30827)) {
6209 * According to MSDN, the MS time functions can't handle dates outside
6210 * this interval.
6212 return 1;
6215 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6216 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6217 tz_info.StandardDate.wYear = year;
6218 convert_to_absolute_date(&tz_info.StandardDate);
6219 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6220 //g_assert(err);
6221 if (err == 0)
6222 return 0;
6224 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6225 tz_info.DaylightDate.wYear = year;
6226 convert_to_absolute_date(&tz_info.DaylightDate);
6227 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6228 //g_assert(err);
6229 if (err == 0)
6230 return 0;
6232 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6234 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6235 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6237 return 1;
6238 #endif
6241 static gpointer
6242 ves_icall_System_Object_obj_address (MonoObject *this)
6244 MONO_ARCH_SAVE_REGS;
6246 return this;
6249 /* System.Buffer */
6251 static inline gint32
6252 mono_array_get_byte_length (MonoArray *array)
6254 MonoClass *klass;
6255 int length;
6256 int i;
6258 klass = array->obj.vtable->klass;
6260 if (array->bounds == NULL)
6261 length = array->max_length;
6262 else {
6263 length = 1;
6264 for (i = 0; i < klass->rank; ++ i)
6265 length *= array->bounds [i].length;
6268 switch (klass->element_class->byval_arg.type) {
6269 case MONO_TYPE_I1:
6270 case MONO_TYPE_U1:
6271 case MONO_TYPE_BOOLEAN:
6272 return length;
6273 case MONO_TYPE_I2:
6274 case MONO_TYPE_U2:
6275 case MONO_TYPE_CHAR:
6276 return length << 1;
6277 case MONO_TYPE_I4:
6278 case MONO_TYPE_U4:
6279 case MONO_TYPE_R4:
6280 return length << 2;
6281 case MONO_TYPE_I:
6282 case MONO_TYPE_U:
6283 return length * sizeof (gpointer);
6284 case MONO_TYPE_I8:
6285 case MONO_TYPE_U8:
6286 case MONO_TYPE_R8:
6287 return length << 3;
6288 default:
6289 return -1;
6293 static gint32
6294 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6296 MONO_ARCH_SAVE_REGS;
6298 return mono_array_get_byte_length (array);
6301 static gint8
6302 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6304 MONO_ARCH_SAVE_REGS;
6306 return mono_array_get (array, gint8, idx);
6309 static void
6310 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6312 MONO_ARCH_SAVE_REGS;
6314 mono_array_set (array, gint8, idx, value);
6317 static MonoBoolean
6318 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6320 guint8 *src_buf, *dest_buf;
6322 MONO_ARCH_SAVE_REGS;
6324 /* watch out for integer overflow */
6325 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6326 return FALSE;
6328 src_buf = (guint8 *)src->vector + src_offset;
6329 dest_buf = (guint8 *)dest->vector + dest_offset;
6331 if (src != dest)
6332 memcpy (dest_buf, src_buf, count);
6333 else
6334 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6336 return TRUE;
6339 static MonoObject *
6340 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6342 MonoDomain *domain = mono_object_domain (this);
6343 MonoObject *res;
6344 MonoRealProxy *rp = ((MonoRealProxy *)this);
6345 MonoTransparentProxy *tp;
6346 MonoType *type;
6347 MonoClass *klass;
6349 MONO_ARCH_SAVE_REGS;
6351 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6352 tp = (MonoTransparentProxy*) res;
6354 MONO_OBJECT_SETREF (tp, rp, rp);
6355 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6356 klass = mono_class_from_mono_type (type);
6358 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6359 tp->remote_class = mono_remote_class (domain, class_name, klass);
6361 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6362 return res;
6365 static MonoReflectionType *
6366 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6368 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6371 /* System.Environment */
6373 MonoString*
6374 ves_icall_System_Environment_get_UserName (void)
6376 MONO_ARCH_SAVE_REGS;
6378 /* using glib is more portable */
6379 return mono_string_new (mono_domain_get (), g_get_user_name ());
6383 static MonoString *
6384 ves_icall_System_Environment_get_MachineName (void)
6386 #if defined (PLATFORM_WIN32)
6387 gunichar2 *buf;
6388 guint32 len;
6389 MonoString *result;
6391 len = MAX_COMPUTERNAME_LENGTH + 1;
6392 buf = g_new (gunichar2, len);
6394 result = NULL;
6395 if (GetComputerName (buf, (PDWORD) &len))
6396 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6398 g_free (buf);
6399 return result;
6400 #elif !defined(DISABLE_SOCKETS)
6401 gchar buf [256];
6402 MonoString *result;
6404 if (gethostname (buf, sizeof (buf)) == 0)
6405 result = mono_string_new (mono_domain_get (), buf);
6406 else
6407 result = NULL;
6409 return result;
6410 #else
6411 return mono_string_new (mono_domain_get (), "mono");
6412 #endif
6415 static int
6416 ves_icall_System_Environment_get_Platform (void)
6418 #if defined (PLATFORM_WIN32)
6419 /* Win32NT */
6420 return 2;
6421 #elif defined(__MACH__)
6422 /* OSX */
6423 if (mono_framework_version () < 2)
6424 return 128;
6427 // For compatibility with our client code, this will be 4 for a while.
6428 // We will eventually move to 6 to match .NET, but it requires all client
6429 // code to be updated and the documentation everywhere to be updated
6430 // first.
6432 return 4;
6433 #else
6434 /* Unix */
6435 if (mono_framework_version () < 2)
6436 return 128;
6437 return 4;
6438 #endif
6441 static MonoString *
6442 ves_icall_System_Environment_get_NewLine (void)
6444 MONO_ARCH_SAVE_REGS;
6446 #if defined (PLATFORM_WIN32)
6447 return mono_string_new (mono_domain_get (), "\r\n");
6448 #else
6449 return mono_string_new (mono_domain_get (), "\n");
6450 #endif
6453 static MonoString *
6454 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6456 const gchar *value;
6457 gchar *utf8_name;
6459 MONO_ARCH_SAVE_REGS;
6461 if (name == NULL)
6462 return NULL;
6464 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6465 value = g_getenv (utf8_name);
6467 g_free (utf8_name);
6469 if (value == 0)
6470 return NULL;
6472 return mono_string_new (mono_domain_get (), value);
6476 * There is no standard way to get at environ.
6478 #ifndef _MSC_VER
6479 #ifndef __MINGW32_VERSION
6480 #ifdef __APPLE__
6481 /* Apple defines this in crt_externs.h but doesn't provide that header for
6482 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6483 * in fact exist on all implementations (so far)
6485 gchar ***_NSGetEnviron();
6486 #define environ (*_NSGetEnviron())
6487 #else
6488 extern
6489 char **environ;
6490 #endif
6491 #endif
6492 #endif
6494 static MonoArray *
6495 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6497 #ifdef PLATFORM_WIN32
6498 MonoArray *names;
6499 MonoDomain *domain;
6500 MonoString *str;
6501 WCHAR* env_strings;
6502 WCHAR* env_string;
6503 WCHAR* equal_str;
6504 int n = 0;
6506 env_strings = GetEnvironmentStrings();
6508 if (env_strings) {
6509 env_string = env_strings;
6510 while (*env_string != '\0') {
6511 /* weird case that MS seems to skip */
6512 if (*env_string != '=')
6513 n++;
6514 while (*env_string != '\0')
6515 env_string++;
6516 env_string++;
6520 domain = mono_domain_get ();
6521 names = mono_array_new (domain, mono_defaults.string_class, n);
6523 if (env_strings) {
6524 n = 0;
6525 env_string = env_strings;
6526 while (*env_string != '\0') {
6527 /* weird case that MS seems to skip */
6528 if (*env_string != '=') {
6529 equal_str = wcschr(env_string, '=');
6530 g_assert(equal_str);
6531 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6532 mono_array_setref (names, n, str);
6533 n++;
6535 while (*env_string != '\0')
6536 env_string++;
6537 env_string++;
6540 FreeEnvironmentStrings (env_strings);
6543 return names;
6545 #else
6546 MonoArray *names;
6547 MonoDomain *domain;
6548 MonoString *str;
6549 gchar **e, **parts;
6550 int n;
6552 MONO_ARCH_SAVE_REGS;
6554 n = 0;
6555 for (e = environ; *e != 0; ++ e)
6556 ++ n;
6558 domain = mono_domain_get ();
6559 names = mono_array_new (domain, mono_defaults.string_class, n);
6561 n = 0;
6562 for (e = environ; *e != 0; ++ e) {
6563 parts = g_strsplit (*e, "=", 2);
6564 if (*parts != 0) {
6565 str = mono_string_new (domain, *parts);
6566 mono_array_setref (names, n, str);
6569 g_strfreev (parts);
6571 ++ n;
6574 return names;
6575 #endif
6579 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6581 #if !GLIB_CHECK_VERSION(2,4,0)
6582 #define g_setenv(a,b,c) setenv(a,b,c)
6583 #define g_unsetenv(a) unsetenv(a)
6584 #endif
6586 static void
6587 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6589 #ifdef PLATFORM_WIN32
6590 gunichar2 *utf16_name, *utf16_value;
6591 #else
6592 gchar *utf8_name, *utf8_value;
6593 #endif
6595 MONO_ARCH_SAVE_REGS;
6597 #ifdef PLATFORM_WIN32
6598 utf16_name = mono_string_to_utf16 (name);
6599 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6600 SetEnvironmentVariable (utf16_name, NULL);
6601 g_free (utf16_name);
6602 return;
6605 utf16_value = mono_string_to_utf16 (value);
6607 SetEnvironmentVariable (utf16_name, utf16_value);
6609 g_free (utf16_name);
6610 g_free (utf16_value);
6611 #else
6612 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6614 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6615 g_unsetenv (utf8_name);
6616 g_free (utf8_name);
6617 return;
6620 utf8_value = mono_string_to_utf8 (value);
6621 g_setenv (utf8_name, utf8_value, TRUE);
6623 g_free (utf8_name);
6624 g_free (utf8_value);
6625 #endif
6628 static void
6629 ves_icall_System_Environment_Exit (int result)
6631 MONO_ARCH_SAVE_REGS;
6633 mono_threads_set_shutting_down ();
6635 mono_runtime_set_shutting_down ();
6637 /* Suspend all managed threads since the runtime is going away */
6638 mono_thread_suspend_all_other_threads ();
6640 mono_runtime_quit ();
6642 /* we may need to do some cleanup here... */
6643 exit (result);
6646 static MonoString*
6647 ves_icall_System_Environment_GetGacPath (void)
6649 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6652 static MonoString*
6653 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6655 #if defined (PLATFORM_WIN32)
6656 #ifndef CSIDL_FLAG_CREATE
6657 #define CSIDL_FLAG_CREATE 0x8000
6658 #endif
6660 WCHAR path [MAX_PATH];
6661 /* Create directory if no existing */
6662 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6663 int len = 0;
6664 while (path [len])
6665 ++ len;
6666 return mono_string_new_utf16 (mono_domain_get (), path, len);
6668 #else
6669 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6670 #endif
6671 return mono_string_new (mono_domain_get (), "");
6674 static MonoArray *
6675 ves_icall_System_Environment_GetLogicalDrives (void)
6677 gunichar2 buf [128], *ptr, *dname;
6678 gunichar2 *u16;
6679 guint initial_size = 127, size = 128;
6680 gint ndrives;
6681 MonoArray *result;
6682 MonoString *drivestr;
6683 MonoDomain *domain = mono_domain_get ();
6684 gint len;
6686 MONO_ARCH_SAVE_REGS;
6688 buf [0] = '\0';
6689 ptr = buf;
6691 while (size > initial_size) {
6692 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6693 if (size > initial_size) {
6694 if (ptr != buf)
6695 g_free (ptr);
6696 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6697 initial_size = size;
6698 size++;
6702 /* Count strings */
6703 dname = ptr;
6704 ndrives = 0;
6705 do {
6706 while (*dname++);
6707 ndrives++;
6708 } while (*dname);
6710 dname = ptr;
6711 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6712 ndrives = 0;
6713 do {
6714 len = 0;
6715 u16 = dname;
6716 while (*u16) { u16++; len ++; }
6717 drivestr = mono_string_new_utf16 (domain, dname, len);
6718 mono_array_setref (result, ndrives++, drivestr);
6719 while (*dname++);
6720 } while (*dname);
6722 if (ptr != buf)
6723 g_free (ptr);
6725 return result;
6728 static MonoString *
6729 ves_icall_System_Environment_InternalGetHome (void)
6731 MONO_ARCH_SAVE_REGS;
6733 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6736 static const char *encodings [] = {
6737 (char *) 1,
6738 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6739 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6740 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6741 (char *) 2,
6742 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6743 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6744 "x_unicode_2_0_utf_7",
6745 (char *) 3,
6746 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6747 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6748 (char *) 4,
6749 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6750 "iso_10646_ucs2",
6751 (char *) 5,
6752 "unicodefffe", "utf_16be",
6753 (char *) 6,
6754 "iso_8859_1",
6755 (char *) 0
6759 * Returns the internal codepage, if the value of "int_code_page" is
6760 * 1 at entry, and we can not compute a suitable code page number,
6761 * returns the code page as a string
6763 static MonoString*
6764 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6766 const char *cset;
6767 const char *p;
6768 char *c;
6769 char *codepage = NULL;
6770 int code;
6771 int want_name = *int_code_page;
6772 int i;
6774 *int_code_page = -1;
6775 MONO_ARCH_SAVE_REGS;
6777 g_get_charset (&cset);
6778 c = codepage = strdup (cset);
6779 for (c = codepage; *c; c++){
6780 if (isascii (*c) && isalpha (*c))
6781 *c = tolower (*c);
6782 if (*c == '-')
6783 *c = '_';
6785 /* g_print ("charset: %s\n", cset); */
6787 /* handle some common aliases */
6788 p = encodings [0];
6789 code = 0;
6790 for (i = 0; p != 0; ){
6791 if ((gssize) p < 7){
6792 code = (gssize) p;
6793 p = encodings [++i];
6794 continue;
6796 if (strcmp (p, codepage) == 0){
6797 *int_code_page = code;
6798 break;
6800 p = encodings [++i];
6803 if (strstr (codepage, "utf_8") != NULL)
6804 *int_code_page |= 0x10000000;
6805 free (codepage);
6807 if (want_name && *int_code_page == -1)
6808 return mono_string_new (mono_domain_get (), cset);
6809 else
6810 return NULL;
6813 static MonoBoolean
6814 ves_icall_System_Environment_get_HasShutdownStarted (void)
6816 if (mono_runtime_is_shutting_down ())
6817 return TRUE;
6819 if (mono_domain_is_unloading (mono_domain_get ()))
6820 return TRUE;
6822 return FALSE;
6825 static void
6826 ves_icall_System_Environment_BroadcastSettingChange (void)
6828 #ifdef PLATFORM_WIN32
6829 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6830 #endif
6833 static void
6834 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6835 MonoReflectionMethod *method,
6836 MonoArray *out_args)
6838 MONO_ARCH_SAVE_REGS;
6840 mono_message_init (mono_object_domain (this), this, method, out_args);
6843 static MonoBoolean
6844 ves_icall_IsTransparentProxy (MonoObject *proxy)
6846 MONO_ARCH_SAVE_REGS;
6848 if (!proxy)
6849 return 0;
6851 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6852 return 1;
6854 return 0;
6857 static MonoReflectionMethod *
6858 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6859 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6861 MonoClass *klass;
6862 MonoMethod *method;
6863 MonoMethod **vtable;
6864 MonoMethod *res = NULL;
6866 MONO_CHECK_ARG_NULL (rtype);
6867 MONO_CHECK_ARG_NULL (rmethod);
6869 method = rmethod->method;
6870 klass = mono_class_from_mono_type (rtype->type);
6872 if (MONO_CLASS_IS_INTERFACE (klass))
6873 return NULL;
6875 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6876 return NULL;
6878 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6879 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6880 return rmethod;
6881 else
6882 return NULL;
6885 mono_class_setup_vtable (klass);
6886 vtable = klass->vtable;
6888 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6889 int offs = mono_class_interface_offset (klass, method->klass);
6890 if (offs >= 0)
6891 res = vtable [offs + method->slot];
6892 } else {
6893 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6894 return NULL;
6896 if (method->slot != -1)
6897 res = vtable [method->slot];
6900 if (!res)
6901 return NULL;
6903 return mono_method_get_object (mono_domain_get (), res, NULL);
6906 static void
6907 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6909 MonoClass *klass;
6910 MonoVTable* vtable;
6912 MONO_ARCH_SAVE_REGS;
6914 klass = mono_class_from_mono_type (type->type);
6915 vtable = mono_class_vtable (mono_domain_get (), klass);
6917 if (enable) vtable->remote = 1;
6918 else vtable->remote = 0;
6921 static MonoObject *
6922 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6924 MonoClass *klass;
6925 MonoDomain *domain;
6927 MONO_ARCH_SAVE_REGS;
6929 domain = mono_object_domain (type);
6930 klass = mono_class_from_mono_type (type->type);
6932 if (klass->rank >= 1) {
6933 g_assert (klass->rank == 1);
6934 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6935 } else {
6936 /* Bypass remoting object creation check */
6937 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6941 static MonoString *
6942 ves_icall_System_IO_get_temp_path (void)
6944 MONO_ARCH_SAVE_REGS;
6946 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6949 #ifndef PLATFORM_NO_DRIVEINFO
6950 static MonoBoolean
6951 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6952 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6953 gint32 *error)
6955 gboolean result;
6956 ULARGE_INTEGER wapi_free_bytes_avail;
6957 ULARGE_INTEGER wapi_total_number_of_bytes;
6958 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6960 MONO_ARCH_SAVE_REGS;
6962 *error = ERROR_SUCCESS;
6963 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6964 &wapi_total_number_of_free_bytes);
6966 if (result) {
6967 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6968 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6969 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6970 } else {
6971 *free_bytes_avail = 0;
6972 *total_number_of_bytes = 0;
6973 *total_number_of_free_bytes = 0;
6974 *error = GetLastError ();
6977 return result;
6980 static guint32
6981 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6983 MONO_ARCH_SAVE_REGS;
6985 return GetDriveType (mono_string_chars (root_path_name));
6987 #endif
6989 static gpointer
6990 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6992 MONO_ARCH_SAVE_REGS;
6994 return mono_compile_method (method);
6997 static MonoString *
6998 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7000 MonoString *mcpath;
7001 gchar *path;
7003 MONO_ARCH_SAVE_REGS;
7005 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7007 #if defined (PLATFORM_WIN32)
7008 /* Avoid mixing '/' and '\\' */
7010 gint i;
7011 for (i = strlen (path) - 1; i >= 0; i--)
7012 if (path [i] == '/')
7013 path [i] = '\\';
7015 #endif
7016 mcpath = mono_string_new (mono_domain_get (), path);
7017 g_free (path);
7019 return mcpath;
7022 static MonoString *
7023 get_bundled_machine_config (void)
7025 const gchar *machine_config;
7027 MONO_ARCH_SAVE_REGS;
7029 machine_config = mono_get_machine_config ();
7031 if (!machine_config)
7032 return NULL;
7034 return mono_string_new (mono_domain_get (), machine_config);
7037 static MonoString *
7038 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7040 MonoString *ipath;
7041 gchar *path;
7043 MONO_ARCH_SAVE_REGS;
7045 path = g_path_get_dirname (mono_get_config_dir ());
7047 #if defined (PLATFORM_WIN32)
7048 /* Avoid mixing '/' and '\\' */
7050 gint i;
7051 for (i = strlen (path) - 1; i >= 0; i--)
7052 if (path [i] == '/')
7053 path [i] = '\\';
7055 #endif
7056 ipath = mono_string_new (mono_domain_get (), path);
7057 g_free (path);
7059 return ipath;
7062 static MonoBoolean
7063 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7065 return mono_debug_using_mono_debugger ();
7068 static void
7069 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7071 #if defined (PLATFORM_WIN32)
7072 OutputDebugString (mono_string_chars (message));
7073 #else
7074 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7075 #endif
7078 /* Only used for value types */
7079 static MonoObject *
7080 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7082 MonoClass *klass;
7083 MonoDomain *domain;
7085 MONO_ARCH_SAVE_REGS;
7087 domain = mono_object_domain (type);
7088 klass = mono_class_from_mono_type (type->type);
7090 if (mono_class_is_nullable (klass))
7091 /* No arguments -> null */
7092 return NULL;
7094 return mono_object_new (domain, klass);
7097 static MonoReflectionMethod *
7098 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7100 MonoClass *klass, *parent;
7101 MonoMethod *method = m->method;
7102 MonoMethod *result = NULL;
7104 MONO_ARCH_SAVE_REGS;
7106 if (method->klass == NULL)
7107 return m;
7109 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7110 MONO_CLASS_IS_INTERFACE (method->klass) ||
7111 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7112 return m;
7114 klass = method->klass;
7115 if (klass->generic_class)
7116 klass = klass->generic_class->container_class;
7118 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7119 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7120 mono_class_setup_vtable (parent);
7121 if (parent->vtable_size <= method->slot)
7122 break;
7123 klass = parent;
7126 if (klass == method->klass)
7127 return m;
7129 result = klass->vtable [method->slot];
7130 if (result == NULL) {
7131 /* It is an abstract method */
7132 gpointer iter = NULL;
7133 while ((result = mono_class_get_methods (klass, &iter)))
7134 if (result->slot == method->slot)
7135 break;
7138 if (result == NULL)
7139 return m;
7141 return mono_method_get_object (mono_domain_get (), result, NULL);
7144 static MonoString*
7145 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7147 MonoMethod *method = m->method;
7149 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7150 return m->name;
7153 static void
7154 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7156 MONO_ARCH_SAVE_REGS;
7158 iter->sig = *(MonoMethodSignature**)argsp;
7160 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7161 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7163 iter->next_arg = 0;
7164 /* FIXME: it's not documented what start is exactly... */
7165 if (start) {
7166 iter->args = start;
7167 } else {
7168 guint32 i, arg_size;
7169 gint32 align;
7170 iter->args = argsp + sizeof (gpointer);
7171 #ifndef MONO_ARCH_REGPARMS
7172 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7173 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7174 iter->args = (char*)iter->args + arg_size;
7176 #endif
7178 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7180 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7183 static MonoTypedRef
7184 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7186 guint32 i, arg_size;
7187 gint32 align;
7188 MonoTypedRef res;
7189 MONO_ARCH_SAVE_REGS;
7191 i = iter->sig->sentinelpos + iter->next_arg;
7193 g_assert (i < iter->sig->param_count);
7195 res.type = iter->sig->params [i];
7196 res.klass = mono_class_from_mono_type (res.type);
7197 res.value = iter->args;
7198 arg_size = mono_type_stack_size (res.type, &align);
7199 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7200 if (arg_size <= sizeof (gpointer)) {
7201 int dummy;
7202 int padding = arg_size - mono_type_size (res.type, &dummy);
7203 res.value = (guint8*)res.value + padding;
7205 #endif
7206 iter->args = (char*)iter->args + arg_size;
7207 iter->next_arg++;
7209 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7211 return res;
7214 static MonoTypedRef
7215 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7217 guint32 i, arg_size;
7218 gint32 align;
7219 MonoTypedRef res;
7220 MONO_ARCH_SAVE_REGS;
7222 i = iter->sig->sentinelpos + iter->next_arg;
7224 g_assert (i < iter->sig->param_count);
7226 while (i < iter->sig->param_count) {
7227 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7228 continue;
7229 res.type = iter->sig->params [i];
7230 res.klass = mono_class_from_mono_type (res.type);
7231 /* FIXME: endianess issue... */
7232 res.value = iter->args;
7233 arg_size = mono_type_stack_size (res.type, &align);
7234 iter->args = (char*)iter->args + arg_size;
7235 iter->next_arg++;
7236 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7237 return res;
7239 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7241 res.type = NULL;
7242 res.value = NULL;
7243 res.klass = NULL;
7244 return res;
7247 static MonoType*
7248 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7250 gint i;
7251 MONO_ARCH_SAVE_REGS;
7253 i = iter->sig->sentinelpos + iter->next_arg;
7255 g_assert (i < iter->sig->param_count);
7257 return iter->sig->params [i];
7260 static MonoObject*
7261 mono_TypedReference_ToObject (MonoTypedRef tref)
7263 MONO_ARCH_SAVE_REGS;
7265 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7266 MonoObject** objp = tref.value;
7267 return *objp;
7270 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7273 static MonoObject*
7274 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7276 MONO_ARCH_SAVE_REGS;
7278 if (MONO_TYPE_IS_REFERENCE (type)) {
7279 MonoObject** objp = value;
7280 return *objp;
7283 return mono_value_box (mono_domain_get (), klass, value);
7286 static void
7287 prelink_method (MonoMethod *method)
7289 const char *exc_class, *exc_arg;
7290 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7291 return;
7292 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7293 if (exc_class) {
7294 mono_raise_exception(
7295 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7297 /* create the wrapper, too? */
7300 static void
7301 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7303 MONO_ARCH_SAVE_REGS;
7304 prelink_method (method->method);
7307 static void
7308 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7310 MonoClass *klass = mono_class_from_mono_type (type->type);
7311 MonoMethod* m;
7312 gpointer iter = NULL;
7313 MONO_ARCH_SAVE_REGS;
7315 while ((m = mono_class_get_methods (klass, &iter)))
7316 prelink_method (m);
7319 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7320 static void
7321 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7322 gint32 const **exponents,
7323 gunichar2 const **digitLowerTable,
7324 gunichar2 const **digitUpperTable,
7325 gint64 const **tenPowersList,
7326 gint32 const **decHexDigits)
7328 *mantissas = Formatter_MantissaBitsTable;
7329 *exponents = Formatter_TensExponentTable;
7330 *digitLowerTable = Formatter_DigitLowerTable;
7331 *digitUpperTable = Formatter_DigitUpperTable;
7332 *tenPowersList = Formatter_TenPowersList;
7333 *decHexDigits = Formatter_DecHexDigits;
7336 /* These parameters are "readonly" in corlib/System/Char.cs */
7337 static void
7338 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7339 guint8 const **numeric_data,
7340 gdouble const **numeric_data_values,
7341 guint16 const **to_lower_data_low,
7342 guint16 const **to_lower_data_high,
7343 guint16 const **to_upper_data_low,
7344 guint16 const **to_upper_data_high)
7346 *category_data = CategoryData;
7347 *numeric_data = NumericData;
7348 *numeric_data_values = NumericDataValues;
7349 *to_lower_data_low = ToLowerDataLow;
7350 *to_lower_data_high = ToLowerDataHigh;
7351 *to_upper_data_low = ToUpperDataLow;
7352 *to_upper_data_high = ToUpperDataHigh;
7355 static gint32
7356 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7358 return method->method->token;
7362 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7363 * and avoid useless allocations.
7365 static MonoArray*
7366 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7368 MonoArray *res;
7369 int i, count = 0;
7370 for (i = 0; i < type->num_mods; ++i) {
7371 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7372 count++;
7374 if (!count)
7375 return NULL;
7376 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7377 count = 0;
7378 for (i = 0; i < type->num_mods; ++i) {
7379 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7380 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7381 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7382 count++;
7385 return res;
7388 static MonoArray*
7389 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7391 MonoType *type = param->ClassImpl->type;
7392 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7393 MonoImage *image = method->method->klass->image;
7394 int pos = param->PositionImpl;
7395 MonoMethodSignature *sig = mono_method_signature (method->method);
7396 if (pos == -1)
7397 type = sig->ret;
7398 else
7399 type = sig->params [pos];
7401 return type_array_from_modifiers (image, type, optional);
7404 static MonoType*
7405 get_property_type (MonoProperty *prop)
7407 MonoMethodSignature *sig;
7408 if (prop->get) {
7409 sig = mono_method_signature (prop->get);
7410 return sig->ret;
7411 } else if (prop->set) {
7412 sig = mono_method_signature (prop->set);
7413 return sig->params [sig->param_count - 1];
7415 return NULL;
7418 static MonoArray*
7419 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7421 MonoType *type = get_property_type (property->property);
7422 MonoImage *image = property->klass->image;
7424 if (!type)
7425 return NULL;
7426 return type_array_from_modifiers (image, type, optional);
7429 static MonoBoolean
7430 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7432 MonoCustomAttrInfo *cinfo;
7433 gboolean found;
7435 cinfo = mono_reflection_get_custom_attrs_info (obj);
7436 if (!cinfo)
7437 return FALSE;
7438 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7439 if (!cinfo->cached)
7440 mono_custom_attrs_free (cinfo);
7441 return found;
7444 static MonoArray*
7445 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7447 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7449 if (mono_loader_get_last_error ()) {
7450 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7451 g_assert_not_reached ();
7452 } else {
7453 return res;
7457 static MonoBoolean
7458 GCHandle_CheckCurrentDomain (guint32 gchandle)
7460 return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
7463 static MonoString*
7464 ves_icall_Mono_Runtime_GetDisplayName (void)
7466 static const char display_name_str [] = "Mono " VERSION;
7467 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7468 return display_name;
7471 static MonoString*
7472 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7474 MonoString *message;
7475 guint32 ret;
7476 gunichar2 buf[256];
7478 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7479 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7480 buf, 255, NULL);
7481 if (ret == 0) {
7482 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7483 } else {
7484 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7487 return message;
7490 const static guchar
7491 dbase64 [] = {
7492 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7493 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7494 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7495 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7496 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7497 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7498 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7499 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7502 static MonoArray *
7503 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7505 gint ignored;
7506 gint i;
7507 gunichar2 c;
7508 gunichar2 last, prev_last, prev2_last;
7509 gint olength;
7510 MonoArray *result;
7511 guchar *res_ptr;
7512 gint a [4], b [4];
7513 MonoException *exc;
7515 ignored = 0;
7516 last = prev_last = 0, prev2_last = 0;
7517 for (i = 0; i < ilength; i++) {
7518 c = start [i];
7519 if (c >= sizeof (dbase64)) {
7520 exc = mono_exception_from_name_msg (mono_get_corlib (),
7521 "System", "FormatException",
7522 "Invalid character found.");
7523 mono_raise_exception (exc);
7524 } else if (isspace (c)) {
7525 ignored++;
7526 } else {
7527 prev2_last = prev_last;
7528 prev_last = last;
7529 last = c;
7533 olength = ilength - ignored;
7535 if (allowWhitespaceOnly && olength == 0) {
7536 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7539 if ((olength & 3) != 0 || olength <= 0) {
7540 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7541 "FormatException", "Invalid length.");
7542 mono_raise_exception (exc);
7545 if (prev2_last == '=') {
7546 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7547 mono_raise_exception (exc);
7550 olength = (olength * 3) / 4;
7551 if (last == '=')
7552 olength--;
7554 if (prev_last == '=')
7555 olength--;
7557 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7558 res_ptr = mono_array_addr (result, guchar, 0);
7559 for (i = 0; i < ilength; ) {
7560 int k;
7562 for (k = 0; k < 4 && i < ilength;) {
7563 c = start [i++];
7564 if (isspace (c))
7565 continue;
7567 a [k] = (guchar) c;
7568 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7569 exc = mono_exception_from_name_msg (mono_get_corlib (),
7570 "System", "FormatException",
7571 "Invalid character found.");
7572 mono_raise_exception (exc);
7574 k++;
7577 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7578 if (a [2] != '=')
7579 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7580 if (a [3] != '=')
7581 *res_ptr++ = (b [2] << 6) | b [3];
7583 while (i < ilength && isspace (start [i]))
7584 i++;
7587 return result;
7590 static MonoArray *
7591 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7593 MONO_ARCH_SAVE_REGS;
7595 return base64_to_byte_array (mono_string_chars (str),
7596 mono_string_length (str), allowWhitespaceOnly);
7599 static MonoArray *
7600 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7602 MONO_ARCH_SAVE_REGS;
7604 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7605 length, FALSE);
7608 #define ICALL_TYPE(id,name,first)
7609 #define ICALL(id,name,func) Icall_ ## id,
7611 enum {
7612 #include "metadata/icall-def.h"
7613 Icall_last
7616 #undef ICALL_TYPE
7617 #undef ICALL
7618 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7619 #define ICALL(id,name,func)
7620 enum {
7621 #include "metadata/icall-def.h"
7622 Icall_type_num
7625 #undef ICALL_TYPE
7626 #undef ICALL
7627 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7628 #define ICALL(id,name,func)
7629 typedef struct {
7630 guint16 first_icall;
7631 } IcallTypeDesc;
7633 static const IcallTypeDesc
7634 icall_type_descs [] = {
7635 #include "metadata/icall-def.h"
7636 {Icall_last}
7639 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7641 #undef ICALL_TYPE
7642 #define ICALL_TYPE(id,name,first)
7643 #undef ICALL
7645 #ifdef HAVE_ARRAY_ELEM_INIT
7646 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7647 #define MSGSTRFIELD1(line) str##line
7649 static const struct msgstrtn_t {
7650 #define ICALL(id,name,func)
7651 #undef ICALL_TYPE
7652 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7653 #include "metadata/icall-def.h"
7654 #undef ICALL_TYPE
7655 } icall_type_names_str = {
7656 #define ICALL_TYPE(id,name,first) (name),
7657 #include "metadata/icall-def.h"
7658 #undef ICALL_TYPE
7660 static const guint16 icall_type_names_idx [] = {
7661 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7662 #include "metadata/icall-def.h"
7663 #undef ICALL_TYPE
7665 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7667 static const struct msgstr_t {
7668 #undef ICALL
7669 #define ICALL_TYPE(id,name,first)
7670 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7671 #include "metadata/icall-def.h"
7672 #undef ICALL
7673 } icall_names_str = {
7674 #define ICALL(id,name,func) (name),
7675 #include "metadata/icall-def.h"
7676 #undef ICALL
7678 static const guint16 icall_names_idx [] = {
7679 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7680 #include "metadata/icall-def.h"
7681 #undef ICALL
7683 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7685 #else
7687 #undef ICALL_TYPE
7688 #undef ICALL
7689 #define ICALL_TYPE(id,name,first) name,
7690 #define ICALL(id,name,func)
7691 static const char* const
7692 icall_type_names [] = {
7693 #include "metadata/icall-def.h"
7694 NULL
7697 #define icall_type_name_get(id) (icall_type_names [(id)])
7699 #undef ICALL_TYPE
7700 #undef ICALL
7701 #define ICALL_TYPE(id,name,first)
7702 #define ICALL(id,name,func) name,
7703 static const char* const
7704 icall_names [] = {
7705 #include "metadata/icall-def.h"
7706 NULL
7708 #define icall_name_get(id) icall_names [(id)]
7710 #endif /* !HAVE_ARRAY_ELEM_INIT */
7712 #undef ICALL_TYPE
7713 #undef ICALL
7714 #define ICALL_TYPE(id,name,first)
7715 #define ICALL(id,name,func) func,
7716 static const gconstpointer
7717 icall_functions [] = {
7718 #include "metadata/icall-def.h"
7719 NULL
7722 static GHashTable *icall_hash = NULL;
7723 static GHashTable *jit_icall_hash_name = NULL;
7724 static GHashTable *jit_icall_hash_addr = NULL;
7726 void
7727 mono_icall_init (void)
7729 int i = 0;
7731 /* check that tables are sorted: disable in release */
7732 if (TRUE) {
7733 int j;
7734 const char *prev_class = NULL;
7735 const char *prev_method;
7737 for (i = 0; i < Icall_type_num; ++i) {
7738 const IcallTypeDesc *desc;
7739 int num_icalls;
7740 prev_method = NULL;
7741 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7742 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7743 prev_class = icall_type_name_get (i);
7744 desc = &icall_type_descs [i];
7745 num_icalls = icall_desc_num_icalls (desc);
7746 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7747 for (j = 0; j < num_icalls; ++j) {
7748 const char *methodn = icall_name_get (desc->first_icall + j);
7749 if (prev_method && strcmp (prev_method, methodn) >= 0)
7750 g_print ("method %s should come before method %s\n", methodn, prev_method);
7751 prev_method = methodn;
7756 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7759 void
7760 mono_icall_cleanup (void)
7762 g_hash_table_destroy (icall_hash);
7763 g_hash_table_destroy (jit_icall_hash_name);
7764 g_hash_table_destroy (jit_icall_hash_addr);
7767 void
7768 mono_add_internal_call (const char *name, gconstpointer method)
7770 mono_loader_lock ();
7772 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7774 mono_loader_unlock ();
7777 #ifdef HAVE_ARRAY_ELEM_INIT
7778 static int
7779 compare_method_imap (const void *key, const void *elem)
7781 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7782 return strcmp (key, method_name);
7785 static gpointer
7786 find_method_icall (const IcallTypeDesc *imap, const char *name)
7788 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7789 if (!nameslot)
7790 return NULL;
7791 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7794 static int
7795 compare_class_imap (const void *key, const void *elem)
7797 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7798 return strcmp (key, class_name);
7801 static const IcallTypeDesc*
7802 find_class_icalls (const char *name)
7804 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7805 if (!nameslot)
7806 return NULL;
7807 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7810 #else
7811 static int
7812 compare_method_imap (const void *key, const void *elem)
7814 const char** method_name = (const char**)elem;
7815 return strcmp (key, *method_name);
7818 static gpointer
7819 find_method_icall (const IcallTypeDesc *imap, const char *name)
7821 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7822 if (!nameslot)
7823 return NULL;
7824 return (gpointer)icall_functions [(nameslot - icall_names)];
7827 static int
7828 compare_class_imap (const void *key, const void *elem)
7830 const char** class_name = (const char**)elem;
7831 return strcmp (key, *class_name);
7834 static const IcallTypeDesc*
7835 find_class_icalls (const char *name)
7837 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7838 if (!nameslot)
7839 return NULL;
7840 return &icall_type_descs [nameslot - icall_type_names];
7843 #endif
7846 * we should probably export this as an helper (handle nested types).
7847 * Returns the number of chars written in buf.
7849 static int
7850 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7852 int nspacelen, cnamelen;
7853 nspacelen = strlen (klass->name_space);
7854 cnamelen = strlen (klass->name);
7855 if (nspacelen + cnamelen + 2 > bufsize)
7856 return 0;
7857 if (nspacelen) {
7858 memcpy (buf, klass->name_space, nspacelen);
7859 buf [nspacelen ++] = '.';
7861 memcpy (buf + nspacelen, klass->name, cnamelen);
7862 buf [nspacelen + cnamelen] = 0;
7863 return nspacelen + cnamelen;
7866 gpointer
7867 mono_lookup_internal_call (MonoMethod *method)
7869 char *sigstart;
7870 char *tmpsig;
7871 char mname [2048];
7872 int typelen = 0, mlen, siglen;
7873 gpointer res;
7874 const IcallTypeDesc *imap;
7876 g_assert (method != NULL);
7878 if (method->is_inflated)
7879 method = ((MonoMethodInflated *) method)->declaring;
7881 if (method->klass->nested_in) {
7882 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7883 if (!pos)
7884 return NULL;
7886 mname [pos++] = '/';
7887 mname [pos] = 0;
7889 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7890 if (!typelen)
7891 return NULL;
7893 typelen += pos;
7894 } else {
7895 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7896 if (!typelen)
7897 return NULL;
7900 imap = find_class_icalls (mname);
7902 mname [typelen] = ':';
7903 mname [typelen + 1] = ':';
7905 mlen = strlen (method->name);
7906 memcpy (mname + typelen + 2, method->name, mlen);
7907 sigstart = mname + typelen + 2 + mlen;
7908 *sigstart = 0;
7910 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7911 siglen = strlen (tmpsig);
7912 if (typelen + mlen + siglen + 6 > sizeof (mname))
7913 return NULL;
7914 sigstart [0] = '(';
7915 memcpy (sigstart + 1, tmpsig, siglen);
7916 sigstart [siglen + 1] = ')';
7917 sigstart [siglen + 2] = 0;
7918 g_free (tmpsig);
7920 mono_loader_lock ();
7922 res = g_hash_table_lookup (icall_hash, mname);
7923 if (res) {
7924 mono_loader_unlock ();
7925 return res;
7927 /* try without signature */
7928 *sigstart = 0;
7929 res = g_hash_table_lookup (icall_hash, mname);
7930 if (res) {
7931 mono_loader_unlock ();
7932 return res;
7935 /* it wasn't found in the static call tables */
7936 if (!imap) {
7937 mono_loader_unlock ();
7938 return NULL;
7940 res = find_method_icall (imap, sigstart - mlen);
7941 if (res) {
7942 mono_loader_unlock ();
7943 return res;
7945 /* try _with_ signature */
7946 *sigstart = '(';
7947 res = find_method_icall (imap, sigstart - mlen);
7948 if (res) {
7949 mono_loader_unlock ();
7950 return res;
7953 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7954 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7955 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7956 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7957 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");
7958 g_print ("If you see other errors or faults after this message they are probably related\n");
7959 g_print ("and you need to fix your mono install first.\n");
7961 mono_loader_unlock ();
7963 return NULL;
7966 static MonoType*
7967 type_from_typename (char *typename)
7969 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7971 if (!strcmp (typename, "int"))
7972 klass = mono_defaults.int_class;
7973 else if (!strcmp (typename, "ptr"))
7974 klass = mono_defaults.int_class;
7975 else if (!strcmp (typename, "void"))
7976 klass = mono_defaults.void_class;
7977 else if (!strcmp (typename, "int32"))
7978 klass = mono_defaults.int32_class;
7979 else if (!strcmp (typename, "uint32"))
7980 klass = mono_defaults.uint32_class;
7981 else if (!strcmp (typename, "int8"))
7982 klass = mono_defaults.sbyte_class;
7983 else if (!strcmp (typename, "uint8"))
7984 klass = mono_defaults.byte_class;
7985 else if (!strcmp (typename, "int16"))
7986 klass = mono_defaults.int16_class;
7987 else if (!strcmp (typename, "uint16"))
7988 klass = mono_defaults.uint16_class;
7989 else if (!strcmp (typename, "long"))
7990 klass = mono_defaults.int64_class;
7991 else if (!strcmp (typename, "ulong"))
7992 klass = mono_defaults.uint64_class;
7993 else if (!strcmp (typename, "float"))
7994 klass = mono_defaults.single_class;
7995 else if (!strcmp (typename, "double"))
7996 klass = mono_defaults.double_class;
7997 else if (!strcmp (typename, "object"))
7998 klass = mono_defaults.object_class;
7999 else if (!strcmp (typename, "obj"))
8000 klass = mono_defaults.object_class;
8001 else if (!strcmp (typename, "string"))
8002 klass = mono_defaults.string_class;
8003 else if (!strcmp (typename, "bool"))
8004 klass = mono_defaults.boolean_class;
8005 else if (!strcmp (typename, "boolean"))
8006 klass = mono_defaults.boolean_class;
8007 else {
8008 g_error ("%s", typename);
8009 g_assert_not_reached ();
8011 return &klass->byval_arg;
8014 MonoMethodSignature*
8015 mono_create_icall_signature (const char *sigstr)
8017 gchar **parts;
8018 int i, len;
8019 gchar **tmp;
8020 MonoMethodSignature *res;
8022 mono_loader_lock ();
8023 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8024 if (res) {
8025 mono_loader_unlock ();
8026 return res;
8029 parts = g_strsplit (sigstr, " ", 256);
8031 tmp = parts;
8032 len = 0;
8033 while (*tmp) {
8034 len ++;
8035 tmp ++;
8038 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8039 res->pinvoke = 1;
8041 #ifdef PLATFORM_WIN32
8043 * Under windows, the default pinvoke calling convention is STDCALL but
8044 * we need CDECL.
8046 res->call_convention = MONO_CALL_C;
8047 #endif
8049 res->ret = type_from_typename (parts [0]);
8050 for (i = 1; i < len; ++i) {
8051 res->params [i - 1] = type_from_typename (parts [i]);
8054 g_strfreev (parts);
8056 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8058 mono_loader_unlock ();
8060 return res;
8063 MonoJitICallInfo *
8064 mono_find_jit_icall_by_name (const char *name)
8066 MonoJitICallInfo *info;
8067 g_assert (jit_icall_hash_name);
8069 mono_loader_lock ();
8070 info = g_hash_table_lookup (jit_icall_hash_name, name);
8071 mono_loader_unlock ();
8072 return info;
8075 MonoJitICallInfo *
8076 mono_find_jit_icall_by_addr (gconstpointer addr)
8078 MonoJitICallInfo *info;
8079 g_assert (jit_icall_hash_addr);
8081 mono_loader_lock ();
8082 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8083 mono_loader_unlock ();
8085 return info;
8089 * mono_get_jit_icall_info:
8091 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8092 * caller should access it while holding the loader lock.
8094 GHashTable*
8095 mono_get_jit_icall_info (void)
8097 return jit_icall_hash_name;
8100 void
8101 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8103 mono_loader_lock ();
8104 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8105 mono_loader_unlock ();
8108 MonoJitICallInfo *
8109 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8111 MonoJitICallInfo *info;
8113 g_assert (func);
8114 g_assert (name);
8116 mono_loader_lock ();
8118 if (!jit_icall_hash_name) {
8119 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8120 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8123 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8124 g_warning ("jit icall already defined \"%s\"\n", name);
8125 g_assert_not_reached ();
8128 info = g_new0 (MonoJitICallInfo, 1);
8130 info->name = name;
8131 info->func = func;
8132 info->sig = sig;
8134 if (is_save) {
8135 info->wrapper = func;
8136 } else {
8137 info->wrapper = NULL;
8140 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8141 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8143 mono_loader_unlock ();
8144 return info;