2010-01-19 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / icall.c
blob12f85e374508960e7676d0f2a9243368cdb2dcec
1 /*
2 * icall.c:
4 * Authors:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 #include <config.h>
14 #include <glib.h>
15 #include <stdarg.h>
16 #include <string.h>
17 #include <ctype.h>
18 #ifdef HAVE_ALLOCA_H
19 #include <alloca.h>
20 #endif
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #if defined (HOST_WIN32)
28 #include <stdlib.h>
29 #endif
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/io-layer/io-layer.h>
71 #include <mono/utils/strtod.h>
72 #include <mono/utils/monobitset.h>
73 #include <mono/utils/mono-time.h>
74 #include <mono/utils/mono-proclib.h>
75 #include <mono/utils/mono-string.h>
76 #include <mono/utils/mono-error-internals.h>
78 #if defined (HOST_WIN32)
79 #include <windows.h>
80 #include <shlobj.h>
81 #endif
82 #include "decimal.h"
84 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
86 static MonoArray*
87 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
89 /* This is an implementation of a growable pointer array that avoids doing memory allocations for small sizes.
90 * It works by allocating an initial small array on stack and only going to malloc'd memory if needed.
92 typedef struct {
93 void **data;
94 int size;
95 int capacity;
96 } MonoPtrArray;
98 #define MONO_PTR_ARRAY_MAX_ON_STACK (16)
100 #define mono_ptr_array_init(ARRAY, INITIAL_SIZE) do {\
101 (ARRAY).size = 0; \
102 (ARRAY).capacity = MAX (INITIAL_SIZE, MONO_PTR_ARRAY_MAX_ON_STACK); \
103 (ARRAY).data = INITIAL_SIZE > MONO_PTR_ARRAY_MAX_ON_STACK ? mono_gc_alloc_fixed (sizeof (void*) * INITIAL_SIZE, NULL) : g_newa (void*, MONO_PTR_ARRAY_MAX_ON_STACK); \
104 } while (0)
106 #define mono_ptr_array_destroy(ARRAY) do {\
107 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
108 mono_gc_free_fixed ((ARRAY).data); \
109 } while (0)
111 #define mono_ptr_array_append(ARRAY, VALUE) do { \
112 if ((ARRAY).size >= (ARRAY).capacity) {\
113 void *__tmp = mono_gc_alloc_fixed (sizeof (void*) * (ARRAY).capacity * 2, NULL); \
114 memcpy (__tmp, (ARRAY).data, (ARRAY).capacity * sizeof (void*)); \
115 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
116 mono_gc_free_fixed ((ARRAY).data); \
117 (ARRAY).data = __tmp; \
118 (ARRAY).capacity *= 2;\
120 ((ARRAY).data [(ARRAY).size++] = VALUE); \
121 } while (0)
123 #define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \
124 ((ARRAY).data [(IDX)] = VALUE); \
125 } while (0)
127 #define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)])
129 #define mono_ptr_array_size(ARRAY) ((ARRAY).size)
132 static inline MonoBoolean
133 is_generic_parameter (MonoType *type)
135 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
139 * We expect a pointer to a char, not a string
141 static gboolean
142 mono_double_ParseImpl (char *ptr, double *result)
144 gchar *endptr = NULL;
145 *result = 0.0;
147 MONO_ARCH_SAVE_REGS;
149 #ifdef __arm__
150 if (*ptr)
151 *result = strtod (ptr, &endptr);
152 #else
153 if (*ptr){
154 #ifdef _EGLIB_MAJOR
155 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
156 EnterCriticalSection (&mono_strtod_mutex);
157 *result = mono_strtod (ptr, &endptr);
158 LeaveCriticalSection (&mono_strtod_mutex);
159 #else
160 *result = mono_strtod (ptr, &endptr);
161 #endif
163 #endif
165 if (!*ptr || (endptr && *endptr))
166 return FALSE;
168 return TRUE;
171 static MonoObject *
172 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
174 MonoClass *ac;
175 MonoArray *ao;
176 gint32 esize;
177 gpointer *ea;
179 MONO_ARCH_SAVE_REGS;
181 ao = (MonoArray *)this;
182 ac = (MonoClass *)ao->obj.vtable->klass;
184 esize = mono_array_element_size (ac);
185 ea = (gpointer*)((char*)ao->vector + (pos * esize));
187 if (ac->element_class->valuetype)
188 return mono_value_box (this->vtable->domain, ac->element_class, ea);
189 else
190 return *ea;
193 static MonoObject *
194 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
196 MonoClass *ac, *ic;
197 MonoArray *ao, *io;
198 gint32 i, pos, *ind;
200 MONO_ARCH_SAVE_REGS;
202 MONO_CHECK_ARG_NULL (idxs);
204 io = (MonoArray *)idxs;
205 ic = (MonoClass *)io->obj.vtable->klass;
207 ao = (MonoArray *)this;
208 ac = (MonoClass *)ao->obj.vtable->klass;
210 g_assert (ic->rank == 1);
211 if (io->bounds != NULL || io->max_length != ac->rank)
212 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
214 ind = (gint32 *)io->vector;
216 if (ao->bounds == NULL) {
217 if (*ind < 0 || *ind >= ao->max_length)
218 mono_raise_exception (mono_get_exception_index_out_of_range ());
220 return ves_icall_System_Array_GetValueImpl (this, *ind);
223 for (i = 0; i < ac->rank; i++)
224 if ((ind [i] < ao->bounds [i].lower_bound) ||
225 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
226 mono_raise_exception (mono_get_exception_index_out_of_range ());
228 pos = ind [0] - ao->bounds [0].lower_bound;
229 for (i = 1; i < ac->rank; i++)
230 pos = pos*ao->bounds [i].length + ind [i] -
231 ao->bounds [i].lower_bound;
233 return ves_icall_System_Array_GetValueImpl (this, pos);
236 static void
237 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
239 MonoClass *ac, *vc, *ec;
240 gint32 esize, vsize;
241 gpointer *ea, *va;
242 int et, vt;
244 guint64 u64 = 0;
245 gint64 i64 = 0;
246 gdouble r64 = 0;
248 MONO_ARCH_SAVE_REGS;
250 if (value)
251 vc = value->vtable->klass;
252 else
253 vc = NULL;
255 ac = this->obj.vtable->klass;
256 ec = ac->element_class;
258 esize = mono_array_element_size (ac);
259 ea = (gpointer*)((char*)this->vector + (pos * esize));
260 va = (gpointer*)((char*)value + sizeof (MonoObject));
262 if (!value) {
263 memset (ea, 0, esize);
264 return;
267 #define NO_WIDENING_CONVERSION G_STMT_START{\
268 mono_raise_exception (mono_get_exception_argument ( \
269 "value", "not a widening conversion")); \
270 }G_STMT_END
272 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
273 if (esize < vsize + (extra)) \
274 mono_raise_exception (mono_get_exception_argument ( \
275 "value", "not a widening conversion")); \
276 }G_STMT_END
278 #define INVALID_CAST G_STMT_START{\
279 mono_raise_exception (mono_get_exception_invalid_cast ()); \
280 }G_STMT_END
282 /* Check element (destination) type. */
283 switch (ec->byval_arg.type) {
284 case MONO_TYPE_STRING:
285 switch (vc->byval_arg.type) {
286 case MONO_TYPE_STRING:
287 break;
288 default:
289 INVALID_CAST;
291 break;
292 case MONO_TYPE_BOOLEAN:
293 switch (vc->byval_arg.type) {
294 case MONO_TYPE_BOOLEAN:
295 break;
296 case MONO_TYPE_CHAR:
297 case MONO_TYPE_U1:
298 case MONO_TYPE_U2:
299 case MONO_TYPE_U4:
300 case MONO_TYPE_U8:
301 case MONO_TYPE_I1:
302 case MONO_TYPE_I2:
303 case MONO_TYPE_I4:
304 case MONO_TYPE_I8:
305 case MONO_TYPE_R4:
306 case MONO_TYPE_R8:
307 NO_WIDENING_CONVERSION;
308 default:
309 INVALID_CAST;
311 break;
314 if (!ec->valuetype) {
315 if (!mono_object_isinst (value, ec))
316 INVALID_CAST;
317 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
318 return;
321 if (mono_object_isinst (value, ec)) {
322 if (ec->has_references)
323 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
324 else
325 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
326 return;
329 if (!vc->valuetype)
330 INVALID_CAST;
332 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
334 et = ec->byval_arg.type;
335 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
336 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
338 vt = vc->byval_arg.type;
339 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
340 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
342 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
343 switch (vt) { \
344 case MONO_TYPE_U1: \
345 case MONO_TYPE_U2: \
346 case MONO_TYPE_U4: \
347 case MONO_TYPE_U8: \
348 case MONO_TYPE_CHAR: \
349 CHECK_WIDENING_CONVERSION(0); \
350 *(etype *) ea = (etype) u64; \
351 return; \
352 /* You can't assign a signed value to an unsigned array. */ \
353 case MONO_TYPE_I1: \
354 case MONO_TYPE_I2: \
355 case MONO_TYPE_I4: \
356 case MONO_TYPE_I8: \
357 /* You can't assign a floating point number to an integer array. */ \
358 case MONO_TYPE_R4: \
359 case MONO_TYPE_R8: \
360 NO_WIDENING_CONVERSION; \
362 }G_STMT_END
364 #define ASSIGN_SIGNED(etype) G_STMT_START{\
365 switch (vt) { \
366 case MONO_TYPE_I1: \
367 case MONO_TYPE_I2: \
368 case MONO_TYPE_I4: \
369 case MONO_TYPE_I8: \
370 CHECK_WIDENING_CONVERSION(0); \
371 *(etype *) ea = (etype) i64; \
372 return; \
373 /* You can assign an unsigned value to a signed array if the array's */ \
374 /* element size is larger than the value size. */ \
375 case MONO_TYPE_U1: \
376 case MONO_TYPE_U2: \
377 case MONO_TYPE_U4: \
378 case MONO_TYPE_U8: \
379 case MONO_TYPE_CHAR: \
380 CHECK_WIDENING_CONVERSION(1); \
381 *(etype *) ea = (etype) u64; \
382 return; \
383 /* You can't assign a floating point number to an integer array. */ \
384 case MONO_TYPE_R4: \
385 case MONO_TYPE_R8: \
386 NO_WIDENING_CONVERSION; \
388 }G_STMT_END
390 #define ASSIGN_REAL(etype) G_STMT_START{\
391 switch (vt) { \
392 case MONO_TYPE_R4: \
393 case MONO_TYPE_R8: \
394 CHECK_WIDENING_CONVERSION(0); \
395 *(etype *) ea = (etype) r64; \
396 return; \
397 /* All integer values fit into a floating point array, so we don't */ \
398 /* need to CHECK_WIDENING_CONVERSION here. */ \
399 case MONO_TYPE_I1: \
400 case MONO_TYPE_I2: \
401 case MONO_TYPE_I4: \
402 case MONO_TYPE_I8: \
403 *(etype *) ea = (etype) i64; \
404 return; \
405 case MONO_TYPE_U1: \
406 case MONO_TYPE_U2: \
407 case MONO_TYPE_U4: \
408 case MONO_TYPE_U8: \
409 case MONO_TYPE_CHAR: \
410 *(etype *) ea = (etype) u64; \
411 return; \
413 }G_STMT_END
415 switch (vt) {
416 case MONO_TYPE_U1:
417 u64 = *(guint8 *) va;
418 break;
419 case MONO_TYPE_U2:
420 u64 = *(guint16 *) va;
421 break;
422 case MONO_TYPE_U4:
423 u64 = *(guint32 *) va;
424 break;
425 case MONO_TYPE_U8:
426 u64 = *(guint64 *) va;
427 break;
428 case MONO_TYPE_I1:
429 i64 = *(gint8 *) va;
430 break;
431 case MONO_TYPE_I2:
432 i64 = *(gint16 *) va;
433 break;
434 case MONO_TYPE_I4:
435 i64 = *(gint32 *) va;
436 break;
437 case MONO_TYPE_I8:
438 i64 = *(gint64 *) va;
439 break;
440 case MONO_TYPE_R4:
441 r64 = *(gfloat *) va;
442 break;
443 case MONO_TYPE_R8:
444 r64 = *(gdouble *) va;
445 break;
446 case MONO_TYPE_CHAR:
447 u64 = *(guint16 *) va;
448 break;
449 case MONO_TYPE_BOOLEAN:
450 /* Boolean is only compatible with itself. */
451 switch (et) {
452 case MONO_TYPE_CHAR:
453 case MONO_TYPE_U1:
454 case MONO_TYPE_U2:
455 case MONO_TYPE_U4:
456 case MONO_TYPE_U8:
457 case MONO_TYPE_I1:
458 case MONO_TYPE_I2:
459 case MONO_TYPE_I4:
460 case MONO_TYPE_I8:
461 case MONO_TYPE_R4:
462 case MONO_TYPE_R8:
463 NO_WIDENING_CONVERSION;
464 default:
465 INVALID_CAST;
467 break;
470 /* If we can't do a direct copy, let's try a widening conversion. */
471 switch (et) {
472 case MONO_TYPE_CHAR:
473 ASSIGN_UNSIGNED (guint16);
474 case MONO_TYPE_U1:
475 ASSIGN_UNSIGNED (guint8);
476 case MONO_TYPE_U2:
477 ASSIGN_UNSIGNED (guint16);
478 case MONO_TYPE_U4:
479 ASSIGN_UNSIGNED (guint32);
480 case MONO_TYPE_U8:
481 ASSIGN_UNSIGNED (guint64);
482 case MONO_TYPE_I1:
483 ASSIGN_SIGNED (gint8);
484 case MONO_TYPE_I2:
485 ASSIGN_SIGNED (gint16);
486 case MONO_TYPE_I4:
487 ASSIGN_SIGNED (gint32);
488 case MONO_TYPE_I8:
489 ASSIGN_SIGNED (gint64);
490 case MONO_TYPE_R4:
491 ASSIGN_REAL (gfloat);
492 case MONO_TYPE_R8:
493 ASSIGN_REAL (gdouble);
496 INVALID_CAST;
497 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
498 return;
500 #undef INVALID_CAST
501 #undef NO_WIDENING_CONVERSION
502 #undef CHECK_WIDENING_CONVERSION
503 #undef ASSIGN_UNSIGNED
504 #undef ASSIGN_SIGNED
505 #undef ASSIGN_REAL
508 static void
509 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
510 MonoArray *idxs)
512 MonoClass *ac, *ic;
513 gint32 i, pos, *ind;
515 MONO_ARCH_SAVE_REGS;
517 MONO_CHECK_ARG_NULL (idxs);
519 ic = idxs->obj.vtable->klass;
520 ac = this->obj.vtable->klass;
522 g_assert (ic->rank == 1);
523 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
524 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
526 ind = (gint32 *)idxs->vector;
528 if (this->bounds == NULL) {
529 if (*ind < 0 || *ind >= this->max_length)
530 mono_raise_exception (mono_get_exception_index_out_of_range ());
532 ves_icall_System_Array_SetValueImpl (this, value, *ind);
533 return;
536 for (i = 0; i < ac->rank; i++)
537 if ((ind [i] < this->bounds [i].lower_bound) ||
538 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
539 mono_raise_exception (mono_get_exception_index_out_of_range ());
541 pos = ind [0] - this->bounds [0].lower_bound;
542 for (i = 1; i < ac->rank; i++)
543 pos = pos * this->bounds [i].length + ind [i] -
544 this->bounds [i].lower_bound;
546 ves_icall_System_Array_SetValueImpl (this, value, pos);
549 static MonoArray *
550 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
552 MonoClass *aklass;
553 MonoArray *array;
554 mono_array_size_t *sizes, i;
555 gboolean bounded = FALSE;
557 MONO_ARCH_SAVE_REGS;
559 MONO_CHECK_ARG_NULL (type);
560 MONO_CHECK_ARG_NULL (lengths);
562 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
563 if (bounds)
564 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
566 for (i = 0; i < mono_array_length (lengths); i++)
567 if (mono_array_get (lengths, gint32, i) < 0)
568 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
570 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
571 /* vectors are not the same as one dimensional arrays with no-zero bounds */
572 bounded = TRUE;
573 else
574 bounded = FALSE;
576 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
578 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
579 for (i = 0; i < aklass->rank; ++i) {
580 sizes [i] = mono_array_get (lengths, guint32, i);
581 if (bounds)
582 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
583 else
584 sizes [i + aklass->rank] = 0;
587 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
589 return array;
592 static MonoArray *
593 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
595 MonoClass *aklass;
596 MonoArray *array;
597 mono_array_size_t *sizes, i;
598 gboolean bounded = FALSE;
600 MONO_ARCH_SAVE_REGS;
602 MONO_CHECK_ARG_NULL (type);
603 MONO_CHECK_ARG_NULL (lengths);
605 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
606 if (bounds)
607 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
609 for (i = 0; i < mono_array_length (lengths); i++)
610 if ((mono_array_get (lengths, gint64, i) < 0) ||
611 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
612 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
614 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
615 /* vectors are not the same as one dimensional arrays with no-zero bounds */
616 bounded = TRUE;
617 else
618 bounded = FALSE;
620 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
622 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
623 for (i = 0; i < aklass->rank; ++i) {
624 sizes [i] = mono_array_get (lengths, guint64, i);
625 if (bounds)
626 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
627 else
628 sizes [i + aklass->rank] = 0;
631 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
633 return array;
636 static gint32
637 ves_icall_System_Array_GetRank (MonoObject *this)
639 MONO_ARCH_SAVE_REGS;
641 return this->vtable->klass->rank;
644 static gint32
645 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
647 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
648 mono_array_size_t length;
650 MONO_ARCH_SAVE_REGS;
652 if ((dimension < 0) || (dimension >= rank))
653 mono_raise_exception (mono_get_exception_index_out_of_range ());
655 if (this->bounds == NULL)
656 length = this->max_length;
657 else
658 length = this->bounds [dimension].length;
660 #ifdef MONO_BIG_ARRAYS
661 if (length > G_MAXINT32)
662 mono_raise_exception (mono_get_exception_overflow ());
663 #endif
664 return length;
667 static gint64
668 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
670 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
672 MONO_ARCH_SAVE_REGS;
674 if ((dimension < 0) || (dimension >= rank))
675 mono_raise_exception (mono_get_exception_index_out_of_range ());
677 if (this->bounds == NULL)
678 return this->max_length;
680 return this->bounds [dimension].length;
683 static gint32
684 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
686 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
688 MONO_ARCH_SAVE_REGS;
690 if ((dimension < 0) || (dimension >= rank))
691 mono_raise_exception (mono_get_exception_index_out_of_range ());
693 if (this->bounds == NULL)
694 return 0;
696 return this->bounds [dimension].lower_bound;
699 static void
700 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
702 int sz = mono_array_element_size (mono_object_class (arr));
703 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
706 static gboolean
707 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
709 int element_size;
710 void * dest_addr;
711 void * source_addr;
712 MonoClass *src_class;
713 MonoClass *dest_class;
714 int i;
716 MONO_ARCH_SAVE_REGS;
718 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
719 return FALSE;
721 if (source->bounds || dest->bounds)
722 return FALSE;
724 /* there's no integer overflow since mono_array_length returns an unsigned integer */
725 if ((dest_idx + length > mono_array_length (dest)) ||
726 (source_idx + length > mono_array_length (source)))
727 return FALSE;
729 src_class = source->obj.vtable->klass->element_class;
730 dest_class = dest->obj.vtable->klass->element_class;
733 * Handle common cases.
736 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
737 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
738 int has_refs = dest_class->has_references;
739 for (i = source_idx; i < source_idx + length; ++i) {
740 MonoObject *elem = mono_array_get (source, MonoObject*, i);
741 if (elem && !mono_object_isinst (elem, dest_class))
742 return FALSE;
745 element_size = mono_array_element_size (dest->obj.vtable->klass);
746 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
747 for (i = 0; i < length; ++i) {
748 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
749 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
750 if (!elem)
751 continue;
752 if (has_refs)
753 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
754 else
755 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
757 return TRUE;
760 /* Check if we're copying a char[] <==> (u)short[] */
761 if (src_class != dest_class) {
762 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
763 return FALSE;
765 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
767 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
768 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
769 for (i = source_idx; i < source_idx + length; ++i) {
770 MonoObject *elem = mono_array_get (source, MonoObject*, i);
771 if (elem && !mono_object_isinst (elem, dest_class))
772 return FALSE;
774 else
775 return FALSE;
778 if (dest_class->valuetype) {
779 element_size = mono_array_element_size (source->obj.vtable->klass);
780 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
781 if (dest_class->has_references) {
782 mono_value_copy_array (dest, dest_idx, source_addr, length);
783 } else {
784 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
785 memmove (dest_addr, source_addr, element_size * length);
787 } else {
788 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
791 return TRUE;
794 static void
795 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
797 MonoClass *ac;
798 MonoArray *ao;
799 gint32 esize;
800 gpointer *ea;
802 MONO_ARCH_SAVE_REGS;
804 ao = (MonoArray *)this;
805 ac = (MonoClass *)ao->obj.vtable->klass;
807 esize = mono_array_element_size (ac);
808 ea = (gpointer*)((char*)ao->vector + (pos * esize));
810 memcpy (value, ea, esize);
813 static void
814 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
816 MonoClass *ac, *ec;
817 MonoArray *ao;
818 gint32 esize;
819 gpointer *ea;
821 MONO_ARCH_SAVE_REGS;
823 ao = (MonoArray *)this;
824 ac = (MonoClass *)ao->obj.vtable->klass;
825 ec = ac->element_class;
827 esize = mono_array_element_size (ac);
828 ea = (gpointer*)((char*)ao->vector + (pos * esize));
830 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
831 g_assert (esize == sizeof (gpointer));
832 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
833 } else {
834 g_assert (ec->inited);
835 g_assert (esize == mono_class_value_size (ec, NULL));
836 if (ec->has_references)
837 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
838 else
839 memcpy (ea, value, esize);
843 static void
844 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
846 MonoClass *klass = array->obj.vtable->klass;
847 guint32 size = mono_array_element_size (klass);
848 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
849 int align;
850 const char *field_data;
852 if (MONO_TYPE_IS_REFERENCE (type) ||
853 (type->type == MONO_TYPE_VALUETYPE &&
854 (!mono_type_get_class (type) ||
855 mono_type_get_class (type)->has_references))) {
856 MonoException *exc = mono_get_exception_argument("array",
857 "Cannot initialize array containing references");
858 mono_raise_exception (exc);
861 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
862 MonoException *exc = mono_get_exception_argument("field_handle",
863 "Field doesn't have an RVA");
864 mono_raise_exception (exc);
867 size *= array->max_length;
868 field_data = mono_field_get_data (field_handle);
870 if (size > mono_type_size (field_handle->type, &align)) {
871 MonoException *exc = mono_get_exception_argument("field_handle",
872 "Field not large enough to fill array");
873 mono_raise_exception (exc);
876 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
877 #define SWAP(n) {\
878 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
879 guint ## n *src = (guint ## n *) field_data; \
880 guint ## n *end = (guint ## n *)((char*)src + size); \
882 for (; src < end; data++, src++) { \
883 *data = read ## n (src); \
887 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
889 switch (type->type) {
890 case MONO_TYPE_CHAR:
891 case MONO_TYPE_I2:
892 case MONO_TYPE_U2:
893 SWAP (16);
894 break;
895 case MONO_TYPE_I4:
896 case MONO_TYPE_U4:
897 case MONO_TYPE_R4:
898 SWAP (32);
899 break;
900 case MONO_TYPE_I8:
901 case MONO_TYPE_U8:
902 case MONO_TYPE_R8:
903 SWAP (64);
904 break;
905 default:
906 memcpy (mono_array_addr (array, char, 0), field_data, size);
907 break;
909 #else
910 memcpy (mono_array_addr (array, char, 0), field_data, size);
911 #ifdef ARM_FPU_FPA
912 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
913 gint i;
914 double tmp;
915 double *data = (double*)mono_array_addr (array, double, 0);
917 for (i = 0; i < size; i++, data++) {
918 readr8 (data, &tmp);
919 *data = tmp;
922 #endif
923 #endif
926 static gint
927 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
929 MONO_ARCH_SAVE_REGS;
931 return offsetof (MonoString, chars);
934 static MonoObject *
935 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
937 MONO_ARCH_SAVE_REGS;
939 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
940 return obj;
941 else
942 return mono_object_clone (obj);
945 static void
946 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
948 MonoClass *klass;
949 MonoVTable *vtable;
951 MONO_CHECK_ARG_NULL (handle);
953 klass = mono_class_from_mono_type (handle);
954 MONO_CHECK_ARG (handle, klass);
956 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
958 /* This will call the type constructor */
959 mono_runtime_class_init (vtable);
962 static void
963 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
965 MONO_ARCH_SAVE_REGS;
967 mono_image_check_for_module_cctor (image);
968 if (image->has_module_cctor) {
969 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
970 /*It's fine to raise the exception here*/
971 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
975 static MonoObject *
976 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
978 MONO_ARCH_SAVE_REGS;
980 return mono_object_clone (this);
983 static gint32
984 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
986 MonoClass *klass;
987 MonoObject **values = NULL;
988 MonoObject *o;
989 int count = 0;
990 gint32 result = 0;
991 MonoClassField* field;
992 gpointer iter;
994 MONO_ARCH_SAVE_REGS;
996 klass = mono_object_class (this);
998 if (mono_class_num_fields (klass) == 0)
999 return mono_object_hash (this);
1002 * Compute the starting value of the hashcode for fields of primitive
1003 * types, and return the remaining fields in an array to the managed side.
1004 * This way, we can avoid costly reflection operations in managed code.
1006 iter = NULL;
1007 while ((field = mono_class_get_fields (klass, &iter))) {
1008 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1009 continue;
1010 if (mono_field_is_deleted (field))
1011 continue;
1012 /* FIXME: Add more types */
1013 switch (field->type->type) {
1014 case MONO_TYPE_I4:
1015 result ^= *(gint32*)((guint8*)this + field->offset);
1016 break;
1017 case MONO_TYPE_STRING: {
1018 MonoString *s;
1019 s = *(MonoString**)((guint8*)this + field->offset);
1020 if (s != NULL)
1021 result ^= mono_string_hash (s);
1022 break;
1024 default:
1025 if (!values)
1026 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1027 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1028 values [count++] = o;
1032 if (values) {
1033 int i;
1034 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1035 for (i = 0; i < count; ++i)
1036 mono_array_setref (*fields, i, values [i]);
1037 } else {
1038 *fields = NULL;
1040 return result;
1043 static MonoBoolean
1044 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1046 MonoClass *klass;
1047 MonoObject **values = NULL;
1048 MonoObject *o;
1049 MonoClassField* field;
1050 gpointer iter;
1051 int count = 0;
1053 MONO_ARCH_SAVE_REGS;
1055 MONO_CHECK_ARG_NULL (that);
1057 if (this->vtable != that->vtable)
1058 return FALSE;
1060 klass = mono_object_class (this);
1062 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1063 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1066 * Do the comparison for fields of primitive type and return a result if
1067 * possible. Otherwise, return the remaining fields in an array to the
1068 * managed side. This way, we can avoid costly reflection operations in
1069 * managed code.
1071 *fields = NULL;
1072 iter = NULL;
1073 while ((field = mono_class_get_fields (klass, &iter))) {
1074 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1075 continue;
1076 if (mono_field_is_deleted (field))
1077 continue;
1078 /* FIXME: Add more types */
1079 switch (field->type->type) {
1080 case MONO_TYPE_U1:
1081 case MONO_TYPE_I1:
1082 case MONO_TYPE_BOOLEAN:
1083 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1084 return FALSE;
1085 break;
1086 case MONO_TYPE_U2:
1087 case MONO_TYPE_I2:
1088 case MONO_TYPE_CHAR:
1089 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1090 return FALSE;
1091 break;
1092 case MONO_TYPE_U4:
1093 case MONO_TYPE_I4:
1094 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1095 return FALSE;
1096 break;
1097 case MONO_TYPE_U8:
1098 case MONO_TYPE_I8:
1099 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1100 return FALSE;
1101 break;
1102 case MONO_TYPE_R4:
1103 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1104 return FALSE;
1105 break;
1106 case MONO_TYPE_R8:
1107 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1108 return FALSE;
1109 break;
1112 case MONO_TYPE_STRING: {
1113 MonoString *s1, *s2;
1114 guint32 s1len, s2len;
1115 s1 = *(MonoString**)((guint8*)this + field->offset);
1116 s2 = *(MonoString**)((guint8*)that + field->offset);
1117 if (s1 == s2)
1118 break;
1119 if ((s1 == NULL) || (s2 == NULL))
1120 return FALSE;
1121 s1len = mono_string_length (s1);
1122 s2len = mono_string_length (s2);
1123 if (s1len != s2len)
1124 return FALSE;
1126 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1127 return FALSE;
1128 break;
1130 default:
1131 if (!values)
1132 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1133 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1134 values [count++] = o;
1135 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1136 values [count++] = o;
1139 if (klass->enumtype)
1140 /* enums only have one non-static field */
1141 break;
1144 if (values) {
1145 int i;
1146 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1147 for (i = 0; i < count; ++i)
1148 mono_array_setref (*fields, i, values [i]);
1149 return FALSE;
1150 } else {
1151 return TRUE;
1155 static MonoReflectionType *
1156 ves_icall_System_Object_GetType (MonoObject *obj)
1158 MONO_ARCH_SAVE_REGS;
1160 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1161 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1162 else
1163 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1166 static void
1167 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1169 MONO_ARCH_SAVE_REGS;
1171 mtype->type = &obj->vtable->klass->byval_arg;
1172 g_assert (mtype->type->type);
1175 static gint32
1176 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1178 MONO_ARCH_SAVE_REGS;
1180 MONO_CHECK_ARG_NULL (obj);
1182 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1185 static gint32
1186 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1187 MonoReflectionMethod *method,
1188 MonoArray *opt_param_types)
1190 MONO_ARCH_SAVE_REGS;
1192 MONO_CHECK_ARG_NULL (method);
1194 return mono_image_create_method_token (
1195 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1198 static void
1199 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1201 MONO_ARCH_SAVE_REGS;
1203 mono_image_create_pefile (mb, file);
1206 static void
1207 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1209 MONO_ARCH_SAVE_REGS;
1211 mono_image_build_metadata (mb);
1214 static void
1215 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1217 MONO_ARCH_SAVE_REGS;
1219 mono_image_register_token (mb->dynamic_image, token, obj);
1222 static gboolean
1223 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1225 MonoMethod **dest = data;
1227 /* skip unmanaged frames */
1228 if (!managed)
1229 return FALSE;
1231 if (m == *dest) {
1232 *dest = NULL;
1233 return FALSE;
1235 if (!(*dest)) {
1236 *dest = m;
1237 return TRUE;
1239 return FALSE;
1242 static gboolean
1243 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1245 MonoMethod **dest = data;
1247 /* skip unmanaged frames */
1248 if (!managed)
1249 return FALSE;
1251 if (!(*dest)) {
1252 if (!strcmp (m->klass->name_space, "System.Reflection"))
1253 return FALSE;
1254 *dest = m;
1255 return TRUE;
1257 return FALSE;
1260 static gboolean
1261 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1263 MonoMethod **dest = data;
1265 /* skip unmanaged frames */
1266 if (!managed)
1267 return FALSE;
1269 if (m->wrapper_type != MONO_WRAPPER_NONE)
1270 return FALSE;
1272 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1273 return FALSE;
1275 if (m == *dest) {
1276 *dest = NULL;
1277 return FALSE;
1279 if (!(*dest)) {
1280 *dest = m;
1281 return TRUE;
1283 return FALSE;
1286 static MonoReflectionType *
1287 type_from_name (const char *str, MonoBoolean ignoreCase)
1289 MonoType *type = NULL;
1290 MonoAssembly *assembly = NULL;
1291 MonoTypeNameParse info;
1292 char *temp_str = g_strdup (str);
1293 gboolean type_resolve = FALSE;
1295 MONO_ARCH_SAVE_REGS;
1297 /* mono_reflection_parse_type() mangles the string */
1298 if (!mono_reflection_parse_type (temp_str, &info)) {
1299 mono_reflection_free_type_info (&info);
1300 g_free (temp_str);
1301 return NULL;
1304 if (info.assembly.name) {
1305 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1306 } else {
1307 MonoMethod *m = mono_method_get_last_managed ();
1308 MonoMethod *dest = m;
1310 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1311 if (!dest)
1312 dest = m;
1315 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1316 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1317 * to crash. This only seems to happen in some strange remoting
1318 * scenarios and I was unable to figure out what's happening there.
1319 * Dec 10, 2005 - Martin.
1322 if (dest)
1323 assembly = dest->klass->image->assembly;
1324 else {
1325 g_warning (G_STRLOC);
1329 if (assembly)
1330 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1332 if (!info.assembly.name && !type) /* try mscorlib */
1333 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1335 mono_reflection_free_type_info (&info);
1336 g_free (temp_str);
1338 if (!type)
1339 return NULL;
1341 return mono_type_get_object (mono_domain_get (), type);
1344 #ifdef UNUSED
1345 MonoReflectionType *
1346 mono_type_get (const char *str)
1348 char *copy = g_strdup (str);
1349 MonoReflectionType *type = type_from_name (copy, FALSE);
1351 g_free (copy);
1352 return type;
1354 #endif
1356 static MonoReflectionType*
1357 ves_icall_type_from_name (MonoString *name,
1358 MonoBoolean throwOnError,
1359 MonoBoolean ignoreCase)
1361 char *str = mono_string_to_utf8 (name);
1362 MonoReflectionType *type;
1364 type = type_from_name (str, ignoreCase);
1365 g_free (str);
1366 if (type == NULL){
1367 MonoException *e = NULL;
1369 if (throwOnError)
1370 e = mono_get_exception_type_load (name, NULL);
1372 mono_loader_clear_error ();
1373 if (e != NULL)
1374 mono_raise_exception (e);
1377 return type;
1381 static MonoReflectionType*
1382 ves_icall_type_from_handle (MonoType *handle)
1384 MonoDomain *domain = mono_domain_get ();
1385 MonoClass *klass = mono_class_from_mono_type (handle);
1387 MONO_ARCH_SAVE_REGS;
1389 mono_class_init (klass);
1390 return mono_type_get_object (domain, handle);
1393 static MonoBoolean
1394 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1396 MONO_ARCH_SAVE_REGS;
1398 if (c && type->type && c->type)
1399 return mono_metadata_type_equal (type->type, c->type);
1400 else
1401 return (type == c) ? TRUE : FALSE;
1404 /* System.TypeCode */
1405 typedef enum {
1406 TYPECODE_EMPTY,
1407 TYPECODE_OBJECT,
1408 TYPECODE_DBNULL,
1409 TYPECODE_BOOLEAN,
1410 TYPECODE_CHAR,
1411 TYPECODE_SBYTE,
1412 TYPECODE_BYTE,
1413 TYPECODE_INT16,
1414 TYPECODE_UINT16,
1415 TYPECODE_INT32,
1416 TYPECODE_UINT32,
1417 TYPECODE_INT64,
1418 TYPECODE_UINT64,
1419 TYPECODE_SINGLE,
1420 TYPECODE_DOUBLE,
1421 TYPECODE_DECIMAL,
1422 TYPECODE_DATETIME,
1423 TYPECODE_STRING = 18
1424 } TypeCode;
1426 static guint32
1427 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1429 int t = type->type->type;
1431 MONO_ARCH_SAVE_REGS;
1433 if (type->type->byref)
1434 return TYPECODE_OBJECT;
1436 handle_enum:
1437 switch (t) {
1438 case MONO_TYPE_VOID:
1439 return TYPECODE_OBJECT;
1440 case MONO_TYPE_BOOLEAN:
1441 return TYPECODE_BOOLEAN;
1442 case MONO_TYPE_U1:
1443 return TYPECODE_BYTE;
1444 case MONO_TYPE_I1:
1445 return TYPECODE_SBYTE;
1446 case MONO_TYPE_U2:
1447 return TYPECODE_UINT16;
1448 case MONO_TYPE_I2:
1449 return TYPECODE_INT16;
1450 case MONO_TYPE_CHAR:
1451 return TYPECODE_CHAR;
1452 case MONO_TYPE_PTR:
1453 case MONO_TYPE_U:
1454 case MONO_TYPE_I:
1455 return TYPECODE_OBJECT;
1456 case MONO_TYPE_U4:
1457 return TYPECODE_UINT32;
1458 case MONO_TYPE_I4:
1459 return TYPECODE_INT32;
1460 case MONO_TYPE_U8:
1461 return TYPECODE_UINT64;
1462 case MONO_TYPE_I8:
1463 return TYPECODE_INT64;
1464 case MONO_TYPE_R4:
1465 return TYPECODE_SINGLE;
1466 case MONO_TYPE_R8:
1467 return TYPECODE_DOUBLE;
1468 case MONO_TYPE_VALUETYPE:
1469 if (type->type->data.klass->enumtype) {
1470 t = mono_class_enum_basetype (type->type->data.klass)->type;
1471 goto handle_enum;
1472 } else {
1473 MonoClass *k = type->type->data.klass;
1474 if (strcmp (k->name_space, "System") == 0) {
1475 if (strcmp (k->name, "Decimal") == 0)
1476 return TYPECODE_DECIMAL;
1477 else if (strcmp (k->name, "DateTime") == 0)
1478 return TYPECODE_DATETIME;
1481 return TYPECODE_OBJECT;
1482 case MONO_TYPE_STRING:
1483 return TYPECODE_STRING;
1484 case MONO_TYPE_SZARRAY:
1485 case MONO_TYPE_ARRAY:
1486 case MONO_TYPE_OBJECT:
1487 case MONO_TYPE_VAR:
1488 case MONO_TYPE_MVAR:
1489 case MONO_TYPE_TYPEDBYREF:
1490 return TYPECODE_OBJECT;
1491 case MONO_TYPE_CLASS:
1493 MonoClass *k = type->type->data.klass;
1494 if (strcmp (k->name_space, "System") == 0) {
1495 if (strcmp (k->name, "DBNull") == 0)
1496 return TYPECODE_DBNULL;
1499 return TYPECODE_OBJECT;
1500 case MONO_TYPE_GENERICINST:
1501 return TYPECODE_OBJECT;
1502 default:
1503 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1505 return 0;
1508 static guint32
1509 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1511 MonoDomain *domain;
1512 MonoClass *klass;
1513 MonoClass *klassc;
1515 MONO_ARCH_SAVE_REGS;
1517 g_assert (type != NULL);
1519 domain = ((MonoObject *)type)->vtable->domain;
1521 if (!c) /* FIXME: dont know what do do here */
1522 return 0;
1524 klass = mono_class_from_mono_type (type->type);
1525 klassc = mono_class_from_mono_type (c->type);
1527 if (type->type->byref)
1528 return klassc == mono_defaults.object_class;
1530 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1533 static guint32
1534 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1536 MonoDomain *domain;
1537 MonoClass *klass;
1538 MonoClass *klassc;
1540 MONO_ARCH_SAVE_REGS;
1542 g_assert (type != NULL);
1544 domain = ((MonoObject *)type)->vtable->domain;
1546 klass = mono_class_from_mono_type (type->type);
1547 klassc = mono_class_from_mono_type (c->type);
1549 if (type->type->byref && !c->type->byref)
1550 return FALSE;
1552 return mono_class_is_assignable_from (klass, klassc);
1555 static guint32
1556 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1558 MonoClass *klass = mono_class_from_mono_type (type->type);
1559 return mono_object_isinst (obj, klass) != NULL;
1562 static guint32
1563 ves_icall_get_attributes (MonoReflectionType *type)
1565 MonoClass *klass = mono_class_from_mono_type (type->type);
1567 MONO_ARCH_SAVE_REGS;
1569 return klass->flags;
1572 static MonoReflectionMarshal*
1573 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1575 MonoClass *klass = field->field->parent;
1576 MonoMarshalType *info;
1577 int i;
1579 if (klass->generic_container ||
1580 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1581 return NULL;
1583 info = mono_marshal_load_type_info (klass);
1585 for (i = 0; i < info->num_fields; ++i) {
1586 if (info->fields [i].field == field->field) {
1587 if (!info->fields [i].mspec)
1588 return NULL;
1589 else
1590 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1594 return NULL;
1597 static MonoReflectionField*
1598 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1600 gboolean found = FALSE;
1601 MonoClass *klass;
1602 MonoClass *k;
1604 g_assert (handle);
1606 if (!type) {
1607 klass = handle->parent;
1608 } else {
1609 klass = mono_class_from_mono_type (type);
1611 /* Check that the field belongs to the class */
1612 for (k = klass; k; k = k->parent) {
1613 if (k == handle->parent) {
1614 found = TRUE;
1615 break;
1619 if (!found)
1620 /* The managed code will throw the exception */
1621 return NULL;
1624 return mono_field_get_object (mono_domain_get (), klass, handle);
1627 static MonoArray*
1628 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1630 MonoType *type = field->field->type;
1632 return type_array_from_modifiers (field->field->parent->image, type, optional);
1635 static void
1636 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1638 MonoDomain *domain = mono_domain_get ();
1639 MonoMethodSignature* sig;
1640 MONO_ARCH_SAVE_REGS;
1642 sig = mono_method_signature (method);
1643 if (!sig) {
1644 g_assert (mono_loader_get_last_error ());
1645 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1648 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1649 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1650 info->attrs = method->flags;
1651 info->implattrs = method->iflags;
1652 if (sig->call_convention == MONO_CALL_DEFAULT)
1653 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1654 else {
1655 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1656 info->callconv = 2;
1657 else
1658 info->callconv = 1;
1660 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1663 static MonoArray*
1664 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1666 MonoDomain *domain = mono_domain_get ();
1668 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1671 static MonoReflectionMarshal*
1672 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1674 MonoDomain *domain = mono_domain_get ();
1675 MonoReflectionMarshal* res = NULL;
1676 MonoMarshalSpec **mspecs;
1677 int i;
1679 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1680 mono_method_get_marshal_info (method, mspecs);
1682 if (mspecs [0])
1683 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1685 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1686 if (mspecs [i])
1687 mono_metadata_free_marshal_spec (mspecs [i]);
1688 g_free (mspecs);
1690 return res;
1693 static gint32
1694 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1696 return field->field->offset - sizeof (MonoObject);
1699 static MonoReflectionType*
1700 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1702 MonoClass *parent;
1703 MONO_ARCH_SAVE_REGS;
1705 parent = declaring? field->field->parent: field->klass;
1707 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1710 static MonoObject *
1711 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1713 MonoObject *o;
1714 MonoClassField *cf = field->field;
1715 MonoClass *klass;
1716 MonoVTable *vtable;
1717 MonoType *t;
1718 MonoDomain *domain = mono_object_domain (field);
1719 gchar *v;
1720 gboolean is_static = FALSE;
1721 gboolean is_ref = FALSE;
1723 MONO_ARCH_SAVE_REGS;
1725 if (field->klass->image->assembly->ref_only)
1726 mono_raise_exception (mono_get_exception_invalid_operation (
1727 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1729 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1730 mono_security_core_clr_ensure_reflection_access_field (cf);
1732 mono_class_init (field->klass);
1734 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1735 is_static = TRUE;
1737 if (obj && !is_static) {
1738 /* Check that the field belongs to the object */
1739 gboolean found = FALSE;
1740 MonoClass *k;
1742 for (k = obj->vtable->klass; k; k = k->parent) {
1743 if (k == cf->parent) {
1744 found = TRUE;
1745 break;
1749 if (!found) {
1750 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);
1751 MonoException *ex = mono_get_exception_argument (NULL, msg);
1752 g_free (msg);
1753 mono_raise_exception (ex);
1757 t = mono_type_get_underlying_type (cf->type);
1758 switch (t->type) {
1759 case MONO_TYPE_STRING:
1760 case MONO_TYPE_OBJECT:
1761 case MONO_TYPE_CLASS:
1762 case MONO_TYPE_ARRAY:
1763 case MONO_TYPE_SZARRAY:
1764 is_ref = TRUE;
1765 break;
1766 case MONO_TYPE_U1:
1767 case MONO_TYPE_I1:
1768 case MONO_TYPE_BOOLEAN:
1769 case MONO_TYPE_U2:
1770 case MONO_TYPE_I2:
1771 case MONO_TYPE_CHAR:
1772 case MONO_TYPE_U:
1773 case MONO_TYPE_I:
1774 case MONO_TYPE_U4:
1775 case MONO_TYPE_I4:
1776 case MONO_TYPE_R4:
1777 case MONO_TYPE_U8:
1778 case MONO_TYPE_I8:
1779 case MONO_TYPE_R8:
1780 case MONO_TYPE_VALUETYPE:
1781 is_ref = t->byref;
1782 break;
1783 case MONO_TYPE_GENERICINST:
1784 if (mono_type_generic_inst_is_valuetype (t)) {
1785 is_ref = t->byref;
1786 } else {
1787 is_ref = TRUE;
1789 break;
1790 default:
1791 g_error ("type 0x%x not handled in "
1792 "ves_icall_Monofield_GetValue", t->type);
1793 return NULL;
1796 vtable = NULL;
1797 if (is_static) {
1798 vtable = mono_class_vtable_full (domain, cf->parent, TRUE);
1799 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1800 mono_runtime_class_init (vtable);
1803 if (is_ref) {
1804 if (is_static) {
1805 mono_field_static_get_value (vtable, cf, &o);
1806 } else {
1807 mono_field_get_value (obj, cf, &o);
1809 return o;
1812 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1813 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1814 guint8 *buf;
1816 /* Convert the Nullable structure into a boxed vtype */
1817 if (is_static)
1818 buf = (guint8*)vtable->data + cf->offset;
1819 else
1820 buf = (guint8*)obj + cf->offset;
1822 return mono_nullable_box (buf, nklass);
1825 /* boxed value type */
1826 klass = mono_class_from_mono_type (cf->type);
1827 o = mono_object_new (domain, klass);
1828 v = ((gchar *) o) + sizeof (MonoObject);
1829 if (is_static) {
1830 mono_field_static_get_value (vtable, cf, v);
1831 } else {
1832 mono_field_get_value (obj, cf, v);
1835 return o;
1838 static void
1839 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1841 MonoClassField *cf = field->field;
1842 gchar *v;
1844 MONO_ARCH_SAVE_REGS;
1846 if (field->klass->image->assembly->ref_only)
1847 mono_raise_exception (mono_get_exception_invalid_operation (
1848 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1850 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1851 mono_security_core_clr_ensure_reflection_access_field (cf);
1853 v = (gchar *) value;
1854 if (!cf->type->byref) {
1855 switch (cf->type->type) {
1856 case MONO_TYPE_U1:
1857 case MONO_TYPE_I1:
1858 case MONO_TYPE_BOOLEAN:
1859 case MONO_TYPE_U2:
1860 case MONO_TYPE_I2:
1861 case MONO_TYPE_CHAR:
1862 case MONO_TYPE_U:
1863 case MONO_TYPE_I:
1864 case MONO_TYPE_U4:
1865 case MONO_TYPE_I4:
1866 case MONO_TYPE_R4:
1867 case MONO_TYPE_U8:
1868 case MONO_TYPE_I8:
1869 case MONO_TYPE_R8:
1870 case MONO_TYPE_VALUETYPE:
1871 if (v != NULL)
1872 v += sizeof (MonoObject);
1873 break;
1874 case MONO_TYPE_STRING:
1875 case MONO_TYPE_OBJECT:
1876 case MONO_TYPE_CLASS:
1877 case MONO_TYPE_ARRAY:
1878 case MONO_TYPE_SZARRAY:
1879 /* Do nothing */
1880 break;
1881 case MONO_TYPE_GENERICINST: {
1882 MonoGenericClass *gclass = cf->type->data.generic_class;
1883 g_assert (!gclass->context.class_inst->is_open);
1885 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1886 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1887 MonoObject *nullable;
1890 * Convert the boxed vtype into a Nullable structure.
1891 * This is complicated by the fact that Nullables have
1892 * a variable structure.
1894 nullable = mono_object_new (mono_domain_get (), nklass);
1896 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1898 v = mono_object_unbox (nullable);
1900 else
1901 if (gclass->container_class->valuetype && (v != NULL))
1902 v += sizeof (MonoObject);
1903 break;
1905 default:
1906 g_error ("type 0x%x not handled in "
1907 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1908 return;
1912 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1913 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1914 if (!vtable->initialized)
1915 mono_runtime_class_init (vtable);
1916 mono_field_static_set_value (vtable, cf, v);
1917 } else {
1918 mono_field_set_value (obj, cf, v);
1922 static MonoObject *
1923 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1925 MonoObject *o = NULL;
1926 MonoClassField *field = this->field;
1927 MonoClass *klass;
1928 MonoDomain *domain = mono_object_domain (this);
1929 gchar *v;
1930 MonoTypeEnum def_type;
1931 const char *def_value;
1933 MONO_ARCH_SAVE_REGS;
1935 mono_class_init (field->parent);
1937 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1938 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1940 if (field->parent->image->dynamic) {
1941 /* FIXME: */
1942 g_assert_not_reached ();
1945 def_value = mono_class_get_field_default_value (field, &def_type);
1947 switch (def_type) {
1948 case MONO_TYPE_U1:
1949 case MONO_TYPE_I1:
1950 case MONO_TYPE_BOOLEAN:
1951 case MONO_TYPE_U2:
1952 case MONO_TYPE_I2:
1953 case MONO_TYPE_CHAR:
1954 case MONO_TYPE_U:
1955 case MONO_TYPE_I:
1956 case MONO_TYPE_U4:
1957 case MONO_TYPE_I4:
1958 case MONO_TYPE_R4:
1959 case MONO_TYPE_U8:
1960 case MONO_TYPE_I8:
1961 case MONO_TYPE_R8: {
1962 MonoType *t;
1964 /* boxed value type */
1965 t = g_new0 (MonoType, 1);
1966 t->type = def_type;
1967 klass = mono_class_from_mono_type (t);
1968 g_free (t);
1969 o = mono_object_new (domain, klass);
1970 v = ((gchar *) o) + sizeof (MonoObject);
1971 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1972 break;
1974 case MONO_TYPE_STRING:
1975 case MONO_TYPE_CLASS:
1976 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1977 break;
1978 default:
1979 g_assert_not_reached ();
1982 return o;
1985 static MonoReflectionType*
1986 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1988 MonoMethod *method = rmethod->method.method;
1990 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1993 /* From MonoProperty.cs */
1994 typedef enum {
1995 PInfo_Attributes = 1,
1996 PInfo_GetMethod = 1 << 1,
1997 PInfo_SetMethod = 1 << 2,
1998 PInfo_ReflectedType = 1 << 3,
1999 PInfo_DeclaringType = 1 << 4,
2000 PInfo_Name = 1 << 5
2001 } PInfo;
2003 static void
2004 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2006 MonoDomain *domain = mono_object_domain (property);
2008 MONO_ARCH_SAVE_REGS;
2010 if ((req_info & PInfo_ReflectedType) != 0)
2011 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2012 else if ((req_info & PInfo_DeclaringType) != 0)
2013 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
2015 if ((req_info & PInfo_Name) != 0)
2016 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2018 if ((req_info & PInfo_Attributes) != 0)
2019 info->attrs = property->property->attrs;
2021 if ((req_info & PInfo_GetMethod) != 0)
2022 MONO_STRUCT_SETREF (info, get, property->property->get ?
2023 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2025 if ((req_info & PInfo_SetMethod) != 0)
2026 MONO_STRUCT_SETREF (info, set, property->property->set ?
2027 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2029 * There may be other methods defined for properties, though, it seems they are not exposed
2030 * in the reflection API
2034 static void
2035 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2037 MonoDomain *domain = mono_object_domain (event);
2039 MONO_ARCH_SAVE_REGS;
2041 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2042 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2044 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2045 info->attrs = event->event->attrs;
2046 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2047 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2048 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2050 if (event->event->other) {
2051 int i, n = 0;
2052 while (event->event->other [n])
2053 n++;
2054 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2056 for (i = 0; i < n; i++)
2057 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2061 static MonoArray*
2062 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2064 MonoError error;
2065 MonoDomain *domain = mono_object_domain (type);
2066 MonoArray *intf;
2067 GPtrArray *ifaces = NULL;
2068 int i;
2069 MonoClass *class = mono_class_from_mono_type (type->type);
2070 MonoClass *parent;
2071 MonoBitSet *slots;
2072 MonoGenericContext *context = NULL;
2074 MONO_ARCH_SAVE_REGS;
2076 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2077 context = mono_class_get_context (class);
2078 class = class->generic_class->container_class;
2081 mono_class_setup_vtable (class);
2083 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2085 for (parent = class; parent; parent = parent->parent) {
2086 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent, &error);
2087 if (!mono_error_ok (&error)) {
2088 mono_bitset_free (slots);
2089 mono_error_raise_exception (&error);
2090 return NULL;
2091 } else if (tmp_ifaces) {
2092 for (i = 0; i < tmp_ifaces->len; ++i) {
2093 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2095 if (mono_bitset_test (slots, ic->interface_id))
2096 continue;
2098 mono_bitset_set (slots, ic->interface_id);
2099 if (ifaces == NULL)
2100 ifaces = g_ptr_array_new ();
2101 g_ptr_array_add (ifaces, ic);
2103 g_ptr_array_free (tmp_ifaces, TRUE);
2106 mono_bitset_free (slots);
2108 if (!ifaces)
2109 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2111 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2112 for (i = 0; i < ifaces->len; ++i) {
2113 MonoClass *ic = g_ptr_array_index (ifaces, i);
2114 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2115 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2116 inflated = ret = mono_class_inflate_generic_type (ret, context);
2118 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2119 if (inflated)
2120 mono_metadata_free_type (inflated);
2122 g_ptr_array_free (ifaces, TRUE);
2124 return intf;
2127 static void
2128 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2130 gboolean variance_used;
2131 MonoClass *class = mono_class_from_mono_type (type->type);
2132 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2133 MonoReflectionMethod *member;
2134 MonoMethod* method;
2135 gpointer iter;
2136 int i = 0, len, ioffset;
2137 MonoDomain *domain;
2139 MONO_ARCH_SAVE_REGS;
2141 mono_class_setup_vtable (class);
2143 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2144 if (ioffset == -1)
2145 return;
2147 len = mono_class_num_methods (iclass);
2148 domain = mono_object_domain (type);
2149 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2150 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2151 iter = NULL;
2152 while ((method = mono_class_get_methods (iclass, &iter))) {
2153 member = mono_method_get_object (domain, method, iclass);
2154 mono_array_setref (*methods, i, member);
2155 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2156 mono_array_setref (*targets, i, member);
2158 i ++;
2162 static void
2163 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2165 MonoClass *klass = mono_class_from_mono_type (type->type);
2167 if (klass->image->dynamic) {
2168 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2169 *packing = tb->packing_size;
2170 *size = tb->class_size;
2171 } else {
2172 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2176 static MonoReflectionType*
2177 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2179 MonoClass *class;
2181 MONO_ARCH_SAVE_REGS;
2183 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2184 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2186 class = mono_class_from_mono_type (type->type);
2188 // GetElementType should only return a type for:
2189 // Array Pointer PassedByRef
2190 if (type->type->byref)
2191 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2192 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2193 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2194 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2195 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2196 else
2197 return NULL;
2200 static MonoReflectionType*
2201 ves_icall_get_type_parent (MonoReflectionType *type)
2203 MonoClass *class = mono_class_from_mono_type (type->type);
2205 MONO_ARCH_SAVE_REGS;
2207 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2210 static MonoBoolean
2211 ves_icall_type_ispointer (MonoReflectionType *type)
2213 MONO_ARCH_SAVE_REGS;
2215 return type->type->type == MONO_TYPE_PTR;
2218 static MonoBoolean
2219 ves_icall_type_isprimitive (MonoReflectionType *type)
2221 MONO_ARCH_SAVE_REGS;
2223 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)));
2226 static MonoBoolean
2227 ves_icall_type_isbyref (MonoReflectionType *type)
2229 MONO_ARCH_SAVE_REGS;
2231 return type->type->byref;
2234 static MonoBoolean
2235 ves_icall_type_iscomobject (MonoReflectionType *type)
2237 MonoClass *klass = mono_class_from_mono_type (type->type);
2238 MONO_ARCH_SAVE_REGS;
2240 return (klass && klass->is_com_object);
2243 static MonoReflectionModule*
2244 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2246 MonoClass *class = mono_class_from_mono_type (type->type);
2248 MONO_ARCH_SAVE_REGS;
2250 return mono_module_get_object (mono_object_domain (type), class->image);
2253 static MonoReflectionAssembly*
2254 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2256 MonoDomain *domain = mono_domain_get ();
2257 MonoClass *class = mono_class_from_mono_type (type->type);
2259 MONO_ARCH_SAVE_REGS;
2261 return mono_assembly_get_object (domain, class->image->assembly);
2264 static MonoReflectionType*
2265 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2267 MonoDomain *domain = mono_domain_get ();
2268 MonoClass *class;
2270 MONO_ARCH_SAVE_REGS;
2272 if (type->type->byref)
2273 return NULL;
2274 if (type->type->type == MONO_TYPE_VAR)
2275 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2276 else if (type->type->type == MONO_TYPE_MVAR)
2277 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2278 else
2279 class = mono_class_from_mono_type (type->type)->nested_in;
2281 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2284 static MonoReflectionType*
2285 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2287 MonoDomain *domain = mono_domain_get ();
2288 MonoClass *class = mono_class_from_mono_type (type->type);
2290 MONO_ARCH_SAVE_REGS;
2292 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2293 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2294 else if (class->element_class)
2295 return mono_type_get_object (domain, &class->element_class->byval_arg);
2296 else
2297 return NULL;
2300 static MonoString*
2301 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2303 MonoDomain *domain = mono_domain_get ();
2304 MonoClass *class = mono_class_from_mono_type (type->type);
2306 MONO_ARCH_SAVE_REGS;
2308 if (type->type->byref) {
2309 char *n = g_strdup_printf ("%s&", class->name);
2310 MonoString *res = mono_string_new (domain, n);
2312 g_free (n);
2314 return res;
2315 } else {
2316 return mono_string_new (domain, class->name);
2320 static MonoString*
2321 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2323 MonoDomain *domain = mono_domain_get ();
2324 MonoClass *class = mono_class_from_mono_type (type->type);
2326 MONO_ARCH_SAVE_REGS;
2328 while (class->nested_in)
2329 class = class->nested_in;
2331 if (class->name_space [0] == '\0')
2332 return NULL;
2333 else
2334 return mono_string_new (domain, class->name_space);
2337 static gint32
2338 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2340 MonoClass *class;
2342 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2343 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2345 class = mono_class_from_mono_type (type->type);
2346 return class->rank;
2349 static MonoArray*
2350 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2352 MonoArray *res;
2353 MonoClass *klass, *pklass;
2354 MonoDomain *domain = mono_object_domain (type);
2355 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2356 int i;
2357 MONO_ARCH_SAVE_REGS;
2359 klass = mono_class_from_mono_type (type->type);
2361 if (klass->generic_container) {
2362 MonoGenericContainer *container = klass->generic_container;
2363 res = mono_array_new_specific (array_vtable, container->type_argc);
2364 for (i = 0; i < container->type_argc; ++i) {
2365 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2366 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2368 } else if (klass->generic_class) {
2369 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2370 res = mono_array_new_specific (array_vtable, inst->type_argc);
2371 for (i = 0; i < inst->type_argc; ++i)
2372 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2373 } else {
2374 res = mono_array_new_specific (array_vtable, 0);
2376 return res;
2379 static gboolean
2380 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2382 MonoClass *klass;
2383 MONO_ARCH_SAVE_REGS;
2385 if (!IS_MONOTYPE (type))
2386 return FALSE;
2388 if (type->type->byref)
2389 return FALSE;
2391 klass = mono_class_from_mono_type (type->type);
2393 return klass->generic_container != NULL;
2396 static MonoReflectionType*
2397 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2399 MonoClass *klass;
2400 MONO_ARCH_SAVE_REGS;
2402 if (type->type->byref)
2403 return NULL;
2405 klass = mono_class_from_mono_type (type->type);
2406 if (klass->generic_container) {
2407 return type; /* check this one */
2409 if (klass->generic_class) {
2410 MonoClass *generic_class = klass->generic_class->container_class;
2412 if (generic_class->wastypebuilder && generic_class->reflection_info)
2413 return generic_class->reflection_info;
2414 else
2415 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2417 return NULL;
2420 static MonoReflectionType*
2421 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2423 MonoType *geninst, **types;
2424 int i, count;
2426 MONO_ARCH_SAVE_REGS;
2428 count = mono_array_length (type_array);
2429 types = g_new0 (MonoType *, count);
2431 for (i = 0; i < count; i++) {
2432 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2433 types [i] = t->type;
2436 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2437 g_free (types);
2438 if (!geninst)
2439 return NULL;
2441 return mono_type_get_object (mono_object_domain (type), geninst);
2444 static gboolean
2445 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2447 MonoClass *klass;
2448 MONO_ARCH_SAVE_REGS;
2450 if (type->type->byref)
2451 return FALSE;
2453 klass = mono_class_from_mono_type (type->type);
2454 return klass->generic_class != NULL;
2457 static gboolean
2458 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2460 MonoClass *klass;
2461 MONO_ARCH_SAVE_REGS;
2463 if (!IS_MONOTYPE (type))
2464 return FALSE;
2466 if (type->type->byref)
2467 return FALSE;
2469 klass = mono_class_from_mono_type (type->type);
2470 return klass->generic_class != NULL || klass->generic_container != NULL;
2473 static gint32
2474 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2476 MONO_ARCH_SAVE_REGS;
2478 if (!IS_MONOTYPE (type))
2479 return -1;
2481 if (is_generic_parameter (type->type))
2482 return mono_type_get_generic_param_num (type->type);
2483 return -1;
2486 static GenericParameterAttributes
2487 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2489 MONO_ARCH_SAVE_REGS;
2491 g_assert (IS_MONOTYPE (type));
2492 g_assert (is_generic_parameter (type->type));
2493 return mono_generic_param_info (type->type->data.generic_param)->flags;
2496 static MonoArray *
2497 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2499 MonoGenericParamInfo *param_info;
2500 MonoDomain *domain;
2501 MonoClass **ptr;
2502 MonoArray *res;
2503 int i, count;
2505 MONO_ARCH_SAVE_REGS;
2507 g_assert (IS_MONOTYPE (type));
2509 domain = mono_object_domain (type);
2510 param_info = mono_generic_param_info (type->type->data.generic_param);
2511 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2514 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2515 for (i = 0; i < count; i++)
2516 mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
2519 return res;
2522 static MonoBoolean
2523 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2525 MONO_ARCH_SAVE_REGS;
2526 return is_generic_parameter (type->type);
2529 static MonoBoolean
2530 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2532 MONO_ARCH_SAVE_REGS;
2533 return is_generic_parameter (tb->type.type);
2536 static void
2537 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2538 MonoReflectionType *t)
2540 enumtype->type = t->type;
2543 static MonoReflectionMethod*
2544 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2545 MonoReflectionMethod* generic)
2547 MonoDomain *domain;
2548 MonoClass *klass;
2549 MonoMethod *method;
2550 gpointer iter;
2552 MONO_ARCH_SAVE_REGS;
2554 domain = ((MonoObject *)type)->vtable->domain;
2556 klass = mono_class_from_mono_type (type->type);
2558 iter = NULL;
2559 while ((method = mono_class_get_methods (klass, &iter))) {
2560 if (method->token == generic->method->token)
2561 return mono_method_get_object (domain, method, klass);
2564 return NULL;
2569 static MonoReflectionMethod *
2570 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2572 MonoMethod *method;
2573 MonoType *type = ref_type->type;
2575 MONO_ARCH_SAVE_REGS;
2577 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2578 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2579 if (type->type == MONO_TYPE_VAR)
2580 return NULL;
2582 method = mono_type_get_generic_param_owner (type)->owner.method;
2583 g_assert (method);
2584 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2587 static MonoReflectionDllImportAttribute*
2588 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2590 static MonoClass *DllImportAttributeClass = NULL;
2591 MonoDomain *domain = mono_domain_get ();
2592 MonoReflectionDllImportAttribute *attr;
2593 MonoImage *image = method->klass->image;
2594 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2595 MonoTableInfo *tables = image->tables;
2596 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2597 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2598 guint32 im_cols [MONO_IMPLMAP_SIZE];
2599 guint32 scope_token;
2600 const char *import = NULL;
2601 const char *scope = NULL;
2602 guint32 flags;
2604 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2605 return NULL;
2607 if (!DllImportAttributeClass) {
2608 DllImportAttributeClass =
2609 mono_class_from_name (mono_defaults.corlib,
2610 "System.Runtime.InteropServices", "DllImportAttribute");
2611 g_assert (DllImportAttributeClass);
2614 if (method->klass->image->dynamic) {
2615 MonoReflectionMethodAux *method_aux =
2616 g_hash_table_lookup (
2617 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2618 if (method_aux) {
2619 import = method_aux->dllentry;
2620 scope = method_aux->dll;
2623 if (!import || !scope) {
2624 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2625 return NULL;
2628 else {
2629 if (piinfo->implmap_idx) {
2630 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2632 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2633 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2634 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2635 scope = mono_metadata_string_heap (image, scope_token);
2638 flags = piinfo->piflags;
2640 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2642 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2643 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2644 attr->call_conv = (flags & 0x700) >> 8;
2645 attr->charset = ((flags & 0x6) >> 1) + 1;
2646 if (attr->charset == 1)
2647 attr->charset = 2;
2648 attr->exact_spelling = (flags & 0x1) != 0;
2649 attr->set_last_error = (flags & 0x40) != 0;
2650 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2651 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2652 attr->preserve_sig = FALSE;
2654 return attr;
2657 static MonoReflectionMethod *
2658 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2660 MonoMethodInflated *imethod;
2661 MonoMethod *result;
2663 MONO_ARCH_SAVE_REGS;
2665 if (method->method->is_generic)
2666 return method;
2668 if (!method->method->is_inflated)
2669 return NULL;
2671 imethod = (MonoMethodInflated *) method->method;
2673 result = imethod->declaring;
2674 /* Not a generic method. */
2675 if (!result->is_generic)
2676 return NULL;
2678 if (method->method->klass->image->dynamic) {
2679 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2680 MonoReflectionMethod *res;
2683 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2684 * the dynamic case as well ?
2686 mono_loader_lock ();
2687 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2688 mono_loader_unlock ();
2690 if (res)
2691 return res;
2694 if (imethod->context.class_inst) {
2695 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2696 /*Generic methods gets the context of the GTD.*/
2697 if (mono_class_get_context (klass))
2698 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2701 return mono_method_get_object (mono_object_domain (method), result, NULL);
2704 static gboolean
2705 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2707 MONO_ARCH_SAVE_REGS;
2709 return mono_method_signature (method->method)->generic_param_count != 0;
2712 static gboolean
2713 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2715 MONO_ARCH_SAVE_REGS;
2717 return method->method->is_generic;
2720 static MonoArray*
2721 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2723 MonoArray *res;
2724 MonoDomain *domain;
2725 int count, i;
2726 MONO_ARCH_SAVE_REGS;
2728 domain = mono_object_domain (method);
2730 if (method->method->is_inflated) {
2731 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2733 if (inst) {
2734 count = inst->type_argc;
2735 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2737 for (i = 0; i < count; i++)
2738 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2740 return res;
2744 count = mono_method_signature (method->method)->generic_param_count;
2745 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2747 for (i = 0; i < count; i++) {
2748 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2749 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2750 MonoClass *pklass = mono_class_from_generic_parameter (
2751 param, method->method->klass->image, TRUE);
2752 mono_array_setref (res, i,
2753 mono_type_get_object (domain, &pklass->byval_arg));
2756 return res;
2759 static MonoObject *
2760 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2763 * Invoke from reflection is supposed to always be a virtual call (the API
2764 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2765 * greater flexibility.
2767 MonoMethod *m = method->method;
2768 int pcount;
2769 void *obj = this;
2771 MONO_ARCH_SAVE_REGS;
2773 *exc = NULL;
2775 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2776 mono_security_core_clr_ensure_reflection_access_method (m);
2778 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2779 if (this) {
2780 if (!mono_object_isinst (this, m->klass)) {
2781 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2782 return NULL;
2784 m = mono_object_get_virtual_method (this, m);
2785 /* must pass the pointer to the value for valuetype methods */
2786 if (m->klass->valuetype)
2787 obj = mono_object_unbox (this);
2788 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2789 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2790 return NULL;
2794 pcount = params? mono_array_length (params): 0;
2795 if (pcount != mono_method_signature (m)->param_count) {
2796 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2797 return NULL;
2800 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2801 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2802 return NULL;
2805 if (m->klass->image->assembly->ref_only) {
2806 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2807 return NULL;
2810 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2811 int i;
2812 mono_array_size_t *lengths;
2813 mono_array_size_t *lower_bounds;
2814 pcount = mono_array_length (params);
2815 lengths = alloca (sizeof (mono_array_size_t) * pcount);
2816 for (i = 0; i < pcount; ++i)
2817 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2819 if (m->klass->rank == pcount) {
2820 /* Only lengths provided. */
2821 lower_bounds = NULL;
2822 } else {
2823 g_assert (pcount == (m->klass->rank * 2));
2824 /* lower bounds are first. */
2825 lower_bounds = lengths;
2826 lengths += m->klass->rank;
2829 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2831 return mono_runtime_invoke_array (m, obj, params, NULL);
2834 static MonoObject *
2835 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2837 MonoDomain *domain = mono_object_domain (method);
2838 MonoMethod *m = method->method;
2839 MonoMethodSignature *sig = mono_method_signature (m);
2840 MonoArray *out_args;
2841 MonoObject *result;
2842 int i, j, outarg_count = 0;
2844 MONO_ARCH_SAVE_REGS;
2846 if (m->klass == mono_defaults.object_class) {
2848 if (!strcmp (m->name, "FieldGetter")) {
2849 MonoClass *k = this->vtable->klass;
2850 MonoString *name;
2851 char *str;
2853 /* If this is a proxy, then it must be a CBO */
2854 if (k == mono_defaults.transparent_proxy_class) {
2855 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2856 this = tp->rp->unwrapped_server;
2857 g_assert (this);
2858 k = this->vtable->klass;
2861 name = mono_array_get (params, MonoString *, 1);
2862 str = mono_string_to_utf8 (name);
2864 do {
2865 MonoClassField* field = mono_class_get_field_from_name (k, str);
2866 if (field) {
2867 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2868 if (field_klass->valuetype)
2869 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2870 else
2871 result = *((gpointer *)((char *)this + field->offset));
2873 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2874 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2875 mono_array_setref (out_args, 0, result);
2876 g_free (str);
2877 return NULL;
2879 k = k->parent;
2880 } while (k);
2882 g_free (str);
2883 g_assert_not_reached ();
2885 } else if (!strcmp (m->name, "FieldSetter")) {
2886 MonoClass *k = this->vtable->klass;
2887 MonoString *name;
2888 guint32 size;
2889 gint32 align;
2890 char *str;
2892 /* If this is a proxy, then it must be a CBO */
2893 if (k == mono_defaults.transparent_proxy_class) {
2894 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2895 this = tp->rp->unwrapped_server;
2896 g_assert (this);
2897 k = this->vtable->klass;
2900 name = mono_array_get (params, MonoString *, 1);
2901 str = mono_string_to_utf8 (name);
2903 do {
2904 MonoClassField* field = mono_class_get_field_from_name (k, str);
2905 if (field) {
2906 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2907 MonoObject *val = mono_array_get (params, gpointer, 2);
2909 if (field_klass->valuetype) {
2910 size = mono_type_size (field->type, &align);
2911 g_assert (size == mono_class_value_size (field_klass, NULL));
2912 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2913 } else {
2914 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2917 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2918 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2920 g_free (str);
2921 return NULL;
2924 k = k->parent;
2925 } while (k);
2927 g_free (str);
2928 g_assert_not_reached ();
2933 for (i = 0; i < mono_array_length (params); i++) {
2934 if (sig->params [i]->byref)
2935 outarg_count++;
2938 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2940 /* handle constructors only for objects already allocated */
2941 if (!strcmp (method->method->name, ".ctor"))
2942 g_assert (this);
2944 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2945 g_assert (!method->method->klass->valuetype);
2946 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2948 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2949 if (sig->params [i]->byref) {
2950 gpointer arg;
2951 arg = mono_array_get (params, gpointer, i);
2952 mono_array_setref (out_args, j, arg);
2953 j++;
2957 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2959 return result;
2962 static guint64
2963 read_enum_value (char *mem, int type)
2965 switch (type) {
2966 case MONO_TYPE_U1:
2967 return *(guint8*)mem;
2968 case MONO_TYPE_I1:
2969 return *(gint8*)mem;
2970 case MONO_TYPE_U2:
2971 return *(guint16*)mem;
2972 case MONO_TYPE_I2:
2973 return *(gint16*)mem;
2974 case MONO_TYPE_U4:
2975 return *(guint32*)mem;
2976 case MONO_TYPE_I4:
2977 return *(gint32*)mem;
2978 case MONO_TYPE_U8:
2979 return *(guint64*)mem;
2980 case MONO_TYPE_I8:
2981 return *(gint64*)mem;
2982 default:
2983 g_assert_not_reached ();
2985 return 0;
2988 static void
2989 write_enum_value (char *mem, int type, guint64 value)
2991 switch (type) {
2992 case MONO_TYPE_U1:
2993 case MONO_TYPE_I1: {
2994 guint8 *p = (guint8*)mem;
2995 *p = value;
2996 break;
2998 case MONO_TYPE_U2:
2999 case MONO_TYPE_I2: {
3000 guint16 *p = (void*)mem;
3001 *p = value;
3002 break;
3004 case MONO_TYPE_U4:
3005 case MONO_TYPE_I4: {
3006 guint32 *p = (void*)mem;
3007 *p = value;
3008 break;
3010 case MONO_TYPE_U8:
3011 case MONO_TYPE_I8: {
3012 guint64 *p = (void*)mem;
3013 *p = value;
3014 break;
3016 default:
3017 g_assert_not_reached ();
3019 return;
3022 static MonoObject *
3023 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3025 MonoDomain *domain;
3026 MonoClass *enumc, *objc;
3027 MonoObject *res;
3028 guint64 val;
3030 MONO_ARCH_SAVE_REGS;
3032 MONO_CHECK_ARG_NULL (enumType);
3033 MONO_CHECK_ARG_NULL (value);
3035 domain = mono_object_domain (enumType);
3036 enumc = mono_class_from_mono_type (enumType->type);
3037 objc = value->vtable->klass;
3039 if (!enumc->enumtype)
3040 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3041 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3042 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."));
3044 res = mono_object_new (domain, enumc);
3045 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3046 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3048 return res;
3051 static MonoObject *
3052 ves_icall_System_Enum_get_value (MonoObject *this)
3054 MonoObject *res;
3055 MonoClass *enumc;
3056 gpointer dst;
3057 gpointer src;
3058 int size;
3060 MONO_ARCH_SAVE_REGS;
3062 if (!this)
3063 return NULL;
3065 g_assert (this->vtable->klass->enumtype);
3067 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3068 res = mono_object_new (mono_object_domain (this), enumc);
3069 dst = (char *)res + sizeof (MonoObject);
3070 src = (char *)this + sizeof (MonoObject);
3071 size = mono_class_value_size (enumc, NULL);
3073 memcpy (dst, src, size);
3075 return res;
3078 static MonoReflectionType *
3079 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3081 MONO_ARCH_SAVE_REGS;
3083 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3086 static int
3087 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3089 gpointer tdata = (char *)this + sizeof (MonoObject);
3090 gpointer odata = (char *)other + sizeof (MonoObject);
3091 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3092 g_assert (basetype);
3094 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3095 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3096 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3097 if (me == other) \
3098 return 0; \
3099 return me > other ? 1 : -1; \
3100 } while (0)
3102 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3103 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3104 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3105 if (me == other) \
3106 return 0; \
3107 return me - other; \
3108 } while (0)
3110 switch (basetype->type) {
3111 case MONO_TYPE_U1:
3112 COMPARE_ENUM_VALUES (guint8);
3113 case MONO_TYPE_I1:
3114 COMPARE_ENUM_VALUES (gint8);
3115 case MONO_TYPE_CHAR:
3116 case MONO_TYPE_U2:
3117 COMPARE_ENUM_VALUES_RANGE (guint16);
3118 case MONO_TYPE_I2:
3119 COMPARE_ENUM_VALUES (gint16);
3120 case MONO_TYPE_U4:
3121 COMPARE_ENUM_VALUES (guint32);
3122 case MONO_TYPE_I4:
3123 COMPARE_ENUM_VALUES (gint32);
3124 case MONO_TYPE_U8:
3125 COMPARE_ENUM_VALUES (guint64);
3126 case MONO_TYPE_I8:
3127 COMPARE_ENUM_VALUES (gint64);
3128 default:
3129 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3131 #undef COMPARE_ENUM_VALUES_RANGE
3132 #undef COMPARE_ENUM_VALUES
3133 return 0;
3136 static int
3137 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3139 gpointer data = (char *)this + sizeof (MonoObject);
3140 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3141 g_assert (basetype);
3143 switch (basetype->type) {
3144 case MONO_TYPE_I1:
3145 return *((gint8*)data);
3146 case MONO_TYPE_U1:
3147 return *((guint8*)data);
3148 case MONO_TYPE_CHAR:
3149 case MONO_TYPE_U2:
3150 return *((guint16*)data);
3152 case MONO_TYPE_I2:
3153 return *((gint16*)data);
3154 case MONO_TYPE_U4:
3155 return *((guint32*)data);
3156 case MONO_TYPE_I4:
3157 return *((gint32*)data);
3158 case MONO_TYPE_U8:
3159 case MONO_TYPE_I8: {
3160 gint64 value = *((gint64*)data);
3161 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3163 default:
3164 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3166 return 0;
3169 static void
3170 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3172 MonoDomain *domain = mono_object_domain (type);
3173 MonoClass *enumc = mono_class_from_mono_type (type->type);
3174 guint j = 0, nvalues, crow;
3175 gpointer iter;
3176 MonoClassField *field;
3178 MONO_ARCH_SAVE_REGS;
3180 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3181 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3182 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3183 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3185 crow = -1;
3186 iter = NULL;
3187 while ((field = mono_class_get_fields (enumc, &iter))) {
3188 const char *p;
3189 int len;
3190 MonoTypeEnum def_type;
3192 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3193 continue;
3194 if (mono_field_is_deleted (field))
3195 continue;
3196 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3198 p = mono_class_get_field_default_value (field, &def_type);
3199 len = mono_metadata_decode_blob_size (p, &p);
3200 switch (mono_class_enum_basetype (enumc)->type) {
3201 case MONO_TYPE_U1:
3202 case MONO_TYPE_I1:
3203 mono_array_set (info->values, gchar, j, *p);
3204 break;
3205 case MONO_TYPE_CHAR:
3206 case MONO_TYPE_U2:
3207 case MONO_TYPE_I2:
3208 mono_array_set (info->values, gint16, j, read16 (p));
3209 break;
3210 case MONO_TYPE_U4:
3211 case MONO_TYPE_I4:
3212 mono_array_set (info->values, gint32, j, read32 (p));
3213 break;
3214 case MONO_TYPE_U8:
3215 case MONO_TYPE_I8:
3216 mono_array_set (info->values, gint64, j, read64 (p));
3217 break;
3218 default:
3219 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3221 ++j;
3225 enum {
3226 BFLAGS_IgnoreCase = 1,
3227 BFLAGS_DeclaredOnly = 2,
3228 BFLAGS_Instance = 4,
3229 BFLAGS_Static = 8,
3230 BFLAGS_Public = 0x10,
3231 BFLAGS_NonPublic = 0x20,
3232 BFLAGS_FlattenHierarchy = 0x40,
3233 BFLAGS_InvokeMethod = 0x100,
3234 BFLAGS_CreateInstance = 0x200,
3235 BFLAGS_GetField = 0x400,
3236 BFLAGS_SetField = 0x800,
3237 BFLAGS_GetProperty = 0x1000,
3238 BFLAGS_SetProperty = 0x2000,
3239 BFLAGS_ExactBinding = 0x10000,
3240 BFLAGS_SuppressChangeType = 0x20000,
3241 BFLAGS_OptionalParamBinding = 0x40000
3244 static MonoReflectionField *
3245 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3247 MonoDomain *domain;
3248 MonoClass *startklass, *klass;
3249 int match;
3250 MonoClassField *field;
3251 gpointer iter;
3252 char *utf8_name;
3253 int (*compare_func) (const char *s1, const char *s2) = NULL;
3254 domain = ((MonoObject *)type)->vtable->domain;
3255 klass = startklass = mono_class_from_mono_type (type->type);
3257 MONO_ARCH_SAVE_REGS;
3259 if (!name)
3260 mono_raise_exception (mono_get_exception_argument_null ("name"));
3261 if (type->type->byref)
3262 return NULL;
3264 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3266 handle_parent:
3267 if (klass->exception_type != MONO_EXCEPTION_NONE)
3268 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3270 iter = NULL;
3271 while ((field = mono_class_get_fields (klass, &iter))) {
3272 match = 0;
3274 if (field->type == NULL)
3275 continue;
3276 if (mono_field_is_deleted (field))
3277 continue;
3278 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3279 if (bflags & BFLAGS_Public)
3280 match++;
3281 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3282 if (bflags & BFLAGS_NonPublic) {
3283 match++;
3286 if (!match)
3287 continue;
3288 match = 0;
3289 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3290 if (bflags & BFLAGS_Static)
3291 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3292 match++;
3293 } else {
3294 if (bflags & BFLAGS_Instance)
3295 match++;
3298 if (!match)
3299 continue;
3301 utf8_name = mono_string_to_utf8 (name);
3303 if (compare_func (mono_field_get_name (field), utf8_name)) {
3304 g_free (utf8_name);
3305 continue;
3307 g_free (utf8_name);
3309 return mono_field_get_object (domain, klass, field);
3311 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3312 goto handle_parent;
3314 return NULL;
3317 static MonoArray*
3318 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3320 MonoDomain *domain;
3321 MonoClass *startklass, *klass, *refklass;
3322 MonoArray *res;
3323 MonoObject *member;
3324 int i, match;
3325 gpointer iter;
3326 MonoClassField *field;
3327 MonoPtrArray tmp_array;
3329 MONO_ARCH_SAVE_REGS;
3331 domain = ((MonoObject *)type)->vtable->domain;
3332 if (type->type->byref)
3333 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3334 klass = startklass = mono_class_from_mono_type (type->type);
3335 refklass = mono_class_from_mono_type (reftype->type);
3337 mono_ptr_array_init (tmp_array, 2);
3339 handle_parent:
3340 if (klass->exception_type != MONO_EXCEPTION_NONE)
3341 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3343 iter = NULL;
3344 while ((field = mono_class_get_fields (klass, &iter))) {
3345 match = 0;
3346 if (mono_field_is_deleted (field))
3347 continue;
3348 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3349 if (bflags & BFLAGS_Public)
3350 match++;
3351 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3352 if (bflags & BFLAGS_NonPublic) {
3353 match++;
3356 if (!match)
3357 continue;
3358 match = 0;
3359 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3360 if (bflags & BFLAGS_Static)
3361 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3362 match++;
3363 } else {
3364 if (bflags & BFLAGS_Instance)
3365 match++;
3368 if (!match)
3369 continue;
3370 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3371 mono_ptr_array_append (tmp_array, member);
3373 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3374 goto handle_parent;
3376 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3378 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3379 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3381 mono_ptr_array_destroy (tmp_array);
3383 return res;
3386 static gboolean
3387 method_nonpublic (MonoMethod* method, gboolean start_klass)
3389 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3390 case METHOD_ATTRIBUTE_ASSEM:
3391 return (start_klass || mono_defaults.generic_ilist_class);
3392 case METHOD_ATTRIBUTE_PRIVATE:
3393 return start_klass;
3394 case METHOD_ATTRIBUTE_PUBLIC:
3395 return FALSE;
3396 default:
3397 return TRUE;
3401 static MonoArray*
3402 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3404 static MonoClass *MethodInfo_array;
3405 MonoDomain *domain;
3406 MonoClass *startklass, *klass, *refklass;
3407 MonoArray *res;
3408 MonoMethod *method;
3409 gpointer iter;
3410 MonoObject *member;
3411 int i, len, match, nslots;
3412 /*FIXME, use MonoBitSet*/
3413 guint32 method_slots_default [8];
3414 guint32 *method_slots = NULL;
3415 gchar *mname = NULL;
3416 int (*compare_func) (const char *s1, const char *s2) = NULL;
3417 MonoVTable *array_vtable;
3418 MonoException *ex;
3419 MonoPtrArray tmp_array;
3421 MONO_ARCH_SAVE_REGS;
3423 mono_ptr_array_init (tmp_array, 4);
3425 if (!MethodInfo_array) {
3426 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3427 mono_memory_barrier ();
3428 MethodInfo_array = klass;
3431 domain = ((MonoObject *)type)->vtable->domain;
3432 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3433 if (type->type->byref)
3434 return mono_array_new_specific (array_vtable, 0);
3435 klass = startklass = mono_class_from_mono_type (type->type);
3436 refklass = mono_class_from_mono_type (reftype->type);
3437 len = 0;
3438 if (name != NULL) {
3439 mname = mono_string_to_utf8 (name);
3440 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3443 /* An optimization for calls made from Delegate:CreateDelegate () */
3444 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3445 method = mono_get_delegate_invoke (klass);
3446 if (mono_loader_get_last_error ())
3447 goto loader_error;
3449 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3451 res = mono_array_new_specific (array_vtable, 1);
3452 mono_array_setref (res, 0, member);
3453 g_free (mname);
3454 return res;
3457 mono_class_setup_vtable (klass);
3458 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3459 goto loader_error;
3461 if (is_generic_parameter (type->type))
3462 nslots = mono_class_get_vtable_size (klass->parent);
3463 else
3464 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3465 if (nslots >= sizeof (method_slots_default) * 8) {
3466 method_slots = g_new0 (guint32, nslots / 32 + 1);
3467 } else {
3468 method_slots = method_slots_default;
3469 memset (method_slots, 0, sizeof (method_slots_default));
3471 handle_parent:
3472 mono_class_setup_vtable (klass);
3473 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3474 goto loader_error;
3476 iter = NULL;
3477 while ((method = mono_class_get_methods (klass, &iter))) {
3478 match = 0;
3479 if (method->slot != -1) {
3480 g_assert (method->slot < nslots);
3481 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3482 continue;
3483 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3484 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3487 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3488 continue;
3489 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3490 if (bflags & BFLAGS_Public)
3491 match++;
3492 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3493 match++;
3495 if (!match)
3496 continue;
3497 match = 0;
3498 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3499 if (bflags & BFLAGS_Static)
3500 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3501 match++;
3502 } else {
3503 if (bflags & BFLAGS_Instance)
3504 match++;
3507 if (!match)
3508 continue;
3510 if (name != NULL) {
3511 if (compare_func (mname, method->name))
3512 continue;
3515 match = 0;
3517 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3519 mono_ptr_array_append (tmp_array, member);
3521 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3522 goto handle_parent;
3524 g_free (mname);
3525 if (method_slots != method_slots_default)
3526 g_free (method_slots);
3528 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3530 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3531 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3533 mono_ptr_array_destroy (tmp_array);
3534 return res;
3536 loader_error:
3537 g_free (mname);
3538 if (method_slots != method_slots_default)
3539 g_free (method_slots);
3540 mono_ptr_array_destroy (tmp_array);
3541 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3542 ex = mono_class_get_exception_for_failure (klass);
3543 } else {
3544 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3545 mono_loader_clear_error ();
3547 mono_raise_exception (ex);
3548 return NULL;
3551 static MonoArray*
3552 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3554 MonoDomain *domain;
3555 static MonoClass *System_Reflection_ConstructorInfo;
3556 MonoClass *startklass, *klass, *refklass;
3557 MonoArray *res;
3558 MonoMethod *method;
3559 MonoObject *member;
3560 int i, match;
3561 gpointer iter = NULL;
3562 MonoPtrArray tmp_array;
3564 MONO_ARCH_SAVE_REGS;
3566 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3568 domain = ((MonoObject *)type)->vtable->domain;
3569 if (type->type->byref)
3570 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3571 klass = startklass = mono_class_from_mono_type (type->type);
3572 refklass = mono_class_from_mono_type (reftype->type);
3574 if (klass->exception_type != MONO_EXCEPTION_NONE)
3575 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3577 if (!System_Reflection_ConstructorInfo)
3578 System_Reflection_ConstructorInfo = mono_class_from_name (
3579 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3581 iter = NULL;
3582 while ((method = mono_class_get_methods (klass, &iter))) {
3583 match = 0;
3584 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3585 continue;
3586 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3587 if (bflags & BFLAGS_Public)
3588 match++;
3589 } else {
3590 if (bflags & BFLAGS_NonPublic)
3591 match++;
3593 if (!match)
3594 continue;
3595 match = 0;
3596 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3597 if (bflags & BFLAGS_Static)
3598 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3599 match++;
3600 } else {
3601 if (bflags & BFLAGS_Instance)
3602 match++;
3605 if (!match)
3606 continue;
3607 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3609 mono_ptr_array_append (tmp_array, member);
3612 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3614 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3615 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3617 mono_ptr_array_destroy (tmp_array);
3619 return res;
3622 static guint
3623 property_hash (gconstpointer data)
3625 MonoProperty *prop = (MonoProperty*)data;
3627 return g_str_hash (prop->name);
3630 static gboolean
3631 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3633 // Properties are hide-by-name-and-signature
3634 if (!g_str_equal (prop1->name, prop2->name))
3635 return FALSE;
3637 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3638 return FALSE;
3639 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3640 return FALSE;
3641 return TRUE;
3644 static gboolean
3645 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3647 if (!accessor)
3648 return FALSE;
3650 return method_nonpublic (accessor, start_klass);
3653 static MonoArray*
3654 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3656 MonoDomain *domain;
3657 static MonoClass *System_Reflection_PropertyInfo;
3658 MonoClass *startklass, *klass;
3659 MonoArray *res;
3660 MonoMethod *method;
3661 MonoProperty *prop;
3662 int i, match;
3663 guint32 flags;
3664 gchar *propname = NULL;
3665 int (*compare_func) (const char *s1, const char *s2) = NULL;
3666 gpointer iter;
3667 GHashTable *properties;
3668 MonoPtrArray tmp_array;
3670 MONO_ARCH_SAVE_REGS;
3672 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3674 if (!System_Reflection_PropertyInfo)
3675 System_Reflection_PropertyInfo = mono_class_from_name (
3676 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3678 domain = ((MonoObject *)type)->vtable->domain;
3679 if (type->type->byref)
3680 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3681 klass = startklass = mono_class_from_mono_type (type->type);
3682 if (name != NULL) {
3683 propname = mono_string_to_utf8 (name);
3684 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3687 mono_class_setup_vtable (klass);
3689 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3690 handle_parent:
3691 mono_class_setup_vtable (klass);
3692 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3693 g_hash_table_destroy (properties);
3694 if (name != NULL)
3695 g_free (propname);
3696 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3699 iter = NULL;
3700 while ((prop = mono_class_get_properties (klass, &iter))) {
3701 match = 0;
3702 method = prop->get;
3703 if (!method)
3704 method = prop->set;
3705 if (method)
3706 flags = method->flags;
3707 else
3708 flags = 0;
3709 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3710 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3711 if (bflags & BFLAGS_Public)
3712 match++;
3713 } else if (bflags & BFLAGS_NonPublic) {
3714 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3715 property_accessor_nonpublic(prop->set, startklass == klass)) {
3716 match++;
3719 if (!match)
3720 continue;
3721 match = 0;
3722 if (flags & METHOD_ATTRIBUTE_STATIC) {
3723 if (bflags & BFLAGS_Static)
3724 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3725 match++;
3726 } else {
3727 if (bflags & BFLAGS_Instance)
3728 match++;
3731 if (!match)
3732 continue;
3733 match = 0;
3735 if (name != NULL) {
3736 if (compare_func (propname, prop->name))
3737 continue;
3740 if (g_hash_table_lookup (properties, prop))
3741 continue;
3743 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3745 g_hash_table_insert (properties, prop, prop);
3747 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3748 goto handle_parent;
3750 g_hash_table_destroy (properties);
3751 g_free (propname);
3753 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3754 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3755 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3757 mono_ptr_array_destroy (tmp_array);
3759 return res;
3762 static MonoReflectionEvent *
3763 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3765 MonoDomain *domain;
3766 MonoClass *klass, *startklass;
3767 gpointer iter;
3768 MonoEvent *event;
3769 MonoMethod *method;
3770 gchar *event_name;
3772 MONO_ARCH_SAVE_REGS;
3774 event_name = mono_string_to_utf8 (name);
3775 if (type->type->byref)
3776 return NULL;
3777 klass = startklass = mono_class_from_mono_type (type->type);
3778 domain = mono_object_domain (type);
3780 handle_parent:
3781 if (klass->exception_type != MONO_EXCEPTION_NONE)
3782 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3784 iter = NULL;
3785 while ((event = mono_class_get_events (klass, &iter))) {
3786 if (strcmp (event->name, event_name))
3787 continue;
3789 method = event->add;
3790 if (!method)
3791 method = event->remove;
3792 if (!method)
3793 method = event->raise;
3794 if (method) {
3795 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3796 if (!(bflags & BFLAGS_Public))
3797 continue;
3798 } else {
3799 if (!(bflags & BFLAGS_NonPublic))
3800 continue;
3801 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3802 continue;
3805 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3806 if (!(bflags & BFLAGS_Static))
3807 continue;
3808 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3809 continue;
3810 } else {
3811 if (!(bflags & BFLAGS_Instance))
3812 continue;
3814 } else
3815 if (!(bflags & BFLAGS_NonPublic))
3816 continue;
3818 g_free (event_name);
3819 return mono_event_get_object (domain, startklass, event);
3822 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3823 goto handle_parent;
3825 g_free (event_name);
3826 return NULL;
3829 static MonoArray*
3830 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3832 MonoDomain *domain;
3833 static MonoClass *System_Reflection_EventInfo;
3834 MonoClass *startklass, *klass;
3835 MonoArray *res;
3836 MonoMethod *method;
3837 MonoEvent *event;
3838 int i, match;
3839 gpointer iter;
3841 MonoPtrArray tmp_array;
3843 MONO_ARCH_SAVE_REGS;
3845 mono_ptr_array_init (tmp_array, 4);
3847 if (!System_Reflection_EventInfo)
3848 System_Reflection_EventInfo = mono_class_from_name (
3849 mono_defaults.corlib, "System.Reflection", "EventInfo");
3851 domain = mono_object_domain (type);
3852 if (type->type->byref)
3853 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3854 klass = startklass = mono_class_from_mono_type (type->type);
3856 handle_parent:
3857 if (klass->exception_type != MONO_EXCEPTION_NONE)
3858 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3860 iter = NULL;
3861 while ((event = mono_class_get_events (klass, &iter))) {
3862 match = 0;
3863 method = event->add;
3864 if (!method)
3865 method = event->remove;
3866 if (!method)
3867 method = event->raise;
3868 if (method) {
3869 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3870 if (bflags & BFLAGS_Public)
3871 match++;
3872 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3873 if (bflags & BFLAGS_NonPublic)
3874 match++;
3877 else
3878 if (bflags & BFLAGS_NonPublic)
3879 match ++;
3880 if (!match)
3881 continue;
3882 match = 0;
3883 if (method) {
3884 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3885 if (bflags & BFLAGS_Static)
3886 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3887 match++;
3888 } else {
3889 if (bflags & BFLAGS_Instance)
3890 match++;
3893 else
3894 if (bflags & BFLAGS_Instance)
3895 match ++;
3896 if (!match)
3897 continue;
3898 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3900 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3901 goto handle_parent;
3903 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3905 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3906 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3908 mono_ptr_array_destroy (tmp_array);
3910 return res;
3913 static MonoReflectionType *
3914 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3916 MonoDomain *domain;
3917 MonoClass *klass;
3918 MonoClass *nested;
3919 char *str;
3920 gpointer iter;
3922 MONO_ARCH_SAVE_REGS;
3924 if (name == NULL)
3925 mono_raise_exception (mono_get_exception_argument_null ("name"));
3927 domain = ((MonoObject *)type)->vtable->domain;
3928 if (type->type->byref)
3929 return NULL;
3930 klass = mono_class_from_mono_type (type->type);
3931 str = mono_string_to_utf8 (name);
3933 handle_parent:
3934 if (klass->exception_type != MONO_EXCEPTION_NONE)
3935 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3938 * If a nested type is generic, return its generic type definition.
3939 * Note that this means that the return value is essentially a
3940 * nested type of the generic type definition of @klass.
3942 * A note in MSDN claims that a generic type definition can have
3943 * nested types that aren't generic. In any case, the container of that
3944 * nested type would be the generic type definition.
3946 if (klass->generic_class)
3947 klass = klass->generic_class->container_class;
3949 iter = NULL;
3950 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3951 int match = 0;
3952 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3953 if (bflags & BFLAGS_Public)
3954 match++;
3955 } else {
3956 if (bflags & BFLAGS_NonPublic)
3957 match++;
3959 if (!match)
3960 continue;
3961 if (strcmp (nested->name, str) == 0){
3962 g_free (str);
3963 return mono_type_get_object (domain, &nested->byval_arg);
3966 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3967 goto handle_parent;
3968 g_free (str);
3969 return NULL;
3972 static MonoArray*
3973 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
3975 MonoDomain *domain;
3976 MonoClass *klass;
3977 MonoArray *res;
3978 MonoObject *member;
3979 int i, match;
3980 MonoClass *nested;
3981 gpointer iter;
3982 MonoPtrArray tmp_array;
3984 MONO_ARCH_SAVE_REGS;
3986 domain = ((MonoObject *)type)->vtable->domain;
3987 if (type->type->byref)
3988 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3989 klass = mono_class_from_mono_type (type->type);
3990 if (klass->exception_type != MONO_EXCEPTION_NONE)
3991 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3994 * If a nested type is generic, return its generic type definition.
3995 * Note that this means that the return value is essentially the set
3996 * of nested types of the generic type definition of @klass.
3998 * A note in MSDN claims that a generic type definition can have
3999 * nested types that aren't generic. In any case, the container of that
4000 * nested type would be the generic type definition.
4002 if (klass->generic_class)
4003 klass = klass->generic_class->container_class;
4005 mono_ptr_array_init (tmp_array, 1);
4006 iter = NULL;
4007 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4008 match = 0;
4009 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4010 if (bflags & BFLAGS_Public)
4011 match++;
4012 } else {
4013 if (bflags & BFLAGS_NonPublic)
4014 match++;
4016 if (!match)
4017 continue;
4018 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4019 mono_ptr_array_append (tmp_array, member);
4022 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4024 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4025 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4027 mono_ptr_array_destroy (tmp_array);
4029 return res;
4032 static MonoReflectionType*
4033 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4035 gchar *str;
4036 MonoType *type = NULL;
4037 MonoTypeNameParse info;
4038 gboolean type_resolve;
4040 MONO_ARCH_SAVE_REGS;
4042 /* On MS.NET, this does not fire a TypeResolve event */
4043 type_resolve = TRUE;
4044 str = mono_string_to_utf8 (name);
4045 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4046 if (!mono_reflection_parse_type (str, &info)) {
4047 g_free (str);
4048 mono_reflection_free_type_info (&info);
4049 if (throwOnError) /* uhm: this is a parse error, though... */
4050 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4051 /*g_print ("failed parse\n");*/
4052 return NULL;
4055 if (info.assembly.name) {
4056 g_free (str);
4057 mono_reflection_free_type_info (&info);
4058 if (throwOnError) {
4059 /* 1.0 and 2.0 throw different exceptions */
4060 if (mono_defaults.generic_ilist_class)
4061 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4062 else
4063 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4065 return NULL;
4068 if (module != NULL) {
4069 if (module->image)
4070 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4071 else
4072 type = NULL;
4074 else
4075 if (assembly->assembly->dynamic) {
4076 /* Enumerate all modules */
4077 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4078 int i;
4080 type = NULL;
4081 if (abuilder->modules) {
4082 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4083 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4084 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4085 if (type)
4086 break;
4090 if (!type && abuilder->loaded_modules) {
4091 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4092 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4093 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4094 if (type)
4095 break;
4099 else
4100 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4101 g_free (str);
4102 mono_reflection_free_type_info (&info);
4103 if (!type) {
4104 MonoException *e = NULL;
4106 if (throwOnError)
4107 e = mono_get_exception_type_load (name, NULL);
4109 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4110 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4112 mono_loader_clear_error ();
4114 if (e != NULL)
4115 mono_raise_exception (e);
4117 return NULL;
4120 if (type->type == MONO_TYPE_CLASS) {
4121 MonoClass *klass = mono_type_get_class (type);
4123 if (mono_is_security_manager_active () && !klass->exception_type)
4124 /* Some security problems are detected during generic vtable construction */
4125 mono_class_setup_vtable (klass);
4126 /* need to report exceptions ? */
4127 if (throwOnError && klass->exception_type) {
4128 /* report SecurityException (or others) that occured when loading the assembly */
4129 MonoException *exc = mono_class_get_exception_for_failure (klass);
4130 mono_loader_clear_error ();
4131 mono_raise_exception (exc);
4132 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4133 return NULL;
4137 /* g_print ("got it\n"); */
4138 return mono_type_get_object (mono_object_domain (assembly), type);
4141 static gboolean
4142 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4144 gchar *content;
4145 gchar *shadow_ini_file;
4146 gsize len;
4148 /* Check for shadow-copied assembly */
4149 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4150 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4151 content = NULL;
4152 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4153 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4154 if (content) {
4155 g_free (content);
4156 content = NULL;
4159 g_free (shadow_ini_file);
4160 if (content != NULL) {
4161 if (*filename)
4162 g_free (*filename);
4163 *filename = content;
4164 return TRUE;
4167 return FALSE;
4170 static MonoString *
4171 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4173 MonoDomain *domain = mono_object_domain (assembly);
4174 MonoAssembly *mass = assembly->assembly;
4175 MonoString *res = NULL;
4176 gchar *uri;
4177 gchar *absolute;
4178 gchar *dirname;
4180 MONO_ARCH_SAVE_REGS;
4182 if (g_path_is_absolute (mass->image->name)) {
4183 absolute = g_strdup (mass->image->name);
4184 dirname = g_path_get_dirname (absolute);
4185 } else {
4186 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4187 dirname = g_strdup (mass->basedir);
4190 replace_shadow_path (domain, dirname, &absolute);
4191 g_free (dirname);
4192 #if HOST_WIN32
4194 gint i;
4195 for (i = strlen (absolute) - 1; i >= 0; i--)
4196 if (absolute [i] == '\\')
4197 absolute [i] = '/';
4199 #endif
4200 if (escaped) {
4201 uri = g_filename_to_uri (absolute, NULL, NULL);
4202 } else {
4203 const char *prepend = "file://";
4204 #if HOST_WIN32
4205 if (*absolute == '/' && *(absolute + 1) == '/') {
4206 prepend = "file:";
4207 } else {
4208 prepend = "file:///";
4210 #endif
4211 uri = g_strconcat (prepend, absolute, NULL);
4214 if (uri) {
4215 res = mono_string_new (domain, uri);
4216 g_free (uri);
4218 g_free (absolute);
4219 return res;
4222 static MonoBoolean
4223 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4225 MonoAssembly *mass = assembly->assembly;
4227 MONO_ARCH_SAVE_REGS;
4229 return mass->in_gac;
4232 static MonoReflectionAssembly*
4233 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4235 gchar *name;
4236 MonoAssembly *res;
4237 MonoImageOpenStatus status;
4239 MONO_ARCH_SAVE_REGS;
4241 name = mono_string_to_utf8 (mname);
4242 res = mono_assembly_load_with_partial_name (name, &status);
4244 g_free (name);
4246 if (res == NULL)
4247 return NULL;
4248 return mono_assembly_get_object (mono_domain_get (), res);
4251 static MonoString *
4252 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4254 MonoDomain *domain = mono_object_domain (assembly);
4255 MonoString *res;
4257 MONO_ARCH_SAVE_REGS;
4259 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4261 return res;
4264 static MonoBoolean
4265 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4267 MONO_ARCH_SAVE_REGS;
4269 return assembly->assembly->ref_only;
4272 static MonoString *
4273 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4275 MonoDomain *domain = mono_object_domain (assembly);
4277 MONO_ARCH_SAVE_REGS;
4279 return mono_string_new (domain, assembly->assembly->image->version);
4282 static MonoReflectionMethod*
4283 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4285 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4287 MONO_ARCH_SAVE_REGS;
4289 if (!token)
4290 return NULL;
4291 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4294 static MonoReflectionModule*
4295 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4297 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4300 static MonoArray*
4301 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4303 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4304 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4305 int i;
4306 const char *val;
4308 MONO_ARCH_SAVE_REGS;
4310 for (i = 0; i < table->rows; ++i) {
4311 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4312 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4314 return result;
4317 static MonoObject*
4318 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4320 static MonoClass *System_Version = NULL;
4321 static MonoMethod *create_version = NULL;
4322 MonoObject *result;
4323 gpointer args [4];
4325 if (!System_Version) {
4326 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4327 g_assert (System_Version);
4330 if (!create_version) {
4331 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4332 create_version = mono_method_desc_search_in_class (desc, System_Version);
4333 g_assert (create_version);
4334 mono_method_desc_free (desc);
4337 args [0] = &major;
4338 args [1] = &minor;
4339 args [2] = &build;
4340 args [3] = &revision;
4341 result = mono_object_new (domain, System_Version);
4342 mono_runtime_invoke (create_version, result, args, NULL);
4344 return result;
4347 static MonoArray*
4348 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4350 static MonoClass *System_Reflection_AssemblyName;
4351 MonoArray *result;
4352 MonoDomain *domain = mono_object_domain (assembly);
4353 int i, count = 0;
4354 static MonoMethod *create_culture = NULL;
4355 MonoImage *image = assembly->assembly->image;
4356 MonoTableInfo *t;
4358 MONO_ARCH_SAVE_REGS;
4360 if (!System_Reflection_AssemblyName)
4361 System_Reflection_AssemblyName = mono_class_from_name (
4362 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4364 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4365 count = t->rows;
4367 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4369 if (count > 0 && !create_culture) {
4370 MonoMethodDesc *desc = mono_method_desc_new (
4371 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4372 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4373 g_assert (create_culture);
4374 mono_method_desc_free (desc);
4377 for (i = 0; i < count; i++) {
4378 MonoReflectionAssemblyName *aname;
4379 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4381 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4383 aname = (MonoReflectionAssemblyName *) mono_object_new (
4384 domain, System_Reflection_AssemblyName);
4386 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4388 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4389 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4390 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4391 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4392 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4393 aname->versioncompat = 1; /* SameMachine (default) */
4394 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4395 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4397 if (create_culture) {
4398 gpointer args [2];
4399 MonoBoolean assembly_ref = 1;
4400 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4401 args [1] = &assembly_ref;
4402 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4405 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4406 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4407 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4409 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4410 /* public key token isn't copied - the class library will
4411 automatically generate it from the public key if required */
4412 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4413 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4414 } else {
4415 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4416 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4418 } else {
4419 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4422 /* note: this function doesn't return the codebase on purpose (i.e. it can
4423 be used under partial trust as path information isn't present). */
4425 mono_array_setref (result, i, aname);
4427 return result;
4430 typedef struct {
4431 MonoArray *res;
4432 int idx;
4433 } NameSpaceInfo;
4435 static void
4436 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4438 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4440 mono_array_setref (info->res, info->idx, name);
4441 info->idx++;
4444 static MonoArray*
4445 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4447 MonoImage *img = assembly->assembly->image;
4448 MonoArray *res;
4449 NameSpaceInfo info;
4450 int len;
4452 MONO_ARCH_SAVE_REGS;
4454 mono_image_lock (img);
4455 mono_image_init_name_cache (img);
4457 RETRY_LEN:
4458 len = g_hash_table_size (img->name_cache);
4459 mono_image_unlock (img);
4461 /*we can't create objects holding the image lock */
4462 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4464 mono_image_lock (img);
4465 /*len might have changed, create a new array*/
4466 if (len != g_hash_table_size (img->name_cache))
4467 goto RETRY_LEN;
4469 info.res = res;
4470 info.idx = 0;
4471 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4472 mono_image_unlock (img);
4474 return res;
4477 /* move this in some file in mono/util/ */
4478 static char *
4479 g_concat_dir_and_file (const char *dir, const char *file)
4481 g_return_val_if_fail (dir != NULL, NULL);
4482 g_return_val_if_fail (file != NULL, NULL);
4485 * If the directory name doesn't have a / on the end, we need
4486 * to add one so we get a proper path to the file
4488 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4489 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4490 else
4491 return g_strconcat (dir, file, NULL);
4494 static void *
4495 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4497 char *n = mono_string_to_utf8 (name);
4498 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4499 guint32 i;
4500 guint32 cols [MONO_MANIFEST_SIZE];
4501 guint32 impl, file_idx;
4502 const char *val;
4503 MonoImage *module;
4505 MONO_ARCH_SAVE_REGS;
4507 for (i = 0; i < table->rows; ++i) {
4508 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4509 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4510 if (strcmp (val, n) == 0)
4511 break;
4513 g_free (n);
4514 if (i == table->rows)
4515 return NULL;
4516 /* FIXME */
4517 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4518 if (impl) {
4520 * this code should only be called after obtaining the
4521 * ResourceInfo and handling the other cases.
4523 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4524 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4526 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4527 if (!module)
4528 return NULL;
4530 else
4531 module = assembly->assembly->image;
4533 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4535 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4538 static gboolean
4539 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4541 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4542 int i;
4543 guint32 cols [MONO_MANIFEST_SIZE];
4544 guint32 file_cols [MONO_FILE_SIZE];
4545 const char *val;
4546 char *n;
4548 MONO_ARCH_SAVE_REGS;
4550 n = mono_string_to_utf8 (name);
4551 for (i = 0; i < table->rows; ++i) {
4552 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4553 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4554 if (strcmp (val, n) == 0)
4555 break;
4557 g_free (n);
4558 if (i == table->rows)
4559 return FALSE;
4561 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4562 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4564 else {
4565 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4566 case MONO_IMPLEMENTATION_FILE:
4567 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4568 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4569 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4570 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4571 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4572 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4573 info->location = 0;
4574 else
4575 info->location = RESOURCE_LOCATION_EMBEDDED;
4576 break;
4578 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4579 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4580 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4581 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4582 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4583 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4584 g_free (msg);
4585 mono_raise_exception (ex);
4587 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4589 /* Obtain info recursively */
4590 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4591 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4592 break;
4594 case MONO_IMPLEMENTATION_EXP_TYPE:
4595 g_assert_not_reached ();
4596 break;
4600 return TRUE;
4603 static MonoObject*
4604 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4606 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4607 MonoArray *result = NULL;
4608 int i, count;
4609 const char *val;
4610 char *n;
4612 MONO_ARCH_SAVE_REGS;
4614 /* check hash if needed */
4615 if (name) {
4616 n = mono_string_to_utf8 (name);
4617 for (i = 0; i < table->rows; ++i) {
4618 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4619 if (strcmp (val, n) == 0) {
4620 MonoString *fn;
4621 g_free (n);
4622 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4623 fn = mono_string_new (mono_object_domain (assembly), n);
4624 g_free (n);
4625 return (MonoObject*)fn;
4628 g_free (n);
4629 return NULL;
4632 count = 0;
4633 for (i = 0; i < table->rows; ++i) {
4634 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4635 count ++;
4638 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4640 count = 0;
4641 for (i = 0; i < table->rows; ++i) {
4642 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4643 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4644 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4645 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4646 g_free (n);
4647 count ++;
4650 return (MonoObject*)result;
4653 static MonoArray*
4654 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4656 MonoDomain *domain = mono_domain_get();
4657 MonoArray *res;
4658 MonoClass *klass;
4659 int i, j, file_count = 0;
4660 MonoImage **modules;
4661 guint32 module_count, real_module_count;
4662 MonoTableInfo *table;
4663 guint32 cols [MONO_FILE_SIZE];
4664 MonoImage *image = assembly->assembly->image;
4666 g_assert (image != NULL);
4667 g_assert (!assembly->assembly->dynamic);
4669 table = &image->tables [MONO_TABLE_FILE];
4670 file_count = table->rows;
4672 modules = image->modules;
4673 module_count = image->module_count;
4675 real_module_count = 0;
4676 for (i = 0; i < module_count; ++i)
4677 if (modules [i])
4678 real_module_count ++;
4680 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4681 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4683 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4684 j = 1;
4685 for (i = 0; i < module_count; ++i)
4686 if (modules [i]) {
4687 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4688 ++j;
4691 for (i = 0; i < file_count; ++i, ++j) {
4692 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4693 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4694 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4695 else {
4696 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4697 if (!m) {
4698 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4699 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4701 mono_array_setref (res, j, mono_module_get_object (domain, m));
4705 return res;
4708 static MonoReflectionMethod*
4709 ves_icall_GetCurrentMethod (void)
4711 MonoMethod *m = mono_method_get_last_managed ();
4713 while (m->is_inflated)
4714 m = ((MonoMethodInflated*)m)->declaring;
4716 return mono_method_get_object (mono_domain_get (), m, NULL);
4720 static MonoMethod*
4721 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4723 int offset = -1, i;
4724 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4725 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4726 //method is inflated, we should inflate it on the other class
4727 MonoGenericContext ctx;
4728 ctx.method_inst = inflated->context.method_inst;
4729 ctx.class_inst = inflated->context.class_inst;
4730 if (klass->generic_class)
4731 ctx.class_inst = klass->generic_class->context.class_inst;
4732 else if (klass->generic_container)
4733 ctx.class_inst = klass->generic_container->context.class_inst;
4734 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4737 mono_class_setup_methods (method->klass);
4738 if (method->klass->exception_type)
4739 return NULL;
4740 for (i = 0; i < method->klass->method.count; ++i) {
4741 if (method->klass->methods [i] == method) {
4742 offset = i;
4743 break;
4746 mono_class_setup_methods (klass);
4747 if (klass->exception_type)
4748 return NULL;
4749 g_assert (offset >= 0 && offset < klass->method.count);
4750 return klass->methods [offset];
4753 static MonoReflectionMethod*
4754 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4756 MonoClass *klass;
4757 if (type) {
4758 klass = mono_class_from_mono_type (type);
4759 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4760 return NULL;
4761 if (method->klass != klass) {
4762 method = mono_method_get_equivalent_method (method, klass);
4763 if (!method)
4764 return NULL;
4766 } else
4767 klass = method->klass;
4768 return mono_method_get_object (mono_domain_get (), method, klass);
4771 static MonoReflectionMethod*
4772 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4774 return mono_method_get_object (mono_domain_get (), method, NULL);
4777 static MonoReflectionMethodBody*
4778 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4780 return mono_method_body_get_object (mono_domain_get (), method);
4783 static MonoReflectionAssembly*
4784 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4786 MonoMethod *dest = NULL;
4788 MONO_ARCH_SAVE_REGS;
4790 mono_stack_walk_no_il (get_executing, &dest);
4791 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4795 static MonoReflectionAssembly*
4796 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4798 MonoDomain* domain = mono_domain_get ();
4800 MONO_ARCH_SAVE_REGS;
4802 if (!domain->entry_assembly)
4803 return NULL;
4805 return mono_assembly_get_object (domain, domain->entry_assembly);
4808 static MonoReflectionAssembly*
4809 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4811 MonoMethod *m;
4812 MonoMethod *dest;
4814 MONO_ARCH_SAVE_REGS;
4816 dest = NULL;
4817 mono_stack_walk_no_il (get_executing, &dest);
4818 m = dest;
4819 mono_stack_walk_no_il (get_caller, &dest);
4820 if (!dest)
4821 dest = m;
4822 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4825 static MonoString *
4826 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4827 gboolean assembly_qualified)
4829 MonoDomain *domain = mono_object_domain (object);
4830 MonoTypeNameFormat format;
4831 MonoString *res;
4832 gchar *name;
4834 MONO_ARCH_SAVE_REGS;
4835 if (full_name)
4836 format = assembly_qualified ?
4837 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4838 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4839 else
4840 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4842 name = mono_type_get_name_full (object->type, format);
4843 if (!name)
4844 return NULL;
4846 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4847 g_free (name);
4848 return NULL;
4851 res = mono_string_new (domain, name);
4852 g_free (name);
4854 return res;
4857 static void
4858 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4860 static MonoMethod *create_culture = NULL;
4861 gpointer args [2];
4862 guint32 pkey_len;
4863 const char *pkey_ptr;
4864 gchar *codebase;
4865 MonoBoolean assembly_ref = 0;
4867 MONO_ARCH_SAVE_REGS;
4869 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4870 aname->major = name->major;
4871 aname->minor = name->minor;
4872 aname->build = name->build;
4873 aname->flags = name->flags;
4874 aname->revision = name->revision;
4875 aname->hashalg = name->hash_alg;
4876 aname->versioncompat = 1; /* SameMachine (default) */
4878 if (by_default_version)
4879 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4881 codebase = NULL;
4882 if (absolute != NULL && *absolute != '\0') {
4883 const gchar *prepend = "file://";
4884 gchar *result;
4886 codebase = g_strdup (absolute);
4888 #if HOST_WIN32
4890 gint i;
4891 for (i = strlen (codebase) - 1; i >= 0; i--)
4892 if (codebase [i] == '\\')
4893 codebase [i] = '/';
4895 if (*codebase == '/' && *(codebase + 1) == '/') {
4896 prepend = "file:";
4897 } else {
4898 prepend = "file:///";
4901 #endif
4902 result = g_strconcat (prepend, codebase, NULL);
4903 g_free (codebase);
4904 codebase = result;
4907 if (codebase) {
4908 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4909 g_free (codebase);
4912 if (!create_culture) {
4913 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4914 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4915 g_assert (create_culture);
4916 mono_method_desc_free (desc);
4919 if (name->culture) {
4920 args [0] = mono_string_new (domain, name->culture);
4921 args [1] = &assembly_ref;
4922 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4925 if (name->public_key) {
4926 pkey_ptr = (char*)name->public_key;
4927 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4929 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4930 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4931 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4932 } else if (default_publickey) {
4933 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4934 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4937 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4938 if (name->public_key_token [0]) {
4939 int i, j;
4940 char *p;
4942 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4943 p = mono_array_addr (aname->keyToken, char, 0);
4945 for (i = 0, j = 0; i < 8; i++) {
4946 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4947 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4948 p++;
4950 } else if (default_token) {
4951 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4955 static MonoString *
4956 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4958 MonoDomain *domain = mono_object_domain (assembly);
4959 MonoAssembly *mass = assembly->assembly;
4960 MonoString *res;
4961 gchar *name;
4963 name = g_strdup_printf (
4964 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
4965 mass->aname.name,
4966 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
4967 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
4968 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
4969 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
4971 res = mono_string_new (domain, name);
4972 g_free (name);
4974 return res;
4977 static void
4978 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4980 gchar *absolute;
4981 MonoAssembly *mass = assembly->assembly;
4983 MONO_ARCH_SAVE_REGS;
4985 if (g_path_is_absolute (mass->image->name)) {
4986 fill_reflection_assembly_name (mono_object_domain (assembly),
4987 aname, &mass->aname, mass->image->name, TRUE,
4988 TRUE, mono_framework_version () >= 2);
4989 return;
4991 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4993 fill_reflection_assembly_name (mono_object_domain (assembly),
4994 aname, &mass->aname, absolute, TRUE, TRUE,
4995 mono_framework_version () >= 2);
4997 g_free (absolute);
5000 static void
5001 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5003 char *filename;
5004 MonoImageOpenStatus status = MONO_IMAGE_OK;
5005 gboolean res;
5006 MonoImage *image;
5007 MonoAssemblyName name;
5008 char *dirname
5010 MONO_ARCH_SAVE_REGS;
5012 filename = mono_string_to_utf8 (fname);
5014 dirname = g_path_get_dirname (filename);
5015 replace_shadow_path (mono_domain_get (), dirname, &filename);
5016 g_free (dirname);
5018 image = mono_image_open (filename, &status);
5020 if (!image){
5021 MonoException *exc;
5023 g_free (filename);
5024 if (status == MONO_IMAGE_IMAGE_INVALID)
5025 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5026 else
5027 exc = mono_get_exception_file_not_found2 (NULL, fname);
5028 mono_raise_exception (exc);
5031 res = mono_assembly_fill_assembly_name (image, &name);
5032 if (!res) {
5033 mono_image_close (image);
5034 g_free (filename);
5035 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5038 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5039 TRUE, mono_framework_version () == 1,
5040 mono_framework_version () >= 2);
5042 g_free (filename);
5043 mono_image_close (image);
5046 static MonoBoolean
5047 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5048 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5050 MonoBoolean result = FALSE;
5051 MonoDeclSecurityEntry entry;
5053 /* SecurityAction.RequestMinimum */
5054 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5055 *minimum = entry.blob;
5056 *minLength = entry.size;
5057 result = TRUE;
5059 /* SecurityAction.RequestOptional */
5060 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5061 *optional = entry.blob;
5062 *optLength = entry.size;
5063 result = TRUE;
5065 /* SecurityAction.RequestRefuse */
5066 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5067 *refused = entry.blob;
5068 *refLength = entry.size;
5069 result = TRUE;
5072 return result;
5075 static MonoArray*
5076 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5078 MonoArray *res;
5079 MonoClass *klass;
5080 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5081 int i, count;
5082 guint32 attrs, visibility;
5084 /* we start the count from 1 because we skip the special type <Module> */
5085 if (exportedOnly) {
5086 count = 0;
5087 for (i = 1; i < tdef->rows; ++i) {
5088 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5089 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5090 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5091 count++;
5093 } else {
5094 count = tdef->rows - 1;
5096 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5097 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5098 count = 0;
5099 for (i = 1; i < tdef->rows; ++i) {
5100 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5101 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5102 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5103 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5104 if (klass) {
5105 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5106 } else {
5107 MonoLoaderError *error;
5108 MonoException *ex;
5110 error = mono_loader_get_last_error ();
5111 g_assert (error != NULL);
5113 ex = mono_loader_error_prepare_exception (error);
5114 mono_array_setref (*exceptions, count, ex);
5116 if (mono_loader_get_last_error ())
5117 mono_loader_clear_error ();
5118 count++;
5122 return res;
5125 static MonoArray*
5126 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5128 MonoArray *res = NULL;
5129 MonoArray *exceptions = NULL;
5130 MonoImage *image = NULL;
5131 MonoTableInfo *table = NULL;
5132 MonoDomain *domain;
5133 GList *list = NULL;
5134 int i, len, ex_count;
5136 MONO_ARCH_SAVE_REGS;
5138 domain = mono_object_domain (assembly);
5140 g_assert (!assembly->assembly->dynamic);
5141 image = assembly->assembly->image;
5142 table = &image->tables [MONO_TABLE_FILE];
5143 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5145 /* Append data from all modules in the assembly */
5146 for (i = 0; i < table->rows; ++i) {
5147 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5148 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5149 if (loaded_image) {
5150 MonoArray *ex2;
5151 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5152 /* Append the new types to the end of the array */
5153 if (mono_array_length (res2) > 0) {
5154 guint32 len1, len2;
5155 MonoArray *res3, *ex3;
5157 len1 = mono_array_length (res);
5158 len2 = mono_array_length (res2);
5160 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5161 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5162 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5163 res = res3;
5165 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5166 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5167 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5168 exceptions = ex3;
5174 /* the ReflectionTypeLoadException must have all the types (Types property),
5175 * NULL replacing types which throws an exception. The LoaderException must
5176 * contain all exceptions for NULL items.
5179 len = mono_array_length (res);
5181 ex_count = 0;
5182 for (i = 0; i < len; i++) {
5183 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5184 MonoClass *klass;
5186 if (t) {
5187 klass = mono_type_get_class (t->type);
5188 if ((klass != NULL) && klass->exception_type) {
5189 /* keep the class in the list */
5190 list = g_list_append (list, klass);
5191 /* and replace Type with NULL */
5192 mono_array_setref (res, i, NULL);
5194 } else {
5195 ex_count ++;
5199 if (list || ex_count) {
5200 GList *tmp = NULL;
5201 MonoException *exc = NULL;
5202 MonoArray *exl = NULL;
5203 int j, length = g_list_length (list) + ex_count;
5205 mono_loader_clear_error ();
5207 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5208 /* Types for which mono_class_get () succeeded */
5209 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5210 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5211 mono_array_setref (exl, i, exc);
5213 /* Types for which it don't */
5214 for (j = 0; j < mono_array_length (exceptions); ++j) {
5215 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5216 if (exc) {
5217 g_assert (i < length);
5218 mono_array_setref (exl, i, exc);
5219 i ++;
5222 g_list_free (list);
5223 list = NULL;
5225 exc = mono_get_exception_reflection_type_load (res, exl);
5226 mono_loader_clear_error ();
5227 mono_raise_exception (exc);
5230 return res;
5233 static gboolean
5234 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5236 MonoAssemblyName aname;
5237 MonoDomain *domain = mono_object_domain (name);
5238 char *val;
5239 gboolean is_version_defined;
5240 gboolean is_token_defined;
5242 aname.public_key = NULL;
5243 val = mono_string_to_utf8 (assname);
5244 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5245 g_free ((guint8*) aname.public_key);
5246 g_free (val);
5247 return FALSE;
5250 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5251 FALSE, is_token_defined);
5253 mono_assembly_name_free (&aname);
5254 g_free ((guint8*) aname.public_key);
5255 g_free (val);
5257 return TRUE;
5260 static MonoReflectionType*
5261 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5263 MonoDomain *domain = mono_object_domain (module);
5264 MonoClass *klass;
5266 MONO_ARCH_SAVE_REGS;
5268 g_assert (module->image);
5270 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5271 /* These images do not have a global type */
5272 return NULL;
5274 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5275 return mono_type_get_object (domain, &klass->byval_arg);
5278 static void
5279 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5281 /*if (module->image)
5282 mono_image_close (module->image);*/
5285 static MonoString*
5286 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5288 MonoDomain *domain = mono_object_domain (module);
5290 MONO_ARCH_SAVE_REGS;
5292 g_assert (module->image);
5293 return mono_string_new (domain, module->image->guid);
5296 static gpointer
5297 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5299 #ifdef HOST_WIN32
5300 if (module->image && module->image->is_module_handle)
5301 return module->image->raw_data;
5302 #endif
5304 return (gpointer) (-1);
5307 static void
5308 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5310 if (image->dynamic) {
5311 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5312 *pe_kind = dyn->pe_kind;
5313 *machine = dyn->machine;
5315 else {
5316 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5317 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5321 static gint32
5322 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5324 return (image->md_version_major << 16) | (image->md_version_minor);
5327 static MonoArray*
5328 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5330 MonoArray *exceptions;
5331 int i;
5333 MONO_ARCH_SAVE_REGS;
5335 if (!module->image)
5336 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5337 else {
5338 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5339 for (i = 0; i < mono_array_length (exceptions); ++i) {
5340 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5341 if (ex)
5342 mono_raise_exception (ex);
5344 return res;
5348 static gboolean
5349 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5351 guint32 cols [MONO_MEMBERREF_SIZE];
5352 const char *sig;
5353 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5354 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5355 mono_metadata_decode_blob_size (sig, &sig);
5356 return (*sig != 0x6);
5359 static void
5360 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5362 if (type_args)
5363 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5364 mono_array_addr (type_args, MonoType*, 0));
5365 else
5366 context->class_inst = NULL;
5367 if (method_args)
5368 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5369 mono_array_addr (method_args, MonoType*, 0));
5370 else
5371 context->method_inst = NULL;
5374 static MonoType*
5375 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5377 MonoClass *klass;
5378 int table = mono_metadata_token_table (token);
5379 int index = mono_metadata_token_index (token);
5380 MonoGenericContext context;
5382 *error = ResolveTokenError_Other;
5384 /* Validate token */
5385 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5386 (table != MONO_TABLE_TYPESPEC)) {
5387 *error = ResolveTokenError_BadTable;
5388 return NULL;
5391 if (image->dynamic) {
5392 if (type_args || method_args)
5393 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5394 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5395 if (!klass)
5396 return NULL;
5397 return &klass->byval_arg;
5400 if ((index <= 0) || (index > image->tables [table].rows)) {
5401 *error = ResolveTokenError_OutOfRange;
5402 return NULL;
5405 init_generic_context_from_args (&context, type_args, method_args);
5406 klass = mono_class_get_full (image, token, &context);
5408 if (mono_loader_get_last_error ())
5409 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5411 if (klass)
5412 return &klass->byval_arg;
5413 else
5414 return NULL;
5417 static MonoMethod*
5418 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5420 int table = mono_metadata_token_table (token);
5421 int index = mono_metadata_token_index (token);
5422 MonoGenericContext context;
5423 MonoMethod *method;
5425 *error = ResolveTokenError_Other;
5427 /* Validate token */
5428 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5429 (table != MONO_TABLE_MEMBERREF)) {
5430 *error = ResolveTokenError_BadTable;
5431 return NULL;
5434 if (image->dynamic) {
5435 if (type_args || method_args)
5436 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5437 /* FIXME: validate memberref token type */
5438 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5441 if ((index <= 0) || (index > image->tables [table].rows)) {
5442 *error = ResolveTokenError_OutOfRange;
5443 return NULL;
5445 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5446 *error = ResolveTokenError_BadTable;
5447 return NULL;
5450 init_generic_context_from_args (&context, type_args, method_args);
5451 method = mono_get_method_full (image, token, NULL, &context);
5453 if (mono_loader_get_last_error ())
5454 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5456 return method;
5459 static MonoString*
5460 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5462 int index = mono_metadata_token_index (token);
5464 *error = ResolveTokenError_Other;
5466 /* Validate token */
5467 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5468 *error = ResolveTokenError_BadTable;
5469 return NULL;
5472 if (image->dynamic)
5473 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5475 if ((index <= 0) || (index >= image->heap_us.size)) {
5476 *error = ResolveTokenError_OutOfRange;
5477 return NULL;
5480 /* FIXME: What to do if the index points into the middle of a string ? */
5482 return mono_ldstr (mono_domain_get (), image, index);
5485 static MonoClassField*
5486 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5488 MonoClass *klass;
5489 int table = mono_metadata_token_table (token);
5490 int index = mono_metadata_token_index (token);
5491 MonoGenericContext context;
5492 MonoClassField *field;
5494 *error = ResolveTokenError_Other;
5496 /* Validate token */
5497 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5498 *error = ResolveTokenError_BadTable;
5499 return NULL;
5502 if (image->dynamic) {
5503 if (type_args || method_args)
5504 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5505 /* FIXME: validate memberref token type */
5506 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5509 if ((index <= 0) || (index > image->tables [table].rows)) {
5510 *error = ResolveTokenError_OutOfRange;
5511 return NULL;
5513 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5514 *error = ResolveTokenError_BadTable;
5515 return NULL;
5518 init_generic_context_from_args (&context, type_args, method_args);
5519 field = mono_field_from_token (image, token, &klass, &context);
5521 if (mono_loader_get_last_error ())
5522 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5524 return field;
5528 static MonoObject*
5529 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5531 int table = mono_metadata_token_table (token);
5533 *error = ResolveTokenError_Other;
5535 switch (table) {
5536 case MONO_TABLE_TYPEDEF:
5537 case MONO_TABLE_TYPEREF:
5538 case MONO_TABLE_TYPESPEC: {
5539 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5540 if (t)
5541 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5542 else
5543 return NULL;
5545 case MONO_TABLE_METHOD:
5546 case MONO_TABLE_METHODSPEC: {
5547 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5548 if (m)
5549 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5550 else
5551 return NULL;
5553 case MONO_TABLE_FIELD: {
5554 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5555 if (f)
5556 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5557 else
5558 return NULL;
5560 case MONO_TABLE_MEMBERREF:
5561 if (mono_metadata_memberref_is_method (image, token)) {
5562 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5563 if (m)
5564 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5565 else
5566 return NULL;
5568 else {
5569 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5570 if (f)
5571 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5572 else
5573 return NULL;
5575 break;
5577 default:
5578 *error = ResolveTokenError_BadTable;
5581 return NULL;
5584 static MonoArray*
5585 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5587 int table = mono_metadata_token_table (token);
5588 int idx = mono_metadata_token_index (token);
5589 MonoTableInfo *tables = image->tables;
5590 guint32 sig, len;
5591 const char *ptr;
5592 MonoArray *res;
5594 *error = ResolveTokenError_OutOfRange;
5596 /* FIXME: Support other tables ? */
5597 if (table != MONO_TABLE_STANDALONESIG)
5598 return NULL;
5600 if (image->dynamic)
5601 return NULL;
5603 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5604 return NULL;
5606 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5608 ptr = mono_metadata_blob_heap (image, sig);
5609 len = mono_metadata_decode_blob_size (ptr, &ptr);
5611 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5612 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5613 return res;
5616 static MonoReflectionType*
5617 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5619 MonoClass *klass;
5620 int isbyref = 0, rank;
5621 char *str = mono_string_to_utf8 (smodifiers);
5622 char *p;
5624 MONO_ARCH_SAVE_REGS;
5626 klass = mono_class_from_mono_type (tb->type.type);
5627 p = str;
5628 /* logic taken from mono_reflection_parse_type(): keep in sync */
5629 while (*p) {
5630 switch (*p) {
5631 case '&':
5632 if (isbyref) { /* only one level allowed by the spec */
5633 g_free (str);
5634 return NULL;
5636 isbyref = 1;
5637 p++;
5638 g_free (str);
5639 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5640 break;
5641 case '*':
5642 klass = mono_ptr_class_get (&klass->byval_arg);
5643 mono_class_init (klass);
5644 p++;
5645 break;
5646 case '[':
5647 rank = 1;
5648 p++;
5649 while (*p) {
5650 if (*p == ']')
5651 break;
5652 if (*p == ',')
5653 rank++;
5654 else if (*p != '*') { /* '*' means unknown lower bound */
5655 g_free (str);
5656 return NULL;
5658 ++p;
5660 if (*p != ']') {
5661 g_free (str);
5662 return NULL;
5664 p++;
5665 klass = mono_array_class_get (klass, rank);
5666 mono_class_init (klass);
5667 break;
5668 default:
5669 break;
5672 g_free (str);
5673 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5676 static MonoBoolean
5677 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5679 MonoType *type;
5680 MonoBoolean res;
5682 MONO_ARCH_SAVE_REGS;
5684 type = t->type;
5685 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5687 return res;
5690 static MonoReflectionType *
5691 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5693 MonoClass *klass, *aklass;
5695 MONO_ARCH_SAVE_REGS;
5697 klass = mono_class_from_mono_type (type->type);
5698 if (rank == 0) //single dimentional array
5699 aklass = mono_array_class_get (klass, 1);
5700 else
5701 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5703 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5706 static MonoReflectionType *
5707 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5709 MonoClass *klass;
5711 MONO_ARCH_SAVE_REGS;
5713 klass = mono_class_from_mono_type (type->type);
5715 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5718 static MonoReflectionType *
5719 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5721 MonoClass *pklass;
5723 MONO_ARCH_SAVE_REGS;
5725 pklass = mono_ptr_class_get (type->type);
5727 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5730 static MonoObject *
5731 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5732 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5734 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5735 MonoObject *delegate;
5736 gpointer func;
5737 MonoMethod *method = info->method;
5739 MONO_ARCH_SAVE_REGS;
5741 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5743 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5744 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5745 return NULL;
5748 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5750 if (method->dynamic) {
5751 /* Creating a trampoline would leak memory */
5752 func = mono_compile_method (method);
5753 } else {
5754 func = mono_create_ftnptr (mono_domain_get (),
5755 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5758 mono_delegate_ctor_with_method (delegate, target, func, method);
5760 return delegate;
5763 static void
5764 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5766 /* Reset the invoke impl to the default one */
5767 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5771 * Magic number to convert a time which is relative to
5772 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5774 #define EPOCH_ADJUST ((guint64)62135596800LL)
5777 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5779 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5781 #ifdef HOST_WIN32
5782 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5783 static void
5784 convert_to_absolute_date(SYSTEMTIME *date)
5786 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5787 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5788 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5789 /* from the calendar FAQ */
5790 int a = (14 - date->wMonth) / 12;
5791 int y = date->wYear - a;
5792 int m = date->wMonth + 12 * a - 2;
5793 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5795 /* d is now the day of the week for the first of the month (0 == Sunday) */
5797 int day_of_week = date->wDayOfWeek;
5799 /* set day_in_month to the first day in the month which falls on day_of_week */
5800 int day_in_month = 1 + (day_of_week - d);
5801 if (day_in_month <= 0)
5802 day_in_month += 7;
5804 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5805 date->wDay = day_in_month + (date->wDay - 1) * 7;
5806 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5807 date->wDay -= 7;
5809 #endif
5811 #ifndef HOST_WIN32
5813 * Return's the offset from GMT of a local time.
5815 * tm is a local time
5816 * t is the same local time as seconds.
5818 static int
5819 gmt_offset(struct tm *tm, time_t t)
5821 #if defined (HAVE_TM_GMTOFF)
5822 return tm->tm_gmtoff;
5823 #else
5824 struct tm g;
5825 time_t t2;
5826 g = *gmtime(&t);
5827 g.tm_isdst = tm->tm_isdst;
5828 t2 = mktime(&g);
5829 return (int)difftime(t, t2);
5830 #endif
5832 #endif
5834 * This is heavily based on zdump.c from glibc 2.2.
5836 * * data[0]: start of daylight saving time (in DateTime ticks).
5837 * * data[1]: end of daylight saving time (in DateTime ticks).
5838 * * data[2]: utcoffset (in TimeSpan ticks).
5839 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5840 * * name[0]: name of this timezone when not daylight saving.
5841 * * name[1]: name of this timezone when daylight saving.
5843 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5844 * the class library allows years between 1 and 9999.
5846 * Returns true on success and zero on failure.
5848 static guint32
5849 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5851 #ifndef HOST_WIN32
5852 MonoDomain *domain = mono_domain_get ();
5853 struct tm start, tt;
5854 time_t t;
5856 long int gmtoff;
5857 int is_daylight = 0, day;
5858 char tzone [64];
5860 MONO_ARCH_SAVE_REGS;
5862 MONO_CHECK_ARG_NULL (data);
5863 MONO_CHECK_ARG_NULL (names);
5865 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5866 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5869 * no info is better than crashing: we'll need our own tz data
5870 * to make this work properly, anyway. The range is probably
5871 * reduced to 1970 .. 2037 because that is what mktime is
5872 * guaranteed to support (we get into an infinite loop
5873 * otherwise).
5876 memset (&start, 0, sizeof (start));
5878 start.tm_mday = 1;
5879 start.tm_year = year-1900;
5881 t = mktime (&start);
5883 if ((year < 1970) || (year > 2037) || (t == -1)) {
5884 t = time (NULL);
5885 tt = *localtime (&t);
5886 strftime (tzone, sizeof (tzone), "%Z", &tt);
5887 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5888 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5889 return 1;
5892 gmtoff = gmt_offset (&start, t);
5894 /* For each day of the year, calculate the tm_gmtoff. */
5895 for (day = 0; day < 365; day++) {
5897 t += 3600*24;
5898 tt = *localtime (&t);
5900 /* Daylight saving starts or ends here. */
5901 if (gmt_offset (&tt, t) != gmtoff) {
5902 struct tm tt1;
5903 time_t t1;
5905 /* Try to find the exact hour when daylight saving starts/ends. */
5906 t1 = t;
5907 do {
5908 t1 -= 3600;
5909 tt1 = *localtime (&t1);
5910 } while (gmt_offset (&tt1, t1) != gmtoff);
5912 /* Try to find the exact minute when daylight saving starts/ends. */
5913 do {
5914 t1 += 60;
5915 tt1 = *localtime (&t1);
5916 } while (gmt_offset (&tt1, t1) == gmtoff);
5917 t1+=gmtoff;
5918 strftime (tzone, sizeof (tzone), "%Z", &tt);
5920 /* Write data, if we're already in daylight saving, we're done. */
5921 if (is_daylight) {
5922 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5923 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5924 return 1;
5925 } else {
5926 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5927 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5928 is_daylight = 1;
5931 /* This is only set once when we enter daylight saving. */
5932 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5933 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5935 gmtoff = gmt_offset (&tt, t);
5939 if (!is_daylight) {
5940 strftime (tzone, sizeof (tzone), "%Z", &tt);
5941 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5942 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5943 mono_array_set ((*data), gint64, 0, 0);
5944 mono_array_set ((*data), gint64, 1, 0);
5945 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5946 mono_array_set ((*data), gint64, 3, 0);
5949 return 1;
5950 #else
5951 MonoDomain *domain = mono_domain_get ();
5952 TIME_ZONE_INFORMATION tz_info;
5953 FILETIME ft;
5954 int i;
5955 int err, tz_id;
5957 tz_id = GetTimeZoneInformation (&tz_info);
5958 if (tz_id == TIME_ZONE_ID_INVALID)
5959 return 0;
5961 MONO_CHECK_ARG_NULL (data);
5962 MONO_CHECK_ARG_NULL (names);
5964 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
5965 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
5967 for (i = 0; i < 32; ++i)
5968 if (!tz_info.DaylightName [i])
5969 break;
5970 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
5971 for (i = 0; i < 32; ++i)
5972 if (!tz_info.StandardName [i])
5973 break;
5974 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
5976 if ((year <= 1601) || (year > 30827)) {
5978 * According to MSDN, the MS time functions can't handle dates outside
5979 * this interval.
5981 return 1;
5984 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
5985 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
5986 tz_info.StandardDate.wYear = year;
5987 convert_to_absolute_date(&tz_info.StandardDate);
5988 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
5989 //g_assert(err);
5990 if (err == 0)
5991 return 0;
5993 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5994 tz_info.DaylightDate.wYear = year;
5995 convert_to_absolute_date(&tz_info.DaylightDate);
5996 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
5997 //g_assert(err);
5998 if (err == 0)
5999 return 0;
6001 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6003 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6004 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6006 return 1;
6007 #endif
6010 static gpointer
6011 ves_icall_System_Object_obj_address (MonoObject *this)
6013 MONO_ARCH_SAVE_REGS;
6015 return this;
6018 /* System.Buffer */
6020 static inline gint32
6021 mono_array_get_byte_length (MonoArray *array)
6023 MonoClass *klass;
6024 int length;
6025 int i;
6027 klass = array->obj.vtable->klass;
6029 if (array->bounds == NULL)
6030 length = array->max_length;
6031 else {
6032 length = 1;
6033 for (i = 0; i < klass->rank; ++ i)
6034 length *= array->bounds [i].length;
6037 switch (klass->element_class->byval_arg.type) {
6038 case MONO_TYPE_I1:
6039 case MONO_TYPE_U1:
6040 case MONO_TYPE_BOOLEAN:
6041 return length;
6042 case MONO_TYPE_I2:
6043 case MONO_TYPE_U2:
6044 case MONO_TYPE_CHAR:
6045 return length << 1;
6046 case MONO_TYPE_I4:
6047 case MONO_TYPE_U4:
6048 case MONO_TYPE_R4:
6049 return length << 2;
6050 case MONO_TYPE_I:
6051 case MONO_TYPE_U:
6052 return length * sizeof (gpointer);
6053 case MONO_TYPE_I8:
6054 case MONO_TYPE_U8:
6055 case MONO_TYPE_R8:
6056 return length << 3;
6057 default:
6058 return -1;
6062 static gint32
6063 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6065 MONO_ARCH_SAVE_REGS;
6067 return mono_array_get_byte_length (array);
6070 static gint8
6071 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6073 MONO_ARCH_SAVE_REGS;
6075 return mono_array_get (array, gint8, idx);
6078 static void
6079 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6081 MONO_ARCH_SAVE_REGS;
6083 mono_array_set (array, gint8, idx, value);
6086 static MonoBoolean
6087 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6089 guint8 *src_buf, *dest_buf;
6091 MONO_ARCH_SAVE_REGS;
6093 /* watch out for integer overflow */
6094 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6095 return FALSE;
6097 src_buf = (guint8 *)src->vector + src_offset;
6098 dest_buf = (guint8 *)dest->vector + dest_offset;
6100 if (src != dest)
6101 memcpy (dest_buf, src_buf, count);
6102 else
6103 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6105 return TRUE;
6108 static MonoObject *
6109 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6111 MonoDomain *domain = mono_object_domain (this);
6112 MonoObject *res;
6113 MonoRealProxy *rp = ((MonoRealProxy *)this);
6114 MonoTransparentProxy *tp;
6115 MonoType *type;
6116 MonoClass *klass;
6118 MONO_ARCH_SAVE_REGS;
6120 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6121 tp = (MonoTransparentProxy*) res;
6123 MONO_OBJECT_SETREF (tp, rp, rp);
6124 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6125 klass = mono_class_from_mono_type (type);
6127 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6128 tp->remote_class = mono_remote_class (domain, class_name, klass);
6130 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6131 return res;
6134 static MonoReflectionType *
6135 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6137 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6140 /* System.Environment */
6142 MonoString*
6143 ves_icall_System_Environment_get_UserName (void)
6145 MONO_ARCH_SAVE_REGS;
6147 /* using glib is more portable */
6148 return mono_string_new (mono_domain_get (), g_get_user_name ());
6152 static MonoString *
6153 ves_icall_System_Environment_get_MachineName (void)
6155 #if defined (HOST_WIN32)
6156 gunichar2 *buf;
6157 guint32 len;
6158 MonoString *result;
6160 len = MAX_COMPUTERNAME_LENGTH + 1;
6161 buf = g_new (gunichar2, len);
6163 result = NULL;
6164 if (GetComputerName (buf, (PDWORD) &len))
6165 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6167 g_free (buf);
6168 return result;
6169 #elif !defined(DISABLE_SOCKETS)
6170 gchar buf [256];
6171 MonoString *result;
6173 if (gethostname (buf, sizeof (buf)) == 0)
6174 result = mono_string_new (mono_domain_get (), buf);
6175 else
6176 result = NULL;
6178 return result;
6179 #else
6180 return mono_string_new (mono_domain_get (), "mono");
6181 #endif
6184 static int
6185 ves_icall_System_Environment_get_Platform (void)
6187 #if defined (TARGET_WIN32)
6188 /* Win32NT */
6189 return 2;
6190 #elif defined(__MACH__)
6191 /* OSX */
6192 if (mono_framework_version () < 2)
6193 return 128;
6196 // For compatibility with our client code, this will be 4 for a while.
6197 // We will eventually move to 6 to match .NET, but it requires all client
6198 // code to be updated and the documentation everywhere to be updated
6199 // first.
6201 return 4;
6202 #else
6203 /* Unix */
6204 if (mono_framework_version () < 2)
6205 return 128;
6206 return 4;
6207 #endif
6210 static MonoString *
6211 ves_icall_System_Environment_get_NewLine (void)
6213 MONO_ARCH_SAVE_REGS;
6215 #if defined (HOST_WIN32)
6216 return mono_string_new (mono_domain_get (), "\r\n");
6217 #else
6218 return mono_string_new (mono_domain_get (), "\n");
6219 #endif
6222 static MonoString *
6223 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6225 const gchar *value;
6226 gchar *utf8_name;
6228 MONO_ARCH_SAVE_REGS;
6230 if (name == NULL)
6231 return NULL;
6233 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6234 value = g_getenv (utf8_name);
6236 g_free (utf8_name);
6238 if (value == 0)
6239 return NULL;
6241 return mono_string_new (mono_domain_get (), value);
6245 * There is no standard way to get at environ.
6247 #ifndef _MSC_VER
6248 #ifndef __MINGW32_VERSION
6249 #ifdef __APPLE__
6250 /* Apple defines this in crt_externs.h but doesn't provide that header for
6251 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6252 * in fact exist on all implementations (so far)
6254 gchar ***_NSGetEnviron(void);
6255 #define environ (*_NSGetEnviron())
6256 #else
6257 extern
6258 char **environ;
6259 #endif
6260 #endif
6261 #endif
6263 static MonoArray *
6264 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6266 #ifdef HOST_WIN32
6267 MonoArray *names;
6268 MonoDomain *domain;
6269 MonoString *str;
6270 WCHAR* env_strings;
6271 WCHAR* env_string;
6272 WCHAR* equal_str;
6273 int n = 0;
6275 env_strings = GetEnvironmentStrings();
6277 if (env_strings) {
6278 env_string = env_strings;
6279 while (*env_string != '\0') {
6280 /* weird case that MS seems to skip */
6281 if (*env_string != '=')
6282 n++;
6283 while (*env_string != '\0')
6284 env_string++;
6285 env_string++;
6289 domain = mono_domain_get ();
6290 names = mono_array_new (domain, mono_defaults.string_class, n);
6292 if (env_strings) {
6293 n = 0;
6294 env_string = env_strings;
6295 while (*env_string != '\0') {
6296 /* weird case that MS seems to skip */
6297 if (*env_string != '=') {
6298 equal_str = wcschr(env_string, '=');
6299 g_assert(equal_str);
6300 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6301 mono_array_setref (names, n, str);
6302 n++;
6304 while (*env_string != '\0')
6305 env_string++;
6306 env_string++;
6309 FreeEnvironmentStrings (env_strings);
6312 return names;
6314 #else
6315 MonoArray *names;
6316 MonoDomain *domain;
6317 MonoString *str;
6318 gchar **e, **parts;
6319 int n;
6321 MONO_ARCH_SAVE_REGS;
6323 n = 0;
6324 for (e = environ; *e != 0; ++ e)
6325 ++ n;
6327 domain = mono_domain_get ();
6328 names = mono_array_new (domain, mono_defaults.string_class, n);
6330 n = 0;
6331 for (e = environ; *e != 0; ++ e) {
6332 parts = g_strsplit (*e, "=", 2);
6333 if (*parts != 0) {
6334 str = mono_string_new (domain, *parts);
6335 mono_array_setref (names, n, str);
6338 g_strfreev (parts);
6340 ++ n;
6343 return names;
6344 #endif
6348 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6350 #if !GLIB_CHECK_VERSION(2,4,0)
6351 #define g_setenv(a,b,c) setenv(a,b,c)
6352 #define g_unsetenv(a) unsetenv(a)
6353 #endif
6355 static void
6356 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6358 MonoError error;
6359 #ifdef HOST_WIN32
6361 gunichar2 *utf16_name, *utf16_value;
6362 #else
6363 gchar *utf8_name, *utf8_value;
6364 #endif
6366 MONO_ARCH_SAVE_REGS;
6368 #ifdef HOST_WIN32
6369 utf16_name = mono_string_to_utf16 (name);
6370 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6371 SetEnvironmentVariable (utf16_name, NULL);
6372 g_free (utf16_name);
6373 return;
6376 utf16_value = mono_string_to_utf16 (value);
6378 SetEnvironmentVariable (utf16_name, utf16_value);
6380 g_free (utf16_name);
6381 g_free (utf16_value);
6382 #else
6383 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6385 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6386 g_unsetenv (utf8_name);
6387 g_free (utf8_name);
6388 return;
6391 utf8_value = mono_string_to_utf8_checked (value, &error);
6392 if (!mono_error_ok (&error)) {
6393 g_free (utf8_name);
6394 mono_error_raise_exception (&error);
6396 g_setenv (utf8_name, utf8_value, TRUE);
6398 g_free (utf8_name);
6399 g_free (utf8_value);
6400 #endif
6403 static void
6404 ves_icall_System_Environment_Exit (int result)
6406 MONO_ARCH_SAVE_REGS;
6408 mono_threads_set_shutting_down ();
6410 mono_runtime_set_shutting_down ();
6412 /* Suspend all managed threads since the runtime is going away */
6413 mono_thread_suspend_all_other_threads ();
6415 mono_runtime_quit ();
6417 /* we may need to do some cleanup here... */
6418 exit (result);
6421 static MonoString*
6422 ves_icall_System_Environment_GetGacPath (void)
6424 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6427 static MonoString*
6428 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6430 #if defined (HOST_WIN32)
6431 #ifndef CSIDL_FLAG_CREATE
6432 #define CSIDL_FLAG_CREATE 0x8000
6433 #endif
6435 WCHAR path [MAX_PATH];
6436 /* Create directory if no existing */
6437 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6438 int len = 0;
6439 while (path [len])
6440 ++ len;
6441 return mono_string_new_utf16 (mono_domain_get (), path, len);
6443 #else
6444 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6445 #endif
6446 return mono_string_new (mono_domain_get (), "");
6449 static MonoArray *
6450 ves_icall_System_Environment_GetLogicalDrives (void)
6452 gunichar2 buf [128], *ptr, *dname;
6453 gunichar2 *u16;
6454 guint initial_size = 127, size = 128;
6455 gint ndrives;
6456 MonoArray *result;
6457 MonoString *drivestr;
6458 MonoDomain *domain = mono_domain_get ();
6459 gint len;
6461 MONO_ARCH_SAVE_REGS;
6463 buf [0] = '\0';
6464 ptr = buf;
6466 while (size > initial_size) {
6467 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6468 if (size > initial_size) {
6469 if (ptr != buf)
6470 g_free (ptr);
6471 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6472 initial_size = size;
6473 size++;
6477 /* Count strings */
6478 dname = ptr;
6479 ndrives = 0;
6480 do {
6481 while (*dname++);
6482 ndrives++;
6483 } while (*dname);
6485 dname = ptr;
6486 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6487 ndrives = 0;
6488 do {
6489 len = 0;
6490 u16 = dname;
6491 while (*u16) { u16++; len ++; }
6492 drivestr = mono_string_new_utf16 (domain, dname, len);
6493 mono_array_setref (result, ndrives++, drivestr);
6494 while (*dname++);
6495 } while (*dname);
6497 if (ptr != buf)
6498 g_free (ptr);
6500 return result;
6503 static MonoString *
6504 ves_icall_System_Environment_InternalGetHome (void)
6506 MONO_ARCH_SAVE_REGS;
6508 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6511 static const char *encodings [] = {
6512 (char *) 1,
6513 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6514 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6515 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6516 (char *) 2,
6517 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6518 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6519 "x_unicode_2_0_utf_7",
6520 (char *) 3,
6521 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6522 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6523 (char *) 4,
6524 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6525 "iso_10646_ucs2",
6526 (char *) 5,
6527 "unicodefffe", "utf_16be",
6528 (char *) 6,
6529 "iso_8859_1",
6530 (char *) 0
6534 * Returns the internal codepage, if the value of "int_code_page" is
6535 * 1 at entry, and we can not compute a suitable code page number,
6536 * returns the code page as a string
6538 static MonoString*
6539 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6541 const char *cset;
6542 const char *p;
6543 char *c;
6544 char *codepage = NULL;
6545 int code;
6546 int want_name = *int_code_page;
6547 int i;
6549 *int_code_page = -1;
6550 MONO_ARCH_SAVE_REGS;
6552 g_get_charset (&cset);
6553 c = codepage = strdup (cset);
6554 for (c = codepage; *c; c++){
6555 if (isascii (*c) && isalpha (*c))
6556 *c = tolower (*c);
6557 if (*c == '-')
6558 *c = '_';
6560 /* g_print ("charset: %s\n", cset); */
6562 /* handle some common aliases */
6563 p = encodings [0];
6564 code = 0;
6565 for (i = 0; p != 0; ){
6566 if ((gssize) p < 7){
6567 code = (gssize) p;
6568 p = encodings [++i];
6569 continue;
6571 if (strcmp (p, codepage) == 0){
6572 *int_code_page = code;
6573 break;
6575 p = encodings [++i];
6578 if (strstr (codepage, "utf_8") != NULL)
6579 *int_code_page |= 0x10000000;
6580 free (codepage);
6582 if (want_name && *int_code_page == -1)
6583 return mono_string_new (mono_domain_get (), cset);
6584 else
6585 return NULL;
6588 static MonoBoolean
6589 ves_icall_System_Environment_get_HasShutdownStarted (void)
6591 if (mono_runtime_is_shutting_down ())
6592 return TRUE;
6594 if (mono_domain_is_unloading (mono_domain_get ()))
6595 return TRUE;
6597 return FALSE;
6600 static void
6601 ves_icall_System_Environment_BroadcastSettingChange (void)
6603 #ifdef HOST_WIN32
6604 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6605 #endif
6608 static void
6609 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6610 MonoReflectionMethod *method,
6611 MonoArray *out_args)
6613 MONO_ARCH_SAVE_REGS;
6615 mono_message_init (mono_object_domain (this), this, method, out_args);
6618 static MonoBoolean
6619 ves_icall_IsTransparentProxy (MonoObject *proxy)
6621 MONO_ARCH_SAVE_REGS;
6623 if (!proxy)
6624 return 0;
6626 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6627 return 1;
6629 return 0;
6632 static MonoReflectionMethod *
6633 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6634 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6636 MonoClass *klass;
6637 MonoMethod *method;
6638 MonoMethod **vtable;
6639 MonoMethod *res = NULL;
6641 MONO_CHECK_ARG_NULL (rtype);
6642 MONO_CHECK_ARG_NULL (rmethod);
6644 method = rmethod->method;
6645 klass = mono_class_from_mono_type (rtype->type);
6647 if (MONO_CLASS_IS_INTERFACE (klass))
6648 return NULL;
6650 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6651 return NULL;
6653 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6654 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6655 return rmethod;
6656 else
6657 return NULL;
6660 mono_class_setup_vtable (klass);
6661 vtable = klass->vtable;
6663 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6664 gboolean variance_used = FALSE;
6665 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6666 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6667 if (offs >= 0)
6668 res = vtable [offs + method->slot];
6669 } else {
6670 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6671 return NULL;
6673 if (method->slot != -1)
6674 res = vtable [method->slot];
6677 if (!res)
6678 return NULL;
6680 return mono_method_get_object (mono_domain_get (), res, NULL);
6683 static void
6684 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6686 MonoClass *klass;
6687 MonoVTable* vtable;
6689 MONO_ARCH_SAVE_REGS;
6691 klass = mono_class_from_mono_type (type->type);
6692 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6694 if (enable) vtable->remote = 1;
6695 else vtable->remote = 0;
6698 static MonoObject *
6699 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6701 MonoClass *klass;
6702 MonoDomain *domain;
6704 MONO_ARCH_SAVE_REGS;
6706 domain = mono_object_domain (type);
6707 klass = mono_class_from_mono_type (type->type);
6709 if (klass->rank >= 1) {
6710 g_assert (klass->rank == 1);
6711 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6712 } else {
6713 /* Bypass remoting object creation check */
6714 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6718 static MonoString *
6719 ves_icall_System_IO_get_temp_path (void)
6721 MONO_ARCH_SAVE_REGS;
6723 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6726 #ifndef PLATFORM_NO_DRIVEINFO
6727 static MonoBoolean
6728 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6729 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6730 gint32 *error)
6732 gboolean result;
6733 ULARGE_INTEGER wapi_free_bytes_avail;
6734 ULARGE_INTEGER wapi_total_number_of_bytes;
6735 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6737 MONO_ARCH_SAVE_REGS;
6739 *error = ERROR_SUCCESS;
6740 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6741 &wapi_total_number_of_free_bytes);
6743 if (result) {
6744 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6745 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6746 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6747 } else {
6748 *free_bytes_avail = 0;
6749 *total_number_of_bytes = 0;
6750 *total_number_of_free_bytes = 0;
6751 *error = GetLastError ();
6754 return result;
6757 static guint32
6758 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6760 MONO_ARCH_SAVE_REGS;
6762 return GetDriveType (mono_string_chars (root_path_name));
6764 #endif
6766 static gpointer
6767 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6769 MONO_ARCH_SAVE_REGS;
6771 return mono_compile_method (method);
6774 static MonoString *
6775 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6777 MonoString *mcpath;
6778 gchar *path;
6780 MONO_ARCH_SAVE_REGS;
6782 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6784 #if defined (HOST_WIN32)
6785 /* Avoid mixing '/' and '\\' */
6787 gint i;
6788 for (i = strlen (path) - 1; i >= 0; i--)
6789 if (path [i] == '/')
6790 path [i] = '\\';
6792 #endif
6793 mcpath = mono_string_new (mono_domain_get (), path);
6794 g_free (path);
6796 return mcpath;
6799 static MonoString *
6800 get_bundled_machine_config (void)
6802 const gchar *machine_config;
6804 MONO_ARCH_SAVE_REGS;
6806 machine_config = mono_get_machine_config ();
6808 if (!machine_config)
6809 return NULL;
6811 return mono_string_new (mono_domain_get (), machine_config);
6814 static MonoString *
6815 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6817 MonoString *ipath;
6818 gchar *path;
6820 MONO_ARCH_SAVE_REGS;
6822 path = g_path_get_dirname (mono_get_config_dir ());
6824 #if defined (HOST_WIN32)
6825 /* Avoid mixing '/' and '\\' */
6827 gint i;
6828 for (i = strlen (path) - 1; i >= 0; i--)
6829 if (path [i] == '/')
6830 path [i] = '\\';
6832 #endif
6833 ipath = mono_string_new (mono_domain_get (), path);
6834 g_free (path);
6836 return ipath;
6839 static gboolean
6840 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6842 MonoPEResourceDataEntry *entry;
6843 MonoImage *image;
6845 MONO_ARCH_SAVE_REGS;
6847 if (!assembly || !result || !size)
6848 return FALSE;
6850 *result = NULL;
6851 *size = 0;
6852 image = assembly->assembly->image;
6853 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6854 if (!entry)
6855 return FALSE;
6857 *result = mono_image_rva_map (image, entry->rde_data_offset);
6858 if (!(*result)) {
6859 g_free (entry);
6860 return FALSE;
6862 *size = entry->rde_size;
6863 g_free (entry);
6864 return TRUE;
6867 static MonoBoolean
6868 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6870 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6873 static void
6874 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6876 #if defined (HOST_WIN32)
6877 OutputDebugString (mono_string_chars (message));
6878 #else
6879 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6880 #endif
6883 /* Only used for value types */
6884 static MonoObject *
6885 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6887 MonoClass *klass;
6888 MonoDomain *domain;
6890 MONO_ARCH_SAVE_REGS;
6892 domain = mono_object_domain (type);
6893 klass = mono_class_from_mono_type (type->type);
6895 if (mono_class_is_nullable (klass))
6896 /* No arguments -> null */
6897 return NULL;
6899 return mono_object_new (domain, klass);
6902 static MonoReflectionMethod *
6903 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6905 MonoClass *klass, *parent;
6906 MonoMethod *method = m->method;
6907 MonoMethod *result = NULL;
6909 MONO_ARCH_SAVE_REGS;
6911 if (method->klass == NULL)
6912 return m;
6914 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6915 MONO_CLASS_IS_INTERFACE (method->klass) ||
6916 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6917 return m;
6919 klass = method->klass;
6920 if (klass->generic_class)
6921 klass = klass->generic_class->container_class;
6923 if (definition) {
6924 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6925 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6926 mono_class_setup_vtable (parent);
6927 if (parent->vtable_size <= method->slot)
6928 break;
6929 klass = parent;
6931 } else {
6932 klass = klass->parent;
6933 if (!klass)
6934 return m;
6937 if (klass == method->klass)
6938 return m;
6940 result = klass->vtable [method->slot];
6941 if (result == NULL) {
6942 /* It is an abstract method */
6943 gpointer iter = NULL;
6944 while ((result = mono_class_get_methods (klass, &iter)))
6945 if (result->slot == method->slot)
6946 break;
6949 if (result == NULL)
6950 return m;
6952 return mono_method_get_object (mono_domain_get (), result, NULL);
6955 static MonoString*
6956 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6958 MonoMethod *method = m->method;
6960 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6961 return m->name;
6964 static void
6965 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6967 MONO_ARCH_SAVE_REGS;
6969 iter->sig = *(MonoMethodSignature**)argsp;
6971 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6972 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6974 iter->next_arg = 0;
6975 /* FIXME: it's not documented what start is exactly... */
6976 if (start) {
6977 iter->args = start;
6978 } else {
6979 iter->args = argsp + sizeof (gpointer);
6981 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6983 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6986 static MonoTypedRef
6987 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6989 guint32 i, arg_size;
6990 gint32 align;
6991 MonoTypedRef res;
6992 MONO_ARCH_SAVE_REGS;
6994 i = iter->sig->sentinelpos + iter->next_arg;
6996 g_assert (i < iter->sig->param_count);
6998 res.type = iter->sig->params [i];
6999 res.klass = mono_class_from_mono_type (res.type);
7000 res.value = iter->args;
7001 arg_size = mono_type_stack_size (res.type, &align);
7002 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7003 if (arg_size <= sizeof (gpointer)) {
7004 int dummy;
7005 int padding = arg_size - mono_type_size (res.type, &dummy);
7006 res.value = (guint8*)res.value + padding;
7008 #endif
7009 iter->args = (char*)iter->args + arg_size;
7010 iter->next_arg++;
7012 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7014 return res;
7017 static MonoTypedRef
7018 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7020 guint32 i, arg_size;
7021 gint32 align;
7022 MonoTypedRef res;
7023 MONO_ARCH_SAVE_REGS;
7025 i = iter->sig->sentinelpos + iter->next_arg;
7027 g_assert (i < iter->sig->param_count);
7029 while (i < iter->sig->param_count) {
7030 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7031 continue;
7032 res.type = iter->sig->params [i];
7033 res.klass = mono_class_from_mono_type (res.type);
7034 /* FIXME: endianess issue... */
7035 res.value = iter->args;
7036 arg_size = mono_type_stack_size (res.type, &align);
7037 iter->args = (char*)iter->args + arg_size;
7038 iter->next_arg++;
7039 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7040 return res;
7042 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7044 res.type = NULL;
7045 res.value = NULL;
7046 res.klass = NULL;
7047 return res;
7050 static MonoType*
7051 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7053 gint i;
7054 MONO_ARCH_SAVE_REGS;
7056 i = iter->sig->sentinelpos + iter->next_arg;
7058 g_assert (i < iter->sig->param_count);
7060 return iter->sig->params [i];
7063 static MonoObject*
7064 mono_TypedReference_ToObject (MonoTypedRef tref)
7066 MONO_ARCH_SAVE_REGS;
7068 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7069 MonoObject** objp = tref.value;
7070 return *objp;
7073 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7076 static MonoObject*
7077 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7079 MONO_ARCH_SAVE_REGS;
7081 if (MONO_TYPE_IS_REFERENCE (type)) {
7082 MonoObject** objp = value;
7083 return *objp;
7086 return mono_value_box (mono_domain_get (), klass, value);
7089 static void
7090 prelink_method (MonoMethod *method)
7092 const char *exc_class, *exc_arg;
7093 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7094 return;
7095 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7096 if (exc_class) {
7097 mono_raise_exception(
7098 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7100 /* create the wrapper, too? */
7103 static void
7104 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7106 MONO_ARCH_SAVE_REGS;
7107 prelink_method (method->method);
7110 static void
7111 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7113 MonoClass *klass = mono_class_from_mono_type (type->type);
7114 MonoMethod* m;
7115 gpointer iter = NULL;
7116 MONO_ARCH_SAVE_REGS;
7118 while ((m = mono_class_get_methods (klass, &iter)))
7119 prelink_method (m);
7122 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7123 static void
7124 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7125 gint32 const **exponents,
7126 gunichar2 const **digitLowerTable,
7127 gunichar2 const **digitUpperTable,
7128 gint64 const **tenPowersList,
7129 gint32 const **decHexDigits)
7131 *mantissas = Formatter_MantissaBitsTable;
7132 *exponents = Formatter_TensExponentTable;
7133 *digitLowerTable = Formatter_DigitLowerTable;
7134 *digitUpperTable = Formatter_DigitUpperTable;
7135 *tenPowersList = Formatter_TenPowersList;
7136 *decHexDigits = Formatter_DecHexDigits;
7139 /* These parameters are "readonly" in corlib/System/Char.cs */
7140 static void
7141 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7142 guint8 const **numeric_data,
7143 gdouble const **numeric_data_values,
7144 guint16 const **to_lower_data_low,
7145 guint16 const **to_lower_data_high,
7146 guint16 const **to_upper_data_low,
7147 guint16 const **to_upper_data_high)
7149 *category_data = CategoryData;
7150 *numeric_data = NumericData;
7151 *numeric_data_values = NumericDataValues;
7152 *to_lower_data_low = ToLowerDataLow;
7153 *to_lower_data_high = ToLowerDataHigh;
7154 *to_upper_data_low = ToUpperDataLow;
7155 *to_upper_data_high = ToUpperDataHigh;
7158 static gint32
7159 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7161 return method->method->token;
7165 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7166 * and avoid useless allocations.
7168 static MonoArray*
7169 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7171 MonoArray *res;
7172 int i, count = 0;
7173 for (i = 0; i < type->num_mods; ++i) {
7174 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7175 count++;
7177 if (!count)
7178 return NULL;
7179 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7180 count = 0;
7181 for (i = 0; i < type->num_mods; ++i) {
7182 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7183 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7184 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7185 count++;
7188 return res;
7191 static MonoArray*
7192 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7194 MonoType *type = param->ClassImpl->type;
7195 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7196 MonoImage *image = method->method->klass->image;
7197 int pos = param->PositionImpl;
7198 MonoMethodSignature *sig = mono_method_signature (method->method);
7199 if (pos == -1)
7200 type = sig->ret;
7201 else
7202 type = sig->params [pos];
7204 return type_array_from_modifiers (image, type, optional);
7207 static MonoType*
7208 get_property_type (MonoProperty *prop)
7210 MonoMethodSignature *sig;
7211 if (prop->get) {
7212 sig = mono_method_signature (prop->get);
7213 return sig->ret;
7214 } else if (prop->set) {
7215 sig = mono_method_signature (prop->set);
7216 return sig->params [sig->param_count - 1];
7218 return NULL;
7221 static MonoArray*
7222 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7224 MonoType *type = get_property_type (property->property);
7225 MonoImage *image = property->klass->image;
7227 if (!type)
7228 return NULL;
7229 return type_array_from_modifiers (image, type, optional);
7232 static MonoBoolean
7233 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7235 MonoCustomAttrInfo *cinfo;
7236 gboolean found;
7238 cinfo = mono_reflection_get_custom_attrs_info (obj);
7239 if (!cinfo)
7240 return FALSE;
7241 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7242 if (!cinfo->cached)
7243 mono_custom_attrs_free (cinfo);
7244 return found;
7247 static MonoArray*
7248 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7250 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7252 if (mono_loader_get_last_error ()) {
7253 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7254 g_assert_not_reached ();
7255 /* Not reached */
7256 return NULL;
7257 } else {
7258 return res;
7262 static MonoString*
7263 ves_icall_Mono_Runtime_GetDisplayName (void)
7265 char *info;
7266 MonoString *display_name;
7268 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7269 display_name = mono_string_new (mono_domain_get (), info);
7270 g_free (info);
7271 return display_name;
7274 static MonoString*
7275 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7277 MonoString *message;
7278 guint32 ret;
7279 gunichar2 buf[256];
7281 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7282 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7283 buf, 255, NULL);
7284 if (ret == 0) {
7285 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7286 } else {
7287 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7290 return message;
7293 const static guchar
7294 dbase64 [] = {
7295 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7296 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7297 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7298 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7299 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7300 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7301 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7302 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7305 static MonoArray *
7306 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7308 gint ignored;
7309 gint i;
7310 gunichar2 c;
7311 gunichar2 last, prev_last, prev2_last;
7312 gint olength;
7313 MonoArray *result;
7314 guchar *res_ptr;
7315 gint a [4], b [4];
7316 MonoException *exc;
7318 ignored = 0;
7319 last = prev_last = 0, prev2_last = 0;
7320 for (i = 0; i < ilength; i++) {
7321 c = start [i];
7322 if (c >= sizeof (dbase64)) {
7323 exc = mono_exception_from_name_msg (mono_get_corlib (),
7324 "System", "FormatException",
7325 "Invalid character found.");
7326 mono_raise_exception (exc);
7327 } else if (isspace (c)) {
7328 ignored++;
7329 } else {
7330 prev2_last = prev_last;
7331 prev_last = last;
7332 last = c;
7336 olength = ilength - ignored;
7338 if (allowWhitespaceOnly && olength == 0) {
7339 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7342 if ((olength & 3) != 0 || olength <= 0) {
7343 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7344 "FormatException", "Invalid length.");
7345 mono_raise_exception (exc);
7348 if (prev2_last == '=') {
7349 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7350 mono_raise_exception (exc);
7353 olength = (olength * 3) / 4;
7354 if (last == '=')
7355 olength--;
7357 if (prev_last == '=')
7358 olength--;
7360 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7361 res_ptr = mono_array_addr (result, guchar, 0);
7362 for (i = 0; i < ilength; ) {
7363 int k;
7365 for (k = 0; k < 4 && i < ilength;) {
7366 c = start [i++];
7367 if (isspace (c))
7368 continue;
7370 a [k] = (guchar) c;
7371 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7372 exc = mono_exception_from_name_msg (mono_get_corlib (),
7373 "System", "FormatException",
7374 "Invalid character found.");
7375 mono_raise_exception (exc);
7377 k++;
7380 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7381 if (a [2] != '=')
7382 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7383 if (a [3] != '=')
7384 *res_ptr++ = (b [2] << 6) | b [3];
7386 while (i < ilength && isspace (start [i]))
7387 i++;
7390 return result;
7393 static MonoArray *
7394 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7396 MONO_ARCH_SAVE_REGS;
7398 return base64_to_byte_array (mono_string_chars (str),
7399 mono_string_length (str), allowWhitespaceOnly);
7402 static MonoArray *
7403 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7405 MONO_ARCH_SAVE_REGS;
7407 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7408 length, FALSE);
7411 #define ICALL_TYPE(id,name,first)
7412 #define ICALL(id,name,func) Icall_ ## id,
7414 enum {
7415 #include "metadata/icall-def.h"
7416 Icall_last
7419 #undef ICALL_TYPE
7420 #undef ICALL
7421 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7422 #define ICALL(id,name,func)
7423 enum {
7424 #include "metadata/icall-def.h"
7425 Icall_type_num
7428 #undef ICALL_TYPE
7429 #undef ICALL
7430 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7431 #define ICALL(id,name,func)
7432 typedef struct {
7433 guint16 first_icall;
7434 } IcallTypeDesc;
7436 static const IcallTypeDesc
7437 icall_type_descs [] = {
7438 #include "metadata/icall-def.h"
7439 {Icall_last}
7442 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7444 #undef ICALL_TYPE
7445 #define ICALL_TYPE(id,name,first)
7446 #undef ICALL
7448 #ifdef HAVE_ARRAY_ELEM_INIT
7449 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7450 #define MSGSTRFIELD1(line) str##line
7452 static const struct msgstrtn_t {
7453 #define ICALL(id,name,func)
7454 #undef ICALL_TYPE
7455 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7456 #include "metadata/icall-def.h"
7457 #undef ICALL_TYPE
7458 } icall_type_names_str = {
7459 #define ICALL_TYPE(id,name,first) (name),
7460 #include "metadata/icall-def.h"
7461 #undef ICALL_TYPE
7463 static const guint16 icall_type_names_idx [] = {
7464 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7465 #include "metadata/icall-def.h"
7466 #undef ICALL_TYPE
7468 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7470 static const struct msgstr_t {
7471 #undef ICALL
7472 #define ICALL_TYPE(id,name,first)
7473 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7474 #include "metadata/icall-def.h"
7475 #undef ICALL
7476 } icall_names_str = {
7477 #define ICALL(id,name,func) (name),
7478 #include "metadata/icall-def.h"
7479 #undef ICALL
7481 static const guint16 icall_names_idx [] = {
7482 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7483 #include "metadata/icall-def.h"
7484 #undef ICALL
7486 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7488 #else
7490 #undef ICALL_TYPE
7491 #undef ICALL
7492 #define ICALL_TYPE(id,name,first) name,
7493 #define ICALL(id,name,func)
7494 static const char* const
7495 icall_type_names [] = {
7496 #include "metadata/icall-def.h"
7497 NULL
7500 #define icall_type_name_get(id) (icall_type_names [(id)])
7502 #undef ICALL_TYPE
7503 #undef ICALL
7504 #define ICALL_TYPE(id,name,first)
7505 #define ICALL(id,name,func) name,
7506 static const char* const
7507 icall_names [] = {
7508 #include "metadata/icall-def.h"
7509 NULL
7511 #define icall_name_get(id) icall_names [(id)]
7513 #endif /* !HAVE_ARRAY_ELEM_INIT */
7515 #undef ICALL_TYPE
7516 #undef ICALL
7517 #define ICALL_TYPE(id,name,first)
7518 #define ICALL(id,name,func) func,
7519 static const gconstpointer
7520 icall_functions [] = {
7521 #include "metadata/icall-def.h"
7522 NULL
7525 static GHashTable *icall_hash = NULL;
7526 static GHashTable *jit_icall_hash_name = NULL;
7527 static GHashTable *jit_icall_hash_addr = NULL;
7529 void
7530 mono_icall_init (void)
7532 int i = 0;
7534 /* check that tables are sorted: disable in release */
7535 if (TRUE) {
7536 int j;
7537 const char *prev_class = NULL;
7538 const char *prev_method;
7540 for (i = 0; i < Icall_type_num; ++i) {
7541 const IcallTypeDesc *desc;
7542 int num_icalls;
7543 prev_method = NULL;
7544 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7545 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7546 prev_class = icall_type_name_get (i);
7547 desc = &icall_type_descs [i];
7548 num_icalls = icall_desc_num_icalls (desc);
7549 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7550 for (j = 0; j < num_icalls; ++j) {
7551 const char *methodn = icall_name_get (desc->first_icall + j);
7552 if (prev_method && strcmp (prev_method, methodn) >= 0)
7553 g_print ("method %s should come before method %s\n", methodn, prev_method);
7554 prev_method = methodn;
7559 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7562 void
7563 mono_icall_cleanup (void)
7565 g_hash_table_destroy (icall_hash);
7566 g_hash_table_destroy (jit_icall_hash_name);
7567 g_hash_table_destroy (jit_icall_hash_addr);
7570 void
7571 mono_add_internal_call (const char *name, gconstpointer method)
7573 mono_loader_lock ();
7575 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7577 mono_loader_unlock ();
7580 #ifdef HAVE_ARRAY_ELEM_INIT
7581 static int
7582 compare_method_imap (const void *key, const void *elem)
7584 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7585 return strcmp (key, method_name);
7588 static gpointer
7589 find_method_icall (const IcallTypeDesc *imap, const char *name)
7591 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7592 if (!nameslot)
7593 return NULL;
7594 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7597 static int
7598 compare_class_imap (const void *key, const void *elem)
7600 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7601 return strcmp (key, class_name);
7604 static const IcallTypeDesc*
7605 find_class_icalls (const char *name)
7607 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7608 if (!nameslot)
7609 return NULL;
7610 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7613 #else
7614 static int
7615 compare_method_imap (const void *key, const void *elem)
7617 const char** method_name = (const char**)elem;
7618 return strcmp (key, *method_name);
7621 static gpointer
7622 find_method_icall (const IcallTypeDesc *imap, const char *name)
7624 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7625 if (!nameslot)
7626 return NULL;
7627 return (gpointer)icall_functions [(nameslot - icall_names)];
7630 static int
7631 compare_class_imap (const void *key, const void *elem)
7633 const char** class_name = (const char**)elem;
7634 return strcmp (key, *class_name);
7637 static const IcallTypeDesc*
7638 find_class_icalls (const char *name)
7640 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7641 if (!nameslot)
7642 return NULL;
7643 return &icall_type_descs [nameslot - icall_type_names];
7646 #endif
7649 * we should probably export this as an helper (handle nested types).
7650 * Returns the number of chars written in buf.
7652 static int
7653 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7655 int nspacelen, cnamelen;
7656 nspacelen = strlen (klass->name_space);
7657 cnamelen = strlen (klass->name);
7658 if (nspacelen + cnamelen + 2 > bufsize)
7659 return 0;
7660 if (nspacelen) {
7661 memcpy (buf, klass->name_space, nspacelen);
7662 buf [nspacelen ++] = '.';
7664 memcpy (buf + nspacelen, klass->name, cnamelen);
7665 buf [nspacelen + cnamelen] = 0;
7666 return nspacelen + cnamelen;
7669 gpointer
7670 mono_lookup_internal_call (MonoMethod *method)
7672 char *sigstart;
7673 char *tmpsig;
7674 char mname [2048];
7675 int typelen = 0, mlen, siglen;
7676 gpointer res;
7677 const IcallTypeDesc *imap;
7679 g_assert (method != NULL);
7681 if (method->is_inflated)
7682 method = ((MonoMethodInflated *) method)->declaring;
7684 if (method->klass->nested_in) {
7685 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7686 if (!pos)
7687 return NULL;
7689 mname [pos++] = '/';
7690 mname [pos] = 0;
7692 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7693 if (!typelen)
7694 return NULL;
7696 typelen += pos;
7697 } else {
7698 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7699 if (!typelen)
7700 return NULL;
7703 imap = find_class_icalls (mname);
7705 mname [typelen] = ':';
7706 mname [typelen + 1] = ':';
7708 mlen = strlen (method->name);
7709 memcpy (mname + typelen + 2, method->name, mlen);
7710 sigstart = mname + typelen + 2 + mlen;
7711 *sigstart = 0;
7713 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7714 siglen = strlen (tmpsig);
7715 if (typelen + mlen + siglen + 6 > sizeof (mname))
7716 return NULL;
7717 sigstart [0] = '(';
7718 memcpy (sigstart + 1, tmpsig, siglen);
7719 sigstart [siglen + 1] = ')';
7720 sigstart [siglen + 2] = 0;
7721 g_free (tmpsig);
7723 mono_loader_lock ();
7725 res = g_hash_table_lookup (icall_hash, mname);
7726 if (res) {
7727 mono_loader_unlock ();
7728 return res;
7730 /* try without signature */
7731 *sigstart = 0;
7732 res = g_hash_table_lookup (icall_hash, mname);
7733 if (res) {
7734 mono_loader_unlock ();
7735 return res;
7738 /* it wasn't found in the static call tables */
7739 if (!imap) {
7740 mono_loader_unlock ();
7741 return NULL;
7743 res = find_method_icall (imap, sigstart - mlen);
7744 if (res) {
7745 mono_loader_unlock ();
7746 return res;
7748 /* try _with_ signature */
7749 *sigstart = '(';
7750 res = find_method_icall (imap, sigstart - mlen);
7751 if (res) {
7752 mono_loader_unlock ();
7753 return res;
7756 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7757 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7758 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7759 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7760 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");
7761 g_print ("If you see other errors or faults after this message they are probably related\n");
7762 g_print ("and you need to fix your mono install first.\n");
7764 mono_loader_unlock ();
7766 return NULL;
7769 static MonoType*
7770 type_from_typename (char *typename)
7772 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7774 if (!strcmp (typename, "int"))
7775 klass = mono_defaults.int_class;
7776 else if (!strcmp (typename, "ptr"))
7777 klass = mono_defaults.int_class;
7778 else if (!strcmp (typename, "void"))
7779 klass = mono_defaults.void_class;
7780 else if (!strcmp (typename, "int32"))
7781 klass = mono_defaults.int32_class;
7782 else if (!strcmp (typename, "uint32"))
7783 klass = mono_defaults.uint32_class;
7784 else if (!strcmp (typename, "int8"))
7785 klass = mono_defaults.sbyte_class;
7786 else if (!strcmp (typename, "uint8"))
7787 klass = mono_defaults.byte_class;
7788 else if (!strcmp (typename, "int16"))
7789 klass = mono_defaults.int16_class;
7790 else if (!strcmp (typename, "uint16"))
7791 klass = mono_defaults.uint16_class;
7792 else if (!strcmp (typename, "long"))
7793 klass = mono_defaults.int64_class;
7794 else if (!strcmp (typename, "ulong"))
7795 klass = mono_defaults.uint64_class;
7796 else if (!strcmp (typename, "float"))
7797 klass = mono_defaults.single_class;
7798 else if (!strcmp (typename, "double"))
7799 klass = mono_defaults.double_class;
7800 else if (!strcmp (typename, "object"))
7801 klass = mono_defaults.object_class;
7802 else if (!strcmp (typename, "obj"))
7803 klass = mono_defaults.object_class;
7804 else if (!strcmp (typename, "string"))
7805 klass = mono_defaults.string_class;
7806 else if (!strcmp (typename, "bool"))
7807 klass = mono_defaults.boolean_class;
7808 else if (!strcmp (typename, "boolean"))
7809 klass = mono_defaults.boolean_class;
7810 else {
7811 g_error ("%s", typename);
7812 g_assert_not_reached ();
7814 return &klass->byval_arg;
7817 MonoMethodSignature*
7818 mono_create_icall_signature (const char *sigstr)
7820 gchar **parts;
7821 int i, len;
7822 gchar **tmp;
7823 MonoMethodSignature *res;
7825 mono_loader_lock ();
7826 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7827 if (res) {
7828 mono_loader_unlock ();
7829 return res;
7832 parts = g_strsplit (sigstr, " ", 256);
7834 tmp = parts;
7835 len = 0;
7836 while (*tmp) {
7837 len ++;
7838 tmp ++;
7841 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7842 res->pinvoke = 1;
7844 #ifdef HOST_WIN32
7846 * Under windows, the default pinvoke calling convention is STDCALL but
7847 * we need CDECL.
7849 res->call_convention = MONO_CALL_C;
7850 #endif
7852 res->ret = type_from_typename (parts [0]);
7853 for (i = 1; i < len; ++i) {
7854 res->params [i - 1] = type_from_typename (parts [i]);
7857 g_strfreev (parts);
7859 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7861 mono_loader_unlock ();
7863 return res;
7866 MonoJitICallInfo *
7867 mono_find_jit_icall_by_name (const char *name)
7869 MonoJitICallInfo *info;
7870 g_assert (jit_icall_hash_name);
7872 mono_loader_lock ();
7873 info = g_hash_table_lookup (jit_icall_hash_name, name);
7874 mono_loader_unlock ();
7875 return info;
7878 MonoJitICallInfo *
7879 mono_find_jit_icall_by_addr (gconstpointer addr)
7881 MonoJitICallInfo *info;
7882 g_assert (jit_icall_hash_addr);
7884 mono_loader_lock ();
7885 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7886 mono_loader_unlock ();
7888 return info;
7892 * mono_get_jit_icall_info:
7894 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7895 * caller should access it while holding the loader lock.
7897 GHashTable*
7898 mono_get_jit_icall_info (void)
7900 return jit_icall_hash_name;
7903 void
7904 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7906 mono_loader_lock ();
7907 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7908 mono_loader_unlock ();
7911 MonoJitICallInfo *
7912 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7914 MonoJitICallInfo *info;
7916 g_assert (func);
7917 g_assert (name);
7919 mono_loader_lock ();
7921 if (!jit_icall_hash_name) {
7922 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7923 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7926 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7927 g_warning ("jit icall already defined \"%s\"\n", name);
7928 g_assert_not_reached ();
7931 info = g_new0 (MonoJitICallInfo, 1);
7933 info->name = name;
7934 info->func = func;
7935 info->sig = sig;
7937 if (is_save) {
7938 info->wrapper = func;
7939 } else {
7940 info->wrapper = NULL;
7943 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7944 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7946 mono_loader_unlock ();
7947 return info;