2008-12-11 Gonzalo Paniagua Javier <gonzalo@novell.com>
[mono.git] / mono / metadata / icall.c
blobf5c7c597e7cb5156951d13e2eb45610f8a9602c6
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 * (C) 2001 Ximian, Inc.
12 #include <config.h>
13 #include <glib.h>
14 #include <stdarg.h>
15 #include <string.h>
16 #include <ctype.h>
17 #ifdef HAVE_SYS_TIME_H
18 #include <sys/time.h>
19 #endif
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #if defined (PLATFORM_WIN32)
24 #include <stdlib.h>
25 #endif
27 #include "mono/utils/mono-membar.h"
28 #include <mono/metadata/object.h>
29 #include <mono/metadata/threads.h>
30 #include <mono/metadata/threads-types.h>
31 #include <mono/metadata/threadpool.h>
32 #include <mono/metadata/monitor.h>
33 #include <mono/metadata/reflection.h>
34 #include <mono/metadata/assembly.h>
35 #include <mono/metadata/tabledefs.h>
36 #include <mono/metadata/exception.h>
37 #include <mono/metadata/file-io.h>
38 #include <mono/metadata/console-io.h>
39 #include <mono/metadata/socket-io.h>
40 #include <mono/metadata/mono-endian.h>
41 #include <mono/metadata/tokentype.h>
42 #include <mono/metadata/domain-internals.h>
43 #include <mono/metadata/metadata-internals.h>
44 #include <mono/metadata/class-internals.h>
45 #include <mono/metadata/marshal.h>
46 #include <mono/metadata/gc-internal.h>
47 #include <mono/metadata/mono-gc.h>
48 #include <mono/metadata/rand.h>
49 #include <mono/metadata/sysmath.h>
50 #include <mono/metadata/string-icalls.h>
51 #include <mono/metadata/debug-helpers.h>
52 #include <mono/metadata/process.h>
53 #include <mono/metadata/environment.h>
54 #include <mono/metadata/profiler-private.h>
55 #include <mono/metadata/locales.h>
56 #include <mono/metadata/filewatcher.h>
57 #include <mono/metadata/char-conversions.h>
58 #include <mono/metadata/security.h>
59 #include <mono/metadata/mono-config.h>
60 #include <mono/metadata/cil-coff.h>
61 #include <mono/metadata/number-formatter.h>
62 #include <mono/metadata/security-manager.h>
63 #include <mono/metadata/security-core-clr.h>
64 #include <mono/metadata/mono-perfcounters.h>
65 #include <mono/metadata/mono-debug.h>
66 #include <mono/io-layer/io-layer.h>
67 #include <mono/utils/strtod.h>
68 #include <mono/utils/monobitset.h>
69 #include <mono/utils/mono-time.h>
70 #include <mono/utils/mono-proclib.h>
72 #if defined (PLATFORM_WIN32)
73 #include <windows.h>
74 #include <shlobj.h>
75 #endif
76 #include "decimal.h"
78 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
80 static MonoArray*
81 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
83 static inline MonoBoolean
84 is_generic_parameter (MonoType *type)
86 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
90 * We expect a pointer to a char, not a string
92 static gboolean
93 mono_double_ParseImpl (char *ptr, double *result)
95 gchar *endptr = NULL;
96 *result = 0.0;
98 MONO_ARCH_SAVE_REGS;
100 #ifdef __arm__
101 if (*ptr)
102 *result = strtod (ptr, &endptr);
103 #else
104 if (*ptr)
105 *result = mono_strtod (ptr, &endptr);
106 #endif
108 if (!*ptr || (endptr && *endptr))
109 return FALSE;
111 return TRUE;
114 static MonoObject *
115 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
117 MonoClass *ac;
118 MonoArray *ao;
119 gint32 esize;
120 gpointer *ea;
122 MONO_ARCH_SAVE_REGS;
124 ao = (MonoArray *)this;
125 ac = (MonoClass *)ao->obj.vtable->klass;
127 esize = mono_array_element_size (ac);
128 ea = (gpointer*)((char*)ao->vector + (pos * esize));
130 if (ac->element_class->valuetype)
131 return mono_value_box (this->vtable->domain, ac->element_class, ea);
132 else
133 return *ea;
136 static MonoObject *
137 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
139 MonoClass *ac, *ic;
140 MonoArray *ao, *io;
141 gint32 i, pos, *ind;
143 MONO_ARCH_SAVE_REGS;
145 MONO_CHECK_ARG_NULL (idxs);
147 io = (MonoArray *)idxs;
148 ic = (MonoClass *)io->obj.vtable->klass;
150 ao = (MonoArray *)this;
151 ac = (MonoClass *)ao->obj.vtable->klass;
153 g_assert (ic->rank == 1);
154 if (io->bounds != NULL || io->max_length != ac->rank)
155 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
157 ind = (gint32 *)io->vector;
159 if (ao->bounds == NULL) {
160 if (*ind < 0 || *ind >= ao->max_length)
161 mono_raise_exception (mono_get_exception_index_out_of_range ());
163 return ves_icall_System_Array_GetValueImpl (this, *ind);
166 for (i = 0; i < ac->rank; i++)
167 if ((ind [i] < ao->bounds [i].lower_bound) ||
168 (ind [i] >= ao->bounds [i].length + ao->bounds [i].lower_bound))
169 mono_raise_exception (mono_get_exception_index_out_of_range ());
171 pos = ind [0] - ao->bounds [0].lower_bound;
172 for (i = 1; i < ac->rank; i++)
173 pos = pos*ao->bounds [i].length + ind [i] -
174 ao->bounds [i].lower_bound;
176 return ves_icall_System_Array_GetValueImpl (this, pos);
179 static void
180 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
182 MonoClass *ac, *vc, *ec;
183 gint32 esize, vsize;
184 gpointer *ea, *va;
185 int et, vt;
187 guint64 u64 = 0;
188 gint64 i64 = 0;
189 gdouble r64 = 0;
191 MONO_ARCH_SAVE_REGS;
193 if (value)
194 vc = value->vtable->klass;
195 else
196 vc = NULL;
198 ac = this->obj.vtable->klass;
199 ec = ac->element_class;
201 esize = mono_array_element_size (ac);
202 ea = (gpointer*)((char*)this->vector + (pos * esize));
203 va = (gpointer*)((char*)value + sizeof (MonoObject));
205 if (!value) {
206 memset (ea, 0, esize);
207 return;
210 #define NO_WIDENING_CONVERSION G_STMT_START{\
211 mono_raise_exception (mono_get_exception_argument ( \
212 "value", "not a widening conversion")); \
213 }G_STMT_END
215 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
216 if (esize < vsize + (extra)) \
217 mono_raise_exception (mono_get_exception_argument ( \
218 "value", "not a widening conversion")); \
219 }G_STMT_END
221 #define INVALID_CAST G_STMT_START{\
222 mono_raise_exception (mono_get_exception_invalid_cast ()); \
223 }G_STMT_END
225 /* Check element (destination) type. */
226 switch (ec->byval_arg.type) {
227 case MONO_TYPE_STRING:
228 switch (vc->byval_arg.type) {
229 case MONO_TYPE_STRING:
230 break;
231 default:
232 INVALID_CAST;
234 break;
235 case MONO_TYPE_BOOLEAN:
236 switch (vc->byval_arg.type) {
237 case MONO_TYPE_BOOLEAN:
238 break;
239 case MONO_TYPE_CHAR:
240 case MONO_TYPE_U1:
241 case MONO_TYPE_U2:
242 case MONO_TYPE_U4:
243 case MONO_TYPE_U8:
244 case MONO_TYPE_I1:
245 case MONO_TYPE_I2:
246 case MONO_TYPE_I4:
247 case MONO_TYPE_I8:
248 case MONO_TYPE_R4:
249 case MONO_TYPE_R8:
250 NO_WIDENING_CONVERSION;
251 default:
252 INVALID_CAST;
254 break;
257 if (!ec->valuetype) {
258 if (!mono_object_isinst (value, ec))
259 INVALID_CAST;
260 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
261 return;
264 if (mono_object_isinst (value, ec)) {
265 if (ec->has_references)
266 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
267 else
268 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
269 return;
272 if (!vc->valuetype)
273 INVALID_CAST;
275 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
277 et = ec->byval_arg.type;
278 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
279 et = ec->byval_arg.data.klass->enum_basetype->type;
281 vt = vc->byval_arg.type;
282 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
283 vt = vc->byval_arg.data.klass->enum_basetype->type;
285 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
286 switch (vt) { \
287 case MONO_TYPE_U1: \
288 case MONO_TYPE_U2: \
289 case MONO_TYPE_U4: \
290 case MONO_TYPE_U8: \
291 case MONO_TYPE_CHAR: \
292 CHECK_WIDENING_CONVERSION(0); \
293 *(etype *) ea = (etype) u64; \
294 return; \
295 /* You can't assign a signed value to an unsigned array. */ \
296 case MONO_TYPE_I1: \
297 case MONO_TYPE_I2: \
298 case MONO_TYPE_I4: \
299 case MONO_TYPE_I8: \
300 /* You can't assign a floating point number to an integer array. */ \
301 case MONO_TYPE_R4: \
302 case MONO_TYPE_R8: \
303 NO_WIDENING_CONVERSION; \
305 }G_STMT_END
307 #define ASSIGN_SIGNED(etype) G_STMT_START{\
308 switch (vt) { \
309 case MONO_TYPE_I1: \
310 case MONO_TYPE_I2: \
311 case MONO_TYPE_I4: \
312 case MONO_TYPE_I8: \
313 CHECK_WIDENING_CONVERSION(0); \
314 *(etype *) ea = (etype) i64; \
315 return; \
316 /* You can assign an unsigned value to a signed array if the array's */ \
317 /* element size is larger than the value size. */ \
318 case MONO_TYPE_U1: \
319 case MONO_TYPE_U2: \
320 case MONO_TYPE_U4: \
321 case MONO_TYPE_U8: \
322 case MONO_TYPE_CHAR: \
323 CHECK_WIDENING_CONVERSION(1); \
324 *(etype *) ea = (etype) u64; \
325 return; \
326 /* You can't assign a floating point number to an integer array. */ \
327 case MONO_TYPE_R4: \
328 case MONO_TYPE_R8: \
329 NO_WIDENING_CONVERSION; \
331 }G_STMT_END
333 #define ASSIGN_REAL(etype) G_STMT_START{\
334 switch (vt) { \
335 case MONO_TYPE_R4: \
336 case MONO_TYPE_R8: \
337 CHECK_WIDENING_CONVERSION(0); \
338 *(etype *) ea = (etype) r64; \
339 return; \
340 /* All integer values fit into a floating point array, so we don't */ \
341 /* need to CHECK_WIDENING_CONVERSION here. */ \
342 case MONO_TYPE_I1: \
343 case MONO_TYPE_I2: \
344 case MONO_TYPE_I4: \
345 case MONO_TYPE_I8: \
346 *(etype *) ea = (etype) i64; \
347 return; \
348 case MONO_TYPE_U1: \
349 case MONO_TYPE_U2: \
350 case MONO_TYPE_U4: \
351 case MONO_TYPE_U8: \
352 case MONO_TYPE_CHAR: \
353 *(etype *) ea = (etype) u64; \
354 return; \
356 }G_STMT_END
358 switch (vt) {
359 case MONO_TYPE_U1:
360 u64 = *(guint8 *) va;
361 break;
362 case MONO_TYPE_U2:
363 u64 = *(guint16 *) va;
364 break;
365 case MONO_TYPE_U4:
366 u64 = *(guint32 *) va;
367 break;
368 case MONO_TYPE_U8:
369 u64 = *(guint64 *) va;
370 break;
371 case MONO_TYPE_I1:
372 i64 = *(gint8 *) va;
373 break;
374 case MONO_TYPE_I2:
375 i64 = *(gint16 *) va;
376 break;
377 case MONO_TYPE_I4:
378 i64 = *(gint32 *) va;
379 break;
380 case MONO_TYPE_I8:
381 i64 = *(gint64 *) va;
382 break;
383 case MONO_TYPE_R4:
384 r64 = *(gfloat *) va;
385 break;
386 case MONO_TYPE_R8:
387 r64 = *(gdouble *) va;
388 break;
389 case MONO_TYPE_CHAR:
390 u64 = *(guint16 *) va;
391 break;
392 case MONO_TYPE_BOOLEAN:
393 /* Boolean is only compatible with itself. */
394 switch (et) {
395 case MONO_TYPE_CHAR:
396 case MONO_TYPE_U1:
397 case MONO_TYPE_U2:
398 case MONO_TYPE_U4:
399 case MONO_TYPE_U8:
400 case MONO_TYPE_I1:
401 case MONO_TYPE_I2:
402 case MONO_TYPE_I4:
403 case MONO_TYPE_I8:
404 case MONO_TYPE_R4:
405 case MONO_TYPE_R8:
406 NO_WIDENING_CONVERSION;
407 default:
408 INVALID_CAST;
410 break;
413 /* If we can't do a direct copy, let's try a widening conversion. */
414 switch (et) {
415 case MONO_TYPE_CHAR:
416 ASSIGN_UNSIGNED (guint16);
417 case MONO_TYPE_U1:
418 ASSIGN_UNSIGNED (guint8);
419 case MONO_TYPE_U2:
420 ASSIGN_UNSIGNED (guint16);
421 case MONO_TYPE_U4:
422 ASSIGN_UNSIGNED (guint32);
423 case MONO_TYPE_U8:
424 ASSIGN_UNSIGNED (guint64);
425 case MONO_TYPE_I1:
426 ASSIGN_SIGNED (gint8);
427 case MONO_TYPE_I2:
428 ASSIGN_SIGNED (gint16);
429 case MONO_TYPE_I4:
430 ASSIGN_SIGNED (gint32);
431 case MONO_TYPE_I8:
432 ASSIGN_SIGNED (gint64);
433 case MONO_TYPE_R4:
434 ASSIGN_REAL (gfloat);
435 case MONO_TYPE_R8:
436 ASSIGN_REAL (gdouble);
439 INVALID_CAST;
440 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
441 return;
443 #undef INVALID_CAST
444 #undef NO_WIDENING_CONVERSION
445 #undef CHECK_WIDENING_CONVERSION
446 #undef ASSIGN_UNSIGNED
447 #undef ASSIGN_SIGNED
448 #undef ASSIGN_REAL
451 static void
452 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
453 MonoArray *idxs)
455 MonoClass *ac, *ic;
456 gint32 i, pos, *ind;
458 MONO_ARCH_SAVE_REGS;
460 MONO_CHECK_ARG_NULL (idxs);
462 ic = idxs->obj.vtable->klass;
463 ac = this->obj.vtable->klass;
465 g_assert (ic->rank == 1);
466 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
467 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
469 ind = (gint32 *)idxs->vector;
471 if (this->bounds == NULL) {
472 if (*ind < 0 || *ind >= this->max_length)
473 mono_raise_exception (mono_get_exception_index_out_of_range ());
475 ves_icall_System_Array_SetValueImpl (this, value, *ind);
476 return;
479 for (i = 0; i < ac->rank; i++)
480 if ((ind [i] < this->bounds [i].lower_bound) ||
481 (ind [i] >= this->bounds [i].length + this->bounds [i].lower_bound))
482 mono_raise_exception (mono_get_exception_index_out_of_range ());
484 pos = ind [0] - this->bounds [0].lower_bound;
485 for (i = 1; i < ac->rank; i++)
486 pos = pos * this->bounds [i].length + ind [i] -
487 this->bounds [i].lower_bound;
489 ves_icall_System_Array_SetValueImpl (this, value, pos);
492 static MonoArray *
493 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
495 MonoClass *aklass;
496 MonoArray *array;
497 mono_array_size_t *sizes, i;
498 gboolean bounded = FALSE;
500 MONO_ARCH_SAVE_REGS;
502 MONO_CHECK_ARG_NULL (type);
503 MONO_CHECK_ARG_NULL (lengths);
505 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
506 if (bounds)
507 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
509 for (i = 0; i < mono_array_length (lengths); i++)
510 if (mono_array_get (lengths, gint32, i) < 0)
511 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
513 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
514 /* vectors are not the same as one dimensional arrays with no-zero bounds */
515 bounded = TRUE;
516 else
517 bounded = FALSE;
519 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
521 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
522 for (i = 0; i < aklass->rank; ++i) {
523 sizes [i] = mono_array_get (lengths, guint32, i);
524 if (bounds)
525 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
526 else
527 sizes [i + aklass->rank] = 0;
530 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
532 return array;
535 static MonoArray *
536 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
538 MonoClass *aklass;
539 MonoArray *array;
540 mono_array_size_t *sizes, i;
541 gboolean bounded = FALSE;
543 MONO_ARCH_SAVE_REGS;
545 MONO_CHECK_ARG_NULL (type);
546 MONO_CHECK_ARG_NULL (lengths);
548 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
549 if (bounds)
550 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
552 for (i = 0; i < mono_array_length (lengths); i++)
553 if ((mono_array_get (lengths, gint64, i) < 0) ||
554 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
555 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
557 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
558 /* vectors are not the same as one dimensional arrays with no-zero bounds */
559 bounded = TRUE;
560 else
561 bounded = FALSE;
563 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
565 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
566 for (i = 0; i < aklass->rank; ++i) {
567 sizes [i] = mono_array_get (lengths, guint64, i);
568 if (bounds)
569 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
570 else
571 sizes [i + aklass->rank] = 0;
574 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
576 return array;
579 static gint32
580 ves_icall_System_Array_GetRank (MonoObject *this)
582 MONO_ARCH_SAVE_REGS;
584 return this->vtable->klass->rank;
587 static gint32
588 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
590 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
591 mono_array_size_t length;
593 MONO_ARCH_SAVE_REGS;
595 if ((dimension < 0) || (dimension >= rank))
596 mono_raise_exception (mono_get_exception_index_out_of_range ());
598 if (this->bounds == NULL)
599 length = this->max_length;
600 else
601 length = this->bounds [dimension].length;
603 #ifdef MONO_BIG_ARRAYS
604 if (length > G_MAXINT32)
605 mono_raise_exception (mono_get_exception_overflow ());
606 #endif
607 return length;
610 static gint64
611 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
613 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
615 MONO_ARCH_SAVE_REGS;
617 if ((dimension < 0) || (dimension >= rank))
618 mono_raise_exception (mono_get_exception_index_out_of_range ());
620 if (this->bounds == NULL)
621 return this->max_length;
623 return this->bounds [dimension].length;
626 static gint32
627 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
629 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
631 MONO_ARCH_SAVE_REGS;
633 if ((dimension < 0) || (dimension >= rank))
634 mono_raise_exception (mono_get_exception_index_out_of_range ());
636 if (this->bounds == NULL)
637 return 0;
639 return this->bounds [dimension].lower_bound;
642 static void
643 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
645 int sz = mono_array_element_size (mono_object_class (arr));
646 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
649 static gboolean
650 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
652 int element_size;
653 void * dest_addr;
654 void * source_addr;
655 MonoClass *src_class;
656 MonoClass *dest_class;
657 int i;
659 MONO_ARCH_SAVE_REGS;
661 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
662 return FALSE;
664 if (source->bounds || dest->bounds)
665 return FALSE;
667 if ((dest_idx + length > mono_array_length (dest)) ||
668 (source_idx + length > mono_array_length (source)))
669 return FALSE;
671 src_class = source->obj.vtable->klass->element_class;
672 dest_class = dest->obj.vtable->klass->element_class;
675 * Handle common cases.
678 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
679 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
680 int has_refs = dest_class->has_references;
681 for (i = source_idx; i < source_idx + length; ++i) {
682 MonoObject *elem = mono_array_get (source, MonoObject*, i);
683 if (elem && !mono_object_isinst (elem, dest_class))
684 return FALSE;
687 element_size = mono_array_element_size (dest->obj.vtable->klass);
688 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
689 for (i = 0; i < length; ++i) {
690 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
691 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
692 if (!elem)
693 continue;
694 if (has_refs)
695 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
696 else
697 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
699 return TRUE;
702 /* Check if we're copying a char[] <==> (u)short[] */
703 if (src_class != dest_class) {
704 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
705 return FALSE;
707 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
709 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
710 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
711 for (i = source_idx; i < source_idx + length; ++i) {
712 MonoObject *elem = mono_array_get (source, MonoObject*, i);
713 if (elem && !mono_object_isinst (elem, dest_class))
714 return FALSE;
716 else
717 return FALSE;
720 if (dest_class->valuetype) {
721 element_size = mono_array_element_size (source->obj.vtable->klass);
722 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
723 if (dest_class->has_references) {
724 mono_value_copy_array (dest, dest_idx, source_addr, length);
725 } else {
726 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
727 memmove (dest_addr, source_addr, element_size * length);
729 } else {
730 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
733 return TRUE;
736 static void
737 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
739 MonoClass *ac;
740 MonoArray *ao;
741 gint32 esize;
742 gpointer *ea;
744 MONO_ARCH_SAVE_REGS;
746 ao = (MonoArray *)this;
747 ac = (MonoClass *)ao->obj.vtable->klass;
749 esize = mono_array_element_size (ac);
750 ea = (gpointer*)((char*)ao->vector + (pos * esize));
752 memcpy (value, ea, esize);
755 static void
756 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
758 MonoClass *ac;
759 MonoArray *ao;
760 gint32 esize;
761 gpointer *ea;
763 MONO_ARCH_SAVE_REGS;
765 ao = (MonoArray *)this;
766 ac = (MonoClass *)ao->obj.vtable->klass;
768 esize = mono_array_element_size (ac);
769 ea = (gpointer*)((char*)ao->vector + (pos * esize));
771 memcpy (ea, value, esize);
774 static void
775 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
777 MonoClass *klass = array->obj.vtable->klass;
778 guint32 size = mono_array_element_size (klass);
779 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
780 int align;
781 const char *field_data;
783 if (MONO_TYPE_IS_REFERENCE (type) ||
784 (type->type == MONO_TYPE_VALUETYPE &&
785 (!mono_type_get_class (type) ||
786 mono_type_get_class (type)->has_references))) {
787 MonoException *exc = mono_get_exception_argument("array",
788 "Cannot initialize array containing references");
789 mono_raise_exception (exc);
792 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
793 MonoException *exc = mono_get_exception_argument("field_handle",
794 "Field doesn't have an RVA");
795 mono_raise_exception (exc);
798 size *= array->max_length;
799 field_data = mono_field_get_data (field_handle);
801 if (size > mono_type_size (field_handle->type, &align)) {
802 MonoException *exc = mono_get_exception_argument("field_handle",
803 "Field not large enough to fill array");
804 mono_raise_exception (exc);
807 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
808 #define SWAP(n) {\
809 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
810 guint ## n *src = (guint ## n *) field_data; \
811 guint ## n *end = (guint ## n *)((char*)src + size); \
813 for (; src < end; data++, src++) { \
814 *data = read ## n (src); \
818 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
820 switch (type->type) {
821 case MONO_TYPE_CHAR:
822 case MONO_TYPE_I2:
823 case MONO_TYPE_U2:
824 SWAP (16);
825 break;
826 case MONO_TYPE_I4:
827 case MONO_TYPE_U4:
828 case MONO_TYPE_R4:
829 SWAP (32);
830 break;
831 case MONO_TYPE_I8:
832 case MONO_TYPE_U8:
833 case MONO_TYPE_R8:
834 SWAP (64);
835 break;
836 default:
837 memcpy (mono_array_addr (array, char, 0), field_data, size);
838 break;
840 #else
841 memcpy (mono_array_addr (array, char, 0), field_data, size);
842 #ifdef ARM_FPU_FPA
843 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
844 gint i;
845 double tmp;
846 double *data = (double*)mono_array_addr (array, double, 0);
848 for (i = 0; i < size; i++, data++) {
849 readr8 (data, &tmp);
850 *data = tmp;
853 #endif
854 #endif
857 static gint
858 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
860 MONO_ARCH_SAVE_REGS;
862 return offsetof (MonoString, chars);
865 static MonoObject *
866 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
868 MONO_ARCH_SAVE_REGS;
870 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
871 return obj;
872 else
873 return mono_object_clone (obj);
876 static void
877 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
879 MonoClass *klass;
881 MONO_ARCH_SAVE_REGS;
883 MONO_CHECK_ARG_NULL (handle);
885 klass = mono_class_from_mono_type (handle);
886 MONO_CHECK_ARG (handle, klass);
888 /* This will call the type constructor */
889 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
892 static void
893 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
895 MONO_ARCH_SAVE_REGS;
897 mono_image_check_for_module_cctor (image);
898 if (image->has_module_cctor) {
899 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
900 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), module_klass));
904 static MonoObject *
905 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
907 MONO_ARCH_SAVE_REGS;
909 return mono_object_clone (this);
912 static gint32
913 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
915 MonoClass *klass;
916 MonoObject **values = NULL;
917 MonoObject *o;
918 int count = 0;
919 gint32 result = 0;
920 MonoClassField* field;
921 gpointer iter;
923 MONO_ARCH_SAVE_REGS;
925 klass = mono_object_class (this);
927 if (mono_class_num_fields (klass) == 0)
928 return mono_object_hash (this);
931 * Compute the starting value of the hashcode for fields of primitive
932 * types, and return the remaining fields in an array to the managed side.
933 * This way, we can avoid costly reflection operations in managed code.
935 iter = NULL;
936 while ((field = mono_class_get_fields (klass, &iter))) {
937 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
938 continue;
939 if (mono_field_is_deleted (field))
940 continue;
941 /* FIXME: Add more types */
942 switch (field->type->type) {
943 case MONO_TYPE_I4:
944 result ^= *(gint32*)((guint8*)this + field->offset);
945 break;
946 case MONO_TYPE_STRING: {
947 MonoString *s;
948 s = *(MonoString**)((guint8*)this + field->offset);
949 if (s != NULL)
950 result ^= mono_string_hash (s);
951 break;
953 default:
954 if (!values)
955 values = g_newa (MonoObject*, mono_class_num_fields (klass));
956 o = mono_field_get_value_object (mono_object_domain (this), field, this);
957 values [count++] = o;
961 if (values) {
962 int i;
963 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
964 for (i = 0; i < count; ++i)
965 mono_array_setref (*fields, i, values [i]);
966 } else {
967 *fields = NULL;
969 return result;
972 static MonoBoolean
973 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
975 MonoClass *klass;
976 MonoObject **values = NULL;
977 MonoObject *o;
978 MonoClassField* field;
979 gpointer iter;
980 int count = 0;
982 MONO_ARCH_SAVE_REGS;
984 MONO_CHECK_ARG_NULL (that);
986 if (this->vtable != that->vtable)
987 return FALSE;
989 klass = mono_object_class (this);
991 if (klass->enumtype && klass->enum_basetype && klass->enum_basetype->type == MONO_TYPE_I4)
992 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
995 * Do the comparison for fields of primitive type and return a result if
996 * possible. Otherwise, return the remaining fields in an array to the
997 * managed side. This way, we can avoid costly reflection operations in
998 * managed code.
1000 *fields = NULL;
1001 iter = NULL;
1002 while ((field = mono_class_get_fields (klass, &iter))) {
1003 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1004 continue;
1005 if (mono_field_is_deleted (field))
1006 continue;
1007 /* FIXME: Add more types */
1008 switch (field->type->type) {
1009 case MONO_TYPE_U1:
1010 case MONO_TYPE_I1:
1011 case MONO_TYPE_BOOLEAN:
1012 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1013 return FALSE;
1014 break;
1015 case MONO_TYPE_U2:
1016 case MONO_TYPE_I2:
1017 case MONO_TYPE_CHAR:
1018 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1019 return FALSE;
1020 break;
1021 case MONO_TYPE_U4:
1022 case MONO_TYPE_I4:
1023 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1024 return FALSE;
1025 break;
1026 case MONO_TYPE_U8:
1027 case MONO_TYPE_I8:
1028 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1029 return FALSE;
1030 break;
1031 case MONO_TYPE_R4:
1032 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1033 return FALSE;
1034 break;
1035 case MONO_TYPE_R8:
1036 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1037 return FALSE;
1038 break;
1041 case MONO_TYPE_STRING: {
1042 MonoString *s1, *s2;
1043 guint32 s1len, s2len;
1044 s1 = *(MonoString**)((guint8*)this + field->offset);
1045 s2 = *(MonoString**)((guint8*)that + field->offset);
1046 if (s1 == s2)
1047 break;
1048 if ((s1 == NULL) || (s2 == NULL))
1049 return FALSE;
1050 s1len = mono_string_length (s1);
1051 s2len = mono_string_length (s2);
1052 if (s1len != s2len)
1053 return FALSE;
1055 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1056 return FALSE;
1057 break;
1059 default:
1060 if (!values)
1061 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1062 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1063 values [count++] = o;
1064 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1065 values [count++] = o;
1068 if (klass->enumtype)
1069 /* enums only have one non-static field */
1070 break;
1073 if (values) {
1074 int i;
1075 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
1076 for (i = 0; i < count; ++i)
1077 mono_array_setref (*fields, i, values [i]);
1078 return FALSE;
1079 } else {
1080 return TRUE;
1084 static MonoReflectionType *
1085 ves_icall_System_Object_GetType (MonoObject *obj)
1087 MONO_ARCH_SAVE_REGS;
1089 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1090 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1091 else
1092 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1095 static void
1096 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1098 MONO_ARCH_SAVE_REGS;
1100 mtype->type = &obj->vtable->klass->byval_arg;
1101 g_assert (mtype->type->type);
1104 static gint32
1105 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1107 MONO_ARCH_SAVE_REGS;
1109 MONO_CHECK_ARG_NULL (obj);
1111 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1114 static gint32
1115 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1116 MonoReflectionMethod *method,
1117 MonoArray *opt_param_types)
1119 MONO_ARCH_SAVE_REGS;
1121 MONO_CHECK_ARG_NULL (method);
1123 return mono_image_create_method_token (
1124 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1127 static void
1128 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1130 MONO_ARCH_SAVE_REGS;
1132 mono_image_create_pefile (mb, file);
1135 static void
1136 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1138 MONO_ARCH_SAVE_REGS;
1140 mono_image_build_metadata (mb);
1143 static void
1144 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1146 MONO_ARCH_SAVE_REGS;
1148 mono_image_register_token (mb->dynamic_image, token, obj);
1151 static gboolean
1152 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1154 MonoMethod **dest = data;
1156 /* skip unmanaged frames */
1157 if (!managed)
1158 return FALSE;
1160 if (m == *dest) {
1161 *dest = NULL;
1162 return FALSE;
1164 if (!(*dest)) {
1165 *dest = m;
1166 return TRUE;
1168 return FALSE;
1171 static gboolean
1172 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1174 MonoMethod **dest = data;
1176 /* skip unmanaged frames */
1177 if (!managed)
1178 return FALSE;
1180 if (!(*dest)) {
1181 if (!strcmp (m->klass->name_space, "System.Reflection"))
1182 return FALSE;
1183 *dest = m;
1184 return TRUE;
1186 return FALSE;
1189 static MonoReflectionType *
1190 type_from_name (const char *str, MonoBoolean ignoreCase)
1192 MonoType *type = NULL;
1193 MonoAssembly *assembly = NULL;
1194 MonoTypeNameParse info;
1195 char *temp_str = g_strdup (str);
1196 gboolean type_resolve = FALSE;
1198 MONO_ARCH_SAVE_REGS;
1200 /* mono_reflection_parse_type() mangles the string */
1201 if (!mono_reflection_parse_type (temp_str, &info)) {
1202 mono_reflection_free_type_info (&info);
1203 g_free (temp_str);
1204 return NULL;
1207 if (info.assembly.name) {
1208 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1209 } else {
1210 MonoMethod *m = mono_method_get_last_managed ();
1211 MonoMethod *dest = m;
1213 mono_stack_walk_no_il (get_caller, &dest);
1214 if (!dest)
1215 dest = m;
1218 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1219 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1220 * to crash. This only seems to happen in some strange remoting
1221 * scenarios and I was unable to figure out what's happening there.
1222 * Dec 10, 2005 - Martin.
1225 if (dest)
1226 assembly = dest->klass->image->assembly;
1227 else {
1228 g_warning (G_STRLOC);
1232 if (assembly)
1233 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1235 if (!info.assembly.name && !type) /* try mscorlib */
1236 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1238 mono_reflection_free_type_info (&info);
1239 g_free (temp_str);
1241 if (!type)
1242 return NULL;
1244 return mono_type_get_object (mono_domain_get (), type);
1247 #ifdef UNUSED
1248 MonoReflectionType *
1249 mono_type_get (const char *str)
1251 char *copy = g_strdup (str);
1252 MonoReflectionType *type = type_from_name (copy, FALSE);
1254 g_free (copy);
1255 return type;
1257 #endif
1259 static MonoReflectionType*
1260 ves_icall_type_from_name (MonoString *name,
1261 MonoBoolean throwOnError,
1262 MonoBoolean ignoreCase)
1264 char *str = mono_string_to_utf8 (name);
1265 MonoReflectionType *type;
1267 type = type_from_name (str, ignoreCase);
1268 g_free (str);
1269 if (type == NULL){
1270 MonoException *e = NULL;
1272 if (throwOnError)
1273 e = mono_get_exception_type_load (name, NULL);
1275 mono_loader_clear_error ();
1276 if (e != NULL)
1277 mono_raise_exception (e);
1280 return type;
1284 static MonoReflectionType*
1285 ves_icall_type_from_handle (MonoType *handle)
1287 MonoDomain *domain = mono_domain_get ();
1288 MonoClass *klass = mono_class_from_mono_type (handle);
1290 MONO_ARCH_SAVE_REGS;
1292 mono_class_init (klass);
1293 return mono_type_get_object (domain, handle);
1296 static MonoBoolean
1297 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1299 MONO_ARCH_SAVE_REGS;
1301 if (c && type->type && c->type)
1302 return mono_metadata_type_equal (type->type, c->type);
1303 else
1304 return FALSE;
1307 /* System.TypeCode */
1308 typedef enum {
1309 TYPECODE_EMPTY,
1310 TYPECODE_OBJECT,
1311 TYPECODE_DBNULL,
1312 TYPECODE_BOOLEAN,
1313 TYPECODE_CHAR,
1314 TYPECODE_SBYTE,
1315 TYPECODE_BYTE,
1316 TYPECODE_INT16,
1317 TYPECODE_UINT16,
1318 TYPECODE_INT32,
1319 TYPECODE_UINT32,
1320 TYPECODE_INT64,
1321 TYPECODE_UINT64,
1322 TYPECODE_SINGLE,
1323 TYPECODE_DOUBLE,
1324 TYPECODE_DECIMAL,
1325 TYPECODE_DATETIME,
1326 TYPECODE_STRING = 18
1327 } TypeCode;
1329 static guint32
1330 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1332 int t = type->type->type;
1334 MONO_ARCH_SAVE_REGS;
1336 if (type->type->byref)
1337 return TYPECODE_OBJECT;
1339 handle_enum:
1340 switch (t) {
1341 case MONO_TYPE_VOID:
1342 return TYPECODE_OBJECT;
1343 case MONO_TYPE_BOOLEAN:
1344 return TYPECODE_BOOLEAN;
1345 case MONO_TYPE_U1:
1346 return TYPECODE_BYTE;
1347 case MONO_TYPE_I1:
1348 return TYPECODE_SBYTE;
1349 case MONO_TYPE_U2:
1350 return TYPECODE_UINT16;
1351 case MONO_TYPE_I2:
1352 return TYPECODE_INT16;
1353 case MONO_TYPE_CHAR:
1354 return TYPECODE_CHAR;
1355 case MONO_TYPE_PTR:
1356 case MONO_TYPE_U:
1357 case MONO_TYPE_I:
1358 return TYPECODE_OBJECT;
1359 case MONO_TYPE_U4:
1360 return TYPECODE_UINT32;
1361 case MONO_TYPE_I4:
1362 return TYPECODE_INT32;
1363 case MONO_TYPE_U8:
1364 return TYPECODE_UINT64;
1365 case MONO_TYPE_I8:
1366 return TYPECODE_INT64;
1367 case MONO_TYPE_R4:
1368 return TYPECODE_SINGLE;
1369 case MONO_TYPE_R8:
1370 return TYPECODE_DOUBLE;
1371 case MONO_TYPE_VALUETYPE:
1372 if (type->type->data.klass->enumtype) {
1373 t = type->type->data.klass->enum_basetype->type;
1374 goto handle_enum;
1375 } else {
1376 MonoClass *k = type->type->data.klass;
1377 if (strcmp (k->name_space, "System") == 0) {
1378 if (strcmp (k->name, "Decimal") == 0)
1379 return TYPECODE_DECIMAL;
1380 else if (strcmp (k->name, "DateTime") == 0)
1381 return TYPECODE_DATETIME;
1384 return TYPECODE_OBJECT;
1385 case MONO_TYPE_STRING:
1386 return TYPECODE_STRING;
1387 case MONO_TYPE_SZARRAY:
1388 case MONO_TYPE_ARRAY:
1389 case MONO_TYPE_OBJECT:
1390 case MONO_TYPE_VAR:
1391 case MONO_TYPE_MVAR:
1392 case MONO_TYPE_TYPEDBYREF:
1393 return TYPECODE_OBJECT;
1394 case MONO_TYPE_CLASS:
1396 MonoClass *k = type->type->data.klass;
1397 if (strcmp (k->name_space, "System") == 0) {
1398 if (strcmp (k->name, "DBNull") == 0)
1399 return TYPECODE_DBNULL;
1402 return TYPECODE_OBJECT;
1403 case MONO_TYPE_GENERICINST:
1404 return TYPECODE_OBJECT;
1405 default:
1406 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1408 return 0;
1411 static guint32
1412 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1414 MonoDomain *domain;
1415 MonoClass *klass;
1416 MonoClass *klassc;
1418 MONO_ARCH_SAVE_REGS;
1420 g_assert (type != NULL);
1422 domain = ((MonoObject *)type)->vtable->domain;
1424 if (!c) /* FIXME: dont know what do do here */
1425 return 0;
1427 klass = mono_class_from_mono_type (type->type);
1428 klassc = mono_class_from_mono_type (c->type);
1430 if (type->type->byref)
1431 return klassc == mono_defaults.object_class;
1433 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1436 static guint32
1437 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1439 MonoDomain *domain;
1440 MonoClass *klass;
1441 MonoClass *klassc;
1443 MONO_ARCH_SAVE_REGS;
1445 g_assert (type != NULL);
1447 domain = ((MonoObject *)type)->vtable->domain;
1449 klass = mono_class_from_mono_type (type->type);
1450 klassc = mono_class_from_mono_type (c->type);
1452 if (type->type->byref && !c->type->byref)
1453 return FALSE;
1455 return mono_class_is_assignable_from (klass, klassc);
1458 static guint32
1459 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1461 MonoClass *klass = mono_class_from_mono_type (type->type);
1462 return mono_object_isinst (obj, klass) != NULL;
1465 static guint32
1466 ves_icall_get_attributes (MonoReflectionType *type)
1468 MonoClass *klass = mono_class_from_mono_type (type->type);
1470 MONO_ARCH_SAVE_REGS;
1472 return klass->flags;
1475 static MonoReflectionMarshal*
1476 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1478 MonoClass *klass = field->field->parent;
1479 MonoMarshalType *info;
1480 int i;
1482 if (klass->generic_container ||
1483 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1484 return NULL;
1486 info = mono_marshal_load_type_info (klass);
1488 for (i = 0; i < info->num_fields; ++i) {
1489 if (info->fields [i].field == field->field) {
1490 if (!info->fields [i].mspec)
1491 return NULL;
1492 else
1493 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1497 return NULL;
1500 static MonoReflectionField*
1501 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoClass *klass)
1503 g_assert (handle);
1505 if (!klass)
1506 klass = handle->parent;
1508 /* FIXME: check that handle is a field of klass or of a parent: return null
1509 * and throw the exception in managed code.
1511 return mono_field_get_object (mono_domain_get (), klass, handle);
1514 static MonoReflectionField*
1515 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1517 MONO_ARCH_SAVE_REGS;
1519 g_assert (handle);
1521 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1524 static MonoArray*
1525 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1527 MonoType *type = field->field->type;
1529 return type_array_from_modifiers (field->field->parent->image, type, optional);
1532 static void
1533 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1535 MonoDomain *domain = mono_domain_get ();
1536 MonoMethodSignature* sig;
1537 MONO_ARCH_SAVE_REGS;
1539 sig = mono_method_signature (method);
1540 if (!sig) {
1541 g_assert (mono_loader_get_last_error ());
1542 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1545 info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
1546 info->ret = mono_type_get_object (domain, sig->ret);
1547 info->attrs = method->flags;
1548 info->implattrs = method->iflags;
1549 if (sig->call_convention == MONO_CALL_DEFAULT)
1550 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1551 else {
1552 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1553 info->callconv = 2;
1554 else
1555 info->callconv = 1;
1557 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1560 static MonoArray*
1561 ves_icall_get_parameter_info (MonoMethod *method)
1563 MonoDomain *domain = mono_domain_get ();
1565 return mono_param_get_objects (domain, method);
1568 static MonoReflectionMarshal*
1569 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1571 MonoDomain *domain = mono_domain_get ();
1572 MonoReflectionMarshal* res = NULL;
1573 MonoMarshalSpec **mspecs;
1574 int i;
1576 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1577 mono_method_get_marshal_info (method, mspecs);
1579 if (mspecs [0])
1580 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1582 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1583 if (mspecs [i])
1584 mono_metadata_free_marshal_spec (mspecs [i]);
1585 g_free (mspecs);
1587 return res;
1590 static gint32
1591 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1593 return field->field->offset - sizeof (MonoObject);
1596 static MonoReflectionType*
1597 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1599 MonoClass *parent;
1600 MONO_ARCH_SAVE_REGS;
1602 parent = declaring? field->field->parent: field->klass;
1604 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1607 static MonoObject *
1608 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1610 MonoObject *o;
1611 MonoClassField *cf = field->field;
1612 MonoClass *klass;
1613 MonoVTable *vtable;
1614 MonoType *t;
1615 MonoDomain *domain = mono_object_domain (field);
1616 gchar *v;
1617 gboolean is_static = FALSE;
1618 gboolean is_ref = FALSE;
1620 MONO_ARCH_SAVE_REGS;
1622 if (field->klass->image->assembly->ref_only)
1623 mono_raise_exception (mono_get_exception_invalid_operation (
1624 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1626 mono_class_init (field->klass);
1628 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1629 is_static = TRUE;
1631 if (obj && !is_static) {
1632 /* Check that the field belongs to the object */
1633 gboolean found = FALSE;
1634 MonoClass *k;
1636 for (k = obj->vtable->klass; k; k = k->parent) {
1637 if (k == cf->parent) {
1638 found = TRUE;
1639 break;
1643 if (!found) {
1644 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);
1645 MonoException *ex = mono_get_exception_argument (NULL, msg);
1646 g_free (msg);
1647 mono_raise_exception (ex);
1651 t = mono_type_get_underlying_type (cf->type);
1652 switch (t->type) {
1653 case MONO_TYPE_STRING:
1654 case MONO_TYPE_OBJECT:
1655 case MONO_TYPE_CLASS:
1656 case MONO_TYPE_ARRAY:
1657 case MONO_TYPE_SZARRAY:
1658 is_ref = TRUE;
1659 break;
1660 case MONO_TYPE_U1:
1661 case MONO_TYPE_I1:
1662 case MONO_TYPE_BOOLEAN:
1663 case MONO_TYPE_U2:
1664 case MONO_TYPE_I2:
1665 case MONO_TYPE_CHAR:
1666 case MONO_TYPE_U:
1667 case MONO_TYPE_I:
1668 case MONO_TYPE_U4:
1669 case MONO_TYPE_I4:
1670 case MONO_TYPE_R4:
1671 case MONO_TYPE_U8:
1672 case MONO_TYPE_I8:
1673 case MONO_TYPE_R8:
1674 case MONO_TYPE_VALUETYPE:
1675 is_ref = t->byref;
1676 break;
1677 case MONO_TYPE_GENERICINST:
1678 if (mono_type_generic_inst_is_valuetype (t)) {
1679 is_ref = t->byref;
1680 } else {
1681 is_ref = TRUE;
1683 break;
1684 default:
1685 g_error ("type 0x%x not handled in "
1686 "ves_icall_Monofield_GetValue", t->type);
1687 return NULL;
1690 vtable = NULL;
1691 if (is_static) {
1692 vtable = mono_class_vtable (domain, cf->parent);
1693 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1694 mono_runtime_class_init (vtable);
1697 if (is_ref) {
1698 if (is_static) {
1699 mono_field_static_get_value (vtable, cf, &o);
1700 } else {
1701 mono_field_get_value (obj, cf, &o);
1703 return o;
1706 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1707 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1708 guint8 *buf;
1710 /* Convert the Nullable structure into a boxed vtype */
1711 if (is_static)
1712 buf = (guint8*)vtable->data + cf->offset;
1713 else
1714 buf = (guint8*)obj + cf->offset;
1716 return mono_nullable_box (buf, nklass);
1719 /* boxed value type */
1720 klass = mono_class_from_mono_type (cf->type);
1721 o = mono_object_new (domain, klass);
1722 v = ((gchar *) o) + sizeof (MonoObject);
1723 if (is_static) {
1724 mono_field_static_get_value (vtable, cf, v);
1725 } else {
1726 mono_field_get_value (obj, cf, v);
1729 return o;
1732 static void
1733 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1735 MonoClassField *cf = field->field;
1736 gchar *v;
1738 MONO_ARCH_SAVE_REGS;
1740 if (field->klass->image->assembly->ref_only)
1741 mono_raise_exception (mono_get_exception_invalid_operation (
1742 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1744 v = (gchar *) value;
1745 if (!cf->type->byref) {
1746 switch (cf->type->type) {
1747 case MONO_TYPE_U1:
1748 case MONO_TYPE_I1:
1749 case MONO_TYPE_BOOLEAN:
1750 case MONO_TYPE_U2:
1751 case MONO_TYPE_I2:
1752 case MONO_TYPE_CHAR:
1753 case MONO_TYPE_U:
1754 case MONO_TYPE_I:
1755 case MONO_TYPE_U4:
1756 case MONO_TYPE_I4:
1757 case MONO_TYPE_R4:
1758 case MONO_TYPE_U8:
1759 case MONO_TYPE_I8:
1760 case MONO_TYPE_R8:
1761 case MONO_TYPE_VALUETYPE:
1762 if (v != NULL)
1763 v += sizeof (MonoObject);
1764 break;
1765 case MONO_TYPE_STRING:
1766 case MONO_TYPE_OBJECT:
1767 case MONO_TYPE_CLASS:
1768 case MONO_TYPE_ARRAY:
1769 case MONO_TYPE_SZARRAY:
1770 /* Do nothing */
1771 break;
1772 case MONO_TYPE_GENERICINST: {
1773 MonoGenericClass *gclass = cf->type->data.generic_class;
1774 g_assert (!gclass->context.class_inst->is_open);
1776 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1777 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1778 MonoObject *nullable;
1781 * Convert the boxed vtype into a Nullable structure.
1782 * This is complicated by the fact that Nullables have
1783 * a variable structure.
1785 nullable = mono_object_new (mono_domain_get (), nklass);
1787 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1789 v = mono_object_unbox (nullable);
1791 else
1792 if (gclass->container_class->valuetype && (v != NULL))
1793 v += sizeof (MonoObject);
1794 break;
1796 default:
1797 g_error ("type 0x%x not handled in "
1798 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1799 return;
1803 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1804 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1805 if (!vtable->initialized)
1806 mono_runtime_class_init (vtable);
1807 mono_field_static_set_value (vtable, cf, v);
1808 } else {
1809 mono_field_set_value (obj, cf, v);
1813 static MonoObject *
1814 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1816 MonoObject *o = NULL;
1817 MonoClassField *field = this->field;
1818 MonoClass *klass;
1819 MonoDomain *domain = mono_object_domain (this);
1820 gchar *v;
1821 MonoTypeEnum def_type;
1822 const char *def_value;
1824 MONO_ARCH_SAVE_REGS;
1826 mono_class_init (field->parent);
1828 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1829 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1831 if (field->parent->image->dynamic) {
1832 /* FIXME: */
1833 g_assert_not_reached ();
1836 def_value = mono_class_get_field_default_value (field, &def_type);
1838 switch (def_type) {
1839 case MONO_TYPE_U1:
1840 case MONO_TYPE_I1:
1841 case MONO_TYPE_BOOLEAN:
1842 case MONO_TYPE_U2:
1843 case MONO_TYPE_I2:
1844 case MONO_TYPE_CHAR:
1845 case MONO_TYPE_U:
1846 case MONO_TYPE_I:
1847 case MONO_TYPE_U4:
1848 case MONO_TYPE_I4:
1849 case MONO_TYPE_R4:
1850 case MONO_TYPE_U8:
1851 case MONO_TYPE_I8:
1852 case MONO_TYPE_R8: {
1853 MonoType *t;
1855 /* boxed value type */
1856 t = g_new0 (MonoType, 1);
1857 t->type = def_type;
1858 klass = mono_class_from_mono_type (t);
1859 g_free (t);
1860 o = mono_object_new (domain, klass);
1861 v = ((gchar *) o) + sizeof (MonoObject);
1862 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1863 break;
1865 case MONO_TYPE_STRING:
1866 case MONO_TYPE_CLASS:
1867 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1868 break;
1869 default:
1870 g_assert_not_reached ();
1873 return o;
1876 static MonoReflectionType*
1877 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1879 MonoMethod *method = rmethod->method.method;
1881 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1884 /* From MonoProperty.cs */
1885 typedef enum {
1886 PInfo_Attributes = 1,
1887 PInfo_GetMethod = 1 << 1,
1888 PInfo_SetMethod = 1 << 2,
1889 PInfo_ReflectedType = 1 << 3,
1890 PInfo_DeclaringType = 1 << 4,
1891 PInfo_Name = 1 << 5
1892 } PInfo;
1894 static void
1895 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1897 MonoDomain *domain = mono_object_domain (property);
1899 MONO_ARCH_SAVE_REGS;
1901 if ((req_info & PInfo_ReflectedType) != 0)
1902 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1903 else if ((req_info & PInfo_DeclaringType) != 0)
1904 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1906 if ((req_info & PInfo_Name) != 0)
1907 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1909 if ((req_info & PInfo_Attributes) != 0)
1910 info->attrs = property->property->attrs;
1912 if ((req_info & PInfo_GetMethod) != 0)
1913 MONO_STRUCT_SETREF (info, get, property->property->get ?
1914 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1916 if ((req_info & PInfo_SetMethod) != 0)
1917 MONO_STRUCT_SETREF (info, set, property->property->set ?
1918 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1920 * There may be other methods defined for properties, though, it seems they are not exposed
1921 * in the reflection API
1925 static void
1926 ves_icall_get_event_info (MonoReflectionEvent *event, MonoEventInfo *info)
1928 MonoDomain *domain = mono_object_domain (event);
1930 MONO_ARCH_SAVE_REGS;
1932 info->reflected_type = mono_type_get_object (domain, &event->klass->byval_arg);
1933 info->declaring_type = mono_type_get_object (domain, &event->event->parent->byval_arg);
1935 info->name = mono_string_new (domain, event->event->name);
1936 info->attrs = event->event->attrs;
1937 info->add_method = event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL;
1938 info->remove_method = event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL;
1939 info->raise_method = event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL;
1941 if (event->event->other) {
1942 int i, n = 0;
1943 while (event->event->other [n])
1944 n++;
1945 info->other_methods = mono_array_new (domain, mono_defaults.method_info_class, n);
1947 for (i = 0; i < n; i++)
1948 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
1952 static MonoArray*
1953 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
1955 MonoDomain *domain = mono_object_domain (type);
1956 MonoArray *intf;
1957 GPtrArray *ifaces = NULL;
1958 int i;
1959 MonoClass *class = mono_class_from_mono_type (type->type);
1960 MonoClass *parent;
1961 MonoBitSet *slots;
1962 MonoGenericContext *context = NULL;
1964 MONO_ARCH_SAVE_REGS;
1966 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
1967 context = mono_class_get_context (class);
1968 class = class->generic_class->container_class;
1971 mono_class_setup_vtable (class);
1973 slots = mono_bitset_new (class->max_interface_id + 1, 0);
1975 for (parent = class; parent; parent = parent->parent) {
1976 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
1977 if (tmp_ifaces) {
1978 for (i = 0; i < tmp_ifaces->len; ++i) {
1979 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
1981 if (mono_bitset_test (slots, ic->interface_id))
1982 continue;
1984 mono_bitset_set (slots, ic->interface_id);
1985 if (ifaces == NULL)
1986 ifaces = g_ptr_array_new ();
1987 g_ptr_array_add (ifaces, ic);
1989 g_ptr_array_free (tmp_ifaces, TRUE);
1992 mono_bitset_free (slots);
1994 if (!ifaces)
1995 return mono_array_new (domain, mono_defaults.monotype_class, 0);
1997 intf = mono_array_new (domain, mono_defaults.monotype_class, ifaces->len);
1998 for (i = 0; i < ifaces->len; ++i) {
1999 MonoClass *ic = g_ptr_array_index (ifaces, i);
2000 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2001 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2002 inflated = ret = mono_class_inflate_generic_type (ret, context);
2004 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2005 if (inflated)
2006 mono_metadata_free_type (inflated);
2008 g_ptr_array_free (ifaces, TRUE);
2010 return intf;
2013 static void
2014 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2016 MonoClass *class = mono_class_from_mono_type (type->type);
2017 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2018 MonoReflectionMethod *member;
2019 MonoMethod* method;
2020 gpointer iter;
2021 int i = 0, len, ioffset;
2022 MonoDomain *domain;
2024 MONO_ARCH_SAVE_REGS;
2026 mono_class_setup_vtable (class);
2028 /* type doesn't implement iface: the exception is thrown in managed code */
2029 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2030 return;
2032 len = mono_class_num_methods (iclass);
2033 ioffset = mono_class_interface_offset (class, iclass);
2034 domain = mono_object_domain (type);
2035 *targets = mono_array_new (domain, mono_defaults.method_info_class, len);
2036 *methods = mono_array_new (domain, mono_defaults.method_info_class, len);
2037 iter = NULL;
2038 iter = NULL;
2039 while ((method = mono_class_get_methods (iclass, &iter))) {
2040 member = mono_method_get_object (domain, method, iclass);
2041 mono_array_setref (*methods, i, member);
2042 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2043 mono_array_setref (*targets, i, member);
2045 i ++;
2049 static void
2050 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2052 MonoClass *klass = mono_class_from_mono_type (type->type);
2054 if (klass->image->dynamic) {
2055 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2056 *packing = tb->packing_size;
2057 *size = tb->class_size;
2058 } else {
2059 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2063 static MonoReflectionType*
2064 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2066 MonoClass *class = mono_class_from_mono_type (type->type);
2068 MONO_ARCH_SAVE_REGS;
2070 // GetElementType should only return a type for:
2071 // Array Pointer PassedByRef
2072 if (type->type->byref)
2073 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2074 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2075 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2076 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2077 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2078 else
2079 return NULL;
2082 static MonoReflectionType*
2083 ves_icall_get_type_parent (MonoReflectionType *type)
2085 MonoClass *class = mono_class_from_mono_type (type->type);
2087 MONO_ARCH_SAVE_REGS;
2089 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2092 static MonoBoolean
2093 ves_icall_type_ispointer (MonoReflectionType *type)
2095 MONO_ARCH_SAVE_REGS;
2097 return type->type->type == MONO_TYPE_PTR;
2100 static MonoBoolean
2101 ves_icall_type_isprimitive (MonoReflectionType *type)
2103 MONO_ARCH_SAVE_REGS;
2105 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)));
2108 static MonoBoolean
2109 ves_icall_type_isbyref (MonoReflectionType *type)
2111 MONO_ARCH_SAVE_REGS;
2113 return type->type->byref;
2116 static MonoBoolean
2117 ves_icall_type_iscomobject (MonoReflectionType *type)
2119 MonoClass *klass = mono_class_from_mono_type (type->type);
2120 MONO_ARCH_SAVE_REGS;
2122 return (klass && klass->is_com_object);
2125 static MonoReflectionModule*
2126 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2128 MonoClass *class = mono_class_from_mono_type (type->type);
2130 MONO_ARCH_SAVE_REGS;
2132 return mono_module_get_object (mono_object_domain (type), class->image);
2135 static MonoReflectionAssembly*
2136 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2138 MonoDomain *domain = mono_domain_get ();
2139 MonoClass *class = mono_class_from_mono_type (type->type);
2141 MONO_ARCH_SAVE_REGS;
2143 return mono_assembly_get_object (domain, class->image->assembly);
2146 static MonoReflectionType*
2147 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2149 MonoDomain *domain = mono_domain_get ();
2150 MonoClass *class;
2152 MONO_ARCH_SAVE_REGS;
2154 if (type->type->byref)
2155 return NULL;
2156 if (type->type->type == MONO_TYPE_VAR)
2157 class = type->type->data.generic_param->owner->owner.klass;
2158 else if (type->type->type == MONO_TYPE_MVAR)
2159 class = type->type->data.generic_param->owner->owner.method->klass;
2160 else
2161 class = mono_class_from_mono_type (type->type)->nested_in;
2163 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2166 static MonoReflectionType*
2167 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2169 MonoDomain *domain = mono_domain_get ();
2170 MonoClass *class = mono_class_from_mono_type (type->type);
2172 MONO_ARCH_SAVE_REGS;
2174 if (class->enumtype && class->enum_basetype) /* types that are modified typebuilders may not have enum_basetype set */
2175 return mono_type_get_object (domain, class->enum_basetype);
2176 else if (class->element_class)
2177 return mono_type_get_object (domain, &class->element_class->byval_arg);
2178 else
2179 return NULL;
2182 static MonoString*
2183 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2185 MonoDomain *domain = mono_domain_get ();
2186 MonoClass *class = mono_class_from_mono_type (type->type);
2188 MONO_ARCH_SAVE_REGS;
2190 if (type->type->byref) {
2191 char *n = g_strdup_printf ("%s&", class->name);
2192 MonoString *res = mono_string_new (domain, n);
2194 g_free (n);
2196 return res;
2197 } else {
2198 return mono_string_new (domain, class->name);
2202 static MonoString*
2203 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2205 MonoDomain *domain = mono_domain_get ();
2206 MonoClass *class = mono_class_from_mono_type (type->type);
2208 MONO_ARCH_SAVE_REGS;
2210 while (class->nested_in)
2211 class = class->nested_in;
2213 if (class->name_space [0] == '\0')
2214 return NULL;
2215 else
2216 return mono_string_new (domain, class->name_space);
2219 static gint32
2220 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2222 MonoClass *class = mono_class_from_mono_type (type->type);
2224 MONO_ARCH_SAVE_REGS;
2226 return class->rank;
2229 static MonoArray*
2230 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2232 MonoArray *res;
2233 MonoClass *klass, *pklass;
2234 int i;
2235 MONO_ARCH_SAVE_REGS;
2237 klass = mono_class_from_mono_type (type->type);
2239 if (klass->generic_container) {
2240 MonoGenericContainer *container = klass->generic_container;
2241 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, container->type_argc);
2242 for (i = 0; i < container->type_argc; ++i) {
2243 pklass = mono_class_from_generic_parameter (&container->type_params [i], klass->image, FALSE);
2244 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), &pklass->byval_arg));
2246 } else if (klass->generic_class) {
2247 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2248 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, inst->type_argc);
2249 for (i = 0; i < inst->type_argc; ++i)
2250 mono_array_setref (res, i, mono_type_get_object (mono_object_domain (type), inst->type_argv [i]));
2251 } else {
2252 res = mono_array_new (mono_object_domain (type), mono_defaults.systemtype_class, 0);
2254 return res;
2257 static gboolean
2258 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2260 MonoClass *klass;
2261 MONO_ARCH_SAVE_REGS;
2263 if (type->type->byref)
2264 return FALSE;
2266 klass = mono_class_from_mono_type (type->type);
2268 return klass->generic_container != NULL;
2271 static MonoReflectionType*
2272 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2274 MonoClass *klass;
2275 MONO_ARCH_SAVE_REGS;
2277 if (type->type->byref)
2278 return NULL;
2280 klass = mono_class_from_mono_type (type->type);
2281 if (klass->generic_container) {
2282 return type; /* check this one */
2284 if (klass->generic_class) {
2285 MonoClass *generic_class = klass->generic_class->container_class;
2287 if (generic_class->wastypebuilder && generic_class->reflection_info)
2288 return generic_class->reflection_info;
2289 else
2290 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2292 return NULL;
2295 static MonoReflectionType*
2296 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2298 MonoType *geninst, **types;
2299 int i, count;
2301 MONO_ARCH_SAVE_REGS;
2303 count = mono_array_length (type_array);
2304 types = g_new0 (MonoType *, count);
2306 for (i = 0; i < count; i++) {
2307 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2308 types [i] = t->type;
2311 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2312 g_free (types);
2313 if (!geninst)
2314 return NULL;
2316 return mono_type_get_object (mono_object_domain (type), geninst);
2319 static gboolean
2320 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2322 MonoClass *klass;
2323 MONO_ARCH_SAVE_REGS;
2325 if (type->type->byref)
2326 return FALSE;
2328 klass = mono_class_from_mono_type (type->type);
2329 return klass->generic_class != NULL;
2332 static gboolean
2333 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2335 MonoClass *klass;
2336 MONO_ARCH_SAVE_REGS;
2338 if (type->type->byref)
2339 return FALSE;
2341 klass = mono_class_from_mono_type (type->type);
2342 return klass->generic_class != NULL || klass->generic_container != NULL;
2345 static gint32
2346 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2348 MONO_ARCH_SAVE_REGS;
2350 if (is_generic_parameter (type->type))
2351 return type->type->data.generic_param->num;
2352 return -1;
2355 static GenericParameterAttributes
2356 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2358 MONO_ARCH_SAVE_REGS;
2359 g_assert (is_generic_parameter (type->type));
2360 return type->type->data.generic_param->flags;
2363 static MonoArray *
2364 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2366 MonoGenericParam *param;
2367 MonoDomain *domain;
2368 MonoClass **ptr;
2369 MonoArray *res;
2370 int i, count;
2372 MONO_ARCH_SAVE_REGS;
2374 domain = mono_object_domain (type);
2375 param = type->type->data.generic_param;
2376 for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
2379 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2380 for (i = 0; i < count; i++)
2381 mono_array_setref (res, i, mono_type_get_object (domain, &param->constraints [i]->byval_arg));
2384 return res;
2387 static MonoBoolean
2388 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2390 MONO_ARCH_SAVE_REGS;
2391 return is_generic_parameter (type->type);
2394 static MonoBoolean
2395 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2397 MONO_ARCH_SAVE_REGS;
2398 return is_generic_parameter (tb->type.type);
2401 static void
2402 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2403 MonoReflectionType *t)
2405 enumtype->type = t->type;
2408 static MonoReflectionType*
2409 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2411 MonoDynamicGenericClass *gclass;
2412 MonoReflectionType *parent = NULL, *res;
2413 MonoDomain *domain;
2414 MonoType *inflated;
2415 MonoClass *klass;
2418 MONO_ARCH_SAVE_REGS;
2420 g_assert (type->type.type->data.generic_class->is_dynamic);
2421 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2423 domain = mono_object_domain (type);
2424 klass = mono_class_from_mono_type (type->generic_type->type.type);
2426 if (!klass->generic_class && !klass->generic_container)
2427 return NULL;
2429 parent = type->generic_type->parent;
2431 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2432 return NULL;
2434 inflated = mono_class_inflate_generic_type (
2435 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2437 res = mono_type_get_object (domain, inflated);
2438 mono_metadata_free_type (inflated);
2439 return res;
2442 static MonoArray*
2443 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2445 static MonoClass *System_Reflection_MonoGenericClass;
2446 MonoGenericClass *gclass;
2447 MonoReflectionTypeBuilder *tb = NULL;
2448 MonoClass *klass = NULL;
2449 MonoDomain *domain;
2450 MonoArray *res;
2451 int icount, i;
2453 MONO_ARCH_SAVE_REGS;
2455 if (!System_Reflection_MonoGenericClass) {
2456 System_Reflection_MonoGenericClass = mono_class_from_name (
2457 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2458 g_assert (System_Reflection_MonoGenericClass);
2461 domain = mono_object_domain (type);
2463 gclass = type->type.type->data.generic_class;
2464 g_assert (gclass->is_dynamic);
2466 tb = type->generic_type;
2467 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2469 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2471 for (i = 0; i < icount; i++) {
2472 MonoReflectionType *iface;
2473 MonoType *it;
2475 if (tb) {
2476 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2477 it = iface->type;
2478 } else
2479 it = &klass->interfaces [i]->byval_arg;
2481 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2483 iface = mono_type_get_object (domain, it);
2484 mono_array_setref (res, i, iface);
2485 mono_metadata_free_type (it);
2488 return res;
2491 static MonoReflectionMethod*
2492 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2493 MonoReflectionMethod* generic)
2495 MonoGenericClass *gclass;
2496 MonoDynamicGenericClass *dgclass;
2497 MonoDomain *domain;
2498 int i;
2500 MONO_ARCH_SAVE_REGS;
2502 gclass = type->type.type->data.generic_class;
2503 g_assert (gclass->is_dynamic);
2505 dgclass = (MonoDynamicGenericClass *) gclass;
2507 domain = mono_object_domain (type);
2509 for (i = 0; i < dgclass->count_methods; i++)
2510 if (generic->method->token == dgclass->methods [i]->token)
2511 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2513 return NULL;
2516 static MonoReflectionMethod*
2517 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2518 MonoReflectionMethod* generic)
2520 MonoGenericClass *gclass;
2521 MonoDynamicGenericClass *dgclass;
2522 MonoDomain *domain;
2523 int i;
2525 MONO_ARCH_SAVE_REGS;
2527 gclass = type->type.type->data.generic_class;
2528 g_assert (gclass->is_dynamic);
2530 dgclass = (MonoDynamicGenericClass *) gclass;
2532 domain = mono_object_domain (type);
2534 for (i = 0; i < dgclass->count_ctors; i++)
2535 if (generic->method->token == dgclass->ctors [i]->token)
2536 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2538 return NULL;
2542 static MonoReflectionField*
2543 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2544 MonoString* generic_name)
2546 MonoGenericClass *gclass;
2547 MonoDynamicGenericClass *dgclass;
2548 MonoDomain *domain;
2549 MonoClass *refclass;
2550 char *utf8_name = mono_string_to_utf8 (generic_name);
2551 int i;
2553 MONO_ARCH_SAVE_REGS;
2555 gclass = type->type.type->data.generic_class;
2556 g_assert (gclass->is_dynamic);
2558 dgclass = (MonoDynamicGenericClass *) gclass;
2560 refclass = mono_class_from_mono_type (type->type.type);
2562 domain = mono_object_domain (type);
2564 for (i = 0; i < dgclass->count_fields; i++)
2565 if (strcmp (utf8_name, mono_field_get_name (&dgclass->fields [i])) == 0) {
2566 g_free (utf8_name);
2567 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2570 g_free (utf8_name);
2572 return NULL;
2576 static MonoReflectionMethod*
2577 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2578 MonoReflectionMethod* generic)
2580 MonoDomain *domain;
2581 MonoClass *klass;
2582 MonoMethod *method;
2583 gpointer iter;
2585 MONO_ARCH_SAVE_REGS;
2587 domain = ((MonoObject *)type)->vtable->domain;
2589 klass = mono_class_from_mono_type (type->type);
2591 iter = NULL;
2592 while ((method = mono_class_get_methods (klass, &iter))) {
2593 if (method->token == generic->method->token)
2594 return mono_method_get_object (domain, method, klass);
2597 return NULL;
2600 static MonoArray*
2601 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2602 MonoReflectionType *reflected_type)
2604 MonoGenericClass *gclass;
2605 MonoDynamicGenericClass *dgclass;
2606 MonoDomain *domain;
2607 MonoClass *refclass;
2608 MonoArray *res;
2609 int i;
2611 MONO_ARCH_SAVE_REGS;
2613 gclass = type->type.type->data.generic_class;
2614 g_assert (gclass->is_dynamic);
2615 dgclass = (MonoDynamicGenericClass *) gclass;
2617 refclass = mono_class_from_mono_type (reflected_type->type);
2619 domain = mono_object_domain (type);
2620 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2622 for (i = 0; i < dgclass->count_methods; i++)
2623 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2625 return res;
2628 static MonoArray*
2629 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2630 MonoReflectionType *reflected_type)
2632 static MonoClass *System_Reflection_ConstructorInfo;
2633 MonoGenericClass *gclass;
2634 MonoDynamicGenericClass *dgclass;
2635 MonoDomain *domain;
2636 MonoClass *refclass;
2637 MonoArray *res;
2638 int i;
2640 MONO_ARCH_SAVE_REGS;
2642 if (!System_Reflection_ConstructorInfo)
2643 System_Reflection_ConstructorInfo = mono_class_from_name (
2644 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2646 gclass = type->type.type->data.generic_class;
2647 g_assert (gclass->is_dynamic);
2648 dgclass = (MonoDynamicGenericClass *) gclass;
2650 refclass = mono_class_from_mono_type (reflected_type->type);
2652 domain = mono_object_domain (type);
2653 res = mono_array_new (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2655 for (i = 0; i < dgclass->count_ctors; i++)
2656 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2658 return res;
2661 static MonoArray*
2662 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2663 MonoReflectionType *reflected_type)
2665 MonoGenericClass *gclass;
2666 MonoDynamicGenericClass *dgclass;
2667 MonoDomain *domain;
2668 MonoClass *refclass;
2669 MonoArray *res;
2670 int i;
2672 MONO_ARCH_SAVE_REGS;
2674 gclass = type->type.type->data.generic_class;
2675 g_assert (gclass->is_dynamic);
2676 dgclass = (MonoDynamicGenericClass *) gclass;
2678 refclass = mono_class_from_mono_type (reflected_type->type);
2680 domain = mono_object_domain (type);
2681 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2683 for (i = 0; i < dgclass->count_fields; i++)
2684 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2686 return res;
2689 static MonoArray*
2690 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2691 MonoReflectionType *reflected_type)
2693 static MonoClass *System_Reflection_PropertyInfo;
2694 MonoGenericClass *gclass;
2695 MonoDynamicGenericClass *dgclass;
2696 MonoDomain *domain;
2697 MonoClass *refclass;
2698 MonoArray *res;
2699 int i;
2701 MONO_ARCH_SAVE_REGS;
2703 if (!System_Reflection_PropertyInfo)
2704 System_Reflection_PropertyInfo = mono_class_from_name (
2705 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2707 gclass = type->type.type->data.generic_class;
2708 g_assert (gclass->is_dynamic);
2709 dgclass = (MonoDynamicGenericClass *) gclass;
2711 refclass = mono_class_from_mono_type (reflected_type->type);
2713 domain = mono_object_domain (type);
2714 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2716 for (i = 0; i < dgclass->count_properties; i++)
2717 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2719 return res;
2722 static MonoArray*
2723 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2724 MonoReflectionType *reflected_type)
2726 static MonoClass *System_Reflection_EventInfo;
2727 MonoGenericClass *gclass;
2728 MonoDynamicGenericClass *dgclass;
2729 MonoDomain *domain;
2730 MonoClass *refclass;
2731 MonoArray *res;
2732 int i;
2734 MONO_ARCH_SAVE_REGS;
2736 if (!System_Reflection_EventInfo)
2737 System_Reflection_EventInfo = mono_class_from_name (
2738 mono_defaults.corlib, "System.Reflection", "EventInfo");
2740 gclass = type->type.type->data.generic_class;
2741 g_assert (gclass->is_dynamic);
2742 dgclass = (MonoDynamicGenericClass *) gclass;
2744 refclass = mono_class_from_mono_type (reflected_type->type);
2746 domain = mono_object_domain (type);
2747 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2749 for (i = 0; i < dgclass->count_events; i++)
2750 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2752 return res;
2755 static MonoReflectionType*
2756 ves_icall_MonoGenericClass_InflateType (MonoReflectionGenericClass *type,
2757 MonoReflectionType *target)
2759 MonoType *res_type;
2760 MonoClass *gklass;
2761 MonoReflectionType *res;
2763 MONO_ARCH_SAVE_REGS;
2765 gklass = mono_class_from_mono_type (type->type.type);
2766 res_type = mono_class_inflate_generic_type (target->type, mono_class_get_context (gklass));
2767 res = mono_type_get_object (mono_object_domain (type), res_type);
2768 mono_metadata_free_type (res_type);
2769 return res;
2772 static MonoReflectionMethod *
2773 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2775 MonoMethod *method;
2776 MonoClass *klass;
2778 MONO_ARCH_SAVE_REGS;
2780 if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2781 return NULL;
2783 method = type->type->data.generic_param->owner->owner.method;
2784 g_assert (method);
2785 klass = mono_class_from_mono_type (type->type);
2786 return mono_method_get_object (mono_object_domain (type), method, klass);
2789 static MonoReflectionDllImportAttribute*
2790 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2792 static MonoClass *DllImportAttributeClass = NULL;
2793 MonoDomain *domain = mono_domain_get ();
2794 MonoReflectionDllImportAttribute *attr;
2795 MonoImage *image = method->klass->image;
2796 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2797 MonoTableInfo *tables = image->tables;
2798 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2799 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2800 guint32 im_cols [MONO_IMPLMAP_SIZE];
2801 guint32 scope_token;
2802 const char *import = NULL;
2803 const char *scope = NULL;
2804 guint32 flags;
2806 if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2807 return NULL;
2809 if (!DllImportAttributeClass) {
2810 DllImportAttributeClass =
2811 mono_class_from_name (mono_defaults.corlib,
2812 "System.Runtime.InteropServices", "DllImportAttribute");
2813 g_assert (DllImportAttributeClass);
2816 if (method->klass->image->dynamic) {
2817 MonoReflectionMethodAux *method_aux =
2818 g_hash_table_lookup (
2819 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2820 if (method_aux) {
2821 import = method_aux->dllentry;
2822 scope = method_aux->dll;
2825 else {
2826 if (piinfo->implmap_idx) {
2827 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2829 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2830 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2831 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2832 scope = mono_metadata_string_heap (image, scope_token);
2835 flags = piinfo->piflags;
2837 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2839 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2840 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2841 attr->call_conv = (flags & 0x700) >> 8;
2842 attr->charset = ((flags & 0x6) >> 1) + 1;
2843 if (attr->charset == 1)
2844 attr->charset = 2;
2845 attr->exact_spelling = (flags & 0x1) != 0;
2846 attr->set_last_error = (flags & 0x40) != 0;
2847 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2848 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2849 attr->preserve_sig = FALSE;
2851 return attr;
2854 static MonoReflectionMethod *
2855 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2857 MonoMethodInflated *imethod;
2858 MonoMethod *result;
2860 MONO_ARCH_SAVE_REGS;
2862 if (method->method->is_generic)
2863 return method;
2865 if (!method->method->is_inflated)
2866 return NULL;
2868 imethod = (MonoMethodInflated *) method->method;
2870 result = imethod->declaring;
2871 /* Not a generic method. */
2872 if (!result->is_generic)
2873 return NULL;
2875 if (method->method->klass->image->dynamic) {
2876 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2877 MonoReflectionMethod *res;
2880 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2881 * the dynamic case as well ?
2883 mono_loader_lock ();
2884 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2885 mono_loader_unlock ();
2887 if (res)
2888 return res;
2891 if (imethod->context.class_inst) {
2892 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2893 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2896 return mono_method_get_object (mono_object_domain (method), result, NULL);
2899 static gboolean
2900 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2902 MONO_ARCH_SAVE_REGS;
2904 return mono_method_signature (method->method)->generic_param_count != 0;
2907 static gboolean
2908 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2910 MONO_ARCH_SAVE_REGS;
2912 return method->method->is_generic;
2915 static MonoArray*
2916 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2918 MonoArray *res;
2919 MonoDomain *domain;
2920 int count, i;
2921 MONO_ARCH_SAVE_REGS;
2923 domain = mono_object_domain (method);
2925 if (method->method->is_inflated) {
2926 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2928 if (inst) {
2929 count = inst->type_argc;
2930 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2932 for (i = 0; i < count; i++)
2933 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2935 return res;
2939 count = mono_method_signature (method->method)->generic_param_count;
2940 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2942 for (i = 0; i < count; i++) {
2943 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2944 MonoGenericParam *param = &container->type_params [i];
2945 MonoClass *pklass = mono_class_from_generic_parameter (
2946 param, method->method->klass->image, TRUE);
2947 mono_array_setref (res, i,
2948 mono_type_get_object (domain, &pklass->byval_arg));
2951 return res;
2954 static void
2955 ensure_reflection_security (void)
2957 MonoMethod *m = mono_method_get_last_managed ();
2959 while (m) {
2961 g_print ("method %s.%s.%s in image %s\n",
2962 m->klass->name_space, m->klass->name, m->name, m->klass->image->name);
2965 /* We stop at the first method which is not in
2966 System.Reflection or which is not in a platform
2967 image. */
2968 if (strcmp (m->klass->name_space, "System.Reflection") != 0 ||
2969 !mono_security_core_clr_is_platform_image (m->klass->image)) {
2970 /* If the method is transparent we throw an exception. */
2971 if (mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_TRANSPARENT ) {
2972 MonoException *ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", "Reflection called from transparent code");
2974 mono_raise_exception (ex);
2976 return;
2979 mono_stack_walk_no_il (get_caller, &m);
2983 static MonoObject *
2984 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2987 * Invoke from reflection is supposed to always be a virtual call (the API
2988 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2989 * greater flexibility.
2991 MonoMethod *m = method->method;
2992 int pcount;
2993 void *obj = this;
2995 MONO_ARCH_SAVE_REGS;
2997 *exc = NULL;
2999 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR &&
3000 mono_security_core_clr_method_level (m, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL)
3001 ensure_reflection_security ();
3003 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3004 if (this) {
3005 if (!mono_object_isinst (this, m->klass)) {
3006 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type.");
3007 return NULL;
3009 m = mono_object_get_virtual_method (this, m);
3010 /* must pass the pointer to the value for valuetype methods */
3011 if (m->klass->valuetype)
3012 obj = mono_object_unbox (this);
3013 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3014 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target.");
3015 return NULL;
3019 pcount = params? mono_array_length (params): 0;
3020 if (pcount != mono_method_signature (m)->param_count) {
3021 *exc = mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException");
3022 return NULL;
3025 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
3026 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class.");
3027 return NULL;
3030 if (m->klass->image->assembly->ref_only) {
3031 *exc = mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api.");
3032 return NULL;
3035 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3036 int i;
3037 mono_array_size_t *lengths;
3038 mono_array_size_t *lower_bounds;
3039 pcount = mono_array_length (params);
3040 lengths = alloca (sizeof (mono_array_size_t) * pcount);
3041 for (i = 0; i < pcount; ++i)
3042 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3044 if (m->klass->rank == pcount) {
3045 /* Only lengths provided. */
3046 lower_bounds = NULL;
3047 } else {
3048 g_assert (pcount == (m->klass->rank * 2));
3049 /* lower bounds are first. */
3050 lower_bounds = lengths;
3051 lengths += m->klass->rank;
3054 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
3056 return mono_runtime_invoke_array (m, obj, params, NULL);
3059 static MonoObject *
3060 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
3062 MonoDomain *domain = mono_object_domain (method);
3063 MonoMethod *m = method->method;
3064 MonoMethodSignature *sig = mono_method_signature (m);
3065 MonoArray *out_args;
3066 MonoObject *result;
3067 int i, j, outarg_count = 0;
3069 MONO_ARCH_SAVE_REGS;
3071 if (m->klass == mono_defaults.object_class) {
3073 if (!strcmp (m->name, "FieldGetter")) {
3074 MonoClass *k = this->vtable->klass;
3075 MonoString *name;
3076 char *str;
3078 /* If this is a proxy, then it must be a CBO */
3079 if (k == mono_defaults.transparent_proxy_class) {
3080 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3081 this = tp->rp->unwrapped_server;
3082 g_assert (this);
3083 k = this->vtable->klass;
3086 name = mono_array_get (params, MonoString *, 1);
3087 str = mono_string_to_utf8 (name);
3089 do {
3090 MonoClassField* field = mono_class_get_field_from_name (k, str);
3091 if (field) {
3092 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3093 if (field_klass->valuetype)
3094 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
3095 else
3096 result = *((gpointer *)((char *)this + field->offset));
3098 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3099 *outArgs = out_args;
3100 mono_array_setref (out_args, 0, result);
3101 g_free (str);
3102 return NULL;
3104 k = k->parent;
3105 } while (k);
3107 g_free (str);
3108 g_assert_not_reached ();
3110 } else if (!strcmp (m->name, "FieldSetter")) {
3111 MonoClass *k = this->vtable->klass;
3112 MonoString *name;
3113 guint32 size;
3114 gint32 align;
3115 char *str;
3117 /* If this is a proxy, then it must be a CBO */
3118 if (k == mono_defaults.transparent_proxy_class) {
3119 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3120 this = tp->rp->unwrapped_server;
3121 g_assert (this);
3122 k = this->vtable->klass;
3125 name = mono_array_get (params, MonoString *, 1);
3126 str = mono_string_to_utf8 (name);
3128 do {
3129 MonoClassField* field = mono_class_get_field_from_name (k, str);
3130 if (field) {
3131 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3132 MonoObject *val = mono_array_get (params, gpointer, 2);
3134 if (field_klass->valuetype) {
3135 size = mono_type_size (field->type, &align);
3136 memcpy ((char *)this + field->offset,
3137 ((char *)val) + sizeof (MonoObject), size);
3138 } else
3139 *(MonoObject**)((char *)this + field->offset) = val;
3141 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3142 *outArgs = out_args;
3144 g_free (str);
3145 return NULL;
3148 k = k->parent;
3149 } while (k);
3151 g_free (str);
3152 g_assert_not_reached ();
3157 for (i = 0; i < mono_array_length (params); i++) {
3158 if (sig->params [i]->byref)
3159 outarg_count++;
3162 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3164 /* handle constructors only for objects already allocated */
3165 if (!strcmp (method->method->name, ".ctor"))
3166 g_assert (this);
3168 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3169 g_assert (!method->method->klass->valuetype);
3170 result = mono_runtime_invoke_array (method->method, this, params, NULL);
3172 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3173 if (sig->params [i]->byref) {
3174 gpointer arg;
3175 arg = mono_array_get (params, gpointer, i);
3176 mono_array_setref (out_args, j, arg);
3177 j++;
3181 *outArgs = out_args;
3183 return result;
3186 static guint64
3187 read_enum_value (char *mem, int type)
3189 switch (type) {
3190 case MONO_TYPE_U1:
3191 return *(guint8*)mem;
3192 case MONO_TYPE_I1:
3193 return *(gint8*)mem;
3194 case MONO_TYPE_U2:
3195 return *(guint16*)mem;
3196 case MONO_TYPE_I2:
3197 return *(gint16*)mem;
3198 case MONO_TYPE_U4:
3199 return *(guint32*)mem;
3200 case MONO_TYPE_I4:
3201 return *(gint32*)mem;
3202 case MONO_TYPE_U8:
3203 return *(guint64*)mem;
3204 case MONO_TYPE_I8:
3205 return *(gint64*)mem;
3206 default:
3207 g_assert_not_reached ();
3209 return 0;
3212 static void
3213 write_enum_value (char *mem, int type, guint64 value)
3215 switch (type) {
3216 case MONO_TYPE_U1:
3217 case MONO_TYPE_I1: {
3218 guint8 *p = (guint8*)mem;
3219 *p = value;
3220 break;
3222 case MONO_TYPE_U2:
3223 case MONO_TYPE_I2: {
3224 guint16 *p = (void*)mem;
3225 *p = value;
3226 break;
3228 case MONO_TYPE_U4:
3229 case MONO_TYPE_I4: {
3230 guint32 *p = (void*)mem;
3231 *p = value;
3232 break;
3234 case MONO_TYPE_U8:
3235 case MONO_TYPE_I8: {
3236 guint64 *p = (void*)mem;
3237 *p = value;
3238 break;
3240 default:
3241 g_assert_not_reached ();
3243 return;
3246 static MonoObject *
3247 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3249 MonoDomain *domain;
3250 MonoClass *enumc, *objc;
3251 MonoObject *res;
3252 guint64 val;
3254 MONO_ARCH_SAVE_REGS;
3256 MONO_CHECK_ARG_NULL (enumType);
3257 MONO_CHECK_ARG_NULL (value);
3259 domain = mono_object_domain (enumType);
3260 enumc = mono_class_from_mono_type (enumType->type);
3261 objc = value->vtable->klass;
3263 if (!enumc->enumtype)
3264 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3265 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3266 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."));
3268 res = mono_object_new (domain, enumc);
3269 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? objc->enum_basetype->type: objc->byval_arg.type);
3270 write_enum_value ((char *)res + sizeof (MonoObject), enumc->enum_basetype->type, val);
3272 return res;
3275 static MonoObject *
3276 ves_icall_System_Enum_get_value (MonoObject *this)
3278 MonoObject *res;
3279 MonoClass *enumc;
3280 gpointer dst;
3281 gpointer src;
3282 int size;
3284 MONO_ARCH_SAVE_REGS;
3286 if (!this)
3287 return NULL;
3289 g_assert (this->vtable->klass->enumtype);
3291 enumc = mono_class_from_mono_type (this->vtable->klass->enum_basetype);
3292 res = mono_object_new (mono_object_domain (this), enumc);
3293 dst = (char *)res + sizeof (MonoObject);
3294 src = (char *)this + sizeof (MonoObject);
3295 size = mono_class_value_size (enumc, NULL);
3297 memcpy (dst, src, size);
3299 return res;
3302 static MonoReflectionType *
3303 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3305 MONO_ARCH_SAVE_REGS;
3307 return mono_type_get_object (mono_object_domain (type), mono_class_from_mono_type (type->type)->enum_basetype);
3310 static int
3311 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3313 gpointer data = (char *)this + sizeof (MonoObject);
3314 MonoType *basetype = this->vtable->klass->enum_basetype;
3315 g_assert (basetype);
3317 switch (basetype->type) {
3318 case MONO_TYPE_I1:
3319 return *((gint8*)data);
3320 case MONO_TYPE_U1:
3321 return *((guint8*)data);
3322 case MONO_TYPE_CHAR:
3323 case MONO_TYPE_U2:
3324 return *((guint16*)data);
3326 case MONO_TYPE_I2:
3327 return *((gint16*)data);
3328 case MONO_TYPE_U4:
3329 return *((guint32*)data);
3330 case MONO_TYPE_I4:
3331 return *((gint32*)data);
3332 case MONO_TYPE_U8:
3333 case MONO_TYPE_I8: {
3334 gint64 value = *((gint64*)data);
3335 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3337 default:
3338 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3340 return 0;
3343 static void
3344 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3346 MonoDomain *domain = mono_object_domain (type);
3347 MonoClass *enumc = mono_class_from_mono_type (type->type);
3348 guint j = 0, nvalues, crow;
3349 gpointer iter;
3350 MonoClassField *field;
3352 MONO_ARCH_SAVE_REGS;
3354 info->utype = mono_type_get_object (domain, enumc->enum_basetype);
3355 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3356 info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3357 info->values = mono_array_new (domain, enumc, nvalues);
3359 crow = -1;
3360 iter = NULL;
3361 while ((field = mono_class_get_fields (enumc, &iter))) {
3362 const char *p;
3363 int len;
3364 MonoTypeEnum def_type;
3366 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3367 continue;
3368 if (mono_field_is_deleted (field))
3369 continue;
3370 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3372 p = mono_class_get_field_default_value (field, &def_type);
3373 len = mono_metadata_decode_blob_size (p, &p);
3374 switch (enumc->enum_basetype->type) {
3375 case MONO_TYPE_U1:
3376 case MONO_TYPE_I1:
3377 mono_array_set (info->values, gchar, j, *p);
3378 break;
3379 case MONO_TYPE_CHAR:
3380 case MONO_TYPE_U2:
3381 case MONO_TYPE_I2:
3382 mono_array_set (info->values, gint16, j, read16 (p));
3383 break;
3384 case MONO_TYPE_U4:
3385 case MONO_TYPE_I4:
3386 mono_array_set (info->values, gint32, j, read32 (p));
3387 break;
3388 case MONO_TYPE_U8:
3389 case MONO_TYPE_I8:
3390 mono_array_set (info->values, gint64, j, read64 (p));
3391 break;
3392 default:
3393 g_error ("Implement type 0x%02x in get_enum_info", enumc->enum_basetype->type);
3395 ++j;
3399 enum {
3400 BFLAGS_IgnoreCase = 1,
3401 BFLAGS_DeclaredOnly = 2,
3402 BFLAGS_Instance = 4,
3403 BFLAGS_Static = 8,
3404 BFLAGS_Public = 0x10,
3405 BFLAGS_NonPublic = 0x20,
3406 BFLAGS_FlattenHierarchy = 0x40,
3407 BFLAGS_InvokeMethod = 0x100,
3408 BFLAGS_CreateInstance = 0x200,
3409 BFLAGS_GetField = 0x400,
3410 BFLAGS_SetField = 0x800,
3411 BFLAGS_GetProperty = 0x1000,
3412 BFLAGS_SetProperty = 0x2000,
3413 BFLAGS_ExactBinding = 0x10000,
3414 BFLAGS_SuppressChangeType = 0x20000,
3415 BFLAGS_OptionalParamBinding = 0x40000
3418 static MonoReflectionField *
3419 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3421 MonoDomain *domain;
3422 MonoClass *startklass, *klass;
3423 int match;
3424 MonoClassField *field;
3425 gpointer iter;
3426 char *utf8_name;
3427 int (*compare_func) (const char *s1, const char *s2) = NULL;
3428 domain = ((MonoObject *)type)->vtable->domain;
3429 klass = startklass = mono_class_from_mono_type (type->type);
3431 MONO_ARCH_SAVE_REGS;
3433 if (!name)
3434 mono_raise_exception (mono_get_exception_argument_null ("name"));
3435 if (type->type->byref)
3436 return NULL;
3438 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3440 handle_parent:
3441 if (klass->exception_type != MONO_EXCEPTION_NONE)
3442 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3444 iter = NULL;
3445 while ((field = mono_class_get_fields (klass, &iter))) {
3446 match = 0;
3448 if (field->type == NULL)
3449 continue;
3450 if (mono_field_is_deleted (field))
3451 continue;
3452 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3453 if (bflags & BFLAGS_Public)
3454 match++;
3455 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3456 if (bflags & BFLAGS_NonPublic) {
3457 match++;
3460 if (!match)
3461 continue;
3462 match = 0;
3463 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3464 if (bflags & BFLAGS_Static)
3465 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3466 match++;
3467 } else {
3468 if (bflags & BFLAGS_Instance)
3469 match++;
3472 if (!match)
3473 continue;
3475 utf8_name = mono_string_to_utf8 (name);
3477 if (compare_func (mono_field_get_name (field), utf8_name)) {
3478 g_free (utf8_name);
3479 continue;
3481 g_free (utf8_name);
3483 return mono_field_get_object (domain, klass, field);
3485 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3486 goto handle_parent;
3488 return NULL;
3491 static MonoArray*
3492 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3494 MonoDomain *domain;
3495 MonoClass *startklass, *klass, *refklass;
3496 MonoArray *res;
3497 MonoObject *member;
3498 int i, len, match;
3499 gpointer iter;
3500 MonoClassField *field;
3502 MONO_ARCH_SAVE_REGS;
3504 domain = ((MonoObject *)type)->vtable->domain;
3505 if (type->type->byref)
3506 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3507 klass = startklass = mono_class_from_mono_type (type->type);
3508 refklass = mono_class_from_mono_type (reftype->type);
3510 i = 0;
3511 len = 2;
3512 res = mono_array_new (domain, mono_defaults.field_info_class, len);
3513 handle_parent:
3514 if (klass->exception_type != MONO_EXCEPTION_NONE)
3515 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3517 iter = NULL;
3518 while ((field = mono_class_get_fields (klass, &iter))) {
3519 match = 0;
3520 if (mono_field_is_deleted (field))
3521 continue;
3522 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3523 if (bflags & BFLAGS_Public)
3524 match++;
3525 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3526 if (bflags & BFLAGS_NonPublic) {
3527 match++;
3530 if (!match)
3531 continue;
3532 match = 0;
3533 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3534 if (bflags & BFLAGS_Static)
3535 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3536 match++;
3537 } else {
3538 if (bflags & BFLAGS_Instance)
3539 match++;
3542 if (!match)
3543 continue;
3544 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3545 if (i >= len) {
3546 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, len * 2);
3547 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3548 len *= 2;
3549 res = new_res;
3551 mono_array_setref (res, i, member);
3552 ++i;
3554 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3555 goto handle_parent;
3556 if (i != len) {
3557 MonoArray *new_res = mono_array_new (domain, mono_defaults.field_info_class, i);
3558 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3559 res = new_res;
3561 * Better solution for the new GC.
3562 * res->max_length = i;
3565 return res;
3568 static gboolean
3569 method_nonpublic (MonoMethod* method, gboolean start_klass)
3571 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3572 case METHOD_ATTRIBUTE_ASSEM:
3573 return (start_klass || mono_defaults.generic_ilist_class);
3574 case METHOD_ATTRIBUTE_PRIVATE:
3575 return start_klass;
3576 case METHOD_ATTRIBUTE_PUBLIC:
3577 return FALSE;
3578 default:
3579 return TRUE;
3583 static MonoArray*
3584 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3586 static MonoClass *MethodInfo_array;
3587 MonoDomain *domain;
3588 MonoClass *startklass, *klass, *refklass;
3589 MonoArray *res;
3590 MonoMethod *method;
3591 gpointer iter;
3592 MonoObject *member;
3593 int i, len, match, nslots;
3594 guint32 method_slots_default [8];
3595 guint32 *method_slots;
3596 gchar *mname = NULL;
3597 int (*compare_func) (const char *s1, const char *s2) = NULL;
3598 MonoVTable *array_vtable;
3600 MONO_ARCH_SAVE_REGS;
3602 if (!MethodInfo_array) {
3603 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3604 mono_memory_barrier ();
3605 MethodInfo_array = klass;
3608 domain = ((MonoObject *)type)->vtable->domain;
3609 array_vtable = mono_class_vtable (domain, MethodInfo_array);
3610 if (type->type->byref)
3611 return mono_array_new_specific (array_vtable, 0);
3612 klass = startklass = mono_class_from_mono_type (type->type);
3613 refklass = mono_class_from_mono_type (reftype->type);
3614 len = 0;
3615 if (name != NULL) {
3616 mname = mono_string_to_utf8 (name);
3617 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3620 mono_class_setup_vtable (klass);
3622 if (is_generic_parameter (type->type))
3623 nslots = klass->parent->vtable_size;
3624 else
3625 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3626 if (nslots >= sizeof (method_slots_default) * 8) {
3627 method_slots = g_new0 (guint32, nslots / 32 + 1);
3628 } else {
3629 method_slots = method_slots_default;
3630 memset (method_slots, 0, sizeof (method_slots_default));
3632 i = 0;
3633 len = 1;
3634 res = mono_array_new_specific (array_vtable, len);
3635 handle_parent:
3636 mono_class_setup_vtable (klass);
3637 if (klass->exception_type != MONO_EXCEPTION_NONE)
3638 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3640 iter = NULL;
3641 while ((method = mono_class_get_methods (klass, &iter))) {
3642 match = 0;
3643 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3644 continue;
3645 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3646 if (bflags & BFLAGS_Public)
3647 match++;
3648 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3649 match++;
3651 if (!match)
3652 continue;
3653 match = 0;
3654 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3655 if (bflags & BFLAGS_Static)
3656 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3657 match++;
3658 } else {
3659 if (bflags & BFLAGS_Instance)
3660 match++;
3663 if (!match)
3664 continue;
3666 if (name != NULL) {
3667 if (compare_func (mname, method->name))
3668 continue;
3671 match = 0;
3672 if (method->slot != -1) {
3673 g_assert (method->slot < nslots);
3674 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3675 continue;
3676 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3679 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3681 if (i >= len) {
3682 MonoArray *new_res = mono_array_new_specific (array_vtable, len * 2);
3683 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3684 len *= 2;
3685 res = new_res;
3687 mono_array_setref (res, i, member);
3688 ++i;
3690 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3691 goto handle_parent;
3693 g_free (mname);
3694 if (method_slots != method_slots_default)
3695 g_free (method_slots);
3696 if (i != len) {
3697 MonoArray *new_res = mono_array_new (domain, mono_defaults.method_info_class, i);
3698 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3699 res = new_res;
3701 * Better solution for the new GC.
3702 * res->max_length = i;
3705 return res;
3708 static MonoArray*
3709 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3711 MonoDomain *domain;
3712 static MonoClass *System_Reflection_ConstructorInfo;
3713 MonoClass *startklass, *klass, *refklass;
3714 MonoArray *res;
3715 MonoMethod *method;
3716 MonoObject *member;
3717 int i, len, match;
3718 gpointer iter = NULL;
3720 MONO_ARCH_SAVE_REGS;
3722 domain = ((MonoObject *)type)->vtable->domain;
3723 if (type->type->byref)
3724 return mono_array_new (domain, mono_defaults.method_info_class, 0);
3725 klass = startklass = mono_class_from_mono_type (type->type);
3726 refklass = mono_class_from_mono_type (reftype->type);
3728 if (klass->exception_type != MONO_EXCEPTION_NONE)
3729 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3731 if (!System_Reflection_ConstructorInfo)
3732 System_Reflection_ConstructorInfo = mono_class_from_name (
3733 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3735 i = 0;
3736 len = 2;
3737 res = mono_array_new (domain, System_Reflection_ConstructorInfo, len);
3738 iter = NULL;
3739 while ((method = mono_class_get_methods (klass, &iter))) {
3740 match = 0;
3741 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3742 continue;
3743 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3744 if (bflags & BFLAGS_Public)
3745 match++;
3746 } else {
3747 if (bflags & BFLAGS_NonPublic)
3748 match++;
3750 if (!match)
3751 continue;
3752 match = 0;
3753 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3754 if (bflags & BFLAGS_Static)
3755 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3756 match++;
3757 } else {
3758 if (bflags & BFLAGS_Instance)
3759 match++;
3762 if (!match)
3763 continue;
3764 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3766 if (i >= len) {
3767 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, len * 2);
3768 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3769 len *= 2;
3770 res = new_res;
3772 mono_array_setref (res, i, member);
3773 ++i;
3775 if (i != len) {
3776 MonoArray *new_res = mono_array_new (domain, System_Reflection_ConstructorInfo, i);
3777 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3778 res = new_res;
3780 * Better solution for the new GC.
3781 * res->max_length = i;
3784 return res;
3787 static guint
3788 property_hash (gconstpointer data)
3790 MonoProperty *prop = (MonoProperty*)data;
3792 return g_str_hash (prop->name);
3795 static gboolean
3796 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3798 // Properties are hide-by-name-and-signature
3799 if (!g_str_equal (prop1->name, prop2->name))
3800 return FALSE;
3802 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3803 return FALSE;
3804 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3805 return FALSE;
3806 return TRUE;
3809 static gboolean
3810 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3812 if (!accessor)
3813 return FALSE;
3815 return method_nonpublic (accessor, start_klass);
3818 static MonoArray*
3819 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3821 MonoDomain *domain;
3822 static MonoClass *System_Reflection_PropertyInfo;
3823 MonoClass *startklass, *klass;
3824 MonoArray *res;
3825 MonoMethod *method;
3826 MonoProperty *prop;
3827 int i, match;
3828 int len = 0;
3829 guint32 flags;
3830 gchar *propname = NULL;
3831 int (*compare_func) (const char *s1, const char *s2) = NULL;
3832 gpointer iter;
3833 GHashTable *properties;
3835 MONO_ARCH_SAVE_REGS;
3837 if (!System_Reflection_PropertyInfo)
3838 System_Reflection_PropertyInfo = mono_class_from_name (
3839 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3841 domain = ((MonoObject *)type)->vtable->domain;
3842 if (type->type->byref)
3843 return mono_array_new (domain, System_Reflection_PropertyInfo, 0);
3844 klass = startklass = mono_class_from_mono_type (type->type);
3845 if (name != NULL) {
3846 propname = mono_string_to_utf8 (name);
3847 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3850 mono_class_setup_vtable (klass);
3852 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3853 i = 0;
3854 len = 2;
3855 res = mono_array_new (domain, System_Reflection_PropertyInfo, len);
3856 handle_parent:
3857 mono_class_setup_vtable (klass);
3858 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3859 g_hash_table_destroy (properties);
3860 if (name != NULL)
3861 g_free (propname);
3862 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3865 iter = NULL;
3866 while ((prop = mono_class_get_properties (klass, &iter))) {
3867 match = 0;
3868 method = prop->get;
3869 if (!method)
3870 method = prop->set;
3871 if (method)
3872 flags = method->flags;
3873 else
3874 flags = 0;
3875 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3876 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3877 if (bflags & BFLAGS_Public)
3878 match++;
3879 } else if (bflags & BFLAGS_NonPublic) {
3880 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3881 property_accessor_nonpublic(prop->set, startklass == klass)) {
3882 match++;
3885 if (!match)
3886 continue;
3887 match = 0;
3888 if (flags & METHOD_ATTRIBUTE_STATIC) {
3889 if (bflags & BFLAGS_Static)
3890 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3891 match++;
3892 } else {
3893 if (bflags & BFLAGS_Instance)
3894 match++;
3897 if (!match)
3898 continue;
3899 match = 0;
3901 if (name != NULL) {
3902 if (compare_func (propname, prop->name))
3903 continue;
3906 if (g_hash_table_lookup (properties, prop))
3907 continue;
3909 if (i >= len) {
3910 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, len * 2);
3911 mono_array_memcpy_refs (new_res, 0, res, 0, len);
3912 len *= 2;
3913 res = new_res;
3915 mono_array_setref (res, i, mono_property_get_object (domain, startklass, prop));
3916 ++i;
3918 g_hash_table_insert (properties, prop, prop);
3920 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3921 goto handle_parent;
3923 g_hash_table_destroy (properties);
3924 g_free (propname);
3925 if (i != len) {
3926 MonoArray *new_res = mono_array_new (domain, System_Reflection_PropertyInfo, i);
3927 mono_array_memcpy_refs (new_res, 0, res, 0, i);
3928 res = new_res;
3930 * Better solution for the new GC.
3931 * res->max_length = i;
3934 return res;
3937 static MonoReflectionEvent *
3938 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3940 MonoDomain *domain;
3941 MonoClass *klass, *startklass;
3942 gpointer iter;
3943 MonoEvent *event;
3944 MonoMethod *method;
3945 gchar *event_name;
3947 MONO_ARCH_SAVE_REGS;
3949 event_name = mono_string_to_utf8 (name);
3950 if (type->type->byref)
3951 return NULL;
3952 klass = startklass = mono_class_from_mono_type (type->type);
3953 domain = mono_object_domain (type);
3955 handle_parent:
3956 if (klass->exception_type != MONO_EXCEPTION_NONE)
3957 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3959 iter = NULL;
3960 while ((event = mono_class_get_events (klass, &iter))) {
3961 if (strcmp (event->name, event_name))
3962 continue;
3964 method = event->add;
3965 if (!method)
3966 method = event->remove;
3967 if (!method)
3968 method = event->raise;
3969 if (method) {
3970 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3971 if (!(bflags & BFLAGS_Public))
3972 continue;
3973 } else {
3974 if (!(bflags & BFLAGS_NonPublic))
3975 continue;
3976 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3977 continue;
3980 else
3981 if (!(bflags & BFLAGS_NonPublic))
3982 continue;
3984 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3985 if (!(bflags & BFLAGS_Static))
3986 continue;
3987 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3988 continue;
3989 } else {
3990 if (!(bflags & BFLAGS_Instance))
3991 continue;
3994 g_free (event_name);
3995 return mono_event_get_object (domain, startklass, event);
3998 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3999 goto handle_parent;
4001 g_free (event_name);
4002 return NULL;
4005 static MonoArray*
4006 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4008 MonoDomain *domain;
4009 static MonoClass *System_Reflection_EventInfo;
4010 MonoClass *startklass, *klass;
4011 MonoArray *res;
4012 MonoMethod *method;
4013 MonoEvent *event;
4014 int i, len, match;
4015 gpointer iter;
4017 MONO_ARCH_SAVE_REGS;
4019 if (!System_Reflection_EventInfo)
4020 System_Reflection_EventInfo = mono_class_from_name (
4021 mono_defaults.corlib, "System.Reflection", "EventInfo");
4023 domain = mono_object_domain (type);
4024 if (type->type->byref)
4025 return mono_array_new (domain, System_Reflection_EventInfo, 0);
4026 klass = startklass = mono_class_from_mono_type (type->type);
4028 i = 0;
4029 len = 2;
4030 res = mono_array_new (domain, System_Reflection_EventInfo, len);
4031 handle_parent:
4032 if (klass->exception_type != MONO_EXCEPTION_NONE)
4033 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4035 iter = NULL;
4036 while ((event = mono_class_get_events (klass, &iter))) {
4037 match = 0;
4038 method = event->add;
4039 if (!method)
4040 method = event->remove;
4041 if (!method)
4042 method = event->raise;
4043 if (method) {
4044 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4045 if (bflags & BFLAGS_Public)
4046 match++;
4047 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4048 if (bflags & BFLAGS_NonPublic)
4049 match++;
4052 else
4053 if (bflags & BFLAGS_NonPublic)
4054 match ++;
4055 if (!match)
4056 continue;
4057 match = 0;
4058 if (method) {
4059 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4060 if (bflags & BFLAGS_Static)
4061 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4062 match++;
4063 } else {
4064 if (bflags & BFLAGS_Instance)
4065 match++;
4068 else
4069 if (bflags & BFLAGS_Instance)
4070 match ++;
4071 if (!match)
4072 continue;
4073 match = 0;
4074 if (i >= len) {
4075 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, len * 2);
4076 mono_array_memcpy_refs (new_res, 0, res, 0, len);
4077 len *= 2;
4078 res = new_res;
4080 mono_array_setref (res, i, mono_event_get_object (domain, startklass, event));
4081 ++i;
4083 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4084 goto handle_parent;
4085 if (i != len) {
4086 MonoArray *new_res = mono_array_new (domain, System_Reflection_EventInfo, i);
4087 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4088 res = new_res;
4090 * Better solution for the new GC.
4091 * res->max_length = i;
4094 return res;
4097 static MonoReflectionType *
4098 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4100 MonoDomain *domain;
4101 MonoClass *klass;
4102 MonoClass *nested;
4103 char *str;
4104 gpointer iter;
4106 MONO_ARCH_SAVE_REGS;
4108 domain = ((MonoObject *)type)->vtable->domain;
4109 if (type->type->byref)
4110 return NULL;
4111 klass = mono_class_from_mono_type (type->type);
4112 str = mono_string_to_utf8 (name);
4114 handle_parent:
4115 if (klass->exception_type != MONO_EXCEPTION_NONE)
4116 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4119 * If a nested type is generic, return its generic type definition.
4120 * Note that this means that the return value is essentially a
4121 * nested type of the generic type definition of @klass.
4123 * A note in MSDN claims that a generic type definition can have
4124 * nested types that aren't generic. In any case, the container of that
4125 * nested type would be the generic type definition.
4127 if (klass->generic_class)
4128 klass = klass->generic_class->container_class;
4130 iter = NULL;
4131 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4132 int match = 0;
4133 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4134 if (bflags & BFLAGS_Public)
4135 match++;
4136 } else {
4137 if (bflags & BFLAGS_NonPublic)
4138 match++;
4140 if (!match)
4141 continue;
4142 if (strcmp (nested->name, str) == 0){
4143 g_free (str);
4144 return mono_type_get_object (domain, &nested->byval_arg);
4147 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4148 goto handle_parent;
4149 g_free (str);
4150 return NULL;
4153 static MonoArray*
4154 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4156 MonoDomain *domain;
4157 MonoClass *klass;
4158 MonoArray *res;
4159 MonoObject *member;
4160 int i, len, match;
4161 MonoClass *nested;
4162 gpointer iter;
4164 MONO_ARCH_SAVE_REGS;
4166 domain = ((MonoObject *)type)->vtable->domain;
4167 if (type->type->byref)
4168 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4169 klass = mono_class_from_mono_type (type->type);
4170 if (klass->exception_type != MONO_EXCEPTION_NONE)
4171 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4174 * If a nested type is generic, return its generic type definition.
4175 * Note that this means that the return value is essentially the set
4176 * of nested types of the generic type definition of @klass.
4178 * A note in MSDN claims that a generic type definition can have
4179 * nested types that aren't generic. In any case, the container of that
4180 * nested type would be the generic type definition.
4182 if (klass->generic_class)
4183 klass = klass->generic_class->container_class;
4185 i = 0;
4186 len = 1;
4187 res = mono_array_new (domain, mono_defaults.monotype_class, len);
4188 iter = NULL;
4189 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4190 match = 0;
4191 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4192 if (bflags & BFLAGS_Public)
4193 match++;
4194 } else {
4195 if (bflags & BFLAGS_NonPublic)
4196 match++;
4198 if (!match)
4199 continue;
4200 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4201 if (i >= len) {
4202 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, len * 2);
4203 mono_array_memcpy_refs (new_res, 0, res, 0, len);
4204 len *= 2;
4205 res = new_res;
4207 mono_array_setref (res, i, member);
4208 ++i;
4210 if (i != len) {
4211 MonoArray *new_res = mono_array_new (domain, mono_defaults.monotype_class, i);
4212 mono_array_memcpy_refs (new_res, 0, res, 0, i);
4213 res = new_res;
4215 * Better solution for the new GC.
4216 * res->max_length = i;
4219 return res;
4222 static MonoReflectionType*
4223 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4225 gchar *str;
4226 MonoType *type = NULL;
4227 MonoTypeNameParse info;
4228 gboolean type_resolve;
4230 MONO_ARCH_SAVE_REGS;
4232 /* On MS.NET, this does not fire a TypeResolve event */
4233 type_resolve = TRUE;
4234 str = mono_string_to_utf8 (name);
4235 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4236 if (!mono_reflection_parse_type (str, &info)) {
4237 g_free (str);
4238 mono_reflection_free_type_info (&info);
4239 if (throwOnError) /* uhm: this is a parse error, though... */
4240 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4241 /*g_print ("failed parse\n");*/
4242 return NULL;
4245 if (info.assembly.name) {
4246 g_free (str);
4247 mono_reflection_free_type_info (&info);
4248 if (throwOnError) {
4249 /* 1.0 and 2.0 throw different exceptions */
4250 if (mono_defaults.generic_ilist_class)
4251 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4252 else
4253 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4255 return NULL;
4258 if (module != NULL) {
4259 if (module->image)
4260 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4261 else
4262 type = NULL;
4264 else
4265 if (assembly->assembly->dynamic) {
4266 /* Enumerate all modules */
4267 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4268 int i;
4270 type = NULL;
4271 if (abuilder->modules) {
4272 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4273 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4274 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4275 if (type)
4276 break;
4280 if (!type && abuilder->loaded_modules) {
4281 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4282 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4283 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4284 if (type)
4285 break;
4289 else
4290 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4291 g_free (str);
4292 mono_reflection_free_type_info (&info);
4293 if (!type) {
4294 MonoException *e = NULL;
4296 if (throwOnError)
4297 e = mono_get_exception_type_load (name, NULL);
4299 mono_loader_clear_error ();
4301 if (e != NULL)
4302 mono_raise_exception (e);
4304 return NULL;
4307 if (type->type == MONO_TYPE_CLASS) {
4308 MonoClass *klass = mono_type_get_class (type);
4310 if (mono_is_security_manager_active () && !klass->exception_type)
4311 /* Some security problems are detected during generic vtable construction */
4312 mono_class_setup_vtable (klass);
4313 /* need to report exceptions ? */
4314 if (throwOnError && klass->exception_type) {
4315 /* report SecurityException (or others) that occured when loading the assembly */
4316 MonoException *exc = mono_class_get_exception_for_failure (klass);
4317 mono_loader_clear_error ();
4318 mono_raise_exception (exc);
4319 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4320 return NULL;
4324 /* g_print ("got it\n"); */
4325 return mono_type_get_object (mono_object_domain (assembly), type);
4328 static MonoString *
4329 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4331 MonoDomain *domain = mono_object_domain (assembly);
4332 MonoAssembly *mass = assembly->assembly;
4333 MonoString *res = NULL;
4334 gchar *uri;
4335 gchar *absolute;
4336 gchar *content;
4337 gchar *shadow_ini_file;
4338 gsize len;
4339 gchar *dirname;
4341 MONO_ARCH_SAVE_REGS;
4343 if (g_path_is_absolute (mass->image->name)) {
4344 absolute = g_strdup (mass->image->name);
4345 dirname = g_path_get_dirname (absolute);
4346 } else {
4347 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4348 dirname = g_strdup (mass->basedir);
4351 /* Check for shadow-copied assembly */
4352 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4353 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4354 content = NULL;
4355 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4356 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4357 if (content) {
4358 g_free (content);
4359 content = NULL;
4362 g_free (shadow_ini_file);
4363 if (content != NULL) {
4364 g_free (absolute);
4365 absolute = content;
4368 g_free (dirname);
4370 #if PLATFORM_WIN32
4372 gint i;
4373 for (i = strlen (absolute) - 1; i >= 0; i--)
4374 if (absolute [i] == '\\')
4375 absolute [i] = '/';
4377 #endif
4378 if (escaped) {
4379 uri = g_filename_to_uri (absolute, NULL, NULL);
4380 } else {
4381 const char *prepend = "file://";
4382 #if PLATFORM_WIN32
4383 if (*absolute == '/' && *(absolute + 1) == '/') {
4384 prepend = "file:";
4385 } else {
4386 prepend = "file:///";
4388 #endif
4389 uri = g_strconcat (prepend, absolute, NULL);
4392 if (uri) {
4393 res = mono_string_new (domain, uri);
4394 g_free (uri);
4396 g_free (absolute);
4397 return res;
4400 static MonoBoolean
4401 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4403 MonoAssembly *mass = assembly->assembly;
4405 MONO_ARCH_SAVE_REGS;
4407 return mass->in_gac;
4410 static MonoReflectionAssembly*
4411 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4413 gchar *name;
4414 MonoAssembly *res;
4415 MonoImageOpenStatus status;
4417 MONO_ARCH_SAVE_REGS;
4419 name = mono_string_to_utf8 (mname);
4420 res = mono_assembly_load_with_partial_name (name, &status);
4422 g_free (name);
4424 if (res == NULL)
4425 return NULL;
4426 return mono_assembly_get_object (mono_domain_get (), res);
4429 static MonoString *
4430 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4432 MonoDomain *domain = mono_object_domain (assembly);
4433 MonoString *res;
4435 MONO_ARCH_SAVE_REGS;
4437 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4439 return res;
4442 static MonoBoolean
4443 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4445 MONO_ARCH_SAVE_REGS;
4447 return assembly->assembly->ref_only;
4450 static MonoString *
4451 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4453 MonoDomain *domain = mono_object_domain (assembly);
4455 MONO_ARCH_SAVE_REGS;
4457 return mono_string_new (domain, assembly->assembly->image->version);
4460 static MonoReflectionMethod*
4461 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4463 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4465 MONO_ARCH_SAVE_REGS;
4467 if (!token)
4468 return NULL;
4469 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4472 static MonoReflectionModule*
4473 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4475 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4478 static MonoArray*
4479 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4481 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4482 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4483 int i;
4484 const char *val;
4486 MONO_ARCH_SAVE_REGS;
4488 for (i = 0; i < table->rows; ++i) {
4489 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4490 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4492 return result;
4495 static MonoObject*
4496 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4498 static MonoClass *System_Version = NULL;
4499 static MonoMethod *create_version = NULL;
4500 MonoObject *result;
4501 gpointer args [4];
4503 if (!System_Version) {
4504 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4505 g_assert (System_Version);
4508 if (!create_version) {
4509 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4510 create_version = mono_method_desc_search_in_class (desc, System_Version);
4511 g_assert (create_version);
4512 mono_method_desc_free (desc);
4515 args [0] = &major;
4516 args [1] = &minor;
4517 args [2] = &build;
4518 args [3] = &revision;
4519 result = mono_object_new (domain, System_Version);
4520 mono_runtime_invoke (create_version, result, args, NULL);
4522 return result;
4525 static MonoArray*
4526 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4528 static MonoClass *System_Reflection_AssemblyName;
4529 MonoArray *result;
4530 MonoDomain *domain = mono_object_domain (assembly);
4531 int i, count = 0;
4532 static MonoMethod *create_culture = NULL;
4533 MonoImage *image = assembly->assembly->image;
4534 MonoTableInfo *t;
4536 MONO_ARCH_SAVE_REGS;
4538 if (!System_Reflection_AssemblyName)
4539 System_Reflection_AssemblyName = mono_class_from_name (
4540 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4542 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4543 count = t->rows;
4545 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4547 if (count > 0) {
4548 MonoMethodDesc *desc = mono_method_desc_new (
4549 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4550 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4551 g_assert (create_culture);
4552 mono_method_desc_free (desc);
4555 for (i = 0; i < count; i++) {
4556 MonoReflectionAssemblyName *aname;
4557 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4559 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4561 aname = (MonoReflectionAssemblyName *) mono_object_new (
4562 domain, System_Reflection_AssemblyName);
4564 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4566 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4567 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4568 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4569 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4570 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4571 aname->versioncompat = 1; /* SameMachine (default) */
4572 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4573 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4575 if (create_culture) {
4576 gpointer args [2];
4577 MonoBoolean assembly_ref = 1;
4578 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4579 args [1] = &assembly_ref;
4580 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4583 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4584 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4585 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4587 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4588 /* public key token isn't copied - the class library will
4589 automatically generate it from the public key if required */
4590 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4591 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4592 } else {
4593 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4594 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4596 } else {
4597 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4600 /* note: this function doesn't return the codebase on purpose (i.e. it can
4601 be used under partial trust as path information isn't present). */
4603 mono_array_setref (result, i, aname);
4605 return result;
4608 typedef struct {
4609 MonoArray *res;
4610 int idx;
4611 } NameSpaceInfo;
4613 static void
4614 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4616 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4618 mono_array_setref (info->res, info->idx, name);
4619 info->idx++;
4622 static MonoArray*
4623 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4625 MonoImage *img = assembly->assembly->image;
4626 MonoArray *res;
4627 NameSpaceInfo info;
4629 MONO_ARCH_SAVE_REGS;
4631 if (!img->name_cache)
4632 mono_image_init_name_cache (img);
4634 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4635 info.res = res;
4636 info.idx = 0;
4637 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4639 return res;
4642 /* move this in some file in mono/util/ */
4643 static char *
4644 g_concat_dir_and_file (const char *dir, const char *file)
4646 g_return_val_if_fail (dir != NULL, NULL);
4647 g_return_val_if_fail (file != NULL, NULL);
4650 * If the directory name doesn't have a / on the end, we need
4651 * to add one so we get a proper path to the file
4653 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4654 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4655 else
4656 return g_strconcat (dir, file, NULL);
4659 static void *
4660 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4662 char *n = mono_string_to_utf8 (name);
4663 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4664 guint32 i;
4665 guint32 cols [MONO_MANIFEST_SIZE];
4666 guint32 impl, file_idx;
4667 const char *val;
4668 MonoImage *module;
4670 MONO_ARCH_SAVE_REGS;
4672 for (i = 0; i < table->rows; ++i) {
4673 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4674 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4675 if (strcmp (val, n) == 0)
4676 break;
4678 g_free (n);
4679 if (i == table->rows)
4680 return NULL;
4681 /* FIXME */
4682 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4683 if (impl) {
4685 * this code should only be called after obtaining the
4686 * ResourceInfo and handling the other cases.
4688 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4689 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4691 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4692 if (!module)
4693 return NULL;
4695 else
4696 module = assembly->assembly->image;
4698 *ref_module = mono_module_get_object (mono_domain_get (), module);
4700 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4703 static gboolean
4704 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4706 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4707 int i;
4708 guint32 cols [MONO_MANIFEST_SIZE];
4709 guint32 file_cols [MONO_FILE_SIZE];
4710 const char *val;
4711 char *n;
4713 MONO_ARCH_SAVE_REGS;
4715 n = mono_string_to_utf8 (name);
4716 for (i = 0; i < table->rows; ++i) {
4717 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4718 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4719 if (strcmp (val, n) == 0)
4720 break;
4722 g_free (n);
4723 if (i == table->rows)
4724 return FALSE;
4726 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4727 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4729 else {
4730 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4731 case MONO_IMPLEMENTATION_FILE:
4732 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4733 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4734 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4735 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4736 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4737 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4738 info->location = 0;
4739 else
4740 info->location = RESOURCE_LOCATION_EMBEDDED;
4741 break;
4743 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4744 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4745 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4746 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4747 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4748 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4749 g_free (msg);
4750 mono_raise_exception (ex);
4752 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4754 /* Obtain info recursively */
4755 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4756 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4757 break;
4759 case MONO_IMPLEMENTATION_EXP_TYPE:
4760 g_assert_not_reached ();
4761 break;
4765 return TRUE;
4768 static MonoObject*
4769 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4771 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4772 MonoArray *result = NULL;
4773 int i, count;
4774 const char *val;
4775 char *n;
4777 MONO_ARCH_SAVE_REGS;
4779 /* check hash if needed */
4780 if (name) {
4781 n = mono_string_to_utf8 (name);
4782 for (i = 0; i < table->rows; ++i) {
4783 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4784 if (strcmp (val, n) == 0) {
4785 MonoString *fn;
4786 g_free (n);
4787 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4788 fn = mono_string_new (mono_object_domain (assembly), n);
4789 g_free (n);
4790 return (MonoObject*)fn;
4793 g_free (n);
4794 return NULL;
4797 count = 0;
4798 for (i = 0; i < table->rows; ++i) {
4799 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4800 count ++;
4803 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4805 count = 0;
4806 for (i = 0; i < table->rows; ++i) {
4807 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4808 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4809 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4810 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4811 g_free (n);
4812 count ++;
4815 return (MonoObject*)result;
4818 static MonoArray*
4819 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4821 MonoDomain *domain = mono_domain_get();
4822 MonoArray *res;
4823 MonoClass *klass;
4824 int i, j, file_count = 0;
4825 MonoImage **modules;
4826 guint32 module_count, real_module_count;
4827 MonoTableInfo *table;
4828 guint32 cols [MONO_FILE_SIZE];
4829 MonoImage *image = assembly->assembly->image;
4831 g_assert (image != NULL);
4832 g_assert (!assembly->assembly->dynamic);
4834 table = &image->tables [MONO_TABLE_FILE];
4835 file_count = table->rows;
4837 modules = image->modules;
4838 module_count = image->module_count;
4840 real_module_count = 0;
4841 for (i = 0; i < module_count; ++i)
4842 if (modules [i])
4843 real_module_count ++;
4845 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4846 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4848 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4849 j = 1;
4850 for (i = 0; i < module_count; ++i)
4851 if (modules [i]) {
4852 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4853 ++j;
4856 for (i = 0; i < file_count; ++i, ++j) {
4857 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4858 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4859 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4860 else {
4861 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4862 if (!m) {
4863 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4864 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4866 mono_array_setref (res, j, mono_module_get_object (domain, m));
4870 return res;
4873 static MonoReflectionMethod*
4874 ves_icall_GetCurrentMethod (void)
4876 MonoMethod *m = mono_method_get_last_managed ();
4878 MONO_ARCH_SAVE_REGS;
4880 return mono_method_get_object (mono_domain_get (), m, NULL);
4884 static MonoMethod*
4885 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4887 int offset = -1, i;
4888 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4889 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4890 //method is inflated, we should inflate it on the other class
4891 MonoGenericContext ctx;
4892 ctx.method_inst = inflated->context.method_inst;
4893 ctx.class_inst = inflated->context.class_inst;
4894 if (klass->generic_class)
4895 ctx.class_inst = klass->generic_class->context.class_inst;
4896 else if (klass->generic_container)
4897 ctx.class_inst = klass->generic_container->context.class_inst;
4898 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4901 mono_class_setup_methods (method->klass);
4902 for (i = 0; i < method->klass->method.count; ++i) {
4903 if (method->klass->methods [i] == method) {
4904 offset = i;
4905 break;
4908 mono_class_setup_methods (klass);
4909 g_assert (offset >= 0 && offset < klass->method.count);
4910 return klass->methods [offset];
4913 static MonoReflectionMethod*
4914 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4916 MonoClass *klass;
4917 if (type) {
4918 klass = mono_class_from_mono_type (type);
4919 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4920 return NULL;
4921 if (method->klass != klass)
4922 method = mono_method_get_equivalent_method (method, klass);
4923 } else
4924 klass = method->klass;
4925 return mono_method_get_object (mono_domain_get (), method, klass);
4928 static MonoReflectionMethod*
4929 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4931 return mono_method_get_object (mono_domain_get (), method, NULL);
4934 static MonoReflectionMethodBody*
4935 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4937 return mono_method_body_get_object (mono_domain_get (), method);
4940 static MonoReflectionAssembly*
4941 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4943 MonoMethod *dest = NULL;
4945 MONO_ARCH_SAVE_REGS;
4947 mono_stack_walk_no_il (get_executing, &dest);
4948 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4952 static MonoReflectionAssembly*
4953 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4955 MonoDomain* domain = mono_domain_get ();
4957 MONO_ARCH_SAVE_REGS;
4959 if (!domain->entry_assembly)
4960 return NULL;
4962 return mono_assembly_get_object (domain, domain->entry_assembly);
4965 static MonoReflectionAssembly*
4966 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4968 MonoMethod *m;
4969 MonoMethod *dest;
4971 MONO_ARCH_SAVE_REGS;
4973 dest = NULL;
4974 mono_stack_walk_no_il (get_executing, &dest);
4975 m = dest;
4976 mono_stack_walk_no_il (get_caller, &dest);
4977 if (!dest)
4978 dest = m;
4979 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4982 static MonoString *
4983 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4984 gboolean assembly_qualified)
4986 MonoDomain *domain = mono_object_domain (object);
4987 MonoTypeNameFormat format;
4988 MonoString *res;
4989 gchar *name;
4991 MONO_ARCH_SAVE_REGS;
4992 if (full_name)
4993 format = assembly_qualified ?
4994 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4995 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4996 else
4997 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4999 name = mono_type_get_name_full (object->type, format);
5000 if (!name)
5001 return NULL;
5003 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5004 g_free (name);
5005 return NULL;
5008 res = mono_string_new (domain, name);
5009 g_free (name);
5011 return res;
5014 static void
5015 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5017 static MonoMethod *create_culture = NULL;
5018 gpointer args [2];
5019 guint32 pkey_len;
5020 const char *pkey_ptr;
5021 gchar *codebase;
5022 MonoBoolean assembly_ref = 0;
5024 MONO_ARCH_SAVE_REGS;
5026 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5027 aname->major = name->major;
5028 aname->minor = name->minor;
5029 aname->build = name->build;
5030 aname->flags = name->flags;
5031 aname->revision = name->revision;
5032 aname->hashalg = name->hash_alg;
5033 aname->versioncompat = 1; /* SameMachine (default) */
5035 if (by_default_version)
5036 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5038 codebase = NULL;
5039 if (absolute != NULL && *absolute != '\0') {
5040 const gchar *prepend = "file://";
5041 gchar *result;
5043 codebase = g_strdup (absolute);
5045 #if PLATFORM_WIN32
5047 gint i;
5048 for (i = strlen (codebase) - 1; i >= 0; i--)
5049 if (codebase [i] == '\\')
5050 codebase [i] = '/';
5052 if (*codebase == '/' && *(codebase + 1) == '/') {
5053 prepend = "file:";
5054 } else {
5055 prepend = "file:///";
5058 #endif
5059 result = g_strconcat (prepend, codebase, NULL);
5060 g_free (codebase);
5061 codebase = result;
5064 if (codebase) {
5065 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5066 g_free (codebase);
5069 if (!create_culture) {
5070 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5071 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5072 g_assert (create_culture);
5073 mono_method_desc_free (desc);
5076 if (name->culture) {
5077 args [0] = mono_string_new (domain, name->culture);
5078 args [1] = &assembly_ref;
5079 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5082 if (name->public_key) {
5083 pkey_ptr = (char*)name->public_key;
5084 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5086 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5087 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5088 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5089 } else if (default_publickey) {
5090 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5091 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5094 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5095 if (name->public_key_token [0]) {
5096 int i, j;
5097 char *p;
5099 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5100 p = mono_array_addr (aname->keyToken, char, 0);
5102 for (i = 0, j = 0; i < 8; i++) {
5103 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5104 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5105 p++;
5107 } else if (default_token) {
5108 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5112 static MonoString *
5113 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5115 MonoDomain *domain = mono_object_domain (assembly);
5116 MonoAssembly *mass = assembly->assembly;
5117 MonoString *res;
5118 gchar *name;
5120 name = g_strdup_printf (
5121 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5122 mass->aname.name,
5123 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5124 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5125 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5126 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5128 res = mono_string_new (domain, name);
5129 g_free (name);
5131 return res;
5134 static void
5135 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5137 gchar *absolute;
5138 MonoAssembly *mass = assembly->assembly;
5140 MONO_ARCH_SAVE_REGS;
5142 if (g_path_is_absolute (mass->image->name)) {
5143 fill_reflection_assembly_name (mono_object_domain (assembly),
5144 aname, &mass->aname, mass->image->name, TRUE,
5145 TRUE, mono_framework_version () >= 2);
5146 return;
5148 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5150 fill_reflection_assembly_name (mono_object_domain (assembly),
5151 aname, &mass->aname, absolute, TRUE, TRUE,
5152 mono_framework_version () >= 2);
5154 g_free (absolute);
5157 static void
5158 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5160 char *filename;
5161 MonoImageOpenStatus status = MONO_IMAGE_OK;
5162 gboolean res;
5163 MonoImage *image;
5164 MonoAssemblyName name;
5166 MONO_ARCH_SAVE_REGS;
5168 filename = mono_string_to_utf8 (fname);
5170 image = mono_image_open (filename, &status);
5172 if (!image){
5173 MonoException *exc;
5175 g_free (filename);
5176 if (status == MONO_IMAGE_IMAGE_INVALID)
5177 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5178 else
5179 exc = mono_get_exception_file_not_found2 (NULL, fname);
5180 mono_raise_exception (exc);
5183 res = mono_assembly_fill_assembly_name (image, &name);
5184 if (!res) {
5185 mono_image_close (image);
5186 g_free (filename);
5187 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5190 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5191 TRUE, mono_framework_version () == 1,
5192 mono_framework_version () >= 2);
5194 g_free (filename);
5195 mono_image_close (image);
5198 static MonoBoolean
5199 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5200 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5202 MonoBoolean result = FALSE;
5203 MonoDeclSecurityEntry entry;
5205 /* SecurityAction.RequestMinimum */
5206 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5207 *minimum = entry.blob;
5208 *minLength = entry.size;
5209 result = TRUE;
5211 /* SecurityAction.RequestOptional */
5212 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5213 *optional = entry.blob;
5214 *optLength = entry.size;
5215 result = TRUE;
5217 /* SecurityAction.RequestRefuse */
5218 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5219 *refused = entry.blob;
5220 *refLength = entry.size;
5221 result = TRUE;
5224 return result;
5227 static MonoArray*
5228 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5230 MonoArray *res;
5231 MonoClass *klass;
5232 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5233 int i, count;
5234 guint32 attrs, visibility;
5236 /* we start the count from 1 because we skip the special type <Module> */
5237 if (exportedOnly) {
5238 count = 0;
5239 for (i = 1; i < tdef->rows; ++i) {
5240 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5241 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5242 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5243 count++;
5245 } else {
5246 count = tdef->rows - 1;
5248 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5249 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5250 count = 0;
5251 for (i = 1; i < tdef->rows; ++i) {
5252 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5253 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5254 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5255 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5256 if (klass) {
5257 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5258 } else {
5259 MonoLoaderError *error;
5260 MonoException *ex;
5262 error = mono_loader_get_last_error ();
5263 g_assert (error != NULL);
5265 ex = mono_loader_error_prepare_exception (error);
5266 mono_array_setref (*exceptions, count, ex);
5268 if (mono_loader_get_last_error ())
5269 mono_loader_clear_error ();
5270 count++;
5274 return res;
5277 static MonoArray*
5278 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5280 MonoArray *res = NULL;
5281 MonoArray *exceptions = NULL;
5282 MonoImage *image = NULL;
5283 MonoTableInfo *table = NULL;
5284 MonoDomain *domain;
5285 GList *list = NULL;
5286 int i, len, ex_count;
5288 MONO_ARCH_SAVE_REGS;
5290 domain = mono_object_domain (assembly);
5292 g_assert (!assembly->assembly->dynamic);
5293 image = assembly->assembly->image;
5294 table = &image->tables [MONO_TABLE_FILE];
5295 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5297 /* Append data from all modules in the assembly */
5298 for (i = 0; i < table->rows; ++i) {
5299 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5300 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5301 if (loaded_image) {
5302 MonoArray *ex2;
5303 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5304 /* Append the new types to the end of the array */
5305 if (mono_array_length (res2) > 0) {
5306 guint32 len1, len2;
5307 MonoArray *res3, *ex3;
5309 len1 = mono_array_length (res);
5310 len2 = mono_array_length (res2);
5312 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5313 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5314 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5315 res = res3;
5317 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5318 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5319 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5320 exceptions = ex3;
5326 /* the ReflectionTypeLoadException must have all the types (Types property),
5327 * NULL replacing types which throws an exception. The LoaderException must
5328 * contain all exceptions for NULL items.
5331 len = mono_array_length (res);
5333 ex_count = 0;
5334 for (i = 0; i < len; i++) {
5335 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5336 MonoClass *klass;
5338 if (t) {
5339 klass = mono_type_get_class (t->type);
5340 if ((klass != NULL) && klass->exception_type) {
5341 /* keep the class in the list */
5342 list = g_list_append (list, klass);
5343 /* and replace Type with NULL */
5344 mono_array_setref (res, i, NULL);
5346 } else {
5347 ex_count ++;
5351 if (list || ex_count) {
5352 GList *tmp = NULL;
5353 MonoException *exc = NULL;
5354 MonoArray *exl = NULL;
5355 int j, length = g_list_length (list) + ex_count;
5357 mono_loader_clear_error ();
5359 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5360 /* Types for which mono_class_get () succeeded */
5361 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5362 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5363 mono_array_setref (exl, i, exc);
5365 /* Types for which it don't */
5366 for (j = 0; j < mono_array_length (exceptions); ++j) {
5367 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5368 if (exc) {
5369 g_assert (i < length);
5370 mono_array_setref (exl, i, exc);
5371 i ++;
5374 g_list_free (list);
5375 list = NULL;
5377 exc = mono_get_exception_reflection_type_load (res, exl);
5378 mono_loader_clear_error ();
5379 mono_raise_exception (exc);
5382 return res;
5385 static gboolean
5386 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5388 MonoAssemblyName aname;
5389 MonoDomain *domain = mono_object_domain (name);
5390 char *val;
5391 gboolean is_version_defined;
5392 gboolean is_token_defined;
5394 aname.public_key = NULL;
5395 val = mono_string_to_utf8 (assname);
5396 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5397 g_free ((guint8*) aname.public_key);
5398 g_free (val);
5399 return FALSE;
5402 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5403 FALSE, is_token_defined);
5405 mono_assembly_name_free (&aname);
5406 g_free ((guint8*) aname.public_key);
5407 g_free (val);
5409 return TRUE;
5412 static MonoReflectionType*
5413 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5415 MonoDomain *domain = mono_object_domain (module);
5416 MonoClass *klass;
5418 MONO_ARCH_SAVE_REGS;
5420 g_assert (module->image);
5422 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5423 /* These images do not have a global type */
5424 return NULL;
5426 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5427 return mono_type_get_object (domain, &klass->byval_arg);
5430 static void
5431 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5433 /*if (module->image)
5434 mono_image_close (module->image);*/
5437 static MonoString*
5438 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5440 MonoDomain *domain = mono_object_domain (module);
5442 MONO_ARCH_SAVE_REGS;
5444 g_assert (module->image);
5445 return mono_string_new (domain, module->image->guid);
5448 static gpointer
5449 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5451 #ifdef PLATFORM_WIN32
5452 if (module->image && module->image->is_module_handle)
5453 return module->image->raw_data;
5454 #endif
5456 return (gpointer) (-1);
5459 static void
5460 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5462 if (image->dynamic) {
5463 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5464 *pe_kind = dyn->pe_kind;
5465 *machine = dyn->machine;
5467 else {
5468 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5469 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5473 static gint32
5474 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5476 return (image->md_version_major << 16) | (image->md_version_minor);
5479 static MonoArray*
5480 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5482 MonoArray *exceptions;
5483 int i;
5485 MONO_ARCH_SAVE_REGS;
5487 if (!module->image)
5488 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5489 else {
5490 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5491 for (i = 0; i < mono_array_length (exceptions); ++i) {
5492 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5493 if (ex)
5494 mono_raise_exception (ex);
5496 return res;
5500 static gboolean
5501 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5503 guint32 cols [MONO_MEMBERREF_SIZE];
5504 const char *sig;
5505 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5506 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5507 mono_metadata_decode_blob_size (sig, &sig);
5508 return (*sig != 0x6);
5511 static void
5512 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5514 if (type_args)
5515 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5516 mono_array_addr (type_args, MonoType*, 0));
5517 else
5518 context->class_inst = NULL;
5519 if (method_args)
5520 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5521 mono_array_addr (method_args, MonoType*, 0));
5522 else
5523 context->method_inst = NULL;
5526 static MonoType*
5527 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5529 MonoClass *klass;
5530 int table = mono_metadata_token_table (token);
5531 int index = mono_metadata_token_index (token);
5532 MonoGenericContext context;
5534 *error = ResolveTokenError_Other;
5536 /* Validate token */
5537 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5538 (table != MONO_TABLE_TYPESPEC)) {
5539 *error = ResolveTokenError_BadTable;
5540 return NULL;
5543 if (image->dynamic) {
5544 if (type_args || method_args)
5545 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5546 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5547 if (!klass)
5548 return NULL;
5549 return &klass->byval_arg;
5552 if ((index <= 0) || (index > image->tables [table].rows)) {
5553 *error = ResolveTokenError_OutOfRange;
5554 return NULL;
5557 init_generic_context_from_args (&context, type_args, method_args);
5558 klass = mono_class_get_full (image, token, &context);
5560 if (mono_loader_get_last_error ())
5561 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5563 if (klass)
5564 return &klass->byval_arg;
5565 else
5566 return NULL;
5569 static MonoMethod*
5570 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5572 int table = mono_metadata_token_table (token);
5573 int index = mono_metadata_token_index (token);
5574 MonoGenericContext context;
5575 MonoMethod *method;
5577 *error = ResolveTokenError_Other;
5579 /* Validate token */
5580 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5581 (table != MONO_TABLE_MEMBERREF)) {
5582 *error = ResolveTokenError_BadTable;
5583 return NULL;
5586 if (image->dynamic) {
5587 if (type_args || method_args)
5588 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5589 /* FIXME: validate memberref token type */
5590 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5593 if ((index <= 0) || (index > image->tables [table].rows)) {
5594 *error = ResolveTokenError_OutOfRange;
5595 return NULL;
5597 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5598 *error = ResolveTokenError_BadTable;
5599 return NULL;
5602 init_generic_context_from_args (&context, type_args, method_args);
5603 method = mono_get_method_full (image, token, NULL, &context);
5605 if (mono_loader_get_last_error ())
5606 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5608 return method;
5611 static MonoString*
5612 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5614 int index = mono_metadata_token_index (token);
5616 *error = ResolveTokenError_Other;
5618 /* Validate token */
5619 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5620 *error = ResolveTokenError_BadTable;
5621 return NULL;
5624 if (image->dynamic)
5625 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5627 if ((index <= 0) || (index >= image->heap_us.size)) {
5628 *error = ResolveTokenError_OutOfRange;
5629 return NULL;
5632 /* FIXME: What to do if the index points into the middle of a string ? */
5634 return mono_ldstr (mono_domain_get (), image, index);
5637 static MonoClassField*
5638 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5640 MonoClass *klass;
5641 int table = mono_metadata_token_table (token);
5642 int index = mono_metadata_token_index (token);
5643 MonoGenericContext context;
5644 MonoClassField *field;
5646 *error = ResolveTokenError_Other;
5648 /* Validate token */
5649 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5650 *error = ResolveTokenError_BadTable;
5651 return NULL;
5654 if (image->dynamic) {
5655 if (type_args || method_args)
5656 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5657 /* FIXME: validate memberref token type */
5658 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5661 if ((index <= 0) || (index > image->tables [table].rows)) {
5662 *error = ResolveTokenError_OutOfRange;
5663 return NULL;
5665 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5666 *error = ResolveTokenError_BadTable;
5667 return NULL;
5670 init_generic_context_from_args (&context, type_args, method_args);
5671 field = mono_field_from_token (image, token, &klass, &context);
5673 if (mono_loader_get_last_error ())
5674 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5676 return field;
5680 static MonoObject*
5681 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5683 int table = mono_metadata_token_table (token);
5685 *error = ResolveTokenError_Other;
5687 switch (table) {
5688 case MONO_TABLE_TYPEDEF:
5689 case MONO_TABLE_TYPEREF:
5690 case MONO_TABLE_TYPESPEC: {
5691 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5692 if (t)
5693 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5694 else
5695 return NULL;
5697 case MONO_TABLE_METHOD:
5698 case MONO_TABLE_METHODSPEC: {
5699 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5700 if (m)
5701 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5702 else
5703 return NULL;
5705 case MONO_TABLE_FIELD: {
5706 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5707 if (f)
5708 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5709 else
5710 return NULL;
5712 case MONO_TABLE_MEMBERREF:
5713 if (mono_metadata_memberref_is_method (image, token)) {
5714 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5715 if (m)
5716 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5717 else
5718 return NULL;
5720 else {
5721 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5722 if (f)
5723 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5724 else
5725 return NULL;
5727 break;
5729 default:
5730 *error = ResolveTokenError_BadTable;
5733 return NULL;
5736 static MonoArray*
5737 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5739 int table = mono_metadata_token_table (token);
5740 int idx = mono_metadata_token_index (token);
5741 MonoTableInfo *tables = image->tables;
5742 guint32 sig, len;
5743 const char *ptr;
5744 MonoArray *res;
5746 *error = ResolveTokenError_OutOfRange;
5748 /* FIXME: Support other tables ? */
5749 if (table != MONO_TABLE_STANDALONESIG)
5750 return NULL;
5752 if (image->dynamic)
5753 return NULL;
5755 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5756 return NULL;
5758 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5760 ptr = mono_metadata_blob_heap (image, sig);
5761 len = mono_metadata_decode_blob_size (ptr, &ptr);
5763 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5764 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5765 return res;
5768 static MonoReflectionType*
5769 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5771 MonoClass *klass;
5772 int isbyref = 0, rank;
5773 char *str = mono_string_to_utf8 (smodifiers);
5774 char *p;
5776 MONO_ARCH_SAVE_REGS;
5778 klass = mono_class_from_mono_type (tb->type.type);
5779 p = str;
5780 /* logic taken from mono_reflection_parse_type(): keep in sync */
5781 while (*p) {
5782 switch (*p) {
5783 case '&':
5784 if (isbyref) { /* only one level allowed by the spec */
5785 g_free (str);
5786 return NULL;
5788 isbyref = 1;
5789 p++;
5790 g_free (str);
5791 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5792 break;
5793 case '*':
5794 klass = mono_ptr_class_get (&klass->byval_arg);
5795 mono_class_init (klass);
5796 p++;
5797 break;
5798 case '[':
5799 rank = 1;
5800 p++;
5801 while (*p) {
5802 if (*p == ']')
5803 break;
5804 if (*p == ',')
5805 rank++;
5806 else if (*p != '*') { /* '*' means unknown lower bound */
5807 g_free (str);
5808 return NULL;
5810 ++p;
5812 if (*p != ']') {
5813 g_free (str);
5814 return NULL;
5816 p++;
5817 klass = mono_array_class_get (klass, rank);
5818 mono_class_init (klass);
5819 break;
5820 default:
5821 break;
5824 g_free (str);
5825 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5828 static MonoBoolean
5829 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5831 MonoType *type;
5832 MonoBoolean res;
5834 MONO_ARCH_SAVE_REGS;
5836 type = t->type;
5837 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5839 return res;
5842 static MonoReflectionType *
5843 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5845 MonoClass *klass, *aklass;
5847 MONO_ARCH_SAVE_REGS;
5849 klass = mono_class_from_mono_type (type->type);
5850 aklass = mono_array_class_get (klass, rank);
5852 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5855 static MonoReflectionType *
5856 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5858 MonoClass *klass;
5860 MONO_ARCH_SAVE_REGS;
5862 klass = mono_class_from_mono_type (type->type);
5864 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5867 static MonoReflectionType *
5868 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5870 MonoClass *pklass;
5872 MONO_ARCH_SAVE_REGS;
5874 pklass = mono_ptr_class_get (type->type);
5876 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5879 static MonoObject *
5880 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5881 MonoReflectionMethod *info)
5883 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5884 MonoObject *delegate;
5885 gpointer func;
5886 MonoMethod *method = info->method;
5888 MONO_ARCH_SAVE_REGS;
5890 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5892 /* FIME: We must check if target is visible to the caller under coreclr.
5893 * The check should be disabled otherwise as it shouldn't raise expection under fulltrust.
5896 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5898 if (mono_method_needs_static_rgctx_invoke (method, FALSE)) {
5899 method = mono_marshal_get_static_rgctx_invoke (method);
5900 func = mono_compile_method (method);
5901 } else if (method->dynamic) {
5902 /* Creating a trampoline would leak memory */
5903 func = mono_compile_method (method);
5904 } else {
5905 func = mono_create_ftnptr (mono_domain_get (),
5906 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5909 mono_delegate_ctor_with_method (delegate, target, func, method);
5911 return delegate;
5914 static void
5915 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5917 /* Reset the invoke impl to the default one */
5918 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5922 * Magic number to convert a time which is relative to
5923 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5925 #define EPOCH_ADJUST ((guint64)62135596800LL)
5928 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5930 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5932 #ifdef PLATFORM_WIN32
5933 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5934 static void
5935 convert_to_absolute_date(SYSTEMTIME *date)
5937 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5938 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5939 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5940 /* from the calendar FAQ */
5941 int a = (14 - date->wMonth) / 12;
5942 int y = date->wYear - a;
5943 int m = date->wMonth + 12 * a - 2;
5944 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5946 /* d is now the day of the week for the first of the month (0 == Sunday) */
5948 int day_of_week = date->wDayOfWeek;
5950 /* set day_in_month to the first day in the month which falls on day_of_week */
5951 int day_in_month = 1 + (day_of_week - d);
5952 if (day_in_month <= 0)
5953 day_in_month += 7;
5955 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5956 date->wDay = day_in_month + (date->wDay - 1) * 7;
5957 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5958 date->wDay -= 7;
5960 #endif
5962 #ifndef PLATFORM_WIN32
5964 * Return's the offset from GMT of a local time.
5966 * tm is a local time
5967 * t is the same local time as seconds.
5969 static int
5970 gmt_offset(struct tm *tm, time_t t)
5972 #if defined (HAVE_TM_GMTOFF)
5973 return tm->tm_gmtoff;
5974 #else
5975 struct tm g;
5976 time_t t2;
5977 g = *gmtime(&t);
5978 g.tm_isdst = tm->tm_isdst;
5979 t2 = mktime(&g);
5980 return (int)difftime(t, t2);
5981 #endif
5983 #endif
5985 * This is heavily based on zdump.c from glibc 2.2.
5987 * * data[0]: start of daylight saving time (in DateTime ticks).
5988 * * data[1]: end of daylight saving time (in DateTime ticks).
5989 * * data[2]: utcoffset (in TimeSpan ticks).
5990 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5991 * * name[0]: name of this timezone when not daylight saving.
5992 * * name[1]: name of this timezone when daylight saving.
5994 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5995 * the class library allows years between 1 and 9999.
5997 * Returns true on success and zero on failure.
5999 static guint32
6000 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6002 #ifndef PLATFORM_WIN32
6003 MonoDomain *domain = mono_domain_get ();
6004 struct tm start, tt;
6005 time_t t;
6007 long int gmtoff;
6008 int is_daylight = 0, day;
6009 char tzone [64];
6011 MONO_ARCH_SAVE_REGS;
6013 MONO_CHECK_ARG_NULL (data);
6014 MONO_CHECK_ARG_NULL (names);
6016 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6017 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6020 * no info is better than crashing: we'll need our own tz data
6021 * to make this work properly, anyway. The range is probably
6022 * reduced to 1970 .. 2037 because that is what mktime is
6023 * guaranteed to support (we get into an infinite loop
6024 * otherwise).
6027 memset (&start, 0, sizeof (start));
6029 start.tm_mday = 1;
6030 start.tm_year = year-1900;
6032 t = mktime (&start);
6034 if ((year < 1970) || (year > 2037) || (t == -1)) {
6035 t = time (NULL);
6036 tt = *localtime (&t);
6037 strftime (tzone, sizeof (tzone), "%Z", &tt);
6038 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6039 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6040 return 1;
6043 gmtoff = gmt_offset (&start, t);
6045 /* For each day of the year, calculate the tm_gmtoff. */
6046 for (day = 0; day < 365; day++) {
6048 t += 3600*24;
6049 tt = *localtime (&t);
6051 /* Daylight saving starts or ends here. */
6052 if (gmt_offset (&tt, t) != gmtoff) {
6053 struct tm tt1;
6054 time_t t1;
6056 /* Try to find the exact hour when daylight saving starts/ends. */
6057 t1 = t;
6058 do {
6059 t1 -= 3600;
6060 tt1 = *localtime (&t1);
6061 } while (gmt_offset (&tt1, t1) != gmtoff);
6063 /* Try to find the exact minute when daylight saving starts/ends. */
6064 do {
6065 t1 += 60;
6066 tt1 = *localtime (&t1);
6067 } while (gmt_offset (&tt1, t1) == gmtoff);
6068 t1+=gmtoff;
6069 strftime (tzone, sizeof (tzone), "%Z", &tt);
6071 /* Write data, if we're already in daylight saving, we're done. */
6072 if (is_daylight) {
6073 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6074 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6075 return 1;
6076 } else {
6077 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6078 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6079 is_daylight = 1;
6082 /* This is only set once when we enter daylight saving. */
6083 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6084 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6086 gmtoff = gmt_offset (&tt, t);
6090 if (!is_daylight) {
6091 strftime (tzone, sizeof (tzone), "%Z", &tt);
6092 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6093 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6094 mono_array_set ((*data), gint64, 0, 0);
6095 mono_array_set ((*data), gint64, 1, 0);
6096 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6097 mono_array_set ((*data), gint64, 3, 0);
6100 return 1;
6101 #else
6102 MonoDomain *domain = mono_domain_get ();
6103 TIME_ZONE_INFORMATION tz_info;
6104 FILETIME ft;
6105 int i;
6106 int err, tz_id;
6108 tz_id = GetTimeZoneInformation (&tz_info);
6109 if (tz_id == TIME_ZONE_ID_INVALID)
6110 return 0;
6112 MONO_CHECK_ARG_NULL (data);
6113 MONO_CHECK_ARG_NULL (names);
6115 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6116 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6118 for (i = 0; i < 32; ++i)
6119 if (!tz_info.DaylightName [i])
6120 break;
6121 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6122 for (i = 0; i < 32; ++i)
6123 if (!tz_info.StandardName [i])
6124 break;
6125 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6127 if ((year <= 1601) || (year > 30827)) {
6129 * According to MSDN, the MS time functions can't handle dates outside
6130 * this interval.
6132 return 1;
6135 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6136 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6137 tz_info.StandardDate.wYear = year;
6138 convert_to_absolute_date(&tz_info.StandardDate);
6139 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6140 //g_assert(err);
6141 if (err == 0)
6142 return 0;
6144 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6145 tz_info.DaylightDate.wYear = year;
6146 convert_to_absolute_date(&tz_info.DaylightDate);
6147 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6148 //g_assert(err);
6149 if (err == 0)
6150 return 0;
6152 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6154 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6155 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6157 return 1;
6158 #endif
6161 static gpointer
6162 ves_icall_System_Object_obj_address (MonoObject *this)
6164 MONO_ARCH_SAVE_REGS;
6166 return this;
6169 /* System.Buffer */
6171 static inline gint32
6172 mono_array_get_byte_length (MonoArray *array)
6174 MonoClass *klass;
6175 int length;
6176 int i;
6178 klass = array->obj.vtable->klass;
6180 if (array->bounds == NULL)
6181 length = array->max_length;
6182 else {
6183 length = 1;
6184 for (i = 0; i < klass->rank; ++ i)
6185 length *= array->bounds [i].length;
6188 switch (klass->element_class->byval_arg.type) {
6189 case MONO_TYPE_I1:
6190 case MONO_TYPE_U1:
6191 case MONO_TYPE_BOOLEAN:
6192 return length;
6193 case MONO_TYPE_I2:
6194 case MONO_TYPE_U2:
6195 case MONO_TYPE_CHAR:
6196 return length << 1;
6197 case MONO_TYPE_I4:
6198 case MONO_TYPE_U4:
6199 case MONO_TYPE_R4:
6200 return length << 2;
6201 case MONO_TYPE_I:
6202 case MONO_TYPE_U:
6203 return length * sizeof (gpointer);
6204 case MONO_TYPE_I8:
6205 case MONO_TYPE_U8:
6206 case MONO_TYPE_R8:
6207 return length << 3;
6208 default:
6209 return -1;
6213 static gint32
6214 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6216 MONO_ARCH_SAVE_REGS;
6218 return mono_array_get_byte_length (array);
6221 static gint8
6222 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6224 MONO_ARCH_SAVE_REGS;
6226 return mono_array_get (array, gint8, idx);
6229 static void
6230 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6232 MONO_ARCH_SAVE_REGS;
6234 mono_array_set (array, gint8, idx, value);
6237 static MonoBoolean
6238 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6240 guint8 *src_buf, *dest_buf;
6242 MONO_ARCH_SAVE_REGS;
6244 /* watch out for integer overflow */
6245 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6246 return FALSE;
6248 src_buf = (guint8 *)src->vector + src_offset;
6249 dest_buf = (guint8 *)dest->vector + dest_offset;
6251 if (src != dest)
6252 memcpy (dest_buf, src_buf, count);
6253 else
6254 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6256 return TRUE;
6259 static MonoObject *
6260 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6262 MonoDomain *domain = mono_object_domain (this);
6263 MonoObject *res;
6264 MonoRealProxy *rp = ((MonoRealProxy *)this);
6265 MonoTransparentProxy *tp;
6266 MonoType *type;
6267 MonoClass *klass;
6269 MONO_ARCH_SAVE_REGS;
6271 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6272 tp = (MonoTransparentProxy*) res;
6274 MONO_OBJECT_SETREF (tp, rp, rp);
6275 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6276 klass = mono_class_from_mono_type (type);
6278 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6279 tp->remote_class = mono_remote_class (domain, class_name, klass);
6281 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6282 return res;
6285 static MonoReflectionType *
6286 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6288 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6291 /* System.Environment */
6293 static MonoString *
6294 ves_icall_System_Environment_get_MachineName (void)
6296 #if defined (PLATFORM_WIN32)
6297 gunichar2 *buf;
6298 guint32 len;
6299 MonoString *result;
6301 len = MAX_COMPUTERNAME_LENGTH + 1;
6302 buf = g_new (gunichar2, len);
6304 result = NULL;
6305 if (GetComputerName (buf, (PDWORD) &len))
6306 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6308 g_free (buf);
6309 return result;
6310 #else
6311 gchar buf [256];
6312 MonoString *result;
6314 if (gethostname (buf, sizeof (buf)) == 0)
6315 result = mono_string_new (mono_domain_get (), buf);
6316 else
6317 result = NULL;
6319 return result;
6320 #endif
6323 static int
6324 ves_icall_System_Environment_get_Platform (void)
6326 #if defined (PLATFORM_WIN32)
6327 /* Win32NT */
6328 return 2;
6329 #elif defined(__MACH__)
6330 /* OSX */
6331 if (mono_framework_version () < 2)
6332 return 128;
6333 return 6;
6334 #else
6335 /* Unix */
6336 if (mono_framework_version () < 2)
6337 return 128;
6338 return 4;
6339 #endif
6342 static MonoString *
6343 ves_icall_System_Environment_get_NewLine (void)
6345 MONO_ARCH_SAVE_REGS;
6347 #if defined (PLATFORM_WIN32)
6348 return mono_string_new (mono_domain_get (), "\r\n");
6349 #else
6350 return mono_string_new (mono_domain_get (), "\n");
6351 #endif
6354 static MonoString *
6355 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6357 const gchar *value;
6358 gchar *utf8_name;
6360 MONO_ARCH_SAVE_REGS;
6362 if (name == NULL)
6363 return NULL;
6365 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6366 value = g_getenv (utf8_name);
6368 g_free (utf8_name);
6370 if (value == 0)
6371 return NULL;
6373 return mono_string_new (mono_domain_get (), value);
6377 * There is no standard way to get at environ.
6379 #ifndef _MSC_VER
6380 #ifndef __MINGW32_VERSION
6381 #ifdef __APPLE__
6382 /* Apple defines this in crt_externs.h but doesn't provide that header for
6383 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6384 * in fact exist on all implementations (so far)
6386 gchar ***_NSGetEnviron();
6387 #define environ (*_NSGetEnviron())
6388 #else
6389 extern
6390 char **environ;
6391 #endif
6392 #endif
6393 #endif
6395 static MonoArray *
6396 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6398 #ifdef PLATFORM_WIN32
6399 MonoArray *names;
6400 MonoDomain *domain;
6401 MonoString *str;
6402 WCHAR* env_strings;
6403 WCHAR* env_string;
6404 WCHAR* equal_str;
6405 int n = 0;
6407 env_strings = GetEnvironmentStrings();
6409 if (env_strings) {
6410 env_string = env_strings;
6411 while (*env_string != '\0') {
6412 /* weird case that MS seems to skip */
6413 if (*env_string != '=')
6414 n++;
6415 while (*env_string != '\0')
6416 env_string++;
6417 env_string++;
6421 domain = mono_domain_get ();
6422 names = mono_array_new (domain, mono_defaults.string_class, n);
6424 if (env_strings) {
6425 n = 0;
6426 env_string = env_strings;
6427 while (*env_string != '\0') {
6428 /* weird case that MS seems to skip */
6429 if (*env_string != '=') {
6430 equal_str = wcschr(env_string, '=');
6431 g_assert(equal_str);
6432 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6433 mono_array_setref (names, n, str);
6434 n++;
6436 while (*env_string != '\0')
6437 env_string++;
6438 env_string++;
6441 FreeEnvironmentStrings (env_strings);
6444 return names;
6446 #else
6447 MonoArray *names;
6448 MonoDomain *domain;
6449 MonoString *str;
6450 gchar **e, **parts;
6451 int n;
6453 MONO_ARCH_SAVE_REGS;
6455 n = 0;
6456 for (e = environ; *e != 0; ++ e)
6457 ++ n;
6459 domain = mono_domain_get ();
6460 names = mono_array_new (domain, mono_defaults.string_class, n);
6462 n = 0;
6463 for (e = environ; *e != 0; ++ e) {
6464 parts = g_strsplit (*e, "=", 2);
6465 if (*parts != 0) {
6466 str = mono_string_new (domain, *parts);
6467 mono_array_setref (names, n, str);
6470 g_strfreev (parts);
6472 ++ n;
6475 return names;
6476 #endif
6480 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6482 #if !GLIB_CHECK_VERSION(2,4,0)
6483 #define g_setenv(a,b,c) setenv(a,b,c)
6484 #define g_unsetenv(a) unsetenv(a)
6485 #endif
6487 static void
6488 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6490 #ifdef PLATFORM_WIN32
6491 gunichar2 *utf16_name, *utf16_value;
6492 #else
6493 gchar *utf8_name, *utf8_value;
6494 #endif
6496 MONO_ARCH_SAVE_REGS;
6498 #ifdef PLATFORM_WIN32
6499 utf16_name = mono_string_to_utf16 (name);
6500 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6501 SetEnvironmentVariable (utf16_name, NULL);
6502 g_free (utf16_name);
6503 return;
6506 utf16_value = mono_string_to_utf16 (value);
6508 SetEnvironmentVariable (utf16_name, utf16_value);
6510 g_free (utf16_name);
6511 g_free (utf16_value);
6512 #else
6513 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6515 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6516 g_unsetenv (utf8_name);
6517 g_free (utf8_name);
6518 return;
6521 utf8_value = mono_string_to_utf8 (value);
6522 g_setenv (utf8_name, utf8_value, TRUE);
6524 g_free (utf8_name);
6525 g_free (utf8_value);
6526 #endif
6529 static void
6530 ves_icall_System_Environment_Exit (int result)
6532 MONO_ARCH_SAVE_REGS;
6534 mono_threads_set_shutting_down ();
6536 mono_runtime_set_shutting_down ();
6538 /* Suspend all managed threads since the runtime is going away */
6539 mono_thread_suspend_all_other_threads ();
6541 mono_runtime_quit ();
6543 /* we may need to do some cleanup here... */
6544 exit (result);
6547 static MonoString*
6548 ves_icall_System_Environment_GetGacPath (void)
6550 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6553 static MonoString*
6554 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6556 #if defined (PLATFORM_WIN32)
6557 #ifndef CSIDL_FLAG_CREATE
6558 #define CSIDL_FLAG_CREATE 0x8000
6559 #endif
6561 WCHAR path [MAX_PATH];
6562 /* Create directory if no existing */
6563 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6564 int len = 0;
6565 while (path [len])
6566 ++ len;
6567 return mono_string_new_utf16 (mono_domain_get (), path, len);
6569 #else
6570 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6571 #endif
6572 return mono_string_new (mono_domain_get (), "");
6575 static MonoArray *
6576 ves_icall_System_Environment_GetLogicalDrives (void)
6578 gunichar2 buf [128], *ptr, *dname;
6579 gunichar2 *u16;
6580 guint initial_size = 127, size = 128;
6581 gint ndrives;
6582 MonoArray *result;
6583 MonoString *drivestr;
6584 MonoDomain *domain = mono_domain_get ();
6585 gint len;
6587 MONO_ARCH_SAVE_REGS;
6589 buf [0] = '\0';
6590 ptr = buf;
6592 while (size > initial_size) {
6593 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6594 if (size > initial_size) {
6595 if (ptr != buf)
6596 g_free (ptr);
6597 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6598 initial_size = size;
6599 size++;
6603 /* Count strings */
6604 dname = ptr;
6605 ndrives = 0;
6606 do {
6607 while (*dname++);
6608 ndrives++;
6609 } while (*dname);
6611 dname = ptr;
6612 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6613 ndrives = 0;
6614 do {
6615 len = 0;
6616 u16 = dname;
6617 while (*u16) { u16++; len ++; }
6618 drivestr = mono_string_new_utf16 (domain, dname, len);
6619 mono_array_setref (result, ndrives++, drivestr);
6620 while (*dname++);
6621 } while (*dname);
6623 if (ptr != buf)
6624 g_free (ptr);
6626 return result;
6629 static MonoString *
6630 ves_icall_System_Environment_InternalGetHome (void)
6632 MONO_ARCH_SAVE_REGS;
6634 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6637 static const char *encodings [] = {
6638 (char *) 1,
6639 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6640 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6641 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6642 (char *) 2,
6643 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6644 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6645 "x_unicode_2_0_utf_7",
6646 (char *) 3,
6647 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6648 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6649 (char *) 4,
6650 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6651 "iso_10646_ucs2",
6652 (char *) 5,
6653 "unicodefffe", "utf_16be",
6654 (char *) 6,
6655 "iso_8859_1",
6656 (char *) 0
6660 * Returns the internal codepage, if the value of "int_code_page" is
6661 * 1 at entry, and we can not compute a suitable code page number,
6662 * returns the code page as a string
6664 static MonoString*
6665 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6667 const char *cset;
6668 const char *p;
6669 char *c;
6670 char *codepage = NULL;
6671 int code;
6672 int want_name = *int_code_page;
6673 int i;
6675 *int_code_page = -1;
6676 MONO_ARCH_SAVE_REGS;
6678 g_get_charset (&cset);
6679 c = codepage = strdup (cset);
6680 for (c = codepage; *c; c++){
6681 if (isascii (*c) && isalpha (*c))
6682 *c = tolower (*c);
6683 if (*c == '-')
6684 *c = '_';
6686 /* g_print ("charset: %s\n", cset); */
6688 /* handle some common aliases */
6689 p = encodings [0];
6690 code = 0;
6691 for (i = 0; p != 0; ){
6692 if ((gssize) p < 7){
6693 code = (gssize) p;
6694 p = encodings [++i];
6695 continue;
6697 if (strcmp (p, codepage) == 0){
6698 *int_code_page = code;
6699 break;
6701 p = encodings [++i];
6704 if (strstr (codepage, "utf_8") != NULL)
6705 *int_code_page |= 0x10000000;
6706 free (codepage);
6708 if (want_name && *int_code_page == -1)
6709 return mono_string_new (mono_domain_get (), cset);
6710 else
6711 return NULL;
6714 static MonoBoolean
6715 ves_icall_System_Environment_get_HasShutdownStarted (void)
6717 if (mono_runtime_is_shutting_down ())
6718 return TRUE;
6720 if (mono_domain_is_unloading (mono_domain_get ()))
6721 return TRUE;
6723 return FALSE;
6726 static void
6727 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6728 MonoReflectionMethod *method,
6729 MonoArray *out_args)
6731 MONO_ARCH_SAVE_REGS;
6733 mono_message_init (mono_object_domain (this), this, method, out_args);
6736 static MonoBoolean
6737 ves_icall_IsTransparentProxy (MonoObject *proxy)
6739 MONO_ARCH_SAVE_REGS;
6741 if (!proxy)
6742 return 0;
6744 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6745 return 1;
6747 return 0;
6750 static MonoReflectionMethod *
6751 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6752 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6754 MonoClass *klass;
6755 MonoMethod *method;
6756 MonoMethod **vtable;
6757 MonoMethod *res = NULL;
6759 MONO_CHECK_ARG_NULL (rtype);
6760 MONO_CHECK_ARG_NULL (rmethod);
6762 method = rmethod->method;
6763 klass = mono_class_from_mono_type (rtype->type);
6765 if (MONO_CLASS_IS_INTERFACE (klass))
6766 return NULL;
6768 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6769 return NULL;
6771 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6772 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6773 return rmethod;
6774 else
6775 return NULL;
6778 mono_class_setup_vtable (klass);
6779 vtable = klass->vtable;
6781 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6782 int offs = mono_class_interface_offset (klass, method->klass);
6783 if (offs >= 0)
6784 res = vtable [offs + method->slot];
6785 } else {
6786 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6787 return NULL;
6789 if (method->slot != -1)
6790 res = vtable [method->slot];
6793 if (!res)
6794 return NULL;
6796 return mono_method_get_object (mono_domain_get (), res, NULL);
6799 static void
6800 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6802 MonoClass *klass;
6803 MonoVTable* vtable;
6805 MONO_ARCH_SAVE_REGS;
6807 klass = mono_class_from_mono_type (type->type);
6808 vtable = mono_class_vtable (mono_domain_get (), klass);
6810 if (enable) vtable->remote = 1;
6811 else vtable->remote = 0;
6814 static MonoObject *
6815 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6817 MonoClass *klass;
6818 MonoDomain *domain;
6820 MONO_ARCH_SAVE_REGS;
6822 domain = mono_object_domain (type);
6823 klass = mono_class_from_mono_type (type->type);
6825 if (klass->rank >= 1) {
6826 g_assert (klass->rank == 1);
6827 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6828 } else {
6829 /* Bypass remoting object creation check */
6830 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6834 static MonoString *
6835 ves_icall_System_IO_get_temp_path (void)
6837 MONO_ARCH_SAVE_REGS;
6839 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6842 static gpointer
6843 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6845 MONO_ARCH_SAVE_REGS;
6847 return mono_compile_method (method);
6850 static MonoString *
6851 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6853 MonoString *mcpath;
6854 gchar *path;
6856 MONO_ARCH_SAVE_REGS;
6858 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6860 #if defined (PLATFORM_WIN32)
6861 /* Avoid mixing '/' and '\\' */
6863 gint i;
6864 for (i = strlen (path) - 1; i >= 0; i--)
6865 if (path [i] == '/')
6866 path [i] = '\\';
6868 #endif
6869 mcpath = mono_string_new (mono_domain_get (), path);
6870 g_free (path);
6872 return mcpath;
6875 static MonoString *
6876 get_bundled_machine_config (void)
6878 const gchar *machine_config;
6880 MONO_ARCH_SAVE_REGS;
6882 machine_config = mono_get_machine_config ();
6884 if (!machine_config)
6885 return NULL;
6887 return mono_string_new (mono_domain_get (), machine_config);
6890 static MonoString *
6891 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6893 MonoString *ipath;
6894 gchar *path;
6896 MONO_ARCH_SAVE_REGS;
6898 path = g_path_get_dirname (mono_get_config_dir ());
6900 #if defined (PLATFORM_WIN32)
6901 /* Avoid mixing '/' and '\\' */
6903 gint i;
6904 for (i = strlen (path) - 1; i >= 0; i--)
6905 if (path [i] == '/')
6906 path [i] = '\\';
6908 #endif
6909 ipath = mono_string_new (mono_domain_get (), path);
6910 g_free (path);
6912 return ipath;
6915 static MonoBoolean
6916 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6918 return mono_debug_using_mono_debugger ();
6921 static void
6922 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6924 #if defined (PLATFORM_WIN32)
6925 OutputDebugString (mono_string_chars (message));
6926 #else
6927 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
6928 #endif
6931 /* Only used for value types */
6932 static MonoObject *
6933 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6935 MonoClass *klass;
6936 MonoDomain *domain;
6938 MONO_ARCH_SAVE_REGS;
6940 domain = mono_object_domain (type);
6941 klass = mono_class_from_mono_type (type->type);
6943 if (mono_class_is_nullable (klass))
6944 /* No arguments -> null */
6945 return NULL;
6947 return mono_object_new (domain, klass);
6950 static MonoReflectionMethod *
6951 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
6953 MonoClass *klass, *parent;
6954 MonoMethod *method = m->method;
6955 MonoMethod *result = NULL;
6957 MONO_ARCH_SAVE_REGS;
6959 if (method->klass == NULL)
6960 return m;
6962 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6963 MONO_CLASS_IS_INTERFACE (method->klass) ||
6964 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6965 return m;
6967 klass = method->klass;
6968 if (klass->generic_class)
6969 klass = klass->generic_class->container_class;
6971 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6972 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6973 mono_class_setup_vtable (parent);
6974 if (parent->vtable_size <= method->slot)
6975 break;
6976 klass = parent;
6979 if (klass == method->klass)
6980 return m;
6982 result = klass->vtable [method->slot];
6983 if (result == NULL) {
6984 /* It is an abstract method */
6985 gpointer iter = NULL;
6986 while ((result = mono_class_get_methods (klass, &iter)))
6987 if (result->slot == method->slot)
6988 break;
6991 if (result == NULL)
6992 return m;
6994 return mono_method_get_object (mono_domain_get (), result, NULL);
6997 static MonoString*
6998 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7000 MonoMethod *method = m->method;
7002 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7003 return m->name;
7006 static void
7007 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7009 MONO_ARCH_SAVE_REGS;
7011 iter->sig = *(MonoMethodSignature**)argsp;
7013 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7014 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7016 iter->next_arg = 0;
7017 /* FIXME: it's not documented what start is exactly... */
7018 if (start) {
7019 iter->args = start;
7020 } else {
7021 guint32 i, arg_size;
7022 gint32 align;
7023 iter->args = argsp + sizeof (gpointer);
7024 #ifndef MONO_ARCH_REGPARMS
7025 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7026 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7027 iter->args = (char*)iter->args + arg_size;
7029 #endif
7031 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7033 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7036 static MonoTypedRef
7037 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7039 guint32 i, arg_size;
7040 gint32 align;
7041 MonoTypedRef res;
7042 MONO_ARCH_SAVE_REGS;
7044 i = iter->sig->sentinelpos + iter->next_arg;
7046 g_assert (i < iter->sig->param_count);
7048 res.type = iter->sig->params [i];
7049 res.klass = mono_class_from_mono_type (res.type);
7050 res.value = iter->args;
7051 arg_size = mono_type_stack_size (res.type, &align);
7052 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7053 if (arg_size <= sizeof (gpointer)) {
7054 int dummy;
7055 int padding = arg_size - mono_type_size (res.type, &dummy);
7056 res.value = (guint8*)res.value + padding;
7058 #endif
7059 iter->args = (char*)iter->args + arg_size;
7060 iter->next_arg++;
7062 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7064 return res;
7067 static MonoTypedRef
7068 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7070 guint32 i, arg_size;
7071 gint32 align;
7072 MonoTypedRef res;
7073 MONO_ARCH_SAVE_REGS;
7075 i = iter->sig->sentinelpos + iter->next_arg;
7077 g_assert (i < iter->sig->param_count);
7079 while (i < iter->sig->param_count) {
7080 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7081 continue;
7082 res.type = iter->sig->params [i];
7083 res.klass = mono_class_from_mono_type (res.type);
7084 /* FIXME: endianess issue... */
7085 res.value = iter->args;
7086 arg_size = mono_type_stack_size (res.type, &align);
7087 iter->args = (char*)iter->args + arg_size;
7088 iter->next_arg++;
7089 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7090 return res;
7092 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7094 res.type = NULL;
7095 res.value = NULL;
7096 res.klass = NULL;
7097 return res;
7100 static MonoType*
7101 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7103 gint i;
7104 MONO_ARCH_SAVE_REGS;
7106 i = iter->sig->sentinelpos + iter->next_arg;
7108 g_assert (i < iter->sig->param_count);
7110 return iter->sig->params [i];
7113 static MonoObject*
7114 mono_TypedReference_ToObject (MonoTypedRef tref)
7116 MONO_ARCH_SAVE_REGS;
7118 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7119 MonoObject** objp = tref.value;
7120 return *objp;
7123 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7126 static MonoObject*
7127 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7129 MONO_ARCH_SAVE_REGS;
7131 if (MONO_TYPE_IS_REFERENCE (type)) {
7132 MonoObject** objp = value;
7133 return *objp;
7136 return mono_value_box (mono_domain_get (), klass, value);
7139 static void
7140 prelink_method (MonoMethod *method)
7142 const char *exc_class, *exc_arg;
7143 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7144 return;
7145 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7146 if (exc_class) {
7147 mono_raise_exception(
7148 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7150 /* create the wrapper, too? */
7153 static void
7154 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7156 MONO_ARCH_SAVE_REGS;
7157 prelink_method (method->method);
7160 static void
7161 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7163 MonoClass *klass = mono_class_from_mono_type (type->type);
7164 MonoMethod* m;
7165 gpointer iter = NULL;
7166 MONO_ARCH_SAVE_REGS;
7168 while ((m = mono_class_get_methods (klass, &iter)))
7169 prelink_method (m);
7172 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7173 static void
7174 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7175 gint32 const **exponents,
7176 gunichar2 const **digitLowerTable,
7177 gunichar2 const **digitUpperTable,
7178 gint64 const **tenPowersList,
7179 gint32 const **decHexDigits)
7181 *mantissas = Formatter_MantissaBitsTable;
7182 *exponents = Formatter_TensExponentTable;
7183 *digitLowerTable = Formatter_DigitLowerTable;
7184 *digitUpperTable = Formatter_DigitUpperTable;
7185 *tenPowersList = Formatter_TenPowersList;
7186 *decHexDigits = Formatter_DecHexDigits;
7189 /* These parameters are "readonly" in corlib/System/Char.cs */
7190 static void
7191 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7192 guint8 const **numeric_data,
7193 gdouble const **numeric_data_values,
7194 guint16 const **to_lower_data_low,
7195 guint16 const **to_lower_data_high,
7196 guint16 const **to_upper_data_low,
7197 guint16 const **to_upper_data_high)
7199 *category_data = CategoryData;
7200 *numeric_data = NumericData;
7201 *numeric_data_values = NumericDataValues;
7202 *to_lower_data_low = ToLowerDataLow;
7203 *to_lower_data_high = ToLowerDataHigh;
7204 *to_upper_data_low = ToUpperDataLow;
7205 *to_upper_data_high = ToUpperDataHigh;
7208 static gint32
7209 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7211 return method->method->token;
7215 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7216 * and avoid useless allocations.
7218 static MonoArray*
7219 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7221 MonoArray *res;
7222 int i, count = 0;
7223 for (i = 0; i < type->num_mods; ++i) {
7224 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7225 count++;
7227 if (!count)
7228 return NULL;
7229 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7230 count = 0;
7231 for (i = 0; i < type->num_mods; ++i) {
7232 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7233 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7234 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7235 count++;
7238 return res;
7241 static MonoArray*
7242 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7244 MonoType *type = param->ClassImpl->type;
7245 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7246 MonoImage *image = method->method->klass->image;
7247 int pos = param->PositionImpl;
7248 MonoMethodSignature *sig = mono_method_signature (method->method);
7249 if (pos == -1)
7250 type = sig->ret;
7251 else
7252 type = sig->params [pos];
7254 return type_array_from_modifiers (image, type, optional);
7257 static MonoType*
7258 get_property_type (MonoProperty *prop)
7260 MonoMethodSignature *sig;
7261 if (prop->get) {
7262 sig = mono_method_signature (prop->get);
7263 return sig->ret;
7264 } else if (prop->set) {
7265 sig = mono_method_signature (prop->set);
7266 return sig->params [sig->param_count - 1];
7268 return NULL;
7271 static MonoArray*
7272 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7274 MonoType *type = get_property_type (property->property);
7275 MonoImage *image = property->klass->image;
7277 if (!type)
7278 return NULL;
7279 return type_array_from_modifiers (image, type, optional);
7282 static MonoBoolean
7283 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7285 MonoCustomAttrInfo *cinfo;
7286 gboolean found;
7288 cinfo = mono_reflection_get_custom_attrs_info (obj);
7289 if (!cinfo)
7290 return FALSE;
7291 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7292 if (!cinfo->cached)
7293 mono_custom_attrs_free (cinfo);
7294 return found;
7297 static MonoArray*
7298 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7300 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7302 if (mono_loader_get_last_error ()) {
7303 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7304 g_assert_not_reached ();
7305 } else {
7306 return res;
7310 static MonoBoolean
7311 GCHandle_CheckCurrentDomain (guint32 gchandle)
7313 return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
7316 static MonoString*
7317 ves_icall_Mono_Runtime_GetDisplayName (void)
7319 static const char display_name_str [] = "Mono " VERSION;
7320 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7321 return display_name;
7324 static MonoString*
7325 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7327 MonoString *message;
7328 guint32 ret;
7329 gunichar2 buf[256];
7331 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7332 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7333 buf, 255, NULL);
7334 if (ret == 0) {
7335 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7336 } else {
7337 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7340 return message;
7343 const static guchar
7344 dbase64 [] = {
7345 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7346 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7347 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7348 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7349 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7350 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7351 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7352 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7355 static MonoArray *
7356 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7358 gint ignored;
7359 gint i;
7360 gunichar2 c;
7361 gunichar2 last, prev_last, prev2_last;
7362 gint olength;
7363 MonoArray *result;
7364 guchar *res_ptr;
7365 gint a [4], b [4];
7366 MonoException *exc;
7368 ignored = 0;
7369 last = prev_last = 0, prev2_last = 0;
7370 for (i = 0; i < ilength; i++) {
7371 c = start [i];
7372 if (c >= sizeof (dbase64)) {
7373 exc = mono_exception_from_name_msg (mono_get_corlib (),
7374 "System", "FormatException",
7375 "Invalid character found.");
7376 mono_raise_exception (exc);
7377 } else if (isspace (c)) {
7378 ignored++;
7379 } else {
7380 prev2_last = prev_last;
7381 prev_last = last;
7382 last = c;
7386 olength = ilength - ignored;
7388 if (allowWhitespaceOnly && olength == 0) {
7389 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7392 if ((olength & 3) != 0 || olength <= 0) {
7393 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7394 "FormatException", "Invalid length.");
7395 mono_raise_exception (exc);
7398 if (prev2_last == '=') {
7399 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7400 mono_raise_exception (exc);
7403 olength = (olength * 3) / 4;
7404 if (last == '=')
7405 olength--;
7407 if (prev_last == '=')
7408 olength--;
7410 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7411 res_ptr = mono_array_addr (result, guchar, 0);
7412 for (i = 0; i < ilength; ) {
7413 int k;
7415 for (k = 0; k < 4 && i < ilength;) {
7416 c = start [i++];
7417 if (isspace (c))
7418 continue;
7420 a [k] = (guchar) c;
7421 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7422 exc = mono_exception_from_name_msg (mono_get_corlib (),
7423 "System", "FormatException",
7424 "Invalid character found.");
7425 mono_raise_exception (exc);
7427 k++;
7430 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7431 if (a [2] != '=')
7432 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7433 if (a [3] != '=')
7434 *res_ptr++ = (b [2] << 6) | b [3];
7436 while (i < ilength && isspace (start [i]))
7437 i++;
7440 return result;
7443 static MonoArray *
7444 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7446 MONO_ARCH_SAVE_REGS;
7448 return base64_to_byte_array (mono_string_chars (str),
7449 mono_string_length (str), allowWhitespaceOnly);
7452 static MonoArray *
7453 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7455 MONO_ARCH_SAVE_REGS;
7457 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7458 length, FALSE);
7461 #define ICALL_TYPE(id,name,first)
7462 #define ICALL(id,name,func) Icall_ ## id,
7464 enum {
7465 #include "metadata/icall-def.h"
7466 Icall_last
7469 #undef ICALL_TYPE
7470 #undef ICALL
7471 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7472 #define ICALL(id,name,func)
7473 enum {
7474 #include "metadata/icall-def.h"
7475 Icall_type_num
7478 #undef ICALL_TYPE
7479 #undef ICALL
7480 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7481 #define ICALL(id,name,func)
7482 typedef struct {
7483 guint16 first_icall;
7484 } IcallTypeDesc;
7486 static const IcallTypeDesc
7487 icall_type_descs [] = {
7488 #include "metadata/icall-def.h"
7489 {Icall_last}
7492 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7494 #undef ICALL_TYPE
7495 #define ICALL_TYPE(id,name,first)
7496 #undef ICALL
7498 #ifdef HAVE_ARRAY_ELEM_INIT
7499 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7500 #define MSGSTRFIELD1(line) str##line
7502 static const struct msgstrtn_t {
7503 #define ICALL(id,name,func)
7504 #undef ICALL_TYPE
7505 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7506 #include "metadata/icall-def.h"
7507 #undef ICALL_TYPE
7508 } icall_type_names_str = {
7509 #define ICALL_TYPE(id,name,first) (name),
7510 #include "metadata/icall-def.h"
7511 #undef ICALL_TYPE
7513 static const guint16 icall_type_names_idx [] = {
7514 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7515 #include "metadata/icall-def.h"
7516 #undef ICALL_TYPE
7518 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7520 static const struct msgstr_t {
7521 #undef ICALL
7522 #define ICALL_TYPE(id,name,first)
7523 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7524 #include "metadata/icall-def.h"
7525 #undef ICALL
7526 } icall_names_str = {
7527 #define ICALL(id,name,func) (name),
7528 #include "metadata/icall-def.h"
7529 #undef ICALL
7531 static const guint16 icall_names_idx [] = {
7532 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7533 #include "metadata/icall-def.h"
7534 #undef ICALL
7536 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7538 #else
7540 #undef ICALL_TYPE
7541 #undef ICALL
7542 #define ICALL_TYPE(id,name,first) name,
7543 #define ICALL(id,name,func)
7544 static const char* const
7545 icall_type_names [] = {
7546 #include "metadata/icall-def.h"
7547 NULL
7550 #define icall_type_name_get(id) (icall_type_names [(id)])
7552 #undef ICALL_TYPE
7553 #undef ICALL
7554 #define ICALL_TYPE(id,name,first)
7555 #define ICALL(id,name,func) name,
7556 static const char* const
7557 icall_names [] = {
7558 #include "metadata/icall-def.h"
7559 NULL
7561 #define icall_name_get(id) icall_names [(id)]
7563 #endif /* !HAVE_ARRAY_ELEM_INIT */
7565 #undef ICALL_TYPE
7566 #undef ICALL
7567 #define ICALL_TYPE(id,name,first)
7568 #define ICALL(id,name,func) func,
7569 static const gconstpointer
7570 icall_functions [] = {
7571 #include "metadata/icall-def.h"
7572 NULL
7575 static GHashTable *icall_hash = NULL;
7576 static GHashTable *jit_icall_hash_name = NULL;
7577 static GHashTable *jit_icall_hash_addr = NULL;
7579 void
7580 mono_icall_init (void)
7582 int i = 0;
7584 /* check that tables are sorted: disable in release */
7585 if (TRUE) {
7586 int j;
7587 const char *prev_class = NULL;
7588 const char *prev_method;
7590 for (i = 0; i < Icall_type_num; ++i) {
7591 const IcallTypeDesc *desc;
7592 int num_icalls;
7593 prev_method = NULL;
7594 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7595 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7596 prev_class = icall_type_name_get (i);
7597 desc = &icall_type_descs [i];
7598 num_icalls = icall_desc_num_icalls (desc);
7599 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7600 for (j = 0; j < num_icalls; ++j) {
7601 const char *methodn = icall_name_get (desc->first_icall + j);
7602 if (prev_method && strcmp (prev_method, methodn) >= 0)
7603 g_print ("method %s should come before method %s\n", methodn, prev_method);
7604 prev_method = methodn;
7609 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7612 void
7613 mono_icall_cleanup (void)
7615 g_hash_table_destroy (icall_hash);
7616 g_hash_table_destroy (jit_icall_hash_name);
7617 g_hash_table_destroy (jit_icall_hash_addr);
7620 void
7621 mono_add_internal_call (const char *name, gconstpointer method)
7623 mono_loader_lock ();
7625 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7627 mono_loader_unlock ();
7630 #ifdef HAVE_ARRAY_ELEM_INIT
7631 static int
7632 compare_method_imap (const void *key, const void *elem)
7634 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7635 return strcmp (key, method_name);
7638 static gpointer
7639 find_method_icall (const IcallTypeDesc *imap, const char *name)
7641 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7642 if (!nameslot)
7643 return NULL;
7644 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7647 static int
7648 compare_class_imap (const void *key, const void *elem)
7650 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7651 return strcmp (key, class_name);
7654 static const IcallTypeDesc*
7655 find_class_icalls (const char *name)
7657 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7658 if (!nameslot)
7659 return NULL;
7660 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7663 #else
7664 static int
7665 compare_method_imap (const void *key, const void *elem)
7667 const char** method_name = (const char**)elem;
7668 return strcmp (key, *method_name);
7671 static gpointer
7672 find_method_icall (const IcallTypeDesc *imap, const char *name)
7674 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7675 if (!nameslot)
7676 return NULL;
7677 return (gpointer)icall_functions [(nameslot - icall_names)];
7680 static int
7681 compare_class_imap (const void *key, const void *elem)
7683 const char** class_name = (const char**)elem;
7684 return strcmp (key, *class_name);
7687 static const IcallTypeDesc*
7688 find_class_icalls (const char *name)
7690 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7691 if (!nameslot)
7692 return NULL;
7693 return &icall_type_descs [nameslot - icall_type_names];
7696 #endif
7699 * we should probably export this as an helper (handle nested types).
7700 * Returns the number of chars written in buf.
7702 static int
7703 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7705 int nspacelen, cnamelen;
7706 nspacelen = strlen (klass->name_space);
7707 cnamelen = strlen (klass->name);
7708 if (nspacelen + cnamelen + 2 > bufsize)
7709 return 0;
7710 if (nspacelen) {
7711 memcpy (buf, klass->name_space, nspacelen);
7712 buf [nspacelen ++] = '.';
7714 memcpy (buf + nspacelen, klass->name, cnamelen);
7715 buf [nspacelen + cnamelen] = 0;
7716 return nspacelen + cnamelen;
7719 gpointer
7720 mono_lookup_internal_call (MonoMethod *method)
7722 char *sigstart;
7723 char *tmpsig;
7724 char mname [2048];
7725 int typelen = 0, mlen, siglen;
7726 gpointer res;
7727 const IcallTypeDesc *imap;
7729 g_assert (method != NULL);
7731 if (method->is_inflated)
7732 method = ((MonoMethodInflated *) method)->declaring;
7734 if (method->klass->nested_in) {
7735 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7736 if (!pos)
7737 return NULL;
7739 mname [pos++] = '/';
7740 mname [pos] = 0;
7742 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7743 if (!typelen)
7744 return NULL;
7746 typelen += pos;
7747 } else {
7748 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7749 if (!typelen)
7750 return NULL;
7753 imap = find_class_icalls (mname);
7755 mname [typelen] = ':';
7756 mname [typelen + 1] = ':';
7758 mlen = strlen (method->name);
7759 memcpy (mname + typelen + 2, method->name, mlen);
7760 sigstart = mname + typelen + 2 + mlen;
7761 *sigstart = 0;
7763 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7764 siglen = strlen (tmpsig);
7765 if (typelen + mlen + siglen + 6 > sizeof (mname))
7766 return NULL;
7767 sigstart [0] = '(';
7768 memcpy (sigstart + 1, tmpsig, siglen);
7769 sigstart [siglen + 1] = ')';
7770 sigstart [siglen + 2] = 0;
7771 g_free (tmpsig);
7773 mono_loader_lock ();
7775 res = g_hash_table_lookup (icall_hash, mname);
7776 if (res) {
7777 mono_loader_unlock ();
7778 return res;
7780 /* try without signature */
7781 *sigstart = 0;
7782 res = g_hash_table_lookup (icall_hash, mname);
7783 if (res) {
7784 mono_loader_unlock ();
7785 return res;
7788 /* it wasn't found in the static call tables */
7789 if (!imap) {
7790 mono_loader_unlock ();
7791 return NULL;
7793 res = find_method_icall (imap, sigstart - mlen);
7794 if (res) {
7795 mono_loader_unlock ();
7796 return res;
7798 /* try _with_ signature */
7799 *sigstart = '(';
7800 res = find_method_icall (imap, sigstart - mlen);
7801 if (res) {
7802 mono_loader_unlock ();
7803 return res;
7806 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7807 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7808 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7809 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7810 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");
7811 g_print ("If you see other errors or faults after this message they are probably related\n");
7812 g_print ("and you need to fix your mono install first.\n");
7814 mono_loader_unlock ();
7816 return NULL;
7819 static MonoType*
7820 type_from_typename (char *typename)
7822 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7824 if (!strcmp (typename, "int"))
7825 klass = mono_defaults.int_class;
7826 else if (!strcmp (typename, "ptr"))
7827 klass = mono_defaults.int_class;
7828 else if (!strcmp (typename, "void"))
7829 klass = mono_defaults.void_class;
7830 else if (!strcmp (typename, "int32"))
7831 klass = mono_defaults.int32_class;
7832 else if (!strcmp (typename, "uint32"))
7833 klass = mono_defaults.uint32_class;
7834 else if (!strcmp (typename, "int8"))
7835 klass = mono_defaults.sbyte_class;
7836 else if (!strcmp (typename, "uint8"))
7837 klass = mono_defaults.byte_class;
7838 else if (!strcmp (typename, "int16"))
7839 klass = mono_defaults.int16_class;
7840 else if (!strcmp (typename, "uint16"))
7841 klass = mono_defaults.uint16_class;
7842 else if (!strcmp (typename, "long"))
7843 klass = mono_defaults.int64_class;
7844 else if (!strcmp (typename, "ulong"))
7845 klass = mono_defaults.uint64_class;
7846 else if (!strcmp (typename, "float"))
7847 klass = mono_defaults.single_class;
7848 else if (!strcmp (typename, "double"))
7849 klass = mono_defaults.double_class;
7850 else if (!strcmp (typename, "object"))
7851 klass = mono_defaults.object_class;
7852 else if (!strcmp (typename, "obj"))
7853 klass = mono_defaults.object_class;
7854 else if (!strcmp (typename, "string"))
7855 klass = mono_defaults.string_class;
7856 else if (!strcmp (typename, "bool"))
7857 klass = mono_defaults.boolean_class;
7858 else if (!strcmp (typename, "boolean"))
7859 klass = mono_defaults.boolean_class;
7860 else {
7861 g_error (typename);
7862 g_assert_not_reached ();
7864 return &klass->byval_arg;
7867 MonoMethodSignature*
7868 mono_create_icall_signature (const char *sigstr)
7870 gchar **parts;
7871 int i, len;
7872 gchar **tmp;
7873 MonoMethodSignature *res;
7875 mono_loader_lock ();
7876 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7877 if (res) {
7878 mono_loader_unlock ();
7879 return res;
7882 parts = g_strsplit (sigstr, " ", 256);
7884 tmp = parts;
7885 len = 0;
7886 while (*tmp) {
7887 len ++;
7888 tmp ++;
7891 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7892 res->pinvoke = 1;
7894 #ifdef PLATFORM_WIN32
7896 * Under windows, the default pinvoke calling convention is STDCALL but
7897 * we need CDECL.
7899 res->call_convention = MONO_CALL_C;
7900 #endif
7902 res->ret = type_from_typename (parts [0]);
7903 for (i = 1; i < len; ++i) {
7904 res->params [i - 1] = type_from_typename (parts [i]);
7907 g_strfreev (parts);
7909 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7911 mono_loader_unlock ();
7913 return res;
7916 MonoJitICallInfo *
7917 mono_find_jit_icall_by_name (const char *name)
7919 MonoJitICallInfo *info;
7920 g_assert (jit_icall_hash_name);
7922 mono_loader_lock ();
7923 info = g_hash_table_lookup (jit_icall_hash_name, name);
7924 mono_loader_unlock ();
7925 return info;
7928 MonoJitICallInfo *
7929 mono_find_jit_icall_by_addr (gconstpointer addr)
7931 MonoJitICallInfo *info;
7932 g_assert (jit_icall_hash_addr);
7934 mono_loader_lock ();
7935 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7936 mono_loader_unlock ();
7938 return info;
7942 * mono_get_jit_icall_info:
7944 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7945 * caller should access it while holding the loader lock.
7947 GHashTable*
7948 mono_get_jit_icall_info (void)
7950 return jit_icall_hash_name;
7953 void
7954 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7956 mono_loader_lock ();
7957 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7958 mono_loader_unlock ();
7961 MonoJitICallInfo *
7962 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7964 MonoJitICallInfo *info;
7966 g_assert (func);
7967 g_assert (name);
7969 mono_loader_lock ();
7971 if (!jit_icall_hash_name) {
7972 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7973 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7976 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7977 g_warning ("jit icall already defined \"%s\"\n", name);
7978 g_assert_not_reached ();
7981 info = g_new0 (MonoJitICallInfo, 1);
7983 info->name = name;
7984 info->func = func;
7985 info->sig = sig;
7987 if (is_save) {
7988 info->wrapper = func;
7989 } else {
7990 info->wrapper = NULL;
7993 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7994 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7996 mono_loader_unlock ();
7997 return info;