PageRenderTime 48ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 2ms

/mono/metadata/icall.c

https://bitbucket.org/danipen/mono
C | 8423 lines | 6671 code | 1380 blank | 372 comment | 1506 complexity | c832cf30aabe58006a1dd66b6c1be0bc MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. /*
  2. * icall.c:
  3. *
  4. * Authors:
  5. * Dietmar Maurer (dietmar@ximian.com)
  6. * Paolo Molaro (lupus@ximian.com)
  7. * Patrik Torstensson (patrik.torstensson@labs2.com)
  8. *
  9. * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  10. * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  11. * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
  12. */
  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
  30. #if defined (HAVE_WCHAR_H)
  31. #include <wchar.h>
  32. #endif
  33. #include "mono/utils/mono-membar.h"
  34. #include <mono/metadata/object.h>
  35. #include <mono/metadata/threads.h>
  36. #include <mono/metadata/threads-types.h>
  37. #include <mono/metadata/threadpool.h>
  38. #include <mono/metadata/monitor.h>
  39. #include <mono/metadata/reflection.h>
  40. #include <mono/metadata/assembly.h>
  41. #include <mono/metadata/tabledefs.h>
  42. #include <mono/metadata/exception.h>
  43. #include <mono/metadata/file-io.h>
  44. #include <mono/metadata/console-io.h>
  45. #include <mono/metadata/socket-io.h>
  46. #include <mono/metadata/mono-endian.h>
  47. #include <mono/metadata/tokentype.h>
  48. #include <mono/metadata/domain-internals.h>
  49. #include <mono/metadata/metadata-internals.h>
  50. #include <mono/metadata/class-internals.h>
  51. #include <mono/metadata/marshal.h>
  52. #include <mono/metadata/gc-internal.h>
  53. #include <mono/metadata/mono-gc.h>
  54. #include <mono/metadata/rand.h>
  55. #include <mono/metadata/sysmath.h>
  56. #include <mono/metadata/string-icalls.h>
  57. #include <mono/metadata/debug-helpers.h>
  58. #include <mono/metadata/process.h>
  59. #include <mono/metadata/environment.h>
  60. #include <mono/metadata/profiler-private.h>
  61. #include <mono/metadata/locales.h>
  62. #include <mono/metadata/filewatcher.h>
  63. #include <mono/metadata/char-conversions.h>
  64. #include <mono/metadata/security.h>
  65. #include <mono/metadata/mono-config.h>
  66. #include <mono/metadata/cil-coff.h>
  67. #include <mono/metadata/number-formatter.h>
  68. #include <mono/metadata/security-manager.h>
  69. #include <mono/metadata/security-core-clr.h>
  70. #include <mono/metadata/mono-perfcounters.h>
  71. #include <mono/metadata/mono-debug.h>
  72. #include <mono/metadata/mono-ptr-array.h>
  73. #include <mono/metadata/verify-internals.h>
  74. #include <mono/io-layer/io-layer.h>
  75. #include <mono/utils/strtod.h>
  76. #include <mono/utils/monobitset.h>
  77. #include <mono/utils/mono-time.h>
  78. #include <mono/utils/mono-proclib.h>
  79. #include <mono/utils/mono-string.h>
  80. #include <mono/utils/mono-error-internals.h>
  81. #include <mono/utils/mono-mmap.h>
  82. #include <mono/utils/mono-io-portability.h>
  83. #include <mono/utils/mono-digest.h>
  84. #if defined (HOST_WIN32)
  85. #include <windows.h>
  86. #include <shlobj.h>
  87. #endif
  88. #include "decimal.h"
  89. extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
  90. ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
  91. static MonoArray*
  92. type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
  93. static inline MonoBoolean
  94. is_generic_parameter (MonoType *type)
  95. {
  96. return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
  97. }
  98. static void
  99. mono_class_init_or_throw (MonoClass *klass)
  100. {
  101. if (!mono_class_init (klass))
  102. mono_raise_exception (mono_class_get_exception_for_failure (klass));
  103. }
  104. /*
  105. * We expect a pointer to a char, not a string
  106. */
  107. ICALL_EXPORT gboolean
  108. mono_double_ParseImpl (char *ptr, double *result)
  109. {
  110. gchar *endptr = NULL;
  111. *result = 0.0;
  112. MONO_ARCH_SAVE_REGS;
  113. #ifdef __arm__
  114. if (*ptr)
  115. *result = strtod (ptr, &endptr);
  116. #else
  117. if (*ptr){
  118. /* mono_strtod () is not thread-safe */
  119. EnterCriticalSection (&mono_strtod_mutex);
  120. *result = mono_strtod (ptr, &endptr);
  121. LeaveCriticalSection (&mono_strtod_mutex);
  122. }
  123. #endif
  124. if (!*ptr || (endptr && *endptr))
  125. return FALSE;
  126. return TRUE;
  127. }
  128. ICALL_EXPORT MonoObject *
  129. ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
  130. {
  131. MonoClass *ac;
  132. MonoArray *ao;
  133. gint32 esize;
  134. gpointer *ea;
  135. MONO_ARCH_SAVE_REGS;
  136. ao = (MonoArray *)this;
  137. ac = (MonoClass *)ao->obj.vtable->klass;
  138. esize = mono_array_element_size (ac);
  139. ea = (gpointer*)((char*)ao->vector + (pos * esize));
  140. if (ac->element_class->valuetype)
  141. return mono_value_box (this->vtable->domain, ac->element_class, ea);
  142. else
  143. return *ea;
  144. }
  145. ICALL_EXPORT MonoObject *
  146. ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
  147. {
  148. MonoClass *ac, *ic;
  149. MonoArray *ao, *io;
  150. gint32 i, pos, *ind;
  151. MONO_ARCH_SAVE_REGS;
  152. MONO_CHECK_ARG_NULL (idxs);
  153. io = (MonoArray *)idxs;
  154. ic = (MonoClass *)io->obj.vtable->klass;
  155. ao = (MonoArray *)this;
  156. ac = (MonoClass *)ao->obj.vtable->klass;
  157. g_assert (ic->rank == 1);
  158. if (io->bounds != NULL || io->max_length != ac->rank)
  159. mono_raise_exception (mono_get_exception_argument (NULL, NULL));
  160. ind = (gint32 *)io->vector;
  161. if (ao->bounds == NULL) {
  162. if (*ind < 0 || *ind >= ao->max_length)
  163. mono_raise_exception (mono_get_exception_index_out_of_range ());
  164. return ves_icall_System_Array_GetValueImpl (this, *ind);
  165. }
  166. for (i = 0; i < ac->rank; i++)
  167. if ((ind [i] < ao->bounds [i].lower_bound) ||
  168. (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
  169. mono_raise_exception (mono_get_exception_index_out_of_range ());
  170. pos = ind [0] - ao->bounds [0].lower_bound;
  171. for (i = 1; i < ac->rank; i++)
  172. pos = pos*ao->bounds [i].length + ind [i] -
  173. ao->bounds [i].lower_bound;
  174. return ves_icall_System_Array_GetValueImpl (this, pos);
  175. }
  176. ICALL_EXPORT void
  177. ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
  178. {
  179. MonoClass *ac, *vc, *ec;
  180. gint32 esize, vsize;
  181. gpointer *ea, *va;
  182. int et, vt;
  183. guint64 u64 = 0;
  184. gint64 i64 = 0;
  185. gdouble r64 = 0;
  186. MONO_ARCH_SAVE_REGS;
  187. if (value)
  188. vc = value->vtable->klass;
  189. else
  190. vc = NULL;
  191. ac = this->obj.vtable->klass;
  192. ec = ac->element_class;
  193. esize = mono_array_element_size (ac);
  194. ea = (gpointer*)((char*)this->vector + (pos * esize));
  195. va = (gpointer*)((char*)value + sizeof (MonoObject));
  196. if (mono_class_is_nullable (ec)) {
  197. mono_nullable_init ((guint8*)ea, value, ec);
  198. return;
  199. }
  200. if (!value) {
  201. mono_gc_bzero (ea, esize);
  202. return;
  203. }
  204. #define NO_WIDENING_CONVERSION G_STMT_START{\
  205. mono_raise_exception (mono_get_exception_argument ( \
  206. "value", "not a widening conversion")); \
  207. }G_STMT_END
  208. #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
  209. if (esize < vsize + (extra)) \
  210. mono_raise_exception (mono_get_exception_argument ( \
  211. "value", "not a widening conversion")); \
  212. }G_STMT_END
  213. #define INVALID_CAST G_STMT_START{ \
  214. mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
  215. mono_raise_exception (mono_get_exception_invalid_cast ()); \
  216. }G_STMT_END
  217. /* Check element (destination) type. */
  218. switch (ec->byval_arg.type) {
  219. case MONO_TYPE_STRING:
  220. switch (vc->byval_arg.type) {
  221. case MONO_TYPE_STRING:
  222. break;
  223. default:
  224. INVALID_CAST;
  225. }
  226. break;
  227. case MONO_TYPE_BOOLEAN:
  228. switch (vc->byval_arg.type) {
  229. case MONO_TYPE_BOOLEAN:
  230. break;
  231. case MONO_TYPE_CHAR:
  232. case MONO_TYPE_U1:
  233. case MONO_TYPE_U2:
  234. case MONO_TYPE_U4:
  235. case MONO_TYPE_U8:
  236. case MONO_TYPE_I1:
  237. case MONO_TYPE_I2:
  238. case MONO_TYPE_I4:
  239. case MONO_TYPE_I8:
  240. case MONO_TYPE_R4:
  241. case MONO_TYPE_R8:
  242. NO_WIDENING_CONVERSION;
  243. default:
  244. INVALID_CAST;
  245. }
  246. break;
  247. }
  248. if (!ec->valuetype) {
  249. if (!mono_object_isinst (value, ec))
  250. INVALID_CAST;
  251. mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
  252. return;
  253. }
  254. if (mono_object_isinst (value, ec)) {
  255. if (ec->has_references)
  256. mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
  257. else
  258. mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
  259. return;
  260. }
  261. if (!vc->valuetype)
  262. INVALID_CAST;
  263. vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
  264. et = ec->byval_arg.type;
  265. if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
  266. et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
  267. vt = vc->byval_arg.type;
  268. if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
  269. vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
  270. #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
  271. switch (vt) { \
  272. case MONO_TYPE_U1: \
  273. case MONO_TYPE_U2: \
  274. case MONO_TYPE_U4: \
  275. case MONO_TYPE_U8: \
  276. case MONO_TYPE_CHAR: \
  277. CHECK_WIDENING_CONVERSION(0); \
  278. *(etype *) ea = (etype) u64; \
  279. return; \
  280. /* You can't assign a signed value to an unsigned array. */ \
  281. case MONO_TYPE_I1: \
  282. case MONO_TYPE_I2: \
  283. case MONO_TYPE_I4: \
  284. case MONO_TYPE_I8: \
  285. /* You can't assign a floating point number to an integer array. */ \
  286. case MONO_TYPE_R4: \
  287. case MONO_TYPE_R8: \
  288. NO_WIDENING_CONVERSION; \
  289. } \
  290. }G_STMT_END
  291. #define ASSIGN_SIGNED(etype) G_STMT_START{\
  292. switch (vt) { \
  293. case MONO_TYPE_I1: \
  294. case MONO_TYPE_I2: \
  295. case MONO_TYPE_I4: \
  296. case MONO_TYPE_I8: \
  297. CHECK_WIDENING_CONVERSION(0); \
  298. *(etype *) ea = (etype) i64; \
  299. return; \
  300. /* You can assign an unsigned value to a signed array if the array's */ \
  301. /* element size is larger than the value size. */ \
  302. case MONO_TYPE_U1: \
  303. case MONO_TYPE_U2: \
  304. case MONO_TYPE_U4: \
  305. case MONO_TYPE_U8: \
  306. case MONO_TYPE_CHAR: \
  307. CHECK_WIDENING_CONVERSION(1); \
  308. *(etype *) ea = (etype) u64; \
  309. return; \
  310. /* You can't assign a floating point number to an integer array. */ \
  311. case MONO_TYPE_R4: \
  312. case MONO_TYPE_R8: \
  313. NO_WIDENING_CONVERSION; \
  314. } \
  315. }G_STMT_END
  316. #define ASSIGN_REAL(etype) G_STMT_START{\
  317. switch (vt) { \
  318. case MONO_TYPE_R4: \
  319. case MONO_TYPE_R8: \
  320. CHECK_WIDENING_CONVERSION(0); \
  321. *(etype *) ea = (etype) r64; \
  322. return; \
  323. /* All integer values fit into a floating point array, so we don't */ \
  324. /* need to CHECK_WIDENING_CONVERSION here. */ \
  325. case MONO_TYPE_I1: \
  326. case MONO_TYPE_I2: \
  327. case MONO_TYPE_I4: \
  328. case MONO_TYPE_I8: \
  329. *(etype *) ea = (etype) i64; \
  330. return; \
  331. case MONO_TYPE_U1: \
  332. case MONO_TYPE_U2: \
  333. case MONO_TYPE_U4: \
  334. case MONO_TYPE_U8: \
  335. case MONO_TYPE_CHAR: \
  336. *(etype *) ea = (etype) u64; \
  337. return; \
  338. } \
  339. }G_STMT_END
  340. switch (vt) {
  341. case MONO_TYPE_U1:
  342. u64 = *(guint8 *) va;
  343. break;
  344. case MONO_TYPE_U2:
  345. u64 = *(guint16 *) va;
  346. break;
  347. case MONO_TYPE_U4:
  348. u64 = *(guint32 *) va;
  349. break;
  350. case MONO_TYPE_U8:
  351. u64 = *(guint64 *) va;
  352. break;
  353. case MONO_TYPE_I1:
  354. i64 = *(gint8 *) va;
  355. break;
  356. case MONO_TYPE_I2:
  357. i64 = *(gint16 *) va;
  358. break;
  359. case MONO_TYPE_I4:
  360. i64 = *(gint32 *) va;
  361. break;
  362. case MONO_TYPE_I8:
  363. i64 = *(gint64 *) va;
  364. break;
  365. case MONO_TYPE_R4:
  366. r64 = *(gfloat *) va;
  367. break;
  368. case MONO_TYPE_R8:
  369. r64 = *(gdouble *) va;
  370. break;
  371. case MONO_TYPE_CHAR:
  372. u64 = *(guint16 *) va;
  373. break;
  374. case MONO_TYPE_BOOLEAN:
  375. /* Boolean is only compatible with itself. */
  376. switch (et) {
  377. case MONO_TYPE_CHAR:
  378. case MONO_TYPE_U1:
  379. case MONO_TYPE_U2:
  380. case MONO_TYPE_U4:
  381. case MONO_TYPE_U8:
  382. case MONO_TYPE_I1:
  383. case MONO_TYPE_I2:
  384. case MONO_TYPE_I4:
  385. case MONO_TYPE_I8:
  386. case MONO_TYPE_R4:
  387. case MONO_TYPE_R8:
  388. NO_WIDENING_CONVERSION;
  389. default:
  390. INVALID_CAST;
  391. }
  392. break;
  393. }
  394. /* If we can't do a direct copy, let's try a widening conversion. */
  395. switch (et) {
  396. case MONO_TYPE_CHAR:
  397. ASSIGN_UNSIGNED (guint16);
  398. case MONO_TYPE_U1:
  399. ASSIGN_UNSIGNED (guint8);
  400. case MONO_TYPE_U2:
  401. ASSIGN_UNSIGNED (guint16);
  402. case MONO_TYPE_U4:
  403. ASSIGN_UNSIGNED (guint32);
  404. case MONO_TYPE_U8:
  405. ASSIGN_UNSIGNED (guint64);
  406. case MONO_TYPE_I1:
  407. ASSIGN_SIGNED (gint8);
  408. case MONO_TYPE_I2:
  409. ASSIGN_SIGNED (gint16);
  410. case MONO_TYPE_I4:
  411. ASSIGN_SIGNED (gint32);
  412. case MONO_TYPE_I8:
  413. ASSIGN_SIGNED (gint64);
  414. case MONO_TYPE_R4:
  415. ASSIGN_REAL (gfloat);
  416. case MONO_TYPE_R8:
  417. ASSIGN_REAL (gdouble);
  418. }
  419. INVALID_CAST;
  420. /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
  421. return;
  422. #undef INVALID_CAST
  423. #undef NO_WIDENING_CONVERSION
  424. #undef CHECK_WIDENING_CONVERSION
  425. #undef ASSIGN_UNSIGNED
  426. #undef ASSIGN_SIGNED
  427. #undef ASSIGN_REAL
  428. }
  429. ICALL_EXPORT void
  430. ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
  431. MonoArray *idxs)
  432. {
  433. MonoClass *ac, *ic;
  434. gint32 i, pos, *ind;
  435. MONO_ARCH_SAVE_REGS;
  436. MONO_CHECK_ARG_NULL (idxs);
  437. ic = idxs->obj.vtable->klass;
  438. ac = this->obj.vtable->klass;
  439. g_assert (ic->rank == 1);
  440. if (idxs->bounds != NULL || idxs->max_length != ac->rank)
  441. mono_raise_exception (mono_get_exception_argument (NULL, NULL));
  442. ind = (gint32 *)idxs->vector;
  443. if (this->bounds == NULL) {
  444. if (*ind < 0 || *ind >= this->max_length)
  445. mono_raise_exception (mono_get_exception_index_out_of_range ());
  446. ves_icall_System_Array_SetValueImpl (this, value, *ind);
  447. return;
  448. }
  449. for (i = 0; i < ac->rank; i++)
  450. if ((ind [i] < this->bounds [i].lower_bound) ||
  451. (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
  452. mono_raise_exception (mono_get_exception_index_out_of_range ());
  453. pos = ind [0] - this->bounds [0].lower_bound;
  454. for (i = 1; i < ac->rank; i++)
  455. pos = pos * this->bounds [i].length + ind [i] -
  456. this->bounds [i].lower_bound;
  457. ves_icall_System_Array_SetValueImpl (this, value, pos);
  458. }
  459. ICALL_EXPORT MonoArray *
  460. ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
  461. {
  462. MonoClass *aklass, *klass;
  463. MonoArray *array;
  464. uintptr_t *sizes, i;
  465. gboolean bounded = FALSE;
  466. MONO_ARCH_SAVE_REGS;
  467. MONO_CHECK_ARG_NULL (type);
  468. MONO_CHECK_ARG_NULL (lengths);
  469. MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
  470. if (bounds)
  471. MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
  472. for (i = 0; i < mono_array_length (lengths); i++)
  473. if (mono_array_get (lengths, gint32, i) < 0)
  474. mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
  475. klass = mono_class_from_mono_type (type->type);
  476. mono_class_init_or_throw (klass);
  477. if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
  478. /* vectors are not the same as one dimensional arrays with no-zero bounds */
  479. bounded = TRUE;
  480. else
  481. bounded = FALSE;
  482. aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
  483. sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
  484. for (i = 0; i < aklass->rank; ++i) {
  485. sizes [i] = mono_array_get (lengths, guint32, i);
  486. if (bounds)
  487. sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
  488. else
  489. sizes [i + aklass->rank] = 0;
  490. }
  491. array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
  492. return array;
  493. }
  494. ICALL_EXPORT MonoArray *
  495. ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
  496. {
  497. MonoClass *aklass, *klass;
  498. MonoArray *array;
  499. uintptr_t *sizes, i;
  500. gboolean bounded = FALSE;
  501. MONO_ARCH_SAVE_REGS;
  502. MONO_CHECK_ARG_NULL (type);
  503. MONO_CHECK_ARG_NULL (lengths);
  504. MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
  505. if (bounds)
  506. MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
  507. for (i = 0; i < mono_array_length (lengths); i++)
  508. if ((mono_array_get (lengths, gint64, i) < 0) ||
  509. (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
  510. mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
  511. klass = mono_class_from_mono_type (type->type);
  512. mono_class_init_or_throw (klass);
  513. if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
  514. /* vectors are not the same as one dimensional arrays with no-zero bounds */
  515. bounded = TRUE;
  516. else
  517. bounded = FALSE;
  518. aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
  519. sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
  520. for (i = 0; i < aklass->rank; ++i) {
  521. sizes [i] = mono_array_get (lengths, guint64, i);
  522. if (bounds)
  523. sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
  524. else
  525. sizes [i + aklass->rank] = 0;
  526. }
  527. array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
  528. return array;
  529. }
  530. ICALL_EXPORT gint32
  531. ves_icall_System_Array_GetRank (MonoObject *this)
  532. {
  533. MONO_ARCH_SAVE_REGS;
  534. return this->vtable->klass->rank;
  535. }
  536. ICALL_EXPORT gint32
  537. ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
  538. {
  539. gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
  540. uintptr_t length;
  541. MONO_ARCH_SAVE_REGS;
  542. if ((dimension < 0) || (dimension >= rank))
  543. mono_raise_exception (mono_get_exception_index_out_of_range ());
  544. if (this->bounds == NULL)
  545. length = this->max_length;
  546. else
  547. length = this->bounds [dimension].length;
  548. #ifdef MONO_BIG_ARRAYS
  549. if (length > G_MAXINT32)
  550. mono_raise_exception (mono_get_exception_overflow ());
  551. #endif
  552. return length;
  553. }
  554. ICALL_EXPORT gint64
  555. ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
  556. {
  557. gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
  558. MONO_ARCH_SAVE_REGS;
  559. if ((dimension < 0) || (dimension >= rank))
  560. mono_raise_exception (mono_get_exception_index_out_of_range ());
  561. if (this->bounds == NULL)
  562. return this->max_length;
  563. return this->bounds [dimension].length;
  564. }
  565. ICALL_EXPORT gint32
  566. ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
  567. {
  568. gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
  569. MONO_ARCH_SAVE_REGS;
  570. if ((dimension < 0) || (dimension >= rank))
  571. mono_raise_exception (mono_get_exception_index_out_of_range ());
  572. if (this->bounds == NULL)
  573. return 0;
  574. return this->bounds [dimension].lower_bound;
  575. }
  576. ICALL_EXPORT void
  577. ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
  578. {
  579. int sz = mono_array_element_size (mono_object_class (arr));
  580. mono_gc_bzero (mono_array_addr_with_size (arr, sz, idx), length * sz);
  581. }
  582. ICALL_EXPORT gboolean
  583. ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
  584. {
  585. int element_size;
  586. void * dest_addr;
  587. void * source_addr;
  588. MonoClass *src_class;
  589. MonoClass *dest_class;
  590. MONO_ARCH_SAVE_REGS;
  591. if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
  592. return FALSE;
  593. if (source->bounds || dest->bounds)
  594. return FALSE;
  595. /* there's no integer overflow since mono_array_length returns an unsigned integer */
  596. if ((dest_idx + length > mono_array_length (dest)) ||
  597. (source_idx + length > mono_array_length (source)))
  598. return FALSE;
  599. src_class = source->obj.vtable->klass->element_class;
  600. dest_class = dest->obj.vtable->klass->element_class;
  601. /*
  602. * Handle common cases.
  603. */
  604. /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
  605. if (src_class == mono_defaults.object_class && dest_class->valuetype) {
  606. // FIXME: This is racy
  607. return FALSE;
  608. /*
  609. int i;
  610. int has_refs = dest_class->has_references;
  611. for (i = source_idx; i < source_idx + length; ++i) {
  612. MonoObject *elem = mono_array_get (source, MonoObject*, i);
  613. if (elem && !mono_object_isinst (elem, dest_class))
  614. return FALSE;
  615. }
  616. element_size = mono_array_element_size (dest->obj.vtable->klass);
  617. memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
  618. for (i = 0; i < length; ++i) {
  619. MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
  620. void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
  621. if (!elem)
  622. continue;
  623. if (has_refs)
  624. mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
  625. else
  626. memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
  627. }
  628. return TRUE;
  629. */
  630. }
  631. /* Check if we're copying a char[] <==> (u)short[] */
  632. if (src_class != dest_class) {
  633. if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
  634. return FALSE;
  635. if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
  636. ;
  637. /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
  638. else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
  639. // FIXME: This is racy
  640. return FALSE;
  641. /*
  642. int i;
  643. for (i = source_idx; i < source_idx + length; ++i) {
  644. MonoObject *elem = mono_array_get (source, MonoObject*, i);
  645. if (elem && !mono_object_isinst (elem, dest_class))
  646. return FALSE;
  647. }
  648. */
  649. } else
  650. return FALSE;
  651. }
  652. if (dest_class->valuetype) {
  653. element_size = mono_array_element_size (source->obj.vtable->klass);
  654. source_addr = mono_array_addr_with_size (source, element_size, source_idx);
  655. if (dest_class->has_references) {
  656. mono_value_copy_array (dest, dest_idx, source_addr, length);
  657. } else {
  658. dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
  659. mono_gc_memmove (dest_addr, source_addr, element_size * length);
  660. }
  661. } else {
  662. mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
  663. }
  664. return TRUE;
  665. }
  666. ICALL_EXPORT void
  667. ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
  668. {
  669. MonoClass *ac;
  670. MonoArray *ao;
  671. gint32 esize;
  672. gpointer *ea;
  673. MONO_ARCH_SAVE_REGS;
  674. ao = (MonoArray *)this;
  675. ac = (MonoClass *)ao->obj.vtable->klass;
  676. esize = mono_array_element_size (ac);
  677. ea = (gpointer*)((char*)ao->vector + (pos * esize));
  678. mono_gc_memmove (value, ea, esize);
  679. }
  680. ICALL_EXPORT void
  681. ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
  682. {
  683. MonoClass *ac, *ec;
  684. MonoArray *ao;
  685. gint32 esize;
  686. gpointer *ea;
  687. MONO_ARCH_SAVE_REGS;
  688. ao = (MonoArray *)this;
  689. ac = (MonoClass *)ao->obj.vtable->klass;
  690. ec = ac->element_class;
  691. esize = mono_array_element_size (ac);
  692. ea = (gpointer*)((char*)ao->vector + (pos * esize));
  693. if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
  694. g_assert (esize == sizeof (gpointer));
  695. mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
  696. } else {
  697. g_assert (ec->inited);
  698. g_assert (esize == mono_class_value_size (ec, NULL));
  699. if (ec->has_references)
  700. mono_gc_wbarrier_value_copy (ea, value, 1, ec);
  701. else
  702. mono_gc_memmove (ea, value, esize);
  703. }
  704. }
  705. ICALL_EXPORT void
  706. ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
  707. {
  708. MonoClass *klass = array->obj.vtable->klass;
  709. guint32 size = mono_array_element_size (klass);
  710. MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
  711. int align;
  712. const char *field_data;
  713. if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
  714. MonoException *exc = mono_get_exception_argument("array",
  715. "Cannot initialize array of non-primitive type.");
  716. mono_raise_exception (exc);
  717. }
  718. if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
  719. MonoException *exc = mono_get_exception_argument("field_handle",
  720. "Field doesn't have an RVA");
  721. mono_raise_exception (exc);
  722. }
  723. size *= array->max_length;
  724. field_data = mono_field_get_data (field_handle);
  725. if (size > mono_type_size (field_handle->type, &align)) {
  726. MonoException *exc = mono_get_exception_argument("field_handle",
  727. "Field not large enough to fill array");
  728. mono_raise_exception (exc);
  729. }
  730. #if G_BYTE_ORDER != G_LITTLE_ENDIAN
  731. #define SWAP(n) {\
  732. guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
  733. guint ## n *src = (guint ## n *) field_data; \
  734. guint ## n *end = (guint ## n *)((char*)src + size); \
  735. \
  736. for (; src < end; data++, src++) { \
  737. *data = read ## n (src); \
  738. } \
  739. }
  740. /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
  741. switch (type->type) {
  742. case MONO_TYPE_CHAR:
  743. case MONO_TYPE_I2:
  744. case MONO_TYPE_U2:
  745. SWAP (16);
  746. break;
  747. case MONO_TYPE_I4:
  748. case MONO_TYPE_U4:
  749. case MONO_TYPE_R4:
  750. SWAP (32);
  751. break;
  752. case MONO_TYPE_I8:
  753. case MONO_TYPE_U8:
  754. case MONO_TYPE_R8:
  755. SWAP (64);
  756. break;
  757. default:
  758. memcpy (mono_array_addr (array, char, 0), field_data, size);
  759. break;
  760. }
  761. #else
  762. memcpy (mono_array_addr (array, char, 0), field_data, size);
  763. #ifdef ARM_FPU_FPA
  764. if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
  765. gint i;
  766. double tmp;
  767. double *data = (double*)mono_array_addr (array, double, 0);
  768. for (i = 0; i < size; i++, data++) {
  769. readr8 (data, &tmp);
  770. *data = tmp;
  771. }
  772. }
  773. #endif
  774. #endif
  775. }
  776. ICALL_EXPORT gint
  777. ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
  778. {
  779. MONO_ARCH_SAVE_REGS;
  780. return offsetof (MonoString, chars);
  781. }
  782. ICALL_EXPORT MonoObject *
  783. ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
  784. {
  785. MONO_ARCH_SAVE_REGS;
  786. if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
  787. return obj;
  788. else
  789. return mono_object_clone (obj);
  790. }
  791. ICALL_EXPORT void
  792. ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
  793. {
  794. MonoClass *klass;
  795. MonoVTable *vtable;
  796. MONO_CHECK_ARG_NULL (handle);
  797. klass = mono_class_from_mono_type (handle);
  798. MONO_CHECK_ARG (handle, klass);
  799. vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
  800. /* This will call the type constructor */
  801. mono_runtime_class_init (vtable);
  802. }
  803. ICALL_EXPORT void
  804. ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
  805. {
  806. MONO_ARCH_SAVE_REGS;
  807. mono_image_check_for_module_cctor (image);
  808. if (image->has_module_cctor) {
  809. MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
  810. /*It's fine to raise the exception here*/
  811. mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
  812. }
  813. }
  814. ICALL_EXPORT MonoBoolean
  815. ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
  816. {
  817. guint8 *stack_addr;
  818. guint8 *current;
  819. size_t stack_size;
  820. /* later make this configurable and per-arch */
  821. int min_size = 4096 * 4 * sizeof (void*);
  822. mono_thread_get_stack_bounds (&stack_addr, &stack_size);
  823. /* if we have no info we are optimistic and assume there is enough room */
  824. if (!stack_addr)
  825. return TRUE;
  826. current = (guint8 *)&stack_addr;
  827. if (current > stack_addr) {
  828. if ((current - stack_addr) < min_size)
  829. return FALSE;
  830. } else {
  831. if (current - (stack_addr - stack_size) < min_size)
  832. return FALSE;
  833. }
  834. return TRUE;
  835. }
  836. ICALL_EXPORT MonoObject *
  837. ves_icall_System_Object_MemberwiseClone (MonoObject *this)
  838. {
  839. MONO_ARCH_SAVE_REGS;
  840. return mono_object_clone (this);
  841. }
  842. ICALL_EXPORT gint32
  843. ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
  844. {
  845. MonoClass *klass;
  846. MonoObject **values = NULL;
  847. MonoObject *o;
  848. int count = 0;
  849. gint32 result = 0;
  850. MonoClassField* field;
  851. gpointer iter;
  852. MONO_ARCH_SAVE_REGS;
  853. klass = mono_object_class (this);
  854. if (mono_class_num_fields (klass) == 0)
  855. return mono_object_hash (this);
  856. /*
  857. * Compute the starting value of the hashcode for fields of primitive
  858. * types, and return the remaining fields in an array to the managed side.
  859. * This way, we can avoid costly reflection operations in managed code.
  860. */
  861. iter = NULL;
  862. while ((field = mono_class_get_fields (klass, &iter))) {
  863. if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
  864. continue;
  865. if (mono_field_is_deleted (field))
  866. continue;
  867. /* FIXME: Add more types */
  868. switch (field->type->type) {
  869. case MONO_TYPE_I4:
  870. result ^= *(gint32*)((guint8*)this + field->offset);
  871. break;
  872. case MONO_TYPE_STRING: {
  873. MonoString *s;
  874. s = *(MonoString**)((guint8*)this + field->offset);
  875. if (s != NULL)
  876. result ^= mono_string_hash (s);
  877. break;
  878. }
  879. default:
  880. if (!values)
  881. values = g_newa (MonoObject*, mono_class_num_fields (klass));
  882. o = mono_field_get_value_object (mono_object_domain (this), field, this);
  883. values [count++] = o;
  884. }
  885. }
  886. if (values) {
  887. int i;
  888. mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
  889. for (i = 0; i < count; ++i)
  890. mono_array_setref (*fields, i, values [i]);
  891. } else {
  892. *fields = NULL;
  893. }
  894. return result;
  895. }
  896. ICALL_EXPORT MonoBoolean
  897. ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
  898. {
  899. MonoClass *klass;
  900. MonoObject **values = NULL;
  901. MonoObject *o;
  902. MonoClassField* field;
  903. gpointer iter;
  904. int count = 0;
  905. MONO_ARCH_SAVE_REGS;
  906. MONO_CHECK_ARG_NULL (that);
  907. if (this->vtable != that->vtable)
  908. return FALSE;
  909. klass = mono_object_class (this);
  910. if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
  911. return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
  912. /*
  913. * Do the comparison for fields of primitive type and return a result if
  914. * possible. Otherwise, return the remaining fields in an array to the
  915. * managed side. This way, we can avoid costly reflection operations in
  916. * managed code.
  917. */
  918. *fields = NULL;
  919. iter = NULL;
  920. while ((field = mono_class_get_fields (klass, &iter))) {
  921. if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
  922. continue;
  923. if (mono_field_is_deleted (field))
  924. continue;
  925. /* FIXME: Add more types */
  926. switch (field->type->type) {
  927. case MONO_TYPE_U1:
  928. case MONO_TYPE_I1:
  929. case MONO_TYPE_BOOLEAN:
  930. if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
  931. return FALSE;
  932. break;
  933. case MONO_TYPE_U2:
  934. case MONO_TYPE_I2:
  935. case MONO_TYPE_CHAR:
  936. if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
  937. return FALSE;
  938. break;
  939. case MONO_TYPE_U4:
  940. case MONO_TYPE_I4:
  941. if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
  942. return FALSE;
  943. break;
  944. case MONO_TYPE_U8:
  945. case MONO_TYPE_I8:
  946. if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
  947. return FALSE;
  948. break;
  949. case MONO_TYPE_R4:
  950. if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
  951. return FALSE;
  952. break;
  953. case MONO_TYPE_R8:
  954. if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
  955. return FALSE;
  956. break;
  957. case MONO_TYPE_STRING: {
  958. MonoString *s1, *s2;
  959. guint32 s1len, s2len;
  960. s1 = *(MonoString**)((guint8*)this + field->offset);
  961. s2 = *(MonoString**)((guint8*)that + field->offset);
  962. if (s1 == s2)
  963. break;
  964. if ((s1 == NULL) || (s2 == NULL))
  965. return FALSE;
  966. s1len = mono_string_length (s1);
  967. s2len = mono_string_length (s2);
  968. if (s1len != s2len)
  969. return FALSE;
  970. if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
  971. return FALSE;
  972. break;
  973. }
  974. default:
  975. if (!values)
  976. values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
  977. o = mono_field_get_value_object (mono_object_domain (this), field, this);
  978. values [count++] = o;
  979. o = mono_field_get_value_object (mono_object_domain (this), field, that);
  980. values [count++] = o;
  981. }
  982. if (klass->enumtype)
  983. /* enums only have one non-static field */
  984. break;
  985. }
  986. if (values) {
  987. int i;
  988. mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
  989. for (i = 0; i < count; ++i)
  990. mono_array_setref (*fields, i, values [i]);
  991. return FALSE;
  992. } else {
  993. return TRUE;
  994. }
  995. }
  996. ICALL_EXPORT MonoReflectionType *
  997. ves_icall_System_Object_GetType (MonoObject *obj)
  998. {
  999. MONO_ARCH_SAVE_REGS;
  1000. #ifndef DISABLE_REMOTING
  1001. if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
  1002. return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
  1003. else
  1004. #endif
  1005. return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
  1006. }
  1007. ICALL_EXPORT void
  1008. mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
  1009. {
  1010. MONO_ARCH_SAVE_REGS;
  1011. mtype->type = &obj->vtable->klass->byval_arg;
  1012. g_assert (mtype->type->type);
  1013. }
  1014. ICALL_EXPORT gint32
  1015. ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
  1016. {
  1017. MONO_ARCH_SAVE_REGS;
  1018. MONO_CHECK_ARG_NULL (obj);
  1019. return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
  1020. }
  1021. ICALL_EXPORT gint32
  1022. ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
  1023. MonoReflectionMethod *method,
  1024. MonoArray *opt_param_types)
  1025. {
  1026. MONO_ARCH_SAVE_REGS;
  1027. MONO_CHECK_ARG_NULL (method);
  1028. return mono_image_create_method_token (
  1029. mb->dynamic_image, (MonoObject *) method, opt_param_types);
  1030. }
  1031. ICALL_EXPORT void
  1032. ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
  1033. {
  1034. MONO_ARCH_SAVE_REGS;
  1035. mono_image_create_pefile (mb, file);
  1036. }
  1037. ICALL_EXPORT void
  1038. ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
  1039. {
  1040. MONO_ARCH_SAVE_REGS;
  1041. mono_image_build_metadata (mb);
  1042. }
  1043. ICALL_EXPORT void
  1044. ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
  1045. {
  1046. MONO_ARCH_SAVE_REGS;
  1047. mono_image_register_token (mb->dynamic_image, token, obj);
  1048. }
  1049. static gboolean
  1050. get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
  1051. {
  1052. MonoMethod **dest = data;
  1053. /* skip unmanaged frames */
  1054. if (!managed)
  1055. return FALSE;
  1056. if (m == *dest) {
  1057. *dest = NULL;
  1058. return FALSE;
  1059. }
  1060. if (!(*dest)) {
  1061. *dest = m;
  1062. return TRUE;
  1063. }
  1064. return FALSE;
  1065. }
  1066. static gboolean
  1067. get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
  1068. {
  1069. MonoMethod **dest = data;
  1070. /* skip unmanaged frames */
  1071. if (!managed)
  1072. return FALSE;
  1073. if (!(*dest)) {
  1074. if (!strcmp (m->klass->name_space, "System.Reflection"))
  1075. return FALSE;
  1076. *dest = m;
  1077. return TRUE;
  1078. }
  1079. return FALSE;
  1080. }
  1081. static gboolean
  1082. get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
  1083. {
  1084. MonoMethod **dest = data;
  1085. /* skip unmanaged frames */
  1086. if (!managed)
  1087. return FALSE;
  1088. if (m->wrapper_type != MONO_WRAPPER_NONE)
  1089. return FALSE;
  1090. if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
  1091. return FALSE;
  1092. if (m == *dest) {
  1093. *dest = NULL;
  1094. return FALSE;
  1095. }
  1096. if (!(*dest)) {
  1097. *dest = m;
  1098. return TRUE;
  1099. }
  1100. return FALSE;
  1101. }
  1102. static MonoReflectionType *
  1103. type_from_name (const char *str, MonoBoolean ignoreCase)
  1104. {
  1105. MonoType *type = NULL;
  1106. MonoAssembly *assembly = NULL;
  1107. MonoTypeNameParse info;
  1108. char *temp_str = g_strdup (str);
  1109. gboolean type_resolve = FALSE;
  1110. MONO_ARCH_SAVE_REGS;
  1111. /* mono_reflection_parse_type() mangles the string */
  1112. if (!mono_reflection_parse_type (temp_str, &info)) {
  1113. mono_reflection_free_type_info (&info);
  1114. g_free (temp_str);
  1115. return NULL;
  1116. }
  1117. if (info.assembly.name) {
  1118. assembly = mono_assembly_load (&info.assembly, NULL, NULL);
  1119. } else {
  1120. MonoMethod *m = mono_method_get_last_managed ();
  1121. MonoMethod *dest = m;
  1122. mono_stack_walk_no_il (get_caller_no_reflection, &dest);
  1123. if (!dest)
  1124. dest = m;
  1125. /*
  1126. * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
  1127. * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
  1128. * to crash. This only seems to happen in some strange remoting
  1129. * scenarios and I was unable to figure out what's happening there.
  1130. * Dec 10, 2005 - Martin.
  1131. */
  1132. if (dest) {
  1133. assembly = dest->klass->image->assembly;
  1134. type_resolve = TRUE;
  1135. } else {
  1136. g_warning (G_STRLOC);
  1137. }
  1138. }
  1139. if (assembly) {
  1140. /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
  1141. type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
  1142. }
  1143. if (!info.assembly.name && !type) /* try mscorlib */
  1144. type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
  1145. if (assembly && !type && type_resolve) {
  1146. type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
  1147. type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
  1148. }
  1149. mono_reflection_free_type_info (&info);
  1150. g_free (temp_str);
  1151. if (!type)
  1152. return NULL;
  1153. return mono_type_get_object (mono_domain_get (), type);
  1154. }
  1155. #ifdef UNUSED
  1156. MonoReflectionType *
  1157. mono_type_get (const char *str)
  1158. {
  1159. char *copy = g_strdup (str);
  1160. MonoReflectionType *type = type_from_name (copy, FALSE);
  1161. g_free (copy);
  1162. return type;
  1163. }
  1164. #endif
  1165. ICALL_EXPORT MonoReflectionType*
  1166. ves_icall_type_from_name (MonoString *name,
  1167. MonoBoolean throwOnError,
  1168. MonoBoolean ignoreCase)
  1169. {
  1170. char *str = mono_string_to_utf8 (name);
  1171. MonoReflectionType *type;
  1172. type = type_from_name (str, ignoreCase);
  1173. g_free (str);
  1174. if (type == NULL){
  1175. MonoException *e = NULL;
  1176. if (throwOnError)
  1177. e = mono_get_exception_type_load (name, NULL);
  1178. mono_loader_clear_error ();
  1179. if (e != NULL)
  1180. mono_raise_exception (e);
  1181. }
  1182. return type;
  1183. }
  1184. ICALL_EXPORT MonoReflectionType*
  1185. ves_icall_type_from_handle (MonoType *handle)
  1186. {
  1187. MonoDomain *domain = mono_domain_get ();
  1188. MONO_ARCH_SAVE_REGS;
  1189. return mono_type_get_object (domain, handle);
  1190. }
  1191. ICALL_EXPORT MonoBoolean
  1192. ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
  1193. {
  1194. MONO_ARCH_SAVE_REGS;
  1195. if (c && type->type && c->type)
  1196. return mono_metadata_type_equal (type->type, c->type);
  1197. else
  1198. return (type == c) ? TRUE : FALSE;
  1199. }
  1200. /* System.TypeCode */
  1201. typedef enum {
  1202. TYPECODE_EMPTY,
  1203. TYPECODE_OBJECT,
  1204. TYPECODE_DBNULL,
  1205. TYPECODE_BOOLEAN,
  1206. TYPECODE_CHAR,
  1207. TYPECODE_SBYTE,
  1208. TYPECODE_BYTE,
  1209. TYPECODE_INT16,
  1210. TYPECODE_UINT16,
  1211. TYPECODE_INT32,
  1212. TYPECODE_UINT32,
  1213. TYPECODE_INT64,
  1214. TYPECODE_UINT64,
  1215. TYPECODE_SINGLE,
  1216. TYPECODE_DOUBLE,
  1217. TYPECODE_DECIMAL,
  1218. TYPECODE_DATETIME,
  1219. TYPECODE_STRING = 18
  1220. } TypeCode;
  1221. ICALL_EXPORT guint32
  1222. ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
  1223. {
  1224. int t = type->type->type;
  1225. MONO_ARCH_SAVE_REGS;
  1226. if (type->type->byref)
  1227. return TYPECODE_OBJECT;
  1228. handle_enum:
  1229. switch (t) {
  1230. case MONO_TYPE_VOID:
  1231. return TYPECODE_OBJECT;
  1232. case MONO_TYPE_BOOLEAN:
  1233. return TYPECODE_BOOLEAN;
  1234. case MONO_TYPE_U1:
  1235. return TYPECODE_BYTE;
  1236. case MONO_TYPE_I1:
  1237. return TYPECODE_SBYTE;
  1238. case MONO_TYPE_U2:
  1239. return TYPECODE_UINT16;
  1240. case MONO_TYPE_I2:
  1241. return TYPECODE_INT16;
  1242. case MONO_TYPE_CHAR:
  1243. return TYPECODE_CHAR;
  1244. case MONO_TYPE_PTR:
  1245. case MONO_TYPE_U:
  1246. case MONO_TYPE_I:
  1247. return TYPECODE_OBJECT;
  1248. case MONO_TYPE_U4:
  1249. return TYPECODE_UINT32;
  1250. case MONO_TYPE_I4:
  1251. return TYPECODE_INT32;
  1252. case MONO_TYPE_U8:
  1253. return TYPECODE_UINT64;
  1254. case MONO_TYPE_I8:
  1255. return TYPECODE_INT64;
  1256. case MONO_TYPE_R4:
  1257. return TYPECODE_SINGLE;
  1258. case MONO_TYPE_R8:
  1259. return TYPECODE_DOUBLE;
  1260. case MONO_TYPE_VALUETYPE: {
  1261. MonoClass *klass = type->type->data.klass;
  1262. if (klass->enumtype) {
  1263. t = mono_class_enum_basetype (klass)->type;
  1264. goto handle_enum;
  1265. } else if (mono_is_corlib_image (klass->image)) {
  1266. if (strcmp (klass->name_space, "System") == 0) {
  1267. if (strcmp (klass->name, "Decimal") == 0)
  1268. return TYPECODE_DECIMAL;
  1269. else if (strcmp (klass->name, "DateTime") == 0)
  1270. return TYPECODE_DATETIME;
  1271. }
  1272. }
  1273. return TYPECODE_OBJECT;
  1274. }
  1275. case MONO_TYPE_STRING:
  1276. return TYPECODE_STRING;
  1277. case MONO_TYPE_SZARRAY:
  1278. case MONO_TYPE_ARRAY:
  1279. case MONO_TYPE_OBJECT:
  1280. case MONO_TYPE_VAR:
  1281. case MONO_TYPE_MVAR:
  1282. case MONO_TYPE_TYPEDBYREF:
  1283. return TYPECODE_OBJECT;
  1284. case MONO_TYPE_CLASS:
  1285. {
  1286. MonoClass *klass = type->type->data.klass;
  1287. if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
  1288. if (strcmp (klass->name, "DBNull") == 0)
  1289. return TYPECODE_DBNULL;
  1290. }
  1291. }
  1292. return TYPECODE_OBJECT;
  1293. case MONO_TYPE_GENERICINST:
  1294. return TYPECODE_OBJECT;
  1295. default:
  1296. g_error ("type 0x%02x not handled in GetTypeCode()", t);
  1297. }
  1298. return 0;
  1299. }
  1300. ICALL_EXPORT guint32
  1301. ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
  1302. {
  1303. MonoDomain *domain;
  1304. MonoClass *klass;
  1305. MonoClass *klassc;
  1306. MONO_ARCH_SAVE_REGS;
  1307. g_assert (type != NULL);
  1308. domain = ((MonoObject *)type)->vtable->domain;
  1309. if (!c) /* FIXME: dont know what do do here */
  1310. return 0;
  1311. klass = mono_class_from_mono_type (type->type);
  1312. klassc = mono_class_from_mono_type (c->type);
  1313. /* Interface check requires a more complex setup so we
  1314. * only do for them. Otherwise we simply avoid mono_class_init.
  1315. */
  1316. if (check_interfaces) {
  1317. mono_class_init_or_throw (klass);
  1318. mono_class_init_or_throw (klassc);
  1319. } else if (!klass->supertypes || !klassc->supertypes) {
  1320. mono_loader_lock ();
  1321. mono_class_setup_supertypes (klass);
  1322. mono_class_setup_supertypes (klassc);
  1323. mono_loader_unlock ();
  1324. }
  1325. if (type->type->byref)
  1326. return klassc == mono_defaults.object_class;
  1327. return mono_class_is_subclass_of (klass, klassc, check_interfaces);
  1328. }
  1329. static gboolean
  1330. mono_type_is_primitive (MonoType *type)
  1331. {
  1332. return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
  1333. type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
  1334. }
  1335. static MonoType*
  1336. mono_type_get_underlying_type_ignore_byref (MonoType *type)
  1337. {
  1338. if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
  1339. return mono_class_enum_basetype (type->data.klass);
  1340. if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
  1341. return mono_class_enum_basetype (type->data.generic_class->container_class);
  1342. return type;
  1343. }
  1344. ICALL_EXPORT guint32
  1345. ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
  1346. {
  1347. MonoDomain *domain;
  1348. MonoClass *klass;
  1349. MonoClass *klassc;
  1350. MONO_ARCH_SAVE_REGS;
  1351. g_assert (type != NULL);
  1352. domain = ((MonoObject *)type)->vtable->domain;
  1353. klass = mono_class_from_mono_type (type->type);
  1354. klassc = mono_class_from_mono_type (c->type);
  1355. mono_class_init_or_throw (klass);
  1356. mono_class_init_or_throw (klassc);
  1357. if (type->type->byref ^ c->type->byref)
  1358. return FALSE;
  1359. if (type->type->byref) {
  1360. MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
  1361. MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
  1362. klass = mono_class_from_mono_type (t);
  1363. klassc = mono_class_from_mono_type (ot);
  1364. if (mono_type_is_primitive (t)) {
  1365. return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
  1366. } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
  1367. return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
  1368. } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
  1369. return t->type == ot->type;
  1370. } else {
  1371. if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
  1372. return FALSE;
  1373. if (klass->valuetype)
  1374. return klass == klassc;
  1375. return klass->valuetype == klassc->valuetype;
  1376. }
  1377. }
  1378. return mono_class_is_assignable_from (klass, klassc);
  1379. }
  1380. ICALL_EXPORT guint32
  1381. ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
  1382. {
  1383. MonoClass *klass = mono_class_from_mono_type (type->type);
  1384. mono_class_init_or_throw (klass);
  1385. return mono_object_isinst (obj, klass) != NULL;
  1386. }
  1387. ICALL_EXPORT guint32
  1388. ves_icall_get_attributes (MonoReflectionType *type)
  1389. {
  1390. MonoClass *klass = mono_class_from_mono_type (type->type);
  1391. return klass->flags;
  1392. }
  1393. ICALL_EXPORT MonoReflectionMarshalAsAttribute*
  1394. ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
  1395. {
  1396. MonoClass *klass = field->field->parent;
  1397. MonoMarshalType *info;
  1398. int i;
  1399. if (klass->generic_container ||
  1400. (klass->generic_class && klass->generic_class->context.class_inst->is_open))
  1401. return NULL;
  1402. info = mono_marshal_load_type_info (klass);
  1403. for (i = 0; i < info->num_fields; ++i) {
  1404. if (info->fields [i].field == field->field) {
  1405. if (!info->fields [i].mspec)
  1406. return NULL;
  1407. else
  1408. return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
  1409. }
  1410. }
  1411. return NULL;
  1412. }
  1413. ICALL_EXPORT MonoReflectionField*
  1414. ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
  1415. {
  1416. gboolean found = FALSE;
  1417. MonoClass *klass;
  1418. MonoClass *k;
  1419. g_assert (handle);
  1420. if (!type) {
  1421. klass = handle->parent;
  1422. } else {
  1423. klass = mono_class_from_mono_type (type);
  1424. /* Check that the field belongs to the class */
  1425. for (k = klass; k; k = k->parent) {
  1426. if (k == handle->parent) {
  1427. found = TRUE;
  1428. break;
  1429. }
  1430. }
  1431. if (!found)
  1432. /* The managed code will throw the exception */
  1433. return NULL;
  1434. }
  1435. return mono_field_get_object (mono_domain_get (), klass, handle);
  1436. }
  1437. ICALL_EXPORT MonoArray*
  1438. ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
  1439. {
  1440. MonoError error;
  1441. MonoType *type = mono_field_get_type_checked (field->field, &error);
  1442. if (!mono_error_ok (&error))
  1443. mono_error_raise_exception (&error);
  1444. return type_array_from_modifiers (field->field->parent->image, type, optional);
  1445. }
  1446. ICALL_EXPORT int
  1447. vell_icall_get_method_attributes (MonoMethod *method)
  1448. {
  1449. return method->flags;
  1450. }
  1451. ICALL_EXPORT void
  1452. ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
  1453. {
  1454. MonoError error;
  1455. MonoDomain *domain = mono_domain_get ();
  1456. MonoMethodSignature* sig;
  1457. MONO_ARCH_SAVE_REGS;
  1458. sig = mono_method_signature_checked (method, &error);
  1459. if (!mono_error_ok (&error))
  1460. mono_error_raise_exception (&error);
  1461. MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
  1462. MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
  1463. info->attrs = method->flags;
  1464. info->implattrs = method->iflags;
  1465. if (sig->call_convention == MONO_CALL_DEFAULT)
  1466. info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
  1467. else {
  1468. if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
  1469. info->callconv = 2;
  1470. else
  1471. info->callconv = 1;
  1472. }
  1473. info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
  1474. }
  1475. ICALL_EXPORT MonoArray*
  1476. ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
  1477. {
  1478. MonoDomain *domain = mono_domain_get ();
  1479. return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
  1480. }
  1481. ICALL_EXPORT MonoReflectionMarshalAsAttribute*
  1482. ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
  1483. {
  1484. MonoDomain *domain = mono_domain_get ();
  1485. MonoReflectionMarshalAsAttribute* res = NULL;
  1486. MonoMarshalSpec **mspecs;
  1487. int i;
  1488. mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
  1489. mono_method_get_marshal_info (method, mspecs);
  1490. if (mspecs [0])
  1491. res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
  1492. for (i = mono_method_signature (method)->param_count; i >= 0; i--)
  1493. if (mspecs [i])
  1494. mono_metadata_free_marshal_spec (mspecs [i]);
  1495. g_free (mspecs);
  1496. return res;
  1497. }
  1498. ICALL_EXPORT gint32
  1499. ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
  1500. {
  1501. MonoClass *parent = field->field->parent;
  1502. if (!parent->size_inited)
  1503. mono_class_init (parent);
  1504. return field->field->offset - sizeof (MonoObject);
  1505. }
  1506. ICALL_EXPORT MonoReflectionType*
  1507. ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
  1508. {
  1509. MonoClass *parent;
  1510. MONO_ARCH_SAVE_REGS;
  1511. parent = declaring? field->field->parent: field->klass;
  1512. return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
  1513. }
  1514. ICALL_EXPORT MonoObject *
  1515. ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
  1516. {
  1517. MonoClass *fklass = field->klass;
  1518. MonoClassField *cf = field->field;
  1519. MonoDomain *domain = mono_object_domain (field);
  1520. if (fklass->image->assembly->ref_only)
  1521. mono_raise_exception (mono_get_exception_invalid_operation (
  1522. "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
  1523. if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
  1524. mono_security_core_clr_ensure_reflection_access_field (cf);
  1525. return mono_field_get_value_object (domain, cf, obj);
  1526. }
  1527. ICALL_EXPORT void
  1528. ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
  1529. {
  1530. MonoError error;
  1531. MonoClassField *cf = field->field;
  1532. MonoType *type;
  1533. gchar *v;
  1534. MONO_ARCH_SAVE_REGS;
  1535. if (field->klass->image->assembly->ref_only)
  1536. mono_raise_exception (mono_get_exception_invalid_operation (
  1537. "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
  1538. if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
  1539. mono_security_core_clr_ensure_reflection_access_field (cf);
  1540. type = mono_field_get_type_checked (cf, &error);
  1541. if (!mono_error_ok (&error))
  1542. mono_error_raise_exception (&error);
  1543. v = (gchar *) value;
  1544. if (!type->byref) {
  1545. switch (type->type) {
  1546. case MONO_TYPE_U1:
  1547. case MONO_TYPE_I1:
  1548. case MONO_TYPE_BOOLEAN:
  1549. case MONO_TYPE_U2:
  1550. case MONO_TYPE_I2:
  1551. case MONO_TYPE_CHAR:
  1552. case MONO_TYPE_U:
  1553. case MONO_TYPE_I:
  1554. case MONO_TYPE_U4:
  1555. case MONO_TYPE_I4:
  1556. case MONO_TYPE_R4:
  1557. case MONO_TYPE_U8:
  1558. case MONO_TYPE_I8:
  1559. case MONO_TYPE_R8:
  1560. case MONO_TYPE_VALUETYPE:
  1561. case MONO_TYPE_PTR:
  1562. if (v != NULL)
  1563. v += sizeof (MonoObject);
  1564. break;
  1565. case MONO_TYPE_STRING:
  1566. case MONO_TYPE_OBJECT:
  1567. case MONO_TYPE_CLASS:
  1568. case MONO_TYPE_ARRAY:
  1569. case MONO_TYPE_SZARRAY:
  1570. /* Do nothing */
  1571. break;
  1572. case MONO_TYPE_GENERICINST: {
  1573. MonoGenericClass *gclass = type->data.generic_class;
  1574. g_assert (!gclass->context.class_inst->is_open);
  1575. if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
  1576. MonoClass *nklass = mono_class_from_mono_type (type);
  1577. MonoObject *nullable;
  1578. /*
  1579. * Convert the boxed vtype into a Nullable structure.
  1580. * This is complicated by the fact that Nullables have
  1581. * a variable structure.
  1582. */
  1583. nullable = mono_object_new (mono_domain_get (), nklass);
  1584. mono_nullable_init (mono_object_unbox (nullable), value, nklass);
  1585. v = mono_object_unbox (nullable);
  1586. }
  1587. else
  1588. if (gclass->container_class->valuetype && (v != NULL))
  1589. v += sizeof (MonoObject);
  1590. break;
  1591. }
  1592. default:
  1593. g_error ("type 0x%x not handled in "
  1594. "ves_icall_FieldInfo_SetValueInternal", type->type);
  1595. return;
  1596. }
  1597. }
  1598. if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
  1599. MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
  1600. if (!vtable->initialized)
  1601. mono_runtime_class_init (vtable);
  1602. mono_field_static_set_value (vtable, cf, v);
  1603. } else {
  1604. mono_field_set_value (obj, cf, v);
  1605. }
  1606. }
  1607. ICALL_EXPORT MonoObject *
  1608. ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
  1609. {
  1610. MonoObject *o = NULL;
  1611. MonoClassField *field = this->field;
  1612. MonoClass *klass;
  1613. MonoDomain *domain = mono_object_domain (this);
  1614. gchar *v;
  1615. MonoTypeEnum def_type;
  1616. const char *def_value;
  1617. MonoType *t;
  1618. MonoError error;
  1619. MONO_ARCH_SAVE_REGS;
  1620. mono_class_init (field->parent);
  1621. t = mono_field_get_type_checked (field, &error);
  1622. if (!mono_error_ok (&error))
  1623. mono_error_raise_exception (&error);
  1624. if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
  1625. mono_raise_exception (mono_get_exception_invalid_operation (NULL));
  1626. if (field->parent->image->dynamic) {
  1627. /* FIXME: */
  1628. g_assert_not_reached ();
  1629. }
  1630. def_value = mono_class_get_field_default_value (field, &def_type);
  1631. if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
  1632. mono_raise_exception (mono_get_exception_invalid_operation (NULL));
  1633. /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
  1634. switch (def_type) {
  1635. case MONO_TYPE_U1:
  1636. case MONO_TYPE_I1:
  1637. case MONO_TYPE_BOOLEAN:
  1638. case MONO_TYPE_U2:
  1639. case MONO_TYPE_I2:
  1640. case MONO_TYPE_CHAR:
  1641. case MONO_TYPE_U:
  1642. case MONO_TYPE_I:
  1643. case MONO_TYPE_U4:
  1644. case MONO_TYPE_I4:
  1645. case MONO_TYPE_R4:
  1646. case MONO_TYPE_U8:
  1647. case MONO_TYPE_I8:
  1648. case MONO_TYPE_R8: {
  1649. MonoType *t;
  1650. /* boxed value type */
  1651. t = g_new0 (MonoType, 1);
  1652. t->type = def_type;
  1653. klass = mono_class_from_mono_type (t);
  1654. g_free (t);
  1655. o = mono_object_new (domain, klass);
  1656. v = ((gchar *) o) + sizeof (MonoObject);
  1657. mono_get_constant_value_from_blob (domain, def_type, def_value, v);
  1658. break;
  1659. }
  1660. case MONO_TYPE_STRING:
  1661. case MONO_TYPE_CLASS:
  1662. mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
  1663. break;
  1664. default:
  1665. g_assert_not_reached ();
  1666. }
  1667. return o;
  1668. }
  1669. ICALL_EXPORT MonoReflectionType*
  1670. ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
  1671. {
  1672. MonoError error;
  1673. MonoClassField *field = ref_field->field;
  1674. MonoType *type = mono_field_get_type_checked (field, &error);
  1675. if (!mono_error_ok (&error))
  1676. mono_error_raise_exception (&error);
  1677. return mono_type_get_object (mono_object_domain (ref_field), type);
  1678. }
  1679. ICALL_EXPORT MonoReflectionType*
  1680. ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
  1681. {
  1682. MonoMethod *method = rmethod->method.method;
  1683. return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
  1684. }
  1685. /* From MonoProperty.cs */
  1686. typedef enum {
  1687. PInfo_Attributes = 1,
  1688. PInfo_GetMethod = 1 << 1,
  1689. PInfo_SetMethod = 1 << 2,
  1690. PInfo_ReflectedType = 1 << 3,
  1691. PInfo_DeclaringType = 1 << 4,
  1692. PInfo_Name = 1 << 5
  1693. } PInfo;
  1694. ICALL_EXPORT void
  1695. ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
  1696. {
  1697. MonoDomain *domain = mono_object_domain (property);
  1698. MONO_ARCH_SAVE_REGS;
  1699. if ((req_info & PInfo_ReflectedType) != 0)
  1700. MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
  1701. if ((req_info & PInfo_DeclaringType) != 0)
  1702. MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
  1703. if ((req_info & PInfo_Name) != 0)
  1704. MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
  1705. if ((req_info & PInfo_Attributes) != 0)
  1706. info->attrs = property->property->attrs;
  1707. if ((req_info & PInfo_GetMethod) != 0)
  1708. MONO_STRUCT_SETREF (info, get, property->property->get ?
  1709. mono_method_get_object (domain, property->property->get, property->klass): NULL);
  1710. if ((req_info & PInfo_SetMethod) != 0)
  1711. MONO_STRUCT_SETREF (info, set, property->property->set ?
  1712. mono_method_get_object (domain, property->property->set, property->klass): NULL);
  1713. /*
  1714. * There may be other methods defined for properties, though, it seems they are not exposed
  1715. * in the reflection API
  1716. */
  1717. }
  1718. ICALL_EXPORT void
  1719. ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
  1720. {
  1721. MonoDomain *domain = mono_object_domain (event);
  1722. MONO_ARCH_SAVE_REGS;
  1723. MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
  1724. MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
  1725. MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
  1726. info->attrs = event->event->attrs;
  1727. MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
  1728. MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
  1729. MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
  1730. #ifndef MONO_SMALL_CONFIG
  1731. if (event->event->other) {
  1732. int i, n = 0;
  1733. while (event->event->other [n])
  1734. n++;
  1735. MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
  1736. for (i = 0; i < n; i++)
  1737. mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
  1738. }
  1739. #endif
  1740. }
  1741. static void
  1742. collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
  1743. {
  1744. int i;
  1745. MonoClass *ic;
  1746. mono_class_setup_interfaces (klass, error);
  1747. if (!mono_error_ok (error))
  1748. return;
  1749. for (i = 0; i < klass->interface_count; i++) {
  1750. ic = klass->interfaces [i];
  1751. g_hash_table_insert (ifaces, ic, ic);
  1752. collect_interfaces (ic, ifaces, error);
  1753. if (!mono_error_ok (error))
  1754. return;
  1755. }
  1756. }
  1757. typedef struct {
  1758. MonoArray *iface_array;
  1759. MonoGenericContext *context;
  1760. MonoError *error;
  1761. MonoDomain *domain;
  1762. int next_idx;
  1763. } FillIfaceArrayData;
  1764. static void
  1765. fill_iface_array (gpointer key, gpointer value, gpointer user_data)
  1766. {
  1767. FillIfaceArrayData *data = user_data;
  1768. MonoClass *ic = key;
  1769. MonoType *ret = &ic->byval_arg, *inflated = NULL;
  1770. if (!mono_error_ok (data->error))
  1771. return;
  1772. if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
  1773. inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
  1774. if (!mono_error_ok (data->error))
  1775. return;
  1776. }
  1777. mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
  1778. if (inflated)
  1779. mono_metadata_free_type (inflated);
  1780. }
  1781. ICALL_EXPORT MonoArray*
  1782. ves_icall_Type_GetInterfaces (MonoReflectionType* type)
  1783. {
  1784. MonoError error;
  1785. MonoClass *class = mono_class_from_mono_type (type->type);
  1786. MonoClass *parent;
  1787. FillIfaceArrayData data = { 0 };
  1788. int len;
  1789. GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
  1790. if (class->generic_class && class->generic_class->context.class_inst->is_open) {
  1791. data.context = mono_class_get_context (class);
  1792. class = class->generic_class->container_class;
  1793. }
  1794. for (parent = class; parent; parent = parent->parent) {
  1795. mono_class_setup_interfaces (parent, &error);
  1796. if (!mono_error_ok (&error))
  1797. goto fail;
  1798. collect_interfaces (parent, iface_hash, &error);
  1799. if (!mono_error_ok (&error))
  1800. goto fail;
  1801. }
  1802. data.error = &error;
  1803. data.domain = mono_object_domain (type);
  1804. len = g_hash_table_size (iface_hash);
  1805. if (len == 0) {
  1806. g_hash_table_destroy (iface_hash);
  1807. if (!data.domain->empty_types)
  1808. data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
  1809. return data.domain->empty_types;
  1810. }
  1811. data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
  1812. g_hash_table_foreach (iface_hash, fill_iface_array, &data);
  1813. if (!mono_error_ok (&error))
  1814. goto fail;
  1815. g_hash_table_destroy (iface_hash);
  1816. return data.iface_array;
  1817. fail:
  1818. g_hash_table_destroy (iface_hash);
  1819. mono_error_raise_exception (&error);
  1820. return NULL;
  1821. }
  1822. ICALL_EXPORT void
  1823. ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
  1824. {
  1825. gboolean variance_used;
  1826. MonoClass *class = mono_class_from_mono_type (type->type);
  1827. MonoClass *iclass = mono_class_from_mono_type (iface->type);
  1828. MonoReflectionMethod *member;
  1829. MonoMethod* method;
  1830. gpointer iter;
  1831. int i = 0, len, ioffset;
  1832. MonoDomain *domain;
  1833. MONO_ARCH_SAVE_REGS;
  1834. mono_class_init_or_throw (class);
  1835. mono_class_init_or_throw (iclass);
  1836. mono_class_setup_vtable (class);
  1837. ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
  1838. if (ioffset == -1)
  1839. return;
  1840. len = mono_class_num_methods (iclass);
  1841. domain = mono_object_domain (type);
  1842. mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
  1843. mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
  1844. iter = NULL;
  1845. while ((method = mono_class_get_methods (iclass, &iter))) {
  1846. member = mono_method_get_object (domain, method, iclass);
  1847. mono_array_setref (*methods, i, member);
  1848. member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
  1849. mono_array_setref (*targets, i, member);
  1850. i ++;
  1851. }
  1852. }
  1853. ICALL_EXPORT void
  1854. ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
  1855. {
  1856. MonoClass *klass = mono_class_from_mono_type (type->type);
  1857. mono_class_init_or_throw (klass);
  1858. if (klass->image->dynamic) {
  1859. MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
  1860. *packing = tb->packing_size;
  1861. *size = tb->class_size;
  1862. } else {
  1863. mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
  1864. }
  1865. }
  1866. ICALL_EXPORT MonoReflectionType*
  1867. ves_icall_MonoType_GetElementType (MonoReflectionType *type)
  1868. {
  1869. MonoClass *class;
  1870. MONO_ARCH_SAVE_REGS;
  1871. if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
  1872. return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
  1873. class = mono_class_from_mono_type (type->type);
  1874. mono_class_init_or_throw (class);
  1875. // GetElementType should only return a type for:
  1876. // Array Pointer PassedByRef
  1877. if (type->type->byref)
  1878. return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
  1879. else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
  1880. return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
  1881. else if (class->element_class && type->type->type == MONO_TYPE_PTR)
  1882. return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
  1883. else
  1884. return NULL;
  1885. }
  1886. ICALL_EXPORT MonoReflectionType*
  1887. ves_icall_get_type_parent (MonoReflectionType *type)
  1888. {
  1889. MonoClass *class = mono_class_from_mono_type (type->type);
  1890. return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
  1891. }
  1892. ICALL_EXPORT MonoBoolean
  1893. ves_icall_type_ispointer (MonoReflectionType *type)
  1894. {
  1895. MONO_ARCH_SAVE_REGS;
  1896. return type->type->type == MONO_TYPE_PTR;
  1897. }
  1898. ICALL_EXPORT MonoBoolean
  1899. ves_icall_type_isprimitive (MonoReflectionType *type)
  1900. {
  1901. MONO_ARCH_SAVE_REGS;
  1902. 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)));
  1903. }
  1904. ICALL_EXPORT MonoBoolean
  1905. ves_icall_type_isbyref (MonoReflectionType *type)
  1906. {
  1907. MONO_ARCH_SAVE_REGS;
  1908. return type->type->byref;
  1909. }
  1910. ICALL_EXPORT MonoBoolean
  1911. ves_icall_type_iscomobject (MonoReflectionType *type)
  1912. {
  1913. MonoClass *klass = mono_class_from_mono_type (type->type);
  1914. mono_class_init_or_throw (klass);
  1915. return (klass && klass->is_com_object);
  1916. }
  1917. ICALL_EXPORT MonoReflectionModule*
  1918. ves_icall_MonoType_get_Module (MonoReflectionType *type)
  1919. {
  1920. MonoClass *class = mono_class_from_mono_type (type->type);
  1921. return mono_module_get_object (mono_object_domain (type), class->image);
  1922. }
  1923. ICALL_EXPORT MonoReflectionAssembly*
  1924. ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
  1925. {
  1926. MonoDomain *domain = mono_domain_get ();
  1927. MonoClass *class = mono_class_from_mono_type (type->type);
  1928. return mono_assembly_get_object (domain, class->image->assembly);
  1929. }
  1930. ICALL_EXPORT MonoReflectionType*
  1931. ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
  1932. {
  1933. MonoDomain *domain = mono_domain_get ();
  1934. MonoClass *class;
  1935. MONO_ARCH_SAVE_REGS;
  1936. if (type->type->byref)
  1937. return NULL;
  1938. if (type->type->type == MONO_TYPE_VAR)
  1939. class = mono_type_get_generic_param_owner (type->type)->owner.klass;
  1940. else if (type->type->type == MONO_TYPE_MVAR)
  1941. class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
  1942. else
  1943. class = mono_class_from_mono_type (type->type)->nested_in;
  1944. return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
  1945. }
  1946. ICALL_EXPORT MonoString*
  1947. ves_icall_MonoType_get_Name (MonoReflectionType *type)
  1948. {
  1949. MonoDomain *domain = mono_domain_get ();
  1950. MonoClass *class = mono_class_from_mono_type (type->type);
  1951. if (type->type->byref) {
  1952. char *n = g_strdup_printf ("%s&", class->name);
  1953. MonoString *res = mono_string_new (domain, n);
  1954. g_free (n);
  1955. return res;
  1956. } else {
  1957. return mono_string_new (domain, class->name);
  1958. }
  1959. }
  1960. ICALL_EXPORT MonoString*
  1961. ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
  1962. {
  1963. MonoDomain *domain = mono_domain_get ();
  1964. MonoClass *class = mono_class_from_mono_type (type->type);
  1965. while (class->nested_in)
  1966. class = class->nested_in;
  1967. if (class->name_space [0] == '\0')
  1968. return NULL;
  1969. else
  1970. return mono_string_new (domain, class->name_space);
  1971. }
  1972. ICALL_EXPORT gint32
  1973. ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
  1974. {
  1975. MonoClass *class;
  1976. if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
  1977. mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
  1978. class = mono_class_from_mono_type (type->type);
  1979. return class->rank;
  1980. }
  1981. ICALL_EXPORT MonoArray*
  1982. ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
  1983. {
  1984. MonoArray *res;
  1985. MonoClass *klass, *pklass;
  1986. MonoDomain *domain = mono_object_domain (type);
  1987. MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
  1988. int i;
  1989. MONO_ARCH_SAVE_REGS;
  1990. klass = mono_class_from_mono_type (type->type);
  1991. if (klass->generic_container) {
  1992. MonoGenericContainer *container = klass->generic_container;
  1993. res = mono_array_new_specific (array_vtable, container->type_argc);
  1994. for (i = 0; i < container->type_argc; ++i) {
  1995. pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
  1996. mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
  1997. }
  1998. } else if (klass->generic_class) {
  1999. MonoGenericInst *inst = klass->generic_class->context.class_inst;
  2000. res = mono_array_new_specific (array_vtable, inst->type_argc);
  2001. for (i = 0; i < inst->type_argc; ++i)
  2002. mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
  2003. } else {
  2004. res = mono_array_new_specific (array_vtable, 0);
  2005. }
  2006. return res;
  2007. }
  2008. ICALL_EXPORT gboolean
  2009. ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
  2010. {
  2011. MonoClass *klass;
  2012. MONO_ARCH_SAVE_REGS;
  2013. if (!IS_MONOTYPE (type))
  2014. return FALSE;
  2015. if (type->type->byref)
  2016. return FALSE;
  2017. klass = mono_class_from_mono_type (type->type);
  2018. return klass->generic_container != NULL;
  2019. }
  2020. ICALL_EXPORT MonoReflectionType*
  2021. ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
  2022. {
  2023. MonoClass *klass;
  2024. MONO_ARCH_SAVE_REGS;
  2025. if (type->type->byref)
  2026. return NULL;
  2027. klass = mono_class_from_mono_type (type->type);
  2028. if (klass->generic_container) {
  2029. return type; /* check this one */
  2030. }
  2031. if (klass->generic_class) {
  2032. MonoClass *generic_class = klass->generic_class->container_class;
  2033. gpointer tb;
  2034. tb = mono_class_get_ref_info (generic_class);
  2035. if (generic_class->wastypebuilder && tb)
  2036. return tb;
  2037. else
  2038. return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
  2039. }
  2040. return NULL;
  2041. }
  2042. ICALL_EXPORT MonoReflectionType*
  2043. ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
  2044. {
  2045. MonoClass *class;
  2046. MonoType *geninst, **types;
  2047. int i, count;
  2048. g_assert (IS_MONOTYPE (type));
  2049. mono_class_init_or_throw (mono_class_from_mono_type (type->type));
  2050. count = mono_array_length (type_array);
  2051. types = g_new0 (MonoType *, count);
  2052. for (i = 0; i < count; i++) {
  2053. MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
  2054. types [i] = t->type;
  2055. }
  2056. geninst = mono_reflection_bind_generic_parameters (type, count, types);
  2057. g_free (types);
  2058. if (!geninst)
  2059. return NULL;
  2060. class = mono_class_from_mono_type (geninst);
  2061. /*we might inflate to the GTD*/
  2062. if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
  2063. mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
  2064. return mono_type_get_object (mono_object_domain (type), geninst);
  2065. }
  2066. ICALL_EXPORT gboolean
  2067. ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
  2068. {
  2069. MonoClass *klass;
  2070. MONO_ARCH_SAVE_REGS;
  2071. if (type->type->byref)
  2072. return FALSE;
  2073. klass = mono_class_from_mono_type (type->type);
  2074. return klass->generic_class != NULL;
  2075. }
  2076. ICALL_EXPORT gboolean
  2077. ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
  2078. {
  2079. MonoClass *klass;
  2080. MONO_ARCH_SAVE_REGS;
  2081. if (!IS_MONOTYPE (type))
  2082. return FALSE;
  2083. if (type->type->byref)
  2084. return FALSE;
  2085. klass = mono_class_from_mono_type (type->type);
  2086. return klass->generic_class != NULL || klass->generic_container != NULL;
  2087. }
  2088. ICALL_EXPORT gint32
  2089. ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
  2090. {
  2091. MONO_ARCH_SAVE_REGS;
  2092. if (!IS_MONOTYPE (type))
  2093. return -1;
  2094. if (is_generic_parameter (type->type))
  2095. return mono_type_get_generic_param_num (type->type);
  2096. return -1;
  2097. }
  2098. ICALL_EXPORT GenericParameterAttributes
  2099. ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
  2100. {
  2101. MONO_ARCH_SAVE_REGS;
  2102. g_assert (IS_MONOTYPE (type));
  2103. g_assert (is_generic_parameter (type->type));
  2104. return mono_generic_param_info (type->type->data.generic_param)->flags;
  2105. }
  2106. ICALL_EXPORT MonoArray *
  2107. ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
  2108. {
  2109. MonoGenericParamInfo *param_info;
  2110. MonoDomain *domain;
  2111. MonoClass **ptr;
  2112. MonoArray *res;
  2113. int i, count;
  2114. MONO_ARCH_SAVE_REGS;
  2115. g_assert (IS_MONOTYPE (type));
  2116. domain = mono_object_domain (type);
  2117. param_info = mono_generic_param_info (type->type->data.generic_param);
  2118. for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
  2119. ;
  2120. res = mono_array_new (domain, mono_defaults.monotype_class, count);
  2121. for (i = 0; i < count; i++)
  2122. mono_array_setref (res, i, mono_type_get_object (domain, &param_info->constraints [i]->byval_arg));
  2123. return res;
  2124. }
  2125. ICALL_EXPORT MonoBoolean
  2126. ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
  2127. {
  2128. MONO_ARCH_SAVE_REGS;
  2129. return is_generic_parameter (type->type);
  2130. }
  2131. ICALL_EXPORT MonoBoolean
  2132. ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
  2133. {
  2134. MONO_ARCH_SAVE_REGS;
  2135. return is_generic_parameter (tb->type.type);
  2136. }
  2137. ICALL_EXPORT void
  2138. ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
  2139. MonoReflectionType *t)
  2140. {
  2141. enumtype->type = t->type;
  2142. }
  2143. ICALL_EXPORT MonoReflectionMethod*
  2144. ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
  2145. MonoReflectionMethod* generic)
  2146. {
  2147. MonoDomain *domain;
  2148. MonoClass *klass;
  2149. MonoMethod *method;
  2150. gpointer iter;
  2151. MONO_ARCH_SAVE_REGS;
  2152. domain = ((MonoObject *)type)->vtable->domain;
  2153. klass = mono_class_from_mono_type (type->type);
  2154. mono_class_init_or_throw (klass);
  2155. iter = NULL;
  2156. while ((method = mono_class_get_methods (klass, &iter))) {
  2157. if (method->token == generic->method->token)
  2158. return mono_method_get_object (domain, method, klass);
  2159. }
  2160. return NULL;
  2161. }
  2162. ICALL_EXPORT MonoReflectionMethod *
  2163. ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
  2164. {
  2165. MonoMethod *method;
  2166. MonoType *type = ref_type->type;
  2167. MONO_ARCH_SAVE_REGS;
  2168. if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
  2169. mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
  2170. if (type->type == MONO_TYPE_VAR)
  2171. return NULL;
  2172. method = mono_type_get_generic_param_owner (type)->owner.method;
  2173. g_assert (method);
  2174. return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
  2175. }
  2176. ICALL_EXPORT MonoReflectionDllImportAttribute*
  2177. ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
  2178. {
  2179. static MonoClass *DllImportAttributeClass = NULL;
  2180. MonoDomain *domain = mono_domain_get ();
  2181. MonoReflectionDllImportAttribute *attr;
  2182. MonoImage *image = method->klass->image;
  2183. MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
  2184. MonoTableInfo *tables = image->tables;
  2185. MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
  2186. MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
  2187. guint32 im_cols [MONO_IMPLMAP_SIZE];
  2188. guint32 scope_token;
  2189. const char *import = NULL;
  2190. const char *scope = NULL;
  2191. guint32 flags;
  2192. if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
  2193. return NULL;
  2194. if (!DllImportAttributeClass) {
  2195. DllImportAttributeClass =
  2196. mono_class_from_name (mono_defaults.corlib,
  2197. "System.Runtime.InteropServices", "DllImportAttribute");
  2198. g_assert (DllImportAttributeClass);
  2199. }
  2200. if (method->klass->image->dynamic) {
  2201. MonoReflectionMethodAux *method_aux =
  2202. g_hash_table_lookup (
  2203. ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
  2204. if (method_aux) {
  2205. import = method_aux->dllentry;
  2206. scope = method_aux->dll;
  2207. }
  2208. if (!import || !scope) {
  2209. mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
  2210. return NULL;
  2211. }
  2212. }
  2213. else {
  2214. if (piinfo->implmap_idx) {
  2215. mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
  2216. piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
  2217. import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
  2218. scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
  2219. scope = mono_metadata_string_heap (image, scope_token);
  2220. }
  2221. }
  2222. flags = piinfo->piflags;
  2223. attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
  2224. MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
  2225. MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
  2226. attr->call_conv = (flags & 0x700) >> 8;
  2227. attr->charset = ((flags & 0x6) >> 1) + 1;
  2228. if (attr->charset == 1)
  2229. attr->charset = 2;
  2230. attr->exact_spelling = (flags & 0x1) != 0;
  2231. attr->set_last_error = (flags & 0x40) != 0;
  2232. attr->best_fit_mapping = (flags & 0x30) == 0x10;
  2233. attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
  2234. attr->preserve_sig = FALSE;
  2235. return attr;
  2236. }
  2237. ICALL_EXPORT MonoReflectionMethod *
  2238. ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
  2239. {
  2240. MonoMethodInflated *imethod;
  2241. MonoMethod *result;
  2242. MONO_ARCH_SAVE_REGS;
  2243. if (method->method->is_generic)
  2244. return method;
  2245. if (!method->method->is_inflated)
  2246. return NULL;
  2247. imethod = (MonoMethodInflated *) method->method;
  2248. result = imethod->declaring;
  2249. /* Not a generic method. */
  2250. if (!result->is_generic)
  2251. return NULL;
  2252. if (method->method->klass->image->dynamic) {
  2253. MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
  2254. MonoReflectionMethod *res;
  2255. /*
  2256. * FIXME: Why is this stuff needed at all ? Why can't the code below work for
  2257. * the dynamic case as well ?
  2258. */
  2259. mono_loader_lock ();
  2260. res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
  2261. mono_loader_unlock ();
  2262. if (res)
  2263. return res;
  2264. }
  2265. if (imethod->context.class_inst) {
  2266. MonoClass *klass = ((MonoMethod *) imethod)->klass;
  2267. /*Generic methods gets the context of the GTD.*/
  2268. if (mono_class_get_context (klass))
  2269. result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
  2270. }
  2271. return mono_method_get_object (mono_object_domain (method), result, NULL);
  2272. }
  2273. ICALL_EXPORT gboolean
  2274. ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
  2275. {
  2276. MONO_ARCH_SAVE_REGS;
  2277. return mono_method_signature (method->method)->generic_param_count != 0;
  2278. }
  2279. ICALL_EXPORT gboolean
  2280. ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
  2281. {
  2282. MONO_ARCH_SAVE_REGS;
  2283. return method->method->is_generic;
  2284. }
  2285. ICALL_EXPORT MonoArray*
  2286. ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
  2287. {
  2288. MonoArray *res;
  2289. MonoDomain *domain;
  2290. int count, i;
  2291. MONO_ARCH_SAVE_REGS;
  2292. domain = mono_object_domain (method);
  2293. if (method->method->is_inflated) {
  2294. MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
  2295. if (inst) {
  2296. count = inst->type_argc;
  2297. res = mono_array_new (domain, mono_defaults.systemtype_class, count);
  2298. for (i = 0; i < count; i++)
  2299. mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
  2300. return res;
  2301. }
  2302. }
  2303. count = mono_method_signature (method->method)->generic_param_count;
  2304. res = mono_array_new (domain, mono_defaults.systemtype_class, count);
  2305. for (i = 0; i < count; i++) {
  2306. MonoGenericContainer *container = mono_method_get_generic_container (method->method);
  2307. MonoGenericParam *param = mono_generic_container_get_param (container, i);
  2308. MonoClass *pklass = mono_class_from_generic_parameter (
  2309. param, method->method->klass->image, TRUE);
  2310. mono_array_setref (res, i,
  2311. mono_type_get_object (domain, &pklass->byval_arg));
  2312. }
  2313. return res;
  2314. }
  2315. ICALL_EXPORT MonoObject *
  2316. ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
  2317. {
  2318. /*
  2319. * Invoke from reflection is supposed to always be a virtual call (the API
  2320. * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
  2321. * greater flexibility.
  2322. */
  2323. MonoMethod *m = method->method;
  2324. MonoMethodSignature *sig = mono_method_signature (m);
  2325. int pcount;
  2326. void *obj = this;
  2327. MONO_ARCH_SAVE_REGS;
  2328. *exc = NULL;
  2329. if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
  2330. mono_security_core_clr_ensure_reflection_access_method (m);
  2331. if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
  2332. if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
  2333. mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
  2334. return NULL;
  2335. }
  2336. if (this) {
  2337. if (!mono_object_isinst (this, m->klass)) {
  2338. char *this_name = mono_type_get_full_name (mono_object_get_class (this));
  2339. char *target_name = mono_type_get_full_name (m->klass);
  2340. char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
  2341. mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
  2342. g_free (msg);
  2343. g_free (target_name);
  2344. g_free (this_name);
  2345. return NULL;
  2346. }
  2347. m = mono_object_get_virtual_method (this, m);
  2348. /* must pass the pointer to the value for valuetype methods */
  2349. if (m->klass->valuetype)
  2350. obj = mono_object_unbox (this);
  2351. } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
  2352. mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
  2353. return NULL;
  2354. }
  2355. }
  2356. if (sig->ret->byref) {
  2357. mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
  2358. return NULL;
  2359. }
  2360. pcount = params? mono_array_length (params): 0;
  2361. if (pcount != sig->param_count) {
  2362. mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
  2363. return NULL;
  2364. }
  2365. if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
  2366. 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."));
  2367. return NULL;
  2368. }
  2369. if (m->klass->image->assembly->ref_only) {
  2370. 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."));
  2371. return NULL;
  2372. }
  2373. if (m->klass->rank && !strcmp (m->name, ".ctor")) {
  2374. int i;
  2375. uintptr_t *lengths;
  2376. intptr_t *lower_bounds;
  2377. pcount = mono_array_length (params);
  2378. lengths = alloca (sizeof (uintptr_t) * pcount);
  2379. /* Note: the synthetized array .ctors have int32 as argument type */
  2380. for (i = 0; i < pcount; ++i)
  2381. lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
  2382. if (m->klass->rank == pcount) {
  2383. /* Only lengths provided. */
  2384. lower_bounds = NULL;
  2385. } else {
  2386. g_assert (pcount == (m->klass->rank * 2));
  2387. /* lower bounds are first. */
  2388. lower_bounds = (intptr_t*)lengths;
  2389. lengths += m->klass->rank;
  2390. }
  2391. return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
  2392. }
  2393. return mono_runtime_invoke_array (m, obj, params, NULL);
  2394. }
  2395. #ifndef DISABLE_REMOTING
  2396. ICALL_EXPORT MonoObject *
  2397. ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
  2398. {
  2399. MonoDomain *domain = mono_object_domain (method);
  2400. MonoMethod *m = method->method;
  2401. MonoMethodSignature *sig = mono_method_signature (m);
  2402. MonoArray *out_args;
  2403. MonoObject *result;
  2404. int i, j, outarg_count = 0;
  2405. MONO_ARCH_SAVE_REGS;
  2406. if (m->klass == mono_defaults.object_class) {
  2407. if (!strcmp (m->name, "FieldGetter")) {
  2408. MonoClass *k = this->vtable->klass;
  2409. MonoString *name;
  2410. char *str;
  2411. /* If this is a proxy, then it must be a CBO */
  2412. if (k == mono_defaults.transparent_proxy_class) {
  2413. MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
  2414. this = tp->rp->unwrapped_server;
  2415. g_assert (this);
  2416. k = this->vtable->klass;
  2417. }
  2418. name = mono_array_get (params, MonoString *, 1);
  2419. str = mono_string_to_utf8 (name);
  2420. do {
  2421. MonoClassField* field = mono_class_get_field_from_name (k, str);
  2422. if (field) {
  2423. MonoClass *field_klass = mono_class_from_mono_type (field->type);
  2424. if (field_klass->valuetype)
  2425. result = mono_value_box (domain, field_klass, (char *)this + field->offset);
  2426. else
  2427. result = *((gpointer *)((char *)this + field->offset));
  2428. out_args = mono_array_new (domain, mono_defaults.object_class, 1);
  2429. mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
  2430. mono_array_setref (out_args, 0, result);
  2431. g_free (str);
  2432. return NULL;
  2433. }
  2434. k = k->parent;
  2435. } while (k);
  2436. g_free (str);
  2437. g_assert_not_reached ();
  2438. } else if (!strcmp (m->name, "FieldSetter")) {
  2439. MonoClass *k = this->vtable->klass;
  2440. MonoString *name;
  2441. guint32 size;
  2442. gint32 align;
  2443. char *str;
  2444. /* If this is a proxy, then it must be a CBO */
  2445. if (k == mono_defaults.transparent_proxy_class) {
  2446. MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
  2447. this = tp->rp->unwrapped_server;
  2448. g_assert (this);
  2449. k = this->vtable->klass;
  2450. }
  2451. name = mono_array_get (params, MonoString *, 1);
  2452. str = mono_string_to_utf8 (name);
  2453. do {
  2454. MonoClassField* field = mono_class_get_field_from_name (k, str);
  2455. if (field) {
  2456. MonoClass *field_klass = mono_class_from_mono_type (field->type);
  2457. MonoObject *val = mono_array_get (params, gpointer, 2);
  2458. if (field_klass->valuetype) {
  2459. size = mono_type_size (field->type, &align);
  2460. g_assert (size == mono_class_value_size (field_klass, NULL));
  2461. mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
  2462. } else {
  2463. mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
  2464. }
  2465. out_args = mono_array_new (domain, mono_defaults.object_class, 0);
  2466. mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
  2467. g_free (str);
  2468. return NULL;
  2469. }
  2470. k = k->parent;
  2471. } while (k);
  2472. g_free (str);
  2473. g_assert_not_reached ();
  2474. }
  2475. }
  2476. for (i = 0; i < mono_array_length (params); i++) {
  2477. if (sig->params [i]->byref)
  2478. outarg_count++;
  2479. }
  2480. out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
  2481. /* handle constructors only for objects already allocated */
  2482. if (!strcmp (method->method->name, ".ctor"))
  2483. g_assert (this);
  2484. /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
  2485. g_assert (!method->method->klass->valuetype);
  2486. result = mono_runtime_invoke_array (method->method, this, params, NULL);
  2487. for (i = 0, j = 0; i < mono_array_length (params); i++) {
  2488. if (sig->params [i]->byref) {
  2489. gpointer arg;
  2490. arg = mono_array_get (params, gpointer, i);
  2491. mono_array_setref (out_args, j, arg);
  2492. j++;
  2493. }
  2494. }
  2495. mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
  2496. return result;
  2497. }
  2498. #endif
  2499. static guint64
  2500. read_enum_value (char *mem, int type)
  2501. {
  2502. switch (type) {
  2503. case MONO_TYPE_U1:
  2504. return *(guint8*)mem;
  2505. case MONO_TYPE_I1:
  2506. return *(gint8*)mem;
  2507. case MONO_TYPE_U2:
  2508. return *(guint16*)mem;
  2509. case MONO_TYPE_I2:
  2510. return *(gint16*)mem;
  2511. case MONO_TYPE_U4:
  2512. return *(guint32*)mem;
  2513. case MONO_TYPE_I4:
  2514. return *(gint32*)mem;
  2515. case MONO_TYPE_U8:
  2516. return *(guint64*)mem;
  2517. case MONO_TYPE_I8:
  2518. return *(gint64*)mem;
  2519. default:
  2520. g_assert_not_reached ();
  2521. }
  2522. return 0;
  2523. }
  2524. static void
  2525. write_enum_value (char *mem, int type, guint64 value)
  2526. {
  2527. switch (type) {
  2528. case MONO_TYPE_U1:
  2529. case MONO_TYPE_I1: {
  2530. guint8 *p = (guint8*)mem;
  2531. *p = value;
  2532. break;
  2533. }
  2534. case MONO_TYPE_U2:
  2535. case MONO_TYPE_I2: {
  2536. guint16 *p = (void*)mem;
  2537. *p = value;
  2538. break;
  2539. }
  2540. case MONO_TYPE_U4:
  2541. case MONO_TYPE_I4: {
  2542. guint32 *p = (void*)mem;
  2543. *p = value;
  2544. break;
  2545. }
  2546. case MONO_TYPE_U8:
  2547. case MONO_TYPE_I8: {
  2548. guint64 *p = (void*)mem;
  2549. *p = value;
  2550. break;
  2551. }
  2552. default:
  2553. g_assert_not_reached ();
  2554. }
  2555. return;
  2556. }
  2557. ICALL_EXPORT MonoObject *
  2558. ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
  2559. {
  2560. MonoDomain *domain;
  2561. MonoClass *enumc, *objc;
  2562. MonoObject *res;
  2563. MonoType *etype;
  2564. guint64 val;
  2565. MONO_ARCH_SAVE_REGS;
  2566. MONO_CHECK_ARG_NULL (enumType);
  2567. MONO_CHECK_ARG_NULL (value);
  2568. domain = mono_object_domain (enumType);
  2569. enumc = mono_class_from_mono_type (enumType->type);
  2570. mono_class_init_or_throw (enumc);
  2571. objc = value->vtable->klass;
  2572. if (!enumc->enumtype)
  2573. mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
  2574. if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
  2575. 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."));
  2576. etype = mono_class_enum_basetype (enumc);
  2577. if (!etype)
  2578. /* MS throws this for typebuilders */
  2579. mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
  2580. res = mono_object_new (domain, enumc);
  2581. val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
  2582. write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
  2583. return res;
  2584. }
  2585. ICALL_EXPORT MonoObject *
  2586. ves_icall_System_Enum_get_value (MonoObject *this)
  2587. {
  2588. MonoObject *res;
  2589. MonoClass *enumc;
  2590. gpointer dst;
  2591. gpointer src;
  2592. int size;
  2593. MONO_ARCH_SAVE_REGS;
  2594. if (!this)
  2595. return NULL;
  2596. g_assert (this->vtable->klass->enumtype);
  2597. enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
  2598. res = mono_object_new (mono_object_domain (this), enumc);
  2599. dst = (char *)res + sizeof (MonoObject);
  2600. src = (char *)this + sizeof (MonoObject);
  2601. size = mono_class_value_size (enumc, NULL);
  2602. memcpy (dst, src, size);
  2603. return res;
  2604. }
  2605. ICALL_EXPORT MonoReflectionType *
  2606. ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
  2607. {
  2608. MonoType *etype;
  2609. MonoClass *klass;
  2610. MONO_ARCH_SAVE_REGS;
  2611. klass = mono_class_from_mono_type (type->type);
  2612. mono_class_init_or_throw (klass);
  2613. etype = mono_class_enum_basetype (klass);
  2614. if (!etype)
  2615. /* MS throws this for typebuilders */
  2616. mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
  2617. return mono_type_get_object (mono_object_domain (type), etype);
  2618. }
  2619. ICALL_EXPORT int
  2620. ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
  2621. {
  2622. gpointer tdata = (char *)this + sizeof (MonoObject);
  2623. gpointer odata = (char *)other + sizeof (MonoObject);
  2624. MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
  2625. g_assert (basetype);
  2626. #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
  2627. ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
  2628. ENUM_TYPE other = *((ENUM_TYPE*)odata); \
  2629. if (me == other) \
  2630. return 0; \
  2631. return me > other ? 1 : -1; \
  2632. } while (0)
  2633. #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
  2634. ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
  2635. ENUM_TYPE other = *((ENUM_TYPE*)odata); \
  2636. if (me == other) \
  2637. return 0; \
  2638. return me - other; \
  2639. } while (0)
  2640. switch (basetype->type) {
  2641. case MONO_TYPE_U1:
  2642. COMPARE_ENUM_VALUES (guint8);
  2643. case MONO_TYPE_I1:
  2644. COMPARE_ENUM_VALUES (gint8);
  2645. case MONO_TYPE_CHAR:
  2646. case MONO_TYPE_U2:
  2647. COMPARE_ENUM_VALUES_RANGE (guint16);
  2648. case MONO_TYPE_I2:
  2649. COMPARE_ENUM_VALUES (gint16);
  2650. case MONO_TYPE_U4:
  2651. COMPARE_ENUM_VALUES (guint32);
  2652. case MONO_TYPE_I4:
  2653. COMPARE_ENUM_VALUES (gint32);
  2654. case MONO_TYPE_U8:
  2655. COMPARE_ENUM_VALUES (guint64);
  2656. case MONO_TYPE_I8:
  2657. COMPARE_ENUM_VALUES (gint64);
  2658. default:
  2659. g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
  2660. }
  2661. #undef COMPARE_ENUM_VALUES_RANGE
  2662. #undef COMPARE_ENUM_VALUES
  2663. return 0;
  2664. }
  2665. ICALL_EXPORT int
  2666. ves_icall_System_Enum_get_hashcode (MonoObject *this)
  2667. {
  2668. gpointer data = (char *)this + sizeof (MonoObject);
  2669. MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
  2670. g_assert (basetype);
  2671. switch (basetype->type) {
  2672. case MONO_TYPE_I1:
  2673. return *((gint8*)data);
  2674. case MONO_TYPE_U1:
  2675. return *((guint8*)data);
  2676. case MONO_TYPE_CHAR:
  2677. case MONO_TYPE_U2:
  2678. return *((guint16*)data);
  2679. case MONO_TYPE_I2:
  2680. return *((gint16*)data);
  2681. case MONO_TYPE_U4:
  2682. return *((guint32*)data);
  2683. case MONO_TYPE_I4:
  2684. return *((gint32*)data);
  2685. case MONO_TYPE_U8:
  2686. case MONO_TYPE_I8: {
  2687. gint64 value = *((gint64*)data);
  2688. return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
  2689. }
  2690. default:
  2691. g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
  2692. }
  2693. return 0;
  2694. }
  2695. ICALL_EXPORT void
  2696. ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
  2697. {
  2698. MonoDomain *domain = mono_object_domain (type);
  2699. MonoClass *enumc = mono_class_from_mono_type (type->type);
  2700. guint j = 0, nvalues, crow;
  2701. gpointer iter;
  2702. MonoClassField *field;
  2703. MONO_ARCH_SAVE_REGS;
  2704. mono_class_init_or_throw (enumc);
  2705. MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
  2706. nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
  2707. MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
  2708. MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
  2709. crow = -1;
  2710. iter = NULL;
  2711. while ((field = mono_class_get_fields (enumc, &iter))) {
  2712. const char *p;
  2713. int len;
  2714. MonoTypeEnum def_type;
  2715. if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
  2716. continue;
  2717. if (strcmp ("value__", mono_field_get_name (field)) == 0)
  2718. continue;
  2719. if (mono_field_is_deleted (field))
  2720. continue;
  2721. mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
  2722. p = mono_class_get_field_default_value (field, &def_type);
  2723. len = mono_metadata_decode_blob_size (p, &p);
  2724. switch (mono_class_enum_basetype (enumc)->type) {
  2725. case MONO_TYPE_U1:
  2726. case MONO_TYPE_I1:
  2727. mono_array_set (info->values, gchar, j, *p);
  2728. break;
  2729. case MONO_TYPE_CHAR:
  2730. case MONO_TYPE_U2:
  2731. case MONO_TYPE_I2:
  2732. mono_array_set (info->values, gint16, j, read16 (p));
  2733. break;
  2734. case MONO_TYPE_U4:
  2735. case MONO_TYPE_I4:
  2736. mono_array_set (info->values, gint32, j, read32 (p));
  2737. break;
  2738. case MONO_TYPE_U8:
  2739. case MONO_TYPE_I8:
  2740. mono_array_set (info->values, gint64, j, read64 (p));
  2741. break;
  2742. default:
  2743. g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
  2744. }
  2745. ++j;
  2746. }
  2747. }
  2748. enum {
  2749. BFLAGS_IgnoreCase = 1,
  2750. BFLAGS_DeclaredOnly = 2,
  2751. BFLAGS_Instance = 4,
  2752. BFLAGS_Static = 8,
  2753. BFLAGS_Public = 0x10,
  2754. BFLAGS_NonPublic = 0x20,
  2755. BFLAGS_FlattenHierarchy = 0x40,
  2756. BFLAGS_InvokeMethod = 0x100,
  2757. BFLAGS_CreateInstance = 0x200,
  2758. BFLAGS_GetField = 0x400,
  2759. BFLAGS_SetField = 0x800,
  2760. BFLAGS_GetProperty = 0x1000,
  2761. BFLAGS_SetProperty = 0x2000,
  2762. BFLAGS_ExactBinding = 0x10000,
  2763. BFLAGS_SuppressChangeType = 0x20000,
  2764. BFLAGS_OptionalParamBinding = 0x40000
  2765. };
  2766. ICALL_EXPORT MonoReflectionField *
  2767. ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
  2768. {
  2769. MonoDomain *domain;
  2770. MonoClass *startklass, *klass;
  2771. int match;
  2772. MonoClassField *field;
  2773. gpointer iter;
  2774. char *utf8_name;
  2775. int (*compare_func) (const char *s1, const char *s2) = NULL;
  2776. domain = ((MonoObject *)type)->vtable->domain;
  2777. klass = startklass = mono_class_from_mono_type (type->type);
  2778. if (!name)
  2779. mono_raise_exception (mono_get_exception_argument_null ("name"));
  2780. if (type->type->byref)
  2781. return NULL;
  2782. compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
  2783. handle_parent:
  2784. if (klass->exception_type != MONO_EXCEPTION_NONE)
  2785. mono_raise_exception (mono_class_get_exception_for_failure (klass));
  2786. iter = NULL;
  2787. while ((field = mono_class_get_fields_lazy (klass, &iter))) {
  2788. guint32 flags = mono_field_get_flags (field);
  2789. match = 0;
  2790. if (mono_field_is_deleted_with_flags (field, flags))
  2791. continue;
  2792. if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
  2793. if (bflags & BFLAGS_Public)
  2794. match++;
  2795. } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
  2796. if (bflags & BFLAGS_NonPublic) {
  2797. match++;
  2798. }
  2799. }
  2800. if (!match)
  2801. continue;
  2802. match = 0;
  2803. if (flags & FIELD_ATTRIBUTE_STATIC) {
  2804. if (bflags & BFLAGS_Static)
  2805. if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
  2806. match++;
  2807. } else {
  2808. if (bflags & BFLAGS_Instance)
  2809. match++;
  2810. }
  2811. if (!match)
  2812. continue;
  2813. utf8_name = mono_string_to_utf8 (name);
  2814. if (compare_func (mono_field_get_name (field), utf8_name)) {
  2815. g_free (utf8_name);
  2816. continue;
  2817. }
  2818. g_free (utf8_name);
  2819. return mono_field_get_object (domain, klass, field);
  2820. }
  2821. if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
  2822. goto handle_parent;
  2823. return NULL;
  2824. }
  2825. ICALL_EXPORT MonoArray*
  2826. ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
  2827. {
  2828. MonoDomain *domain;
  2829. MonoClass *startklass, *klass, *refklass;
  2830. MonoArray *res;
  2831. MonoObject *member;
  2832. int i, match;
  2833. gpointer iter;
  2834. MonoClassField *field;
  2835. MonoPtrArray tmp_array;
  2836. MONO_ARCH_SAVE_REGS;
  2837. domain = ((MonoObject *)type)->vtable->domain;
  2838. if (type->type->byref)
  2839. return mono_array_new (domain, mono_defaults.field_info_class, 0);
  2840. klass = startklass = mono_class_from_mono_type (type->type);
  2841. refklass = mono_class_from_mono_type (reftype->type);
  2842. mono_ptr_array_init (tmp_array, 2);
  2843. handle_parent:
  2844. if (klass->exception_type != MONO_EXCEPTION_NONE) {
  2845. mono_ptr_array_destroy (tmp_array);
  2846. mono_raise_exception (mono_class_get_exception_for_failure (klass));
  2847. }
  2848. iter = NULL;
  2849. while ((field = mono_class_get_fields_lazy (klass, &iter))) {
  2850. guint32 flags = mono_field_get_flags (field);
  2851. match = 0;
  2852. if (mono_field_is_deleted_with_flags (field, flags))
  2853. continue;
  2854. if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
  2855. if (bflags & BFLAGS_Public)
  2856. match++;
  2857. } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
  2858. if (bflags & BFLAGS_NonPublic) {
  2859. match++;
  2860. }
  2861. }
  2862. if (!match)
  2863. continue;
  2864. match = 0;
  2865. if (flags & FIELD_ATTRIBUTE_STATIC) {
  2866. if (bflags & BFLAGS_Static)
  2867. if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
  2868. match++;
  2869. } else {
  2870. if (bflags & BFLAGS_Instance)
  2871. match++;
  2872. }
  2873. if (!match)
  2874. continue;
  2875. member = (MonoObject*)mono_field_get_object (domain, refklass, field);
  2876. mono_ptr_array_append (tmp_array, member);
  2877. }
  2878. if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
  2879. goto handle_parent;
  2880. res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
  2881. for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
  2882. mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
  2883. mono_ptr_array_destroy (tmp_array);
  2884. return res;
  2885. }
  2886. static gboolean
  2887. method_nonpublic (MonoMethod* method, gboolean start_klass)
  2888. {
  2889. switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
  2890. case METHOD_ATTRIBUTE_ASSEM:
  2891. return (start_klass || mono_defaults.generic_ilist_class);
  2892. case METHOD_ATTRIBUTE_PRIVATE:
  2893. return start_klass;
  2894. case METHOD_ATTRIBUTE_PUBLIC:
  2895. return FALSE;
  2896. default:
  2897. return TRUE;
  2898. }
  2899. }
  2900. GPtrArray*
  2901. mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
  2902. {
  2903. GPtrArray *array;
  2904. MonoClass *startklass;
  2905. MonoMethod *method;
  2906. gpointer iter;
  2907. int len, match, nslots;
  2908. /*FIXME, use MonoBitSet*/
  2909. guint32 method_slots_default [8];
  2910. guint32 *method_slots = NULL;
  2911. int (*compare_func) (const char *s1, const char *s2) = NULL;
  2912. array = g_ptr_array_new ();
  2913. startklass = klass;
  2914. *ex = NULL;
  2915. len = 0;
  2916. if (name != NULL)
  2917. compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
  2918. /* An optimization for calls made from Delegate:CreateDelegate () */
  2919. if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
  2920. method = mono_get_delegate_invoke (klass);
  2921. if (mono_loader_get_last_error ())
  2922. goto loader_error;
  2923. g_ptr_array_add (array, method);
  2924. return array;
  2925. }
  2926. mono_class_setup_vtable (klass);
  2927. if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
  2928. goto loader_error;
  2929. if (is_generic_parameter (&klass->byval_arg))
  2930. nslots = mono_class_get_vtable_size (klass->parent);
  2931. else
  2932. nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
  2933. if (nslots >= sizeof (method_slots_default) * 8) {
  2934. method_slots = g_new0 (guint32, nslots / 32 + 1);
  2935. } else {
  2936. method_slots = method_slots_default;
  2937. memset (method_slots, 0, sizeof (method_slots_default));
  2938. }
  2939. handle_parent:
  2940. mono_class_setup_vtable (klass);
  2941. if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
  2942. goto loader_error;
  2943. iter = NULL;
  2944. while ((method = mono_class_get_methods (klass, &iter))) {
  2945. match = 0;
  2946. if (method->slot != -1) {
  2947. g_assert (method->slot < nslots);
  2948. if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
  2949. continue;
  2950. if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
  2951. method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
  2952. }
  2953. if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
  2954. continue;
  2955. if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
  2956. if (bflags & BFLAGS_Public)
  2957. match++;
  2958. } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
  2959. match++;
  2960. }
  2961. if (!match)
  2962. continue;
  2963. match = 0;
  2964. if (method->flags & METHOD_ATTRIBUTE_STATIC) {
  2965. if (bflags & BFLAGS_Static)
  2966. if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
  2967. match++;
  2968. } else {
  2969. if (bflags & BFLAGS_Instance)
  2970. match++;
  2971. }
  2972. if (!match)
  2973. continue;
  2974. if (name != NULL) {
  2975. if (compare_func (name, method->name))
  2976. continue;
  2977. }
  2978. match = 0;
  2979. g_ptr_array_add (array, method);
  2980. }
  2981. if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
  2982. goto handle_parent;
  2983. if (method_slots != method_slots_default)
  2984. g_free (method_slots);
  2985. return array;
  2986. loader_error:
  2987. if (method_slots != method_slots_default)
  2988. g_free (method_slots);
  2989. g_ptr_array_free (array, TRUE);
  2990. if (klass->exception_type != MONO_EXCEPTION_NONE) {
  2991. *ex = mono_class_get_exception_for_failure (klass);
  2992. } else {
  2993. *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
  2994. mono_loader_clear_error ();
  2995. }
  2996. return NULL;
  2997. }
  2998. ICALL_EXPORT MonoArray*
  2999. ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
  3000. {
  3001. static MonoClass *MethodInfo_array;
  3002. MonoDomain *domain;
  3003. MonoArray *res;
  3004. MonoVTable *array_vtable;
  3005. MonoException *ex = NULL;
  3006. const char *mname = NULL;
  3007. GPtrArray *method_array;
  3008. MonoClass *klass, *refklass;
  3009. int i;
  3010. if (!MethodInfo_array) {
  3011. MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
  3012. mono_memory_barrier ();
  3013. MethodInfo_array = klass;
  3014. }
  3015. klass = mono_class_from_mono_type (type->type);
  3016. refklass = mono_class_from_mono_type (reftype->type);
  3017. domain = ((MonoObject *)type)->vtable->domain;
  3018. array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
  3019. if (type->type->byref)
  3020. return mono_array_new_specific (array_vtable, 0);
  3021. if (name)
  3022. mname = mono_string_to_utf8 (name);
  3023. method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
  3024. g_free ((char*)mname);
  3025. if (ex)
  3026. mono_raise_exception (ex);
  3027. res = mono_array_new_specific (array_vtable, method_array->len);
  3028. for (i = 0; i < method_array->len; ++i) {
  3029. MonoMethod *method = g_ptr_array_index (method_array, i);
  3030. mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
  3031. }
  3032. g_ptr_array_free (method_array, TRUE);
  3033. return res;
  3034. }
  3035. ICALL_EXPORT MonoArray*
  3036. ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
  3037. {
  3038. MonoDomain *domain;
  3039. static MonoClass *System_Reflection_ConstructorInfo;
  3040. MonoClass *startklass, *klass, *refklass;
  3041. MonoArray *res;
  3042. MonoMethod *method;
  3043. MonoObject *member;
  3044. int i, match;
  3045. gpointer iter = NULL;
  3046. MonoPtrArray tmp_array;
  3047. MONO_ARCH_SAVE_REGS;
  3048. mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
  3049. domain = ((MonoObject *)type)->vtable->domain;
  3050. if (type->type->byref)
  3051. return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
  3052. klass = startklass = mono_class_from_mono_type (type->type);
  3053. refklass = mono_class_from_mono_type (reftype->type);
  3054. if (!System_Reflection_ConstructorInfo)
  3055. System_Reflection_ConstructorInfo = mono_class_from_name (
  3056. mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
  3057. iter = NULL;
  3058. while ((method = mono_class_get_methods (klass, &iter))) {
  3059. match = 0;
  3060. if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
  3061. continue;
  3062. if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
  3063. if (bflags & BFLAGS_Public)
  3064. match++;
  3065. } else {
  3066. if (bflags & BFLAGS_NonPublic)
  3067. match++;
  3068. }
  3069. if (!match)
  3070. continue;
  3071. match = 0;
  3072. if (method->flags & METHOD_ATTRIBUTE_STATIC) {
  3073. if (bflags & BFLAGS_Static)
  3074. if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
  3075. match++;
  3076. } else {
  3077. if (bflags & BFLAGS_Instance)
  3078. match++;
  3079. }
  3080. if (!match)
  3081. continue;
  3082. member = (MonoObject*)mono_method_get_object (domain, method, refklass);
  3083. mono_ptr_array_append (tmp_array, member);
  3084. }
  3085. res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
  3086. for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
  3087. mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
  3088. mono_ptr_array_destroy (tmp_array);
  3089. return res;
  3090. }
  3091. static guint
  3092. property_hash (gconstpointer data)
  3093. {
  3094. MonoProperty *prop = (MonoProperty*)data;
  3095. return g_str_hash (prop->name);
  3096. }
  3097. static gboolean
  3098. property_equal (MonoProperty *prop1, MonoProperty *prop2)
  3099. {
  3100. // Properties are hide-by-name-and-signature
  3101. if (!g_str_equal (prop1->name, prop2->name))
  3102. return FALSE;
  3103. if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
  3104. return FALSE;
  3105. if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
  3106. return FALSE;
  3107. return TRUE;
  3108. }
  3109. static gboolean
  3110. property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
  3111. {
  3112. if (!accessor)
  3113. return FALSE;
  3114. return method_nonpublic (accessor, start_klass);
  3115. }
  3116. ICALL_EXPORT MonoArray*
  3117. ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
  3118. {
  3119. MonoException *ex;
  3120. MonoDomain *domain;
  3121. static MonoClass *System_Reflection_PropertyInfo;
  3122. MonoClass *startklass, *klass;
  3123. MonoArray *res;
  3124. MonoMethod *method;
  3125. MonoProperty *prop;
  3126. int i, match;
  3127. guint32 flags;
  3128. gchar *propname = NULL;
  3129. int (*compare_func) (const char *s1, const char *s2) = NULL;
  3130. gpointer iter;
  3131. GHashTable *properties = NULL;
  3132. MonoPtrArray tmp_array;
  3133. MONO_ARCH_SAVE_REGS;
  3134. mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
  3135. if (!System_Reflection_PropertyInfo)
  3136. System_Reflection_PropertyInfo = mono_class_from_name (
  3137. mono_defaults.corlib, "System.Reflection", "PropertyInfo");
  3138. domain = ((MonoObject *)type)->vtable->domain;
  3139. if (type->type->byref)
  3140. return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
  3141. klass = startklass = mono_class_from_mono_type (type->type);
  3142. if (name != NULL) {
  3143. propname = mono_string_to_utf8 (name);
  3144. compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
  3145. }
  3146. properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
  3147. handle_parent:
  3148. mono_class_setup_vtable (klass);
  3149. if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
  3150. goto loader_error;
  3151. iter = NULL;
  3152. while ((prop = mono_class_get_properties (klass, &iter))) {
  3153. match = 0;
  3154. method = prop->get;
  3155. if (!method)
  3156. method = prop->set;
  3157. if (method)
  3158. flags = method->flags;
  3159. else
  3160. flags = 0;
  3161. if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
  3162. (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
  3163. if (bflags & BFLAGS_Public)
  3164. match++;
  3165. } else if (bflags & BFLAGS_NonPublic) {
  3166. if (property_accessor_nonpublic(prop->get, startklass == klass) ||
  3167. property_accessor_nonpublic(prop->set, startklass == klass)) {
  3168. match++;
  3169. }
  3170. }
  3171. if (!match)
  3172. continue;
  3173. match = 0;
  3174. if (flags & METHOD_ATTRIBUTE_STATIC) {
  3175. if (bflags & BFLAGS_Static)
  3176. if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
  3177. match++;
  3178. } else {
  3179. if (bflags & BFLAGS_Instance)
  3180. match++;
  3181. }
  3182. if (!match)
  3183. continue;
  3184. match = 0;
  3185. if (name != NULL) {
  3186. if (compare_func (propname, prop->name))
  3187. continue;
  3188. }
  3189. if (g_hash_table_lookup (properties, prop))
  3190. continue;
  3191. mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
  3192. g_hash_table_insert (properties, prop, prop);
  3193. }
  3194. if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
  3195. goto handle_parent;
  3196. g_hash_table_destroy (properties);
  3197. g_free (propname);
  3198. res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
  3199. for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
  3200. mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
  3201. mono_ptr_array_destroy (tmp_array);
  3202. return res;
  3203. loader_error:
  3204. if (properties)
  3205. g_hash_table_destroy (properties);
  3206. if (name)
  3207. g_free (propname);
  3208. mono_ptr_array_destroy (tmp_array);
  3209. if (klass->exception_type != MONO_EXCEPTION_NONE) {
  3210. ex = mono_class_get_exception_for_failure (klass);
  3211. } else {
  3212. ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
  3213. mono_loader_clear_error ();
  3214. }
  3215. mono_raise_exception (ex);
  3216. return NULL;
  3217. }
  3218. ICALL_EXPORT MonoReflectionEvent *
  3219. ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
  3220. {
  3221. MonoDomain *domain;
  3222. MonoClass *klass, *startklass;
  3223. gpointer iter;
  3224. MonoEvent *event;
  3225. MonoMethod *method;
  3226. gchar *event_name;
  3227. int (*compare_func) (const char *s1, const char *s2);
  3228. MONO_ARCH_SAVE_REGS;
  3229. event_name = mono_string_to_utf8 (name);
  3230. if (type->type->byref)
  3231. return NULL;
  3232. klass = startklass = mono_class_from_mono_type (type->type);
  3233. domain = mono_object_domain (type);
  3234. mono_class_init_or_throw (klass);
  3235. compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
  3236. handle_parent:
  3237. if (klass->exception_type != MONO_EXCEPTION_NONE)
  3238. mono_raise_exception (mono_class_get_exception_for_failure (klass));
  3239. iter = NULL;
  3240. while ((event = mono_class_get_events (klass, &iter))) {
  3241. if (compare_func (event->name, event_name))
  3242. continue;
  3243. method = event->add;
  3244. if (!method)
  3245. method = event->remove;
  3246. if (!method)
  3247. method = event->raise;
  3248. if (method) {
  3249. if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
  3250. if (!(bflags & BFLAGS_Public))
  3251. continue;
  3252. } else {
  3253. if (!(bflags & BFLAGS_NonPublic))
  3254. continue;
  3255. if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
  3256. continue;
  3257. }
  3258. if (method->flags & METHOD_ATTRIBUTE_STATIC) {
  3259. if (!(bflags & BFLAGS_Static))
  3260. continue;
  3261. if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
  3262. continue;
  3263. } else {
  3264. if (!(bflags & BFLAGS_Instance))
  3265. continue;
  3266. }
  3267. } else
  3268. if (!(bflags & BFLAGS_NonPublic))
  3269. continue;
  3270. g_free (event_name);
  3271. return mono_event_get_object (domain, startklass, event);
  3272. }
  3273. if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
  3274. goto handle_parent;
  3275. g_free (event_name);
  3276. return NULL;
  3277. }
  3278. ICALL_EXPORT MonoArray*
  3279. ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
  3280. {
  3281. MonoException *ex;
  3282. MonoDomain *domain;
  3283. static MonoClass *System_Reflection_EventInfo;
  3284. MonoClass *startklass, *klass;
  3285. MonoArray *res;
  3286. MonoMethod *method;
  3287. MonoEvent *event;
  3288. int i, match;
  3289. gpointer iter;
  3290. MonoPtrArray tmp_array;
  3291. MONO_ARCH_SAVE_REGS;
  3292. mono_ptr_array_init (tmp_array, 4);
  3293. if (!System_Reflection_EventInfo)
  3294. System_Reflection_EventInfo = mono_class_from_name (
  3295. mono_defaults.corlib, "System.Reflection", "EventInfo");
  3296. domain = mono_object_domain (type);
  3297. if (type->type->byref)
  3298. return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
  3299. klass = startklass = mono_class_from_mono_type (type->type);
  3300. handle_parent:
  3301. mono_class_setup_vtable (klass);
  3302. if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
  3303. goto loader_error;
  3304. iter = NULL;
  3305. while ((event = mono_class_get_events (klass, &iter))) {
  3306. match = 0;
  3307. method = event->add;
  3308. if (!method)
  3309. method = event->remove;
  3310. if (!method)
  3311. method = event->raise;
  3312. if (method) {
  3313. if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
  3314. if (bflags & BFLAGS_Public)
  3315. match++;
  3316. } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
  3317. if (bflags & BFLAGS_NonPublic)
  3318. match++;
  3319. }
  3320. }
  3321. else
  3322. if (bflags & BFLAGS_NonPublic)
  3323. match ++;
  3324. if (!match)
  3325. continue;
  3326. match = 0;
  3327. if (method) {
  3328. if (method->flags & METHOD_ATTRIBUTE_STATIC) {
  3329. if (bflags & BFLAGS_Static)
  3330. if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
  3331. match++;
  3332. } else {
  3333. if (bflags & BFLAGS_Instance)
  3334. match++;
  3335. }
  3336. }
  3337. else
  3338. if (bflags & BFLAGS_Instance)
  3339. match ++;
  3340. if (!match)
  3341. continue;
  3342. mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
  3343. }
  3344. if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
  3345. goto handle_parent;
  3346. res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
  3347. for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
  3348. mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
  3349. mono_ptr_array_destroy (tmp_array);
  3350. return res;
  3351. loader_error:
  3352. mono_ptr_array_destroy (tmp_array);
  3353. if (klass->exception_type != MONO_EXCEPTION_NONE) {
  3354. ex = mono_class_get_exception_for_failure (klass);
  3355. } else {
  3356. ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
  3357. mono_loader_clear_error ();
  3358. }
  3359. mono_raise_exception (ex);
  3360. return NULL;
  3361. }
  3362. ICALL_EXPORT MonoReflectionType *
  3363. ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
  3364. {
  3365. MonoDomain *domain;
  3366. MonoClass *klass;
  3367. MonoClass *nested;
  3368. char *str;
  3369. gpointer iter;
  3370. MONO_ARCH_SAVE_REGS;
  3371. if (name == NULL)
  3372. mono_raise_exception (mono_get_exception_argument_null ("name"));
  3373. domain = ((MonoObject *)type)->vtable->domain;
  3374. if (type->type->byref)
  3375. return NULL;
  3376. klass = mono_class_from_mono_type (type->type);
  3377. str = mono_string_to_utf8 (name);
  3378. handle_parent:
  3379. if (klass->exception_type != MONO_EXCEPTION_NONE)
  3380. mono_raise_exception (mono_class_get_exception_for_failure (klass));
  3381. /*
  3382. * If a nested type is generic, return its generic type definition.
  3383. * Note that this means that the return value is essentially a
  3384. * nested type of the generic type definition of @klass.
  3385. *
  3386. * A note in MSDN claims that a generic type definition can have
  3387. * nested types that aren't generic. In any case, the container of that
  3388. * nested type would be the generic type definition.
  3389. */
  3390. if (klass->generic_class)
  3391. klass = klass->generic_class->container_class;
  3392. iter = NULL;
  3393. while ((nested = mono_class_get_nested_types (klass, &iter))) {
  3394. int match = 0;
  3395. if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
  3396. if (bflags & BFLAGS_Public)
  3397. match++;
  3398. } else {
  3399. if (bflags & BFLAGS_NonPublic)
  3400. match++;
  3401. }
  3402. if (!match)
  3403. continue;
  3404. if (strcmp (nested->name, str) == 0){
  3405. g_free (str);
  3406. return mono_type_get_object (domain, &nested->byval_arg);
  3407. }
  3408. }
  3409. if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
  3410. goto handle_parent;
  3411. g_free (str);
  3412. return NULL;
  3413. }
  3414. ICALL_EXPORT MonoArray*
  3415. ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
  3416. {
  3417. MonoDomain *domain;
  3418. MonoClass *klass;
  3419. MonoArray *res;
  3420. MonoObject *member;
  3421. int i, match;
  3422. MonoClass *nested;
  3423. gpointer iter;
  3424. MonoPtrArray tmp_array;
  3425. MONO_ARCH_SAVE_REGS;
  3426. domain = ((MonoObject *)type)->vtable->domain;
  3427. if (type->type->byref)
  3428. return mono_array_new (domain, mono_defaults.monotype_class, 0);
  3429. klass = mono_class_from_mono_type (type->type);
  3430. /*
  3431. * If a nested type is generic, return its generic type definition.
  3432. * Note that this means that the return value is essentially the set
  3433. * of nested types of the generic type definition of @klass.
  3434. *
  3435. * A note in MSDN claims that a generic type definition can have
  3436. * nested types that aren't generic. In any case, the container of that
  3437. * nested type would be the generic type definition.
  3438. */
  3439. if (klass->generic_class)
  3440. klass = klass->generic_class->container_class;
  3441. mono_ptr_array_init (tmp_array, 1);
  3442. iter = NULL;
  3443. while ((nested = mono_class_get_nested_types (klass, &iter))) {
  3444. match = 0;
  3445. if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
  3446. if (bflags & BFLAGS_Public)
  3447. match++;
  3448. } else {
  3449. if (bflags & BFLAGS_NonPublic)
  3450. match++;
  3451. }
  3452. if (!match)
  3453. continue;
  3454. member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
  3455. mono_ptr_array_append (tmp_array, member);
  3456. }
  3457. res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
  3458. for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
  3459. mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
  3460. mono_ptr_array_destroy (tmp_array);
  3461. return res;
  3462. }
  3463. ICALL_EXPORT MonoReflectionType*
  3464. ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
  3465. {
  3466. gchar *str;
  3467. MonoType *type = NULL;
  3468. MonoTypeNameParse info;
  3469. gboolean type_resolve;
  3470. MONO_ARCH_SAVE_REGS;
  3471. /* On MS.NET, this does not fire a TypeResolve event */
  3472. type_resolve = TRUE;
  3473. str = mono_string_to_utf8 (name);
  3474. /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
  3475. if (!mono_reflection_parse_type (str, &info)) {
  3476. g_free (str);
  3477. mono_reflection_free_type_info (&info);
  3478. if (throwOnError) /* uhm: this is a parse error, though... */
  3479. mono_raise_exception (mono_get_exception_type_load (name, NULL));
  3480. /*g_print ("failed parse\n");*/
  3481. return NULL;
  3482. }
  3483. if (info.assembly.name) {
  3484. g_free (str);
  3485. mono_reflection_free_type_info (&info);
  3486. if (throwOnError) {
  3487. /* 1.0 and 2.0 throw different exceptions */
  3488. if (mono_defaults.generic_ilist_class)
  3489. mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
  3490. else
  3491. mono_raise_exception (mono_get_exception_type_load (name, NULL));
  3492. }
  3493. return NULL;
  3494. }
  3495. if (module != NULL) {
  3496. if (module->image)
  3497. type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
  3498. else
  3499. type = NULL;
  3500. }
  3501. else
  3502. if (assembly->assembly->dynamic) {
  3503. /* Enumerate all modules */
  3504. MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
  3505. int i;
  3506. type = NULL;
  3507. if (abuilder->modules) {
  3508. for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
  3509. MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
  3510. type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
  3511. if (type)
  3512. break;
  3513. }
  3514. }
  3515. if (!type && abuilder->loaded_modules) {
  3516. for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
  3517. MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
  3518. type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
  3519. if (type)
  3520. break;
  3521. }
  3522. }
  3523. }
  3524. else
  3525. type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
  3526. g_free (str);
  3527. mono_reflection_free_type_info (&info);
  3528. if (!type) {
  3529. MonoException *e = NULL;
  3530. if (throwOnError)
  3531. e = mono_get_exception_type_load (name, NULL);
  3532. if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
  3533. e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
  3534. mono_loader_clear_error ();
  3535. if (e != NULL)
  3536. mono_raise_exception (e);
  3537. return NULL;
  3538. } else if (mono_loader_get_last_error ()) {
  3539. if (throwOnError)
  3540. mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
  3541. mono_loader_clear_error ();
  3542. }
  3543. if (type->type == MONO_TYPE_CLASS) {
  3544. MonoClass *klass = mono_type_get_class (type);
  3545. if (mono_is_security_manager_active () && !klass->exception_type)
  3546. /* Some security problems are detected during generic vtable construction */
  3547. mono_class_setup_vtable (klass);
  3548. /* need to report exceptions ? */
  3549. if (throwOnError && klass->exception_type) {
  3550. /* report SecurityException (or others) that occured when loading the assembly */
  3551. MonoException *exc = mono_class_get_exception_for_failure (klass);
  3552. mono_loader_clear_error ();
  3553. mono_raise_exception (exc);
  3554. } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
  3555. return NULL;
  3556. }
  3557. }
  3558. /* g_print ("got it\n"); */
  3559. return mono_type_get_object (mono_object_domain (assembly), type);
  3560. }
  3561. static gboolean
  3562. replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
  3563. {
  3564. gchar *content;
  3565. gchar *shadow_ini_file;
  3566. gsize len;
  3567. /* Check for shadow-copied assembly */
  3568. if (mono_is_shadow_copy_enabled (domain, dirname)) {
  3569. shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
  3570. content = NULL;
  3571. if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
  3572. !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
  3573. if (content) {
  3574. g_free (content);
  3575. content = NULL;
  3576. }
  3577. }
  3578. g_free (shadow_ini_file);
  3579. if (content != NULL) {
  3580. if (*filename)
  3581. g_free (*filename);
  3582. *filename = content;
  3583. return TRUE;
  3584. }
  3585. }
  3586. return FALSE;
  3587. }
  3588. ICALL_EXPORT MonoString *
  3589. ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
  3590. {
  3591. MonoDomain *domain = mono_object_domain (assembly);
  3592. MonoAssembly *mass = assembly->assembly;
  3593. MonoString *res = NULL;
  3594. gchar *uri;
  3595. gchar *absolute;
  3596. gchar *dirname;
  3597. MONO_ARCH_SAVE_REGS;
  3598. if (g_path_is_absolute (mass->image->name)) {
  3599. absolute = g_strdup (mass->image->name);
  3600. dirname = g_path_get_dirname (absolute);
  3601. } else {
  3602. absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
  3603. dirname = g_strdup (mass->basedir);
  3604. }
  3605. replace_shadow_path (domain, dirname, &absolute);
  3606. g_free (dirname);
  3607. #if HOST_WIN32
  3608. {
  3609. gint i;
  3610. for (i = strlen (absolute) - 1; i >= 0; i--)
  3611. if (absolute [i] == '\\')
  3612. absolute [i] = '/';
  3613. }
  3614. #endif
  3615. if (escaped) {
  3616. uri = g_filename_to_uri (absolute, NULL, NULL);
  3617. } else {
  3618. const char *prepend = "file://";
  3619. #if HOST_WIN32
  3620. if (*absolute == '/' && *(absolute + 1) == '/') {
  3621. prepend = "file:";
  3622. } else {
  3623. prepend = "file:///";
  3624. }
  3625. #endif
  3626. uri = g_strconcat (prepend, absolute, NULL);
  3627. }
  3628. if (uri) {
  3629. res = mono_string_new (domain, uri);
  3630. g_free (uri);
  3631. }
  3632. g_free (absolute);
  3633. return res;
  3634. }
  3635. ICALL_EXPORT MonoBoolean
  3636. ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
  3637. {
  3638. MonoAssembly *mass = assembly->assembly;
  3639. MONO_ARCH_SAVE_REGS;
  3640. return mass->in_gac;
  3641. }
  3642. ICALL_EXPORT MonoReflectionAssembly*
  3643. ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
  3644. {
  3645. gchar *name;
  3646. MonoAssembly *res;
  3647. MonoImageOpenStatus status;
  3648. MONO_ARCH_SAVE_REGS;
  3649. name = mono_string_to_utf8 (mname);
  3650. res = mono_assembly_load_with_partial_name (name, &status);
  3651. g_free (name);
  3652. if (res == NULL)
  3653. return NULL;
  3654. return mono_assembly_get_object (mono_domain_get (), res);
  3655. }
  3656. ICALL_EXPORT MonoString *
  3657. ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
  3658. {
  3659. MonoDomain *domain = mono_object_domain (assembly);
  3660. MonoString *res;
  3661. MONO_ARCH_SAVE_REGS;
  3662. res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
  3663. return res;
  3664. }
  3665. ICALL_EXPORT MonoBoolean
  3666. ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
  3667. {
  3668. MONO_ARCH_SAVE_REGS;
  3669. return assembly->assembly->ref_only;
  3670. }
  3671. ICALL_EXPORT MonoString *
  3672. ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
  3673. {
  3674. MonoDomain *domain = mono_object_domain (assembly);
  3675. MONO_ARCH_SAVE_REGS;
  3676. return mono_string_new (domain, assembly->assembly->image->version);
  3677. }
  3678. ICALL_EXPORT MonoReflectionMethod*
  3679. ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
  3680. {
  3681. guint32 token = mono_image_get_entry_point (assembly->assembly->image);
  3682. MONO_ARCH_SAVE_REGS;
  3683. if (!token)
  3684. return NULL;
  3685. return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
  3686. }
  3687. ICALL_EXPORT MonoReflectionModule*
  3688. ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
  3689. {
  3690. return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
  3691. }
  3692. ICALL_EXPORT MonoArray*
  3693. ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
  3694. {
  3695. MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
  3696. MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
  3697. int i;
  3698. const char *val;
  3699. MONO_ARCH_SAVE_REGS;
  3700. for (i = 0; i < table->rows; ++i) {
  3701. val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
  3702. mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
  3703. }
  3704. return result;
  3705. }
  3706. static MonoObject*
  3707. create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
  3708. {
  3709. static MonoClass *System_Version = NULL;
  3710. static MonoMethod *create_version = NULL;
  3711. MonoObject *result;
  3712. gpointer args [4];
  3713. if (!System_Version) {
  3714. System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
  3715. g_assert (System_Version);
  3716. }
  3717. if (!create_version) {
  3718. MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
  3719. create_version = mono_method_desc_search_in_class (desc, System_Version);
  3720. g_assert (create_version);
  3721. mono_method_desc_free (desc);
  3722. }
  3723. args [0] = &major;
  3724. args [1] = &minor;
  3725. args [2] = &build;
  3726. args [3] = &revision;
  3727. result = mono_object_new (domain, System_Version);
  3728. mono_runtime_invoke (create_version, result, args, NULL);
  3729. return result;
  3730. }
  3731. ICALL_EXPORT MonoArray*
  3732. ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
  3733. {
  3734. static MonoClass *System_Reflection_AssemblyName;
  3735. MonoArray *result;
  3736. MonoDomain *domain = mono_object_domain (assembly);
  3737. int i, count = 0;
  3738. static MonoMethod *create_culture = NULL;
  3739. MonoImage *image = assembly->assembly->image;
  3740. MonoTableInfo *t;
  3741. MONO_ARCH_SAVE_REGS;
  3742. if (!System_Reflection_AssemblyName)
  3743. System_Reflection_AssemblyName = mono_class_from_name (
  3744. mono_defaults.corlib, "System.Reflection", "AssemblyName");
  3745. t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
  3746. count = t->rows;
  3747. result = mono_array_new (domain, System_Reflection_AssemblyName, count);
  3748. if (count > 0 && !create_culture) {
  3749. MonoMethodDesc *desc = mono_method_desc_new (
  3750. "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
  3751. create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
  3752. g_assert (create_culture);
  3753. mono_method_desc_free (desc);
  3754. }
  3755. for (i = 0; i < count; i++) {
  3756. MonoReflectionAssemblyName *aname;
  3757. guint32 cols [MONO_ASSEMBLYREF_SIZE];
  3758. mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
  3759. aname = (MonoReflectionAssemblyName *) mono_object_new (
  3760. domain, System_Reflection_AssemblyName);
  3761. MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
  3762. aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
  3763. aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
  3764. aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
  3765. aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
  3766. aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
  3767. aname->versioncompat = 1; /* SameMachine (default) */
  3768. aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
  3769. MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
  3770. if (create_culture) {
  3771. gpointer args [2];
  3772. MonoBoolean assembly_ref = 1;
  3773. args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
  3774. args [1] = &assembly_ref;
  3775. MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
  3776. }
  3777. if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
  3778. const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
  3779. guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
  3780. if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
  3781. /* public key token isn't copied - the class library will
  3782. automatically generate it from the public key if required */
  3783. MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
  3784. memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
  3785. } else {
  3786. MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
  3787. memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
  3788. }
  3789. } else {
  3790. MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
  3791. }
  3792. /* note: this function doesn't return the codebase on purpose (i.e. it can
  3793. be used under partial trust as path information isn't present). */
  3794. mono_array_setref (result, i, aname);
  3795. }
  3796. return result;
  3797. }
  3798. /* move this in some file in mono/util/ */
  3799. static char *
  3800. g_concat_dir_and_file (const char *dir, const char *file)
  3801. {
  3802. g_return_val_if_fail (dir != NULL, NULL);
  3803. g_return_val_if_fail (file != NULL, NULL);
  3804. /*
  3805. * If the directory name doesn't have a / on the end, we need
  3806. * to add one so we get a proper path to the file
  3807. */
  3808. if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
  3809. return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
  3810. else
  3811. return g_strconcat (dir, file, NULL);
  3812. }
  3813. ICALL_EXPORT void *
  3814. ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
  3815. {
  3816. char *n = mono_string_to_utf8 (name);
  3817. MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
  3818. guint32 i;
  3819. guint32 cols [MONO_MANIFEST_SIZE];
  3820. guint32 impl, file_idx;
  3821. const char *val;
  3822. MonoImage *module;
  3823. MONO_ARCH_SAVE_REGS;
  3824. for (i = 0; i < table->rows; ++i) {
  3825. mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
  3826. val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
  3827. if (strcmp (val, n) == 0)
  3828. break;
  3829. }
  3830. g_free (n);
  3831. if (i == table->rows)
  3832. return NULL;
  3833. /* FIXME */
  3834. impl = cols [MONO_MANIFEST_IMPLEMENTATION];
  3835. if (impl) {
  3836. /*
  3837. * this code should only be called after obtaining the
  3838. * ResourceInfo and handling the other cases.
  3839. */
  3840. g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
  3841. file_idx = impl >> MONO_IMPLEMENTATION_BITS;
  3842. module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
  3843. if (!module)
  3844. return NULL;
  3845. }
  3846. else
  3847. module = assembly->assembly->image;
  3848. mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
  3849. return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
  3850. }
  3851. ICALL_EXPORT gboolean
  3852. ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
  3853. {
  3854. MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
  3855. int i;
  3856. guint32 cols [MONO_MANIFEST_SIZE];
  3857. guint32 file_cols [MONO_FILE_SIZE];
  3858. const char *val;
  3859. char *n;
  3860. MONO_ARCH_SAVE_REGS;
  3861. n = mono_string_to_utf8 (name);
  3862. for (i = 0; i < table->rows; ++i) {
  3863. mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
  3864. val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
  3865. if (strcmp (val, n) == 0)
  3866. break;
  3867. }
  3868. g_free (n);
  3869. if (i == table->rows)
  3870. return FALSE;
  3871. if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
  3872. info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
  3873. }
  3874. else {
  3875. switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
  3876. case MONO_IMPLEMENTATION_FILE:
  3877. i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
  3878. table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
  3879. mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
  3880. val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
  3881. MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
  3882. if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
  3883. info->location = 0;
  3884. else
  3885. info->location = RESOURCE_LOCATION_EMBEDDED;
  3886. break;
  3887. case MONO_IMPLEMENTATION_ASSEMBLYREF:
  3888. i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
  3889. mono_assembly_load_reference (assembly->assembly->image, i - 1);
  3890. if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
  3891. char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
  3892. MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
  3893. g_free (msg);
  3894. mono_raise_exception (ex);
  3895. }
  3896. MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
  3897. /* Obtain info recursively */
  3898. ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
  3899. info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
  3900. break;
  3901. case MONO_IMPLEMENTATION_EXP_TYPE:
  3902. g_assert_not_reached ();
  3903. break;
  3904. }
  3905. }
  3906. return TRUE;
  3907. }
  3908. ICALL_EXPORT MonoObject*
  3909. ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
  3910. {
  3911. MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
  3912. MonoArray *result = NULL;
  3913. int i, count;
  3914. const char *val;
  3915. char *n;
  3916. MONO_ARCH_SAVE_REGS;
  3917. /* check hash if needed */
  3918. if (name) {
  3919. n = mono_string_to_utf8 (name);
  3920. for (i = 0; i < table->rows; ++i) {
  3921. val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
  3922. if (strcmp (val, n) == 0) {
  3923. MonoString *fn;
  3924. g_free (n);
  3925. n = g_concat_dir_and_file (assembly->assembly->basedir, val);
  3926. fn = mono_string_new (mono_object_domain (assembly), n);
  3927. g_free (n);
  3928. return (MonoObject*)fn;
  3929. }
  3930. }
  3931. g_free (n);
  3932. return NULL;
  3933. }
  3934. count = 0;
  3935. for (i = 0; i < table->rows; ++i) {
  3936. if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
  3937. count ++;
  3938. }
  3939. result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
  3940. count = 0;
  3941. for (i = 0; i < table->rows; ++i) {
  3942. if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
  3943. val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
  3944. n = g_concat_dir_and_file (assembly->assembly->basedir, val);
  3945. mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
  3946. g_free (n);
  3947. count ++;
  3948. }
  3949. }
  3950. return (MonoObject*)result;
  3951. }
  3952. ICALL_EXPORT MonoArray*
  3953. ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
  3954. {
  3955. MonoDomain *domain = mono_domain_get();
  3956. MonoArray *res;
  3957. MonoClass *klass;
  3958. int i, j, file_count = 0;
  3959. MonoImage **modules;
  3960. guint32 module_count, real_module_count;
  3961. MonoTableInfo *table;
  3962. guint32 cols [MONO_FILE_SIZE];
  3963. MonoImage *image = assembly->assembly->image;
  3964. g_assert (image != NULL);
  3965. g_assert (!assembly->assembly->dynamic);
  3966. table = &image->tables [MONO_TABLE_FILE];
  3967. file_count = table->rows;
  3968. modules = image->modules;
  3969. module_count = image->module_count;
  3970. real_module_count = 0;
  3971. for (i = 0; i < module_count; ++i)
  3972. if (modules [i])
  3973. real_module_count ++;
  3974. klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
  3975. res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
  3976. mono_array_setref (res, 0, mono_module_get_object (domain, image));
  3977. j = 1;
  3978. for (i = 0; i < module_count; ++i)
  3979. if (modules [i]) {
  3980. mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
  3981. ++j;
  3982. }
  3983. for (i = 0; i < file_count; ++i, ++j) {
  3984. mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
  3985. if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
  3986. mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
  3987. else {
  3988. MonoImage *m = mono_image_load_file_for_image (image, i + 1);
  3989. if (!m) {
  3990. MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
  3991. mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
  3992. }
  3993. mono_array_setref (res, j, mono_module_get_object (domain, m));
  3994. }
  3995. }
  3996. return res;
  3997. }
  3998. ICALL_EXPORT MonoReflectionMethod*
  3999. ves_icall_GetCurrentMethod (void)
  4000. {
  4001. MonoMethod *m = mono_method_get_last_managed ();
  4002. while (m->is_inflated)
  4003. m = ((MonoMethodInflated*)m)->declaring;
  4004. return mono_method_get_object (mono_domain_get (), m, NULL);
  4005. }
  4006. static MonoMethod*
  4007. mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
  4008. {
  4009. int offset = -1, i;
  4010. if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
  4011. MonoMethodInflated *inflated = (MonoMethodInflated*)method;
  4012. //method is inflated, we should inflate it on the other class
  4013. MonoGenericContext ctx;
  4014. ctx.method_inst = inflated->context.method_inst;
  4015. ctx.class_inst = inflated->context.class_inst;
  4016. if (klass->generic_class)
  4017. ctx.class_inst = klass->generic_class->context.class_inst;
  4018. else if (klass->generic_container)
  4019. ctx.class_inst = klass->generic_container->context.class_inst;
  4020. return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
  4021. }
  4022. mono_class_setup_methods (method->klass);
  4023. if (method->klass->exception_type)
  4024. return NULL;
  4025. for (i = 0; i < method->klass->method.count; ++i) {
  4026. if (method->klass->methods [i] == method) {
  4027. offset = i;
  4028. break;
  4029. }
  4030. }
  4031. mono_class_setup_methods (klass);
  4032. if (klass->exception_type)
  4033. return NULL;
  4034. g_assert (offset >= 0 && offset < klass->method.count);
  4035. return klass->methods [offset];
  4036. }
  4037. ICALL_EXPORT MonoReflectionMethod*
  4038. ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
  4039. {
  4040. MonoClass *klass;
  4041. if (type) {
  4042. klass = mono_class_from_mono_type (type);
  4043. if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
  4044. return NULL;
  4045. if (method->klass != klass) {
  4046. method = mono_method_get_equivalent_method (method, klass);
  4047. if (!method)
  4048. return NULL;
  4049. }
  4050. } else
  4051. klass = method->klass;
  4052. return mono_method_get_object (mono_domain_get (), method, klass);
  4053. }
  4054. ICALL_EXPORT MonoReflectionMethod*
  4055. ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
  4056. {
  4057. return mono_method_get_object (mono_domain_get (), method, NULL);
  4058. }
  4059. ICALL_EXPORT MonoReflectionMethodBody*
  4060. ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
  4061. {
  4062. return mono_method_body_get_object (mono_domain_get (), method);
  4063. }
  4064. ICALL_EXPORT MonoReflectionAssembly*
  4065. ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
  4066. {
  4067. MonoMethod *dest = NULL;
  4068. MONO_ARCH_SAVE_REGS;
  4069. mono_stack_walk_no_il (get_executing, &dest);
  4070. return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
  4071. }
  4072. ICALL_EXPORT MonoReflectionAssembly*
  4073. ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
  4074. {
  4075. MonoDomain* domain = mono_domain_get ();
  4076. MONO_ARCH_SAVE_REGS;
  4077. if (!domain->entry_assembly)
  4078. return NULL;
  4079. return mono_assembly_get_object (domain, domain->entry_assembly);
  4080. }
  4081. ICALL_EXPORT MonoReflectionAssembly*
  4082. ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
  4083. {
  4084. MonoMethod *m;
  4085. MonoMethod *dest;
  4086. MONO_ARCH_SAVE_REGS;
  4087. dest = NULL;
  4088. mono_stack_walk_no_il (get_executing, &dest);
  4089. m = dest;
  4090. mono_stack_walk_no_il (get_caller, &dest);
  4091. if (!dest)
  4092. dest = m;
  4093. return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
  4094. }
  4095. ICALL_EXPORT MonoString *
  4096. ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
  4097. gboolean assembly_qualified)
  4098. {
  4099. MonoDomain *domain = mono_object_domain (object);
  4100. MonoTypeNameFormat format;
  4101. MonoString *res;
  4102. gchar *name;
  4103. if (full_name)
  4104. format = assembly_qualified ?
  4105. MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
  4106. MONO_TYPE_NAME_FORMAT_FULL_NAME;
  4107. else
  4108. format = MONO_TYPE_NAME_FORMAT_REFLECTION;
  4109. name = mono_type_get_name_full (object->type, format);
  4110. if (!name)
  4111. return NULL;
  4112. if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
  4113. g_free (name);
  4114. return NULL;
  4115. }
  4116. res = mono_string_new (domain, name);
  4117. g_free (name);
  4118. return res;
  4119. }
  4120. ICALL_EXPORT int
  4121. vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
  4122. {
  4123. MonoClass *klass = mono_class_from_mono_type (this->type);
  4124. mono_class_init_or_throw (klass);
  4125. return mono_security_core_clr_class_level (klass);
  4126. }
  4127. static void
  4128. fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
  4129. {
  4130. static MonoMethod *create_culture = NULL;
  4131. gpointer args [2];
  4132. guint32 pkey_len;
  4133. const char *pkey_ptr;
  4134. gchar *codebase;
  4135. MonoBoolean assembly_ref = 0;
  4136. MONO_ARCH_SAVE_REGS;
  4137. MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
  4138. aname->major = name->major;
  4139. aname->minor = name->minor;
  4140. aname->build = name->build;
  4141. aname->flags = name->flags;
  4142. aname->revision = name->revision;
  4143. aname->hashalg = name->hash_alg;
  4144. aname->versioncompat = 1; /* SameMachine (default) */
  4145. aname->processor_architecture = name->arch;
  4146. if (by_default_version)
  4147. MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
  4148. codebase = NULL;
  4149. if (absolute != NULL && *absolute != '\0') {
  4150. const gchar *prepend = "file://";
  4151. gchar *result;
  4152. codebase = g_strdup (absolute);
  4153. #if HOST_WIN32
  4154. {
  4155. gint i;
  4156. for (i = strlen (codebase) - 1; i >= 0; i--)
  4157. if (codebase [i] == '\\')
  4158. codebase [i] = '/';
  4159. if (*codebase == '/' && *(codebase + 1) == '/') {
  4160. prepend = "file:";
  4161. } else {
  4162. prepend = "file:///";
  4163. }
  4164. }
  4165. #endif
  4166. result = g_strconcat (prepend, codebase, NULL);
  4167. g_free (codebase);
  4168. codebase = result;
  4169. }
  4170. if (codebase) {
  4171. MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
  4172. g_free (codebase);
  4173. }
  4174. if (!create_culture) {
  4175. MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
  4176. create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
  4177. g_assert (create_culture);
  4178. mono_method_desc_free (desc);
  4179. }
  4180. if (name->culture) {
  4181. args [0] = mono_string_new (domain, name->culture);
  4182. args [1] = &assembly_ref;
  4183. MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
  4184. }
  4185. if (name->public_key) {
  4186. pkey_ptr = (char*)name->public_key;
  4187. pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
  4188. MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
  4189. memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
  4190. aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
  4191. } else if (default_publickey) {
  4192. MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
  4193. aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
  4194. }
  4195. /* MonoAssemblyName keeps the public key token as an hexadecimal string */
  4196. if (name->public_key_token [0]) {
  4197. int i, j;
  4198. char *p;
  4199. MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
  4200. p = mono_array_addr (aname->keyToken, char, 0);
  4201. for (i = 0, j = 0; i < 8; i++) {
  4202. *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
  4203. *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
  4204. p++;
  4205. }
  4206. } else if (default_token) {
  4207. MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
  4208. }
  4209. }
  4210. ICALL_EXPORT MonoString *
  4211. ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
  4212. {
  4213. MonoDomain *domain = mono_object_domain (assembly);
  4214. MonoAssembly *mass = assembly->assembly;
  4215. MonoString *res;
  4216. gchar *name;
  4217. name = mono_stringify_assembly_name (&mass->aname);
  4218. res = mono_string_new (domain, name);
  4219. g_free (name);
  4220. return res;
  4221. }
  4222. ICALL_EXPORT void
  4223. ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
  4224. {
  4225. gchar *absolute;
  4226. MonoAssembly *mass = assembly->assembly;
  4227. MONO_ARCH_SAVE_REGS;
  4228. if (g_path_is_absolute (mass->image->name)) {
  4229. fill_reflection_assembly_name (mono_object_domain (assembly),
  4230. aname, &mass->aname, mass->image->name, TRUE,
  4231. TRUE, TRUE);
  4232. return;
  4233. }
  4234. absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
  4235. fill_reflection_assembly_name (mono_object_domain (assembly),
  4236. aname, &mass->aname, absolute, TRUE, TRUE,
  4237. TRUE);
  4238. g_free (absolute);
  4239. }
  4240. ICALL_EXPORT void
  4241. ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
  4242. {
  4243. char *filename;
  4244. MonoImageOpenStatus status = MONO_IMAGE_OK;
  4245. gboolean res;
  4246. MonoImage *image;
  4247. MonoAssemblyName name;
  4248. char *dirname
  4249. MONO_ARCH_SAVE_REGS;
  4250. filename = mono_string_to_utf8 (fname);
  4251. dirname = g_path_get_dirname (filename);
  4252. replace_shadow_path (mono_domain_get (), dirname, &filename);
  4253. g_free (dirname);
  4254. image = mono_image_open (filename, &status);
  4255. if (!image){
  4256. MonoException *exc;
  4257. g_free (filename);
  4258. if (status == MONO_IMAGE_IMAGE_INVALID)
  4259. exc = mono_get_exception_bad_image_format2 (NULL, fname);
  4260. else
  4261. exc = mono_get_exception_file_not_found2 (NULL, fname);
  4262. mono_raise_exception (exc);
  4263. }
  4264. res = mono_assembly_fill_assembly_name (image, &name);
  4265. if (!res) {
  4266. mono_image_close (image);
  4267. g_free (filename);
  4268. mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
  4269. }
  4270. fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
  4271. TRUE, FALSE, TRUE);
  4272. g_free (filename);
  4273. mono_image_close (image);
  4274. }
  4275. ICALL_EXPORT MonoBoolean
  4276. ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
  4277. char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
  4278. {
  4279. MonoBoolean result = FALSE;
  4280. MonoDeclSecurityEntry entry;
  4281. /* SecurityAction.RequestMinimum */
  4282. if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
  4283. *minimum = entry.blob;
  4284. *minLength = entry.size;
  4285. result = TRUE;
  4286. }
  4287. /* SecurityAction.RequestOptional */
  4288. if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
  4289. *optional = entry.blob;
  4290. *optLength = entry.size;
  4291. result = TRUE;
  4292. }
  4293. /* SecurityAction.RequestRefuse */
  4294. if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
  4295. *refused = entry.blob;
  4296. *refLength = entry.size;
  4297. result = TRUE;
  4298. }
  4299. return result;
  4300. }
  4301. static MonoArray*
  4302. mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
  4303. {
  4304. MonoArray *res;
  4305. MonoClass *klass;
  4306. MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
  4307. int i, count;
  4308. guint32 attrs, visibility;
  4309. /* we start the count from 1 because we skip the special type <Module> */
  4310. if (exportedOnly) {
  4311. count = 0;
  4312. for (i = 1; i < tdef->rows; ++i) {
  4313. attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
  4314. visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
  4315. if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
  4316. count++;
  4317. }
  4318. } else {
  4319. count = tdef->rows - 1;
  4320. }
  4321. res = mono_array_new (domain, mono_defaults.monotype_class, count);
  4322. *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
  4323. count = 0;
  4324. for (i = 1; i < tdef->rows; ++i) {
  4325. attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
  4326. visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
  4327. if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
  4328. klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
  4329. if (klass) {
  4330. mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
  4331. } else {
  4332. MonoLoaderError *error;
  4333. MonoException *ex;
  4334. error = mono_loader_get_last_error ();
  4335. g_assert (error != NULL);
  4336. ex = mono_loader_error_prepare_exception (error);
  4337. mono_array_setref (*exceptions, count, ex);
  4338. }
  4339. if (mono_loader_get_last_error ())
  4340. mono_loader_clear_error ();
  4341. count++;
  4342. }
  4343. }
  4344. return res;
  4345. }
  4346. ICALL_EXPORT MonoArray*
  4347. ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
  4348. {
  4349. MonoArray *res = NULL;
  4350. MonoArray *exceptions = NULL;
  4351. MonoImage *image = NULL;
  4352. MonoTableInfo *table = NULL;
  4353. MonoDomain *domain;
  4354. GList *list = NULL;
  4355. int i, len, ex_count;
  4356. MONO_ARCH_SAVE_REGS;
  4357. domain = mono_object_domain (assembly);
  4358. g_assert (!assembly->assembly->dynamic);
  4359. image = assembly->assembly->image;
  4360. table = &image->tables [MONO_TABLE_FILE];
  4361. res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
  4362. /* Append data from all modules in the assembly */
  4363. for (i = 0; i < table->rows; ++i) {
  4364. if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
  4365. MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
  4366. if (loaded_image) {
  4367. MonoArray *ex2;
  4368. MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
  4369. /* Append the new types to the end of the array */
  4370. if (mono_array_length (res2) > 0) {
  4371. guint32 len1, len2;
  4372. MonoArray *res3, *ex3;
  4373. len1 = mono_array_length (res);
  4374. len2 = mono_array_length (res2);
  4375. res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
  4376. mono_array_memcpy_refs (res3, 0, res, 0, len1);
  4377. mono_array_memcpy_refs (res3, len1, res2, 0, len2);
  4378. res = res3;
  4379. ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
  4380. mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
  4381. mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
  4382. exceptions = ex3;
  4383. }
  4384. }
  4385. }
  4386. }
  4387. /* the ReflectionTypeLoadException must have all the types (Types property),
  4388. * NULL replacing types which throws an exception. The LoaderException must
  4389. * contain all exceptions for NULL items.
  4390. */
  4391. len = mono_array_length (res);
  4392. ex_count = 0;
  4393. for (i = 0; i < len; i++) {
  4394. MonoReflectionType *t = mono_array_get (res, gpointer, i);
  4395. MonoClass *klass;
  4396. if (t) {
  4397. klass = mono_type_get_class (t->type);
  4398. if ((klass != NULL) && klass->exception_type) {
  4399. /* keep the class in the list */
  4400. list = g_list_append (list, klass);
  4401. /* and replace Type with NULL */
  4402. mono_array_setref (res, i, NULL);
  4403. }
  4404. } else {
  4405. ex_count ++;
  4406. }
  4407. }
  4408. if (list || ex_count) {
  4409. GList *tmp = NULL;
  4410. MonoException *exc = NULL;
  4411. MonoArray *exl = NULL;
  4412. int j, length = g_list_length (list) + ex_count;
  4413. mono_loader_clear_error ();
  4414. exl = mono_array_new (domain, mono_defaults.exception_class, length);
  4415. /* Types for which mono_class_get () succeeded */
  4416. for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
  4417. MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
  4418. mono_array_setref (exl, i, exc);
  4419. }
  4420. /* Types for which it don't */
  4421. for (j = 0; j < mono_array_length (exceptions); ++j) {
  4422. MonoException *exc = mono_array_get (exceptions, MonoException*, j);
  4423. if (exc) {
  4424. g_assert (i < length);
  4425. mono_array_setref (exl, i, exc);
  4426. i ++;
  4427. }
  4428. }
  4429. g_list_free (list);
  4430. list = NULL;
  4431. exc = mono_get_exception_reflection_type_load (res, exl);
  4432. mono_loader_clear_error ();
  4433. mono_raise_exception (exc);
  4434. }
  4435. return res;
  4436. }
  4437. ICALL_EXPORT gboolean
  4438. ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
  4439. {
  4440. MonoAssemblyName aname;
  4441. MonoDomain *domain = mono_object_domain (name);
  4442. char *val;
  4443. gboolean is_version_defined;
  4444. gboolean is_token_defined;
  4445. aname.public_key = NULL;
  4446. val = mono_string_to_utf8 (assname);
  4447. if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
  4448. g_free ((guint8*) aname.public_key);
  4449. g_free (val);
  4450. return FALSE;
  4451. }
  4452. fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
  4453. FALSE, is_token_defined);
  4454. mono_assembly_name_free (&aname);
  4455. g_free ((guint8*) aname.public_key);
  4456. g_free (val);
  4457. return TRUE;
  4458. }
  4459. ICALL_EXPORT MonoReflectionType*
  4460. ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
  4461. {
  4462. MonoDomain *domain = mono_object_domain (module);
  4463. MonoClass *klass;
  4464. MONO_ARCH_SAVE_REGS;
  4465. g_assert (module->image);
  4466. if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
  4467. /* These images do not have a global type */
  4468. return NULL;
  4469. klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
  4470. return mono_type_get_object (domain, &klass->byval_arg);
  4471. }
  4472. ICALL_EXPORT void
  4473. ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
  4474. {
  4475. /*if (module->image)
  4476. mono_image_close (module->image);*/
  4477. }
  4478. ICALL_EXPORT MonoString*
  4479. ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
  4480. {
  4481. MonoDomain *domain = mono_object_domain (module);
  4482. MONO_ARCH_SAVE_REGS;
  4483. g_assert (module->image);
  4484. return mono_string_new (domain, module->image->guid);
  4485. }
  4486. ICALL_EXPORT gpointer
  4487. ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
  4488. {
  4489. #ifdef HOST_WIN32
  4490. if (module->image && module->image->is_module_handle)
  4491. return module->image->raw_data;
  4492. #endif
  4493. return (gpointer) (-1);
  4494. }
  4495. ICALL_EXPORT void
  4496. ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
  4497. {
  4498. if (image->dynamic) {
  4499. MonoDynamicImage *dyn = (MonoDynamicImage*)image;
  4500. *pe_kind = dyn->pe_kind;
  4501. *machine = dyn->machine;
  4502. }
  4503. else {
  4504. *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
  4505. *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
  4506. }
  4507. }
  4508. ICALL_EXPORT gint32
  4509. ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
  4510. {
  4511. return (image->md_version_major << 16) | (image->md_version_minor);
  4512. }
  4513. ICALL_EXPORT MonoArray*
  4514. ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
  4515. {
  4516. MonoArray *exceptions;
  4517. int i;
  4518. MONO_ARCH_SAVE_REGS;
  4519. if (!module->image)
  4520. return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
  4521. else {
  4522. MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
  4523. for (i = 0; i < mono_array_length (exceptions); ++i) {
  4524. MonoException *ex = mono_array_get (exceptions, MonoException *, i);
  4525. if (ex)
  4526. mono_raise_exception (ex);
  4527. }
  4528. return res;
  4529. }
  4530. }
  4531. static gboolean
  4532. mono_memberref_is_method (MonoImage *image, guint32 token)
  4533. {
  4534. if (!image->dynamic) {
  4535. guint32 cols [MONO_MEMBERREF_SIZE];
  4536. const char *sig;
  4537. mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
  4538. sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
  4539. mono_metadata_decode_blob_size (sig, &sig);
  4540. return (*sig != 0x6);
  4541. } else {
  4542. MonoClass *handle_class;
  4543. if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
  4544. return FALSE;
  4545. return mono_defaults.methodhandle_class == handle_class;
  4546. }
  4547. }
  4548. static void
  4549. init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
  4550. {
  4551. if (type_args)
  4552. context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
  4553. mono_array_addr (type_args, MonoType*, 0));
  4554. else
  4555. context->class_inst = NULL;
  4556. if (method_args)
  4557. context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
  4558. mono_array_addr (method_args, MonoType*, 0));
  4559. else
  4560. context->method_inst = NULL;
  4561. }
  4562. ICALL_EXPORT MonoType*
  4563. ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
  4564. {
  4565. MonoClass *klass;
  4566. int table = mono_metadata_token_table (token);
  4567. int index = mono_metadata_token_index (token);
  4568. MonoGenericContext context;
  4569. *error = ResolveTokenError_Other;
  4570. /* Validate token */
  4571. if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
  4572. (table != MONO_TABLE_TYPESPEC)) {
  4573. *error = ResolveTokenError_BadTable;
  4574. return NULL;
  4575. }
  4576. if (image->dynamic) {
  4577. if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
  4578. klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
  4579. return klass ? &klass->byval_arg : NULL;
  4580. }
  4581. init_generic_context_from_args (&context, type_args, method_args);
  4582. klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
  4583. return klass ? &klass->byval_arg : NULL;
  4584. }
  4585. if ((index <= 0) || (index > image->tables [table].rows)) {
  4586. *error = ResolveTokenError_OutOfRange;
  4587. return NULL;
  4588. }
  4589. init_generic_context_from_args (&context, type_args, method_args);
  4590. klass = mono_class_get_full (image, token, &context);
  4591. if (mono_loader_get_last_error ())
  4592. mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
  4593. if (klass)
  4594. return &klass->byval_arg;
  4595. else
  4596. return NULL;
  4597. }
  4598. ICALL_EXPORT MonoMethod*
  4599. ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
  4600. {
  4601. int table = mono_metadata_token_table (token);
  4602. int index = mono_metadata_token_index (token);
  4603. MonoGenericContext context;
  4604. MonoMethod *method;
  4605. *error = ResolveTokenError_Other;
  4606. /* Validate token */
  4607. if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
  4608. (table != MONO_TABLE_MEMBERREF)) {
  4609. *error = ResolveTokenError_BadTable;
  4610. return NULL;
  4611. }
  4612. if (image->dynamic) {
  4613. if (table == MONO_TABLE_METHOD)
  4614. return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
  4615. if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
  4616. *error = ResolveTokenError_BadTable;
  4617. return NULL;
  4618. }
  4619. init_generic_context_from_args (&context, type_args, method_args);
  4620. return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
  4621. }
  4622. if ((index <= 0) || (index > image->tables [table].rows)) {
  4623. *error = ResolveTokenError_OutOfRange;
  4624. return NULL;
  4625. }
  4626. if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
  4627. *error = ResolveTokenError_BadTable;
  4628. return NULL;
  4629. }
  4630. init_generic_context_from_args (&context, type_args, method_args);
  4631. method = mono_get_method_full (image, token, NULL, &context);
  4632. if (mono_loader_get_last_error ())
  4633. mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
  4634. return method;
  4635. }
  4636. ICALL_EXPORT MonoString*
  4637. ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
  4638. {
  4639. int index = mono_metadata_token_index (token);
  4640. *error = ResolveTokenError_Other;
  4641. /* Validate token */
  4642. if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
  4643. *error = ResolveTokenError_BadTable;
  4644. return NULL;
  4645. }
  4646. if (image->dynamic)
  4647. return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
  4648. if ((index <= 0) || (index >= image->heap_us.size)) {
  4649. *error = ResolveTokenError_OutOfRange;
  4650. return NULL;
  4651. }
  4652. /* FIXME: What to do if the index points into the middle of a string ? */
  4653. return mono_ldstr (mono_domain_get (), image, index);
  4654. }
  4655. ICALL_EXPORT MonoClassField*
  4656. ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
  4657. {
  4658. MonoClass *klass;
  4659. int table = mono_metadata_token_table (token);
  4660. int index = mono_metadata_token_index (token);
  4661. MonoGenericContext context;
  4662. MonoClassField *field;
  4663. *error = ResolveTokenError_Other;
  4664. /* Validate token */
  4665. if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
  4666. *error = ResolveTokenError_BadTable;
  4667. return NULL;
  4668. }
  4669. if (image->dynamic) {
  4670. if (table == MONO_TABLE_FIELD)
  4671. return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
  4672. if (mono_memberref_is_method (image, token)) {
  4673. *error = ResolveTokenError_BadTable;
  4674. return NULL;
  4675. }
  4676. init_generic_context_from_args (&context, type_args, method_args);
  4677. return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
  4678. }
  4679. if ((index <= 0) || (index > image->tables [table].rows)) {
  4680. *error = ResolveTokenError_OutOfRange;
  4681. return NULL;
  4682. }
  4683. if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
  4684. *error = ResolveTokenError_BadTable;
  4685. return NULL;
  4686. }
  4687. init_generic_context_from_args (&context, type_args, method_args);
  4688. field = mono_field_from_token (image, token, &klass, &context);
  4689. if (mono_loader_get_last_error ())
  4690. mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
  4691. return field;
  4692. }
  4693. ICALL_EXPORT MonoObject*
  4694. ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
  4695. {
  4696. int table = mono_metadata_token_table (token);
  4697. *error = ResolveTokenError_Other;
  4698. switch (table) {
  4699. case MONO_TABLE_TYPEDEF:
  4700. case MONO_TABLE_TYPEREF:
  4701. case MONO_TABLE_TYPESPEC: {
  4702. MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
  4703. if (t)
  4704. return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
  4705. else
  4706. return NULL;
  4707. }
  4708. case MONO_TABLE_METHOD:
  4709. case MONO_TABLE_METHODSPEC: {
  4710. MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
  4711. if (m)
  4712. return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
  4713. else
  4714. return NULL;
  4715. }
  4716. case MONO_TABLE_FIELD: {
  4717. MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
  4718. if (f)
  4719. return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
  4720. else
  4721. return NULL;
  4722. }
  4723. case MONO_TABLE_MEMBERREF:
  4724. if (mono_memberref_is_method (image, token)) {
  4725. MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
  4726. if (m)
  4727. return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
  4728. else
  4729. return NULL;
  4730. }
  4731. else {
  4732. MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
  4733. if (f)
  4734. return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
  4735. else
  4736. return NULL;
  4737. }
  4738. break;
  4739. default:
  4740. *error = ResolveTokenError_BadTable;
  4741. }
  4742. return NULL;
  4743. }
  4744. ICALL_EXPORT MonoArray*
  4745. ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
  4746. {
  4747. int table = mono_metadata_token_table (token);
  4748. int idx = mono_metadata_token_index (token);
  4749. MonoTableInfo *tables = image->tables;
  4750. guint32 sig, len;
  4751. const char *ptr;
  4752. MonoArray *res;
  4753. *error = ResolveTokenError_OutOfRange;
  4754. /* FIXME: Support other tables ? */
  4755. if (table != MONO_TABLE_STANDALONESIG)
  4756. return NULL;
  4757. if (image->dynamic)
  4758. return NULL;
  4759. if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
  4760. return NULL;
  4761. sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
  4762. ptr = mono_metadata_blob_heap (image, sig);
  4763. len = mono_metadata_decode_blob_size (ptr, &ptr);
  4764. res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
  4765. memcpy (mono_array_addr (res, guint8, 0), ptr, len);
  4766. return res;
  4767. }
  4768. ICALL_EXPORT MonoReflectionType*
  4769. ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
  4770. {
  4771. MonoClass *klass;
  4772. int isbyref = 0, rank;
  4773. char *str = mono_string_to_utf8 (smodifiers);
  4774. char *p;
  4775. MONO_ARCH_SAVE_REGS;
  4776. klass = mono_class_from_mono_type (tb->type.type);
  4777. p = str;
  4778. /* logic taken from mono_reflection_parse_type(): keep in sync */
  4779. while (*p) {
  4780. switch (*p) {
  4781. case '&':
  4782. if (isbyref) { /* only one level allowed by the spec */
  4783. g_free (str);
  4784. return NULL;
  4785. }
  4786. isbyref = 1;
  4787. p++;
  4788. g_free (str);
  4789. return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
  4790. break;
  4791. case '*':
  4792. klass = mono_ptr_class_get (&klass->byval_arg);
  4793. mono_class_init (klass);
  4794. p++;
  4795. break;
  4796. case '[':
  4797. rank = 1;
  4798. p++;
  4799. while (*p) {
  4800. if (*p == ']')
  4801. break;
  4802. if (*p == ',')
  4803. rank++;
  4804. else if (*p != '*') { /* '*' means unknown lower bound */
  4805. g_free (str);
  4806. return NULL;
  4807. }
  4808. ++p;
  4809. }
  4810. if (*p != ']') {
  4811. g_free (str);
  4812. return NULL;
  4813. }
  4814. p++;
  4815. klass = mono_array_class_get (klass, rank);
  4816. mono_class_init (klass);
  4817. break;
  4818. default:
  4819. break;
  4820. }
  4821. }
  4822. g_free (str);
  4823. return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
  4824. }
  4825. ICALL_EXPORT MonoBoolean
  4826. ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
  4827. {
  4828. MonoType *type;
  4829. MonoBoolean res;
  4830. MONO_ARCH_SAVE_REGS;
  4831. type = t->type;
  4832. res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
  4833. return res;
  4834. }
  4835. static void
  4836. check_for_invalid_type (MonoClass *klass)
  4837. {
  4838. char *name;
  4839. MonoString *str;
  4840. if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
  4841. return;
  4842. name = mono_type_get_full_name (klass);
  4843. str = mono_string_new (mono_domain_get (), name);
  4844. g_free (name);
  4845. mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
  4846. }
  4847. ICALL_EXPORT MonoReflectionType *
  4848. ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
  4849. {
  4850. MonoClass *klass, *aklass;
  4851. MONO_ARCH_SAVE_REGS;
  4852. klass = mono_class_from_mono_type (type->type);
  4853. check_for_invalid_type (klass);
  4854. if (rank == 0) //single dimentional array
  4855. aklass = mono_array_class_get (klass, 1);
  4856. else
  4857. aklass = mono_bounded_array_class_get (klass, rank, TRUE);
  4858. return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
  4859. }
  4860. ICALL_EXPORT MonoReflectionType *
  4861. ves_icall_Type_make_byref_type (MonoReflectionType *type)
  4862. {
  4863. MonoClass *klass;
  4864. MONO_ARCH_SAVE_REGS;
  4865. klass = mono_class_from_mono_type (type->type);
  4866. mono_class_init_or_throw (klass);
  4867. check_for_invalid_type (klass);
  4868. return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
  4869. }
  4870. ICALL_EXPORT MonoReflectionType *
  4871. ves_icall_Type_MakePointerType (MonoReflectionType *type)
  4872. {
  4873. MonoClass *klass, *pklass;
  4874. klass = mono_class_from_mono_type (type->type);
  4875. mono_class_init_or_throw (klass);
  4876. check_for_invalid_type (klass);
  4877. pklass = mono_ptr_class_get (type->type);
  4878. return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
  4879. }
  4880. ICALL_EXPORT MonoObject *
  4881. ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
  4882. MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
  4883. {
  4884. MonoClass *delegate_class = mono_class_from_mono_type (type->type);
  4885. MonoObject *delegate;
  4886. gpointer func;
  4887. MonoMethod *method = info->method;
  4888. MONO_ARCH_SAVE_REGS;
  4889. mono_class_init_or_throw (delegate_class);
  4890. mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
  4891. if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
  4892. if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
  4893. return NULL;
  4894. }
  4895. delegate = mono_object_new (mono_object_domain (type), delegate_class);
  4896. if (method->dynamic) {
  4897. /* Creating a trampoline would leak memory */
  4898. func = mono_compile_method (method);
  4899. } else {
  4900. if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
  4901. method = mono_object_get_virtual_method (target, method);
  4902. func = mono_create_ftnptr (mono_domain_get (),
  4903. mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
  4904. }
  4905. mono_delegate_ctor_with_method (delegate, target, func, method);
  4906. return delegate;
  4907. }
  4908. ICALL_EXPORT void
  4909. ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
  4910. {
  4911. /* Reset the invoke impl to the default one */
  4912. this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
  4913. }
  4914. /*
  4915. * Magic number to convert a time which is relative to
  4916. * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
  4917. */
  4918. #define EPOCH_ADJUST ((guint64)62135596800LL)
  4919. /*
  4920. * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
  4921. */
  4922. #define FILETIME_ADJUST ((guint64)504911232000000000LL)
  4923. #ifdef HOST_WIN32
  4924. /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
  4925. static void
  4926. convert_to_absolute_date(SYSTEMTIME *date)
  4927. {
  4928. #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
  4929. static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  4930. static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  4931. /* from the calendar FAQ */
  4932. int a = (14 - date->wMonth) / 12;
  4933. int y = date->wYear - a;
  4934. int m = date->wMonth + 12 * a - 2;
  4935. int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
  4936. /* d is now the day of the week for the first of the month (0 == Sunday) */
  4937. int day_of_week = date->wDayOfWeek;
  4938. /* set day_in_month to the first day in the month which falls on day_of_week */
  4939. int day_in_month = 1 + (day_of_week - d);
  4940. if (day_in_month <= 0)
  4941. day_in_month += 7;
  4942. /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
  4943. date->wDay = day_in_month + (date->wDay - 1) * 7;
  4944. if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
  4945. date->wDay -= 7;
  4946. }
  4947. #endif
  4948. #ifndef HOST_WIN32
  4949. /*
  4950. * Return's the offset from GMT of a local time.
  4951. *
  4952. * tm is a local time
  4953. * t is the same local time as seconds.
  4954. */
  4955. static int
  4956. gmt_offset(struct tm *tm, time_t t)
  4957. {
  4958. #if defined (HAVE_TM_GMTOFF)
  4959. return tm->tm_gmtoff;
  4960. #else
  4961. struct tm g;
  4962. time_t t2;
  4963. g = *gmtime(&t);
  4964. g.tm_isdst = tm->tm_isdst;
  4965. t2 = mktime(&g);
  4966. return (int)difftime(t, t2);
  4967. #endif
  4968. }
  4969. #endif
  4970. /*
  4971. * This is heavily based on zdump.c from glibc 2.2.
  4972. *
  4973. * * data[0]: start of daylight saving time (in DateTime ticks).
  4974. * * data[1]: end of daylight saving time (in DateTime ticks).
  4975. * * data[2]: utcoffset (in TimeSpan ticks).
  4976. * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
  4977. * * name[0]: name of this timezone when not daylight saving.
  4978. * * name[1]: name of this timezone when daylight saving.
  4979. *
  4980. * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
  4981. * the class library allows years between 1 and 9999.
  4982. *
  4983. * Returns true on success and zero on failure.
  4984. */
  4985. ICALL_EXPORT guint32
  4986. ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
  4987. {
  4988. #ifndef HOST_WIN32
  4989. MonoDomain *domain = mono_domain_get ();
  4990. struct tm start, tt;
  4991. time_t t;
  4992. long int gmtoff;
  4993. int is_daylight = 0, day;
  4994. char tzone [64];
  4995. MONO_ARCH_SAVE_REGS;
  4996. MONO_CHECK_ARG_NULL (data);
  4997. MONO_CHECK_ARG_NULL (names);
  4998. mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
  4999. mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
  5000. /*
  5001. * no info is better than crashing: we'll need our own tz data
  5002. * to make this work properly, anyway. The range is probably
  5003. * reduced to 1970 .. 2037 because that is what mktime is
  5004. * guaranteed to support (we get into an infinite loop
  5005. * otherwise).
  5006. */
  5007. memset (&start, 0, sizeof (start));
  5008. start.tm_mday = 1;
  5009. start.tm_year = year-1900;
  5010. t = mktime (&start);
  5011. if ((year < 1970) || (year > 2037) || (t == -1)) {
  5012. t = time (NULL);
  5013. tt = *localtime (&t);
  5014. strftime (tzone, sizeof (tzone), "%Z", &tt);
  5015. mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
  5016. mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
  5017. return 1;
  5018. }
  5019. gmtoff = gmt_offset (&start, t);
  5020. /* For each day of the year, calculate the tm_gmtoff. */
  5021. for (day = 0; day < 365; day++) {
  5022. t += 3600*24;
  5023. tt = *localtime (&t);
  5024. /* Daylight saving starts or ends here. */
  5025. if (gmt_offset (&tt, t) != gmtoff) {
  5026. struct tm tt1;
  5027. time_t t1;
  5028. /* Try to find the exact hour when daylight saving starts/ends. */
  5029. t1 = t;
  5030. do {
  5031. t1 -= 3600;
  5032. tt1 = *localtime (&t1);
  5033. } while (gmt_offset (&tt1, t1) != gmtoff);
  5034. /* Try to find the exact minute when daylight saving starts/ends. */
  5035. do {
  5036. t1 += 60;
  5037. tt1 = *localtime (&t1);
  5038. } while (gmt_offset (&tt1, t1) == gmtoff);
  5039. t1+=gmtoff;
  5040. strftime (tzone, sizeof (tzone), "%Z", &tt);
  5041. /* Write data, if we're already in daylight saving, we're done. */
  5042. if (is_daylight) {
  5043. mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
  5044. mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
  5045. return 1;
  5046. } else {
  5047. struct tm end;
  5048. time_t te;
  5049. memset (&end, 0, sizeof (end));
  5050. end.tm_year = year-1900 + 1;
  5051. end.tm_mday = 1;
  5052. te = mktime (&end);
  5053. mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
  5054. mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
  5055. mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
  5056. mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
  5057. is_daylight = 1;
  5058. }
  5059. /* This is only set once when we enter daylight saving. */
  5060. mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
  5061. mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
  5062. gmtoff = gmt_offset (&tt, t);
  5063. }
  5064. }
  5065. if (!is_daylight) {
  5066. strftime (tzone, sizeof (tzone), "%Z", &tt);
  5067. mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
  5068. mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
  5069. mono_array_set ((*data), gint64, 0, 0);
  5070. mono_array_set ((*data), gint64, 1, 0);
  5071. mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
  5072. mono_array_set ((*data), gint64, 3, 0);
  5073. }
  5074. return 1;
  5075. #else
  5076. MonoDomain *domain = mono_domain_get ();
  5077. TIME_ZONE_INFORMATION tz_info;
  5078. FILETIME ft;
  5079. int i;
  5080. int err, tz_id;
  5081. tz_id = GetTimeZoneInformation (&tz_info);
  5082. if (tz_id == TIME_ZONE_ID_INVALID)
  5083. return 0;
  5084. MONO_CHECK_ARG_NULL (data);
  5085. MONO_CHECK_ARG_NULL (names);
  5086. mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
  5087. mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
  5088. for (i = 0; i < 32; ++i)
  5089. if (!tz_info.DaylightName [i])
  5090. break;
  5091. mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
  5092. for (i = 0; i < 32; ++i)
  5093. if (!tz_info.StandardName [i])
  5094. break;
  5095. mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
  5096. if ((year <= 1601) || (year > 30827)) {
  5097. /*
  5098. * According to MSDN, the MS time functions can't handle dates outside
  5099. * this interval.
  5100. */
  5101. return 1;
  5102. }
  5103. /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
  5104. if (tz_id != TIME_ZONE_ID_UNKNOWN) {
  5105. tz_info.StandardDate.wYear = year;
  5106. convert_to_absolute_date(&tz_info.StandardDate);
  5107. err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
  5108. //g_assert(err);
  5109. if (err == 0)
  5110. return 0;
  5111. mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
  5112. tz_info.DaylightDate.wYear = year;
  5113. convert_to_absolute_date(&tz_info.DaylightDate);
  5114. err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
  5115. //g_assert(err);
  5116. if (err == 0)
  5117. return 0;
  5118. mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
  5119. }
  5120. mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
  5121. mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
  5122. return 1;
  5123. #endif
  5124. }
  5125. ICALL_EXPORT gpointer
  5126. ves_icall_System_Object_obj_address (MonoObject *this)
  5127. {
  5128. MONO_ARCH_SAVE_REGS;
  5129. return this;
  5130. }
  5131. /* System.Buffer */
  5132. static inline gint32
  5133. mono_array_get_byte_length (MonoArray *array)
  5134. {
  5135. MonoClass *klass;
  5136. int length;
  5137. int i;
  5138. klass = array->obj.vtable->klass;
  5139. if (array->bounds == NULL)
  5140. length = array->max_length;
  5141. else {
  5142. length = 1;
  5143. for (i = 0; i < klass->rank; ++ i)
  5144. length *= array->bounds [i].length;
  5145. }
  5146. switch (klass->element_class->byval_arg.type) {
  5147. case MONO_TYPE_I1:
  5148. case MONO_TYPE_U1:
  5149. case MONO_TYPE_BOOLEAN:
  5150. return length;
  5151. case MONO_TYPE_I2:
  5152. case MONO_TYPE_U2:
  5153. case MONO_TYPE_CHAR:
  5154. return length << 1;
  5155. case MONO_TYPE_I4:
  5156. case MONO_TYPE_U4:
  5157. case MONO_TYPE_R4:
  5158. return length << 2;
  5159. case MONO_TYPE_I:
  5160. case MONO_TYPE_U:
  5161. return length * sizeof (gpointer);
  5162. case MONO_TYPE_I8:
  5163. case MONO_TYPE_U8:
  5164. case MONO_TYPE_R8:
  5165. return length << 3;
  5166. default:
  5167. return -1;
  5168. }
  5169. }
  5170. ICALL_EXPORT gint32
  5171. ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
  5172. {
  5173. MONO_ARCH_SAVE_REGS;
  5174. return mono_array_get_byte_length (array);
  5175. }
  5176. ICALL_EXPORT gint8
  5177. ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
  5178. {
  5179. MONO_ARCH_SAVE_REGS;
  5180. return mono_array_get (array, gint8, idx);
  5181. }
  5182. ICALL_EXPORT void
  5183. ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
  5184. {
  5185. MONO_ARCH_SAVE_REGS;
  5186. mono_array_set (array, gint8, idx, value);
  5187. }
  5188. ICALL_EXPORT MonoBoolean
  5189. ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
  5190. {
  5191. guint8 *src_buf, *dest_buf;
  5192. MONO_ARCH_SAVE_REGS;
  5193. /* This is called directly from the class libraries without going through the managed wrapper */
  5194. MONO_CHECK_ARG_NULL (src);
  5195. MONO_CHECK_ARG_NULL (dest);
  5196. /* watch out for integer overflow */
  5197. if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
  5198. return FALSE;
  5199. src_buf = (guint8 *)src->vector + src_offset;
  5200. dest_buf = (guint8 *)dest->vector + dest_offset;
  5201. if (src != dest)
  5202. memcpy (dest_buf, src_buf, count);
  5203. else
  5204. mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
  5205. return TRUE;
  5206. }
  5207. #ifndef DISABLE_REMOTING
  5208. ICALL_EXPORT MonoObject *
  5209. ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
  5210. {
  5211. MonoDomain *domain = mono_object_domain (this);
  5212. MonoObject *res;
  5213. MonoRealProxy *rp = ((MonoRealProxy *)this);
  5214. MonoTransparentProxy *tp;
  5215. MonoType *type;
  5216. MonoClass *klass;
  5217. MONO_ARCH_SAVE_REGS;
  5218. res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
  5219. tp = (MonoTransparentProxy*) res;
  5220. MONO_OBJECT_SETREF (tp, rp, rp);
  5221. type = ((MonoReflectionType *)rp->class_to_proxy)->type;
  5222. klass = mono_class_from_mono_type (type);
  5223. tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
  5224. tp->remote_class = mono_remote_class (domain, class_name, klass);
  5225. res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
  5226. return res;
  5227. }
  5228. ICALL_EXPORT MonoReflectionType *
  5229. ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
  5230. {
  5231. return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
  5232. }
  5233. #endif
  5234. /* System.Environment */
  5235. MonoString*
  5236. ves_icall_System_Environment_get_UserName (void)
  5237. {
  5238. MONO_ARCH_SAVE_REGS;
  5239. /* using glib is more portable */
  5240. return mono_string_new (mono_domain_get (), g_get_user_name ());
  5241. }
  5242. ICALL_EXPORT MonoString *
  5243. ves_icall_System_Environment_get_MachineName (void)
  5244. {
  5245. #if defined (HOST_WIN32)
  5246. gunichar2 *buf;
  5247. guint32 len;
  5248. MonoString *result;
  5249. len = MAX_COMPUTERNAME_LENGTH + 1;
  5250. buf = g_new (gunichar2, len);
  5251. result = NULL;
  5252. if (GetComputerName (buf, (PDWORD) &len))
  5253. result = mono_string_new_utf16 (mono_domain_get (), buf, len);
  5254. g_free (buf);
  5255. return result;
  5256. #elif !defined(DISABLE_SOCKETS)
  5257. gchar buf [256];
  5258. MonoString *result;
  5259. if (gethostname (buf, sizeof (buf)) == 0)
  5260. result = mono_string_new (mono_domain_get (), buf);
  5261. else
  5262. result = NULL;
  5263. return result;
  5264. #else
  5265. return mono_string_new (mono_domain_get (), "mono");
  5266. #endif
  5267. }
  5268. ICALL_EXPORT int
  5269. ves_icall_System_Environment_get_Platform (void)
  5270. {
  5271. #if defined (TARGET_WIN32)
  5272. /* Win32NT */
  5273. return 2;
  5274. #elif defined(__MACH__)
  5275. /* OSX */
  5276. //
  5277. // Notice that the value is hidden from user code, and only exposed
  5278. // to mscorlib. This is due to Mono's Unix/MacOS code predating the
  5279. // define and making assumptions based on Unix/128/4 values before there
  5280. // was a MacOS define. Lots of code would assume that not-Unix meant
  5281. // Windows, but in this case, it would be OSX.
  5282. //
  5283. return 6;
  5284. #else
  5285. /* Unix */
  5286. return 4;
  5287. #endif
  5288. }
  5289. ICALL_EXPORT MonoString *
  5290. ves_icall_System_Environment_get_NewLine (void)
  5291. {
  5292. MONO_ARCH_SAVE_REGS;
  5293. #if defined (HOST_WIN32)
  5294. return mono_string_new (mono_domain_get (), "\r\n");
  5295. #else
  5296. return mono_string_new (mono_domain_get (), "\n");
  5297. #endif
  5298. }
  5299. ICALL_EXPORT MonoString *
  5300. ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
  5301. {
  5302. const gchar *value;
  5303. gchar *utf8_name;
  5304. MONO_ARCH_SAVE_REGS;
  5305. if (name == NULL)
  5306. return NULL;
  5307. utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
  5308. value = g_getenv (utf8_name);
  5309. g_free (utf8_name);
  5310. if (value == 0)
  5311. return NULL;
  5312. return mono_string_new (mono_domain_get (), value);
  5313. }
  5314. /*
  5315. * There is no standard way to get at environ.
  5316. */
  5317. #ifndef _MSC_VER
  5318. #ifndef __MINGW32_VERSION
  5319. #if defined(__APPLE__) && !defined (__arm__)
  5320. /* Apple defines this in crt_externs.h but doesn't provide that header for
  5321. * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
  5322. * in fact exist on all implementations (so far)
  5323. */
  5324. gchar ***_NSGetEnviron(void);
  5325. #define environ (*_NSGetEnviron())
  5326. #else
  5327. extern
  5328. char **environ;
  5329. #endif
  5330. #endif
  5331. #endif
  5332. ICALL_EXPORT MonoArray *
  5333. ves_icall_System_Environment_GetEnvironmentVariableNames (void)
  5334. {
  5335. #ifdef HOST_WIN32
  5336. MonoArray *names;
  5337. MonoDomain *domain;
  5338. MonoString *str;
  5339. WCHAR* env_strings;
  5340. WCHAR* env_string;
  5341. WCHAR* equal_str;
  5342. int n = 0;
  5343. env_strings = GetEnvironmentStrings();
  5344. if (env_strings) {
  5345. env_string = env_strings;
  5346. while (*env_string != '\0') {
  5347. /* weird case that MS seems to skip */
  5348. if (*env_string != '=')
  5349. n++;
  5350. while (*env_string != '\0')
  5351. env_string++;
  5352. env_string++;
  5353. }
  5354. }
  5355. domain = mono_domain_get ();
  5356. names = mono_array_new (domain, mono_defaults.string_class, n);
  5357. if (env_strings) {
  5358. n = 0;
  5359. env_string = env_strings;
  5360. while (*env_string != '\0') {
  5361. /* weird case that MS seems to skip */
  5362. if (*env_string != '=') {
  5363. equal_str = wcschr(env_string, '=');
  5364. g_assert(equal_str);
  5365. str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
  5366. mono_array_setref (names, n, str);
  5367. n++;
  5368. }
  5369. while (*env_string != '\0')
  5370. env_string++;
  5371. env_string++;
  5372. }
  5373. FreeEnvironmentStrings (env_strings);
  5374. }
  5375. return names;
  5376. #else
  5377. MonoArray *names;
  5378. MonoDomain *domain;
  5379. MonoString *str;
  5380. gchar **e, **parts;
  5381. int n;
  5382. MONO_ARCH_SAVE_REGS;
  5383. n = 0;
  5384. for (e = environ; *e != 0; ++ e)
  5385. ++ n;
  5386. domain = mono_domain_get ();
  5387. names = mono_array_new (domain, mono_defaults.string_class, n);
  5388. n = 0;
  5389. for (e = environ; *e != 0; ++ e) {
  5390. parts = g_strsplit (*e, "=", 2);
  5391. if (*parts != 0) {
  5392. str = mono_string_new (domain, *parts);
  5393. mono_array_setref (names, n, str);
  5394. }
  5395. g_strfreev (parts);
  5396. ++ n;
  5397. }
  5398. return names;
  5399. #endif
  5400. }
  5401. /*
  5402. * If your platform lacks setenv/unsetenv, you must upgrade your glib.
  5403. */
  5404. #if !GLIB_CHECK_VERSION(2,4,0)
  5405. #define g_setenv(a,b,c) setenv(a,b,c)
  5406. #define g_unsetenv(a) unsetenv(a)
  5407. #endif
  5408. ICALL_EXPORT void
  5409. ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
  5410. {
  5411. MonoError error;
  5412. #ifdef HOST_WIN32
  5413. gunichar2 *utf16_name, *utf16_value;
  5414. #else
  5415. gchar *utf8_name, *utf8_value;
  5416. #endif
  5417. MONO_ARCH_SAVE_REGS;
  5418. #ifdef HOST_WIN32
  5419. utf16_name = mono_string_to_utf16 (name);
  5420. if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
  5421. SetEnvironmentVariable (utf16_name, NULL);
  5422. g_free (utf16_name);
  5423. return;
  5424. }
  5425. utf16_value = mono_string_to_utf16 (value);
  5426. SetEnvironmentVariable (utf16_name, utf16_value);
  5427. g_free (utf16_name);
  5428. g_free (utf16_value);
  5429. #else
  5430. utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
  5431. if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
  5432. g_unsetenv (utf8_name);
  5433. g_free (utf8_name);
  5434. return;
  5435. }
  5436. utf8_value = mono_string_to_utf8_checked (value, &error);
  5437. if (!mono_error_ok (&error)) {
  5438. g_free (utf8_name);
  5439. mono_error_raise_exception (&error);
  5440. }
  5441. g_setenv (utf8_name, utf8_value, TRUE);
  5442. g_free (utf8_name);
  5443. g_free (utf8_value);
  5444. #endif
  5445. }
  5446. ICALL_EXPORT void
  5447. ves_icall_System_Environment_Exit (int result)
  5448. {
  5449. MONO_ARCH_SAVE_REGS;
  5450. mono_threads_set_shutting_down ();
  5451. mono_runtime_set_shutting_down ();
  5452. /* This will kill the tp threads which cannot be suspended */
  5453. mono_thread_pool_cleanup ();
  5454. /* Suspend all managed threads since the runtime is going away */
  5455. mono_thread_suspend_all_other_threads ();
  5456. mono_runtime_quit ();
  5457. /* we may need to do some cleanup here... */
  5458. exit (result);
  5459. }
  5460. ICALL_EXPORT MonoString*
  5461. ves_icall_System_Environment_GetGacPath (void)
  5462. {
  5463. return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
  5464. }
  5465. ICALL_EXPORT MonoString*
  5466. ves_icall_System_Environment_GetWindowsFolderPath (int folder)
  5467. {
  5468. #if defined (HOST_WIN32)
  5469. #ifndef CSIDL_FLAG_CREATE
  5470. #define CSIDL_FLAG_CREATE 0x8000
  5471. #endif
  5472. WCHAR path [MAX_PATH];
  5473. /* Create directory if no existing */
  5474. if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
  5475. int len = 0;
  5476. while (path [len])
  5477. ++ len;
  5478. return mono_string_new_utf16 (mono_domain_get (), path, len);
  5479. }
  5480. #else
  5481. g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
  5482. #endif
  5483. return mono_string_new (mono_domain_get (), "");
  5484. }
  5485. ICALL_EXPORT MonoArray *
  5486. ves_icall_System_Environment_GetLogicalDrives (void)
  5487. {
  5488. gunichar2 buf [256], *ptr, *dname;
  5489. gunichar2 *u16;
  5490. guint initial_size = 127, size = 128;
  5491. gint ndrives;
  5492. MonoArray *result;
  5493. MonoString *drivestr;
  5494. MonoDomain *domain = mono_domain_get ();
  5495. gint len;
  5496. MONO_ARCH_SAVE_REGS;
  5497. buf [0] = '\0';
  5498. ptr = buf;
  5499. while (size > initial_size) {
  5500. size = (guint) GetLogicalDriveStrings (initial_size, ptr);
  5501. if (size > initial_size) {
  5502. if (ptr != buf)
  5503. g_free (ptr);
  5504. ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
  5505. initial_size = size;
  5506. size++;
  5507. }
  5508. }
  5509. /* Count strings */
  5510. dname = ptr;
  5511. ndrives = 0;
  5512. do {
  5513. while (*dname++);
  5514. ndrives++;
  5515. } while (*dname);
  5516. dname = ptr;
  5517. result = mono_array_new (domain, mono_defaults.string_class, ndrives);
  5518. ndrives = 0;
  5519. do {
  5520. len = 0;
  5521. u16 = dname;
  5522. while (*u16) { u16++; len ++; }
  5523. drivestr = mono_string_new_utf16 (domain, dname, len);
  5524. mono_array_setref (result, ndrives++, drivestr);
  5525. while (*dname++);
  5526. } while (*dname);
  5527. if (ptr != buf)
  5528. g_free (ptr);
  5529. return result;
  5530. }
  5531. ICALL_EXPORT MonoString *
  5532. ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
  5533. {
  5534. gunichar2 volume_name [MAX_PATH + 1];
  5535. if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
  5536. return NULL;
  5537. return mono_string_from_utf16 (volume_name);
  5538. }
  5539. ICALL_EXPORT MonoString *
  5540. ves_icall_System_Environment_InternalGetHome (void)
  5541. {
  5542. MONO_ARCH_SAVE_REGS;
  5543. return mono_string_new (mono_domain_get (), g_get_home_dir ());
  5544. }
  5545. static const char *encodings [] = {
  5546. (char *) 1,
  5547. "ascii", "us_ascii", "us", "ansi_x3.4_1968",
  5548. "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
  5549. "iso_ir_6", "iso646_us", "iso_646.irv:1991",
  5550. (char *) 2,
  5551. "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
  5552. "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
  5553. "x_unicode_2_0_utf_7",
  5554. (char *) 3,
  5555. "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
  5556. "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
  5557. (char *) 4,
  5558. "utf_16", "UTF_16LE", "ucs_2", "unicode",
  5559. "iso_10646_ucs2",
  5560. (char *) 5,
  5561. "unicodefffe", "utf_16be",
  5562. (char *) 6,
  5563. "iso_8859_1",
  5564. (char *) 0
  5565. };
  5566. /*
  5567. * Returns the internal codepage, if the value of "int_code_page" is
  5568. * 1 at entry, and we can not compute a suitable code page number,
  5569. * returns the code page as a string
  5570. */
  5571. ICALL_EXPORT MonoString*
  5572. ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
  5573. {
  5574. const char *cset;
  5575. const char *p;
  5576. char *c;
  5577. char *codepage = NULL;
  5578. int code;
  5579. int want_name = *int_code_page;
  5580. int i;
  5581. *int_code_page = -1;
  5582. MONO_ARCH_SAVE_REGS;
  5583. g_get_charset (&cset);
  5584. c = codepage = strdup (cset);
  5585. for (c = codepage; *c; c++){
  5586. if (isascii (*c) && isalpha (*c))
  5587. *c = tolower (*c);
  5588. if (*c == '-')
  5589. *c = '_';
  5590. }
  5591. /* g_print ("charset: %s\n", cset); */
  5592. /* handle some common aliases */
  5593. p = encodings [0];
  5594. code = 0;
  5595. for (i = 0; p != 0; ){
  5596. if ((gssize) p < 7){
  5597. code = (gssize) p;
  5598. p = encodings [++i];
  5599. continue;
  5600. }
  5601. if (strcmp (p, codepage) == 0){
  5602. *int_code_page = code;
  5603. break;
  5604. }
  5605. p = encodings [++i];
  5606. }
  5607. if (strstr (codepage, "utf_8") != NULL)
  5608. *int_code_page |= 0x10000000;
  5609. free (codepage);
  5610. if (want_name && *int_code_page == -1)
  5611. return mono_string_new (mono_domain_get (), cset);
  5612. else
  5613. return NULL;
  5614. }
  5615. ICALL_EXPORT MonoBoolean
  5616. ves_icall_System_Environment_get_HasShutdownStarted (void)
  5617. {
  5618. if (mono_runtime_is_shutting_down ())
  5619. return TRUE;
  5620. if (mono_domain_is_unloading (mono_domain_get ()))
  5621. return TRUE;
  5622. return FALSE;
  5623. }
  5624. ICALL_EXPORT void
  5625. ves_icall_System_Environment_BroadcastSettingChange (void)
  5626. {
  5627. #ifdef HOST_WIN32
  5628. SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
  5629. #endif
  5630. }
  5631. ICALL_EXPORT void
  5632. ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
  5633. MonoReflectionMethod *method,
  5634. MonoArray *out_args)
  5635. {
  5636. MONO_ARCH_SAVE_REGS;
  5637. mono_message_init (mono_object_domain (this), this, method, out_args);
  5638. }
  5639. #ifndef DISABLE_REMOTING
  5640. ICALL_EXPORT MonoBoolean
  5641. ves_icall_IsTransparentProxy (MonoObject *proxy)
  5642. {
  5643. MONO_ARCH_SAVE_REGS;
  5644. if (!proxy)
  5645. return 0;
  5646. if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
  5647. return 1;
  5648. return 0;
  5649. }
  5650. ICALL_EXPORT MonoReflectionMethod *
  5651. ves_icall_Remoting_RemotingServices_GetVirtualMethod (
  5652. MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
  5653. {
  5654. MonoClass *klass;
  5655. MonoMethod *method;
  5656. MonoMethod **vtable;
  5657. MonoMethod *res = NULL;
  5658. MONO_CHECK_ARG_NULL (rtype);
  5659. MONO_CHECK_ARG_NULL (rmethod);
  5660. method = rmethod->method;
  5661. klass = mono_class_from_mono_type (rtype->type);
  5662. mono_class_init_or_throw (klass);
  5663. if (MONO_CLASS_IS_INTERFACE (klass))
  5664. return NULL;
  5665. if (method->flags & METHOD_ATTRIBUTE_STATIC)
  5666. return NULL;
  5667. if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
  5668. if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
  5669. return rmethod;
  5670. else
  5671. return NULL;
  5672. }
  5673. mono_class_setup_vtable (klass);
  5674. vtable = klass->vtable;
  5675. if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
  5676. gboolean variance_used = FALSE;
  5677. /*MS fails with variant interfaces but it's the right thing to do anyway.*/
  5678. int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
  5679. if (offs >= 0)
  5680. res = vtable [offs + method->slot];
  5681. } else {
  5682. if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
  5683. return NULL;
  5684. if (method->slot != -1)
  5685. res = vtable [method->slot];
  5686. }
  5687. if (!res)
  5688. return NULL;
  5689. return mono_method_get_object (mono_domain_get (), res, NULL);
  5690. }
  5691. ICALL_EXPORT void
  5692. ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
  5693. {
  5694. MonoClass *klass;
  5695. MonoVTable* vtable;
  5696. MONO_ARCH_SAVE_REGS;
  5697. klass = mono_class_from_mono_type (type->type);
  5698. vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
  5699. if (enable) vtable->remote = 1;
  5700. else vtable->remote = 0;
  5701. }
  5702. #endif
  5703. ICALL_EXPORT MonoObject *
  5704. ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
  5705. {
  5706. MonoClass *klass;
  5707. MonoDomain *domain;
  5708. MONO_ARCH_SAVE_REGS;
  5709. domain = mono_object_domain (type);
  5710. klass = mono_class_from_mono_type (type->type);
  5711. mono_class_init_or_throw (klass);
  5712. if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
  5713. mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
  5714. if (klass->rank >= 1) {
  5715. g_assert (klass->rank == 1);
  5716. return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
  5717. } else {
  5718. /* Bypass remoting object creation check */
  5719. return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
  5720. }
  5721. }
  5722. ICALL_EXPORT MonoString *
  5723. ves_icall_System_IO_get_temp_path (void)
  5724. {
  5725. MONO_ARCH_SAVE_REGS;
  5726. return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
  5727. }
  5728. #ifndef PLATFORM_NO_DRIVEINFO
  5729. ICALL_EXPORT MonoBoolean
  5730. ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
  5731. guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
  5732. gint32 *error)
  5733. {
  5734. gboolean result;
  5735. ULARGE_INTEGER wapi_free_bytes_avail;
  5736. ULARGE_INTEGER wapi_total_number_of_bytes;
  5737. ULARGE_INTEGER wapi_total_number_of_free_bytes;
  5738. MONO_ARCH_SAVE_REGS;
  5739. *error = ERROR_SUCCESS;
  5740. result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
  5741. &wapi_total_number_of_free_bytes);
  5742. if (result) {
  5743. *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
  5744. *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
  5745. *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
  5746. } else {
  5747. *free_bytes_avail = 0;
  5748. *total_number_of_bytes = 0;
  5749. *total_number_of_free_bytes = 0;
  5750. *error = GetLastError ();
  5751. }
  5752. return result;
  5753. }
  5754. ICALL_EXPORT guint32
  5755. ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
  5756. {
  5757. MONO_ARCH_SAVE_REGS;
  5758. return GetDriveType (mono_string_chars (root_path_name));
  5759. }
  5760. #endif
  5761. ICALL_EXPORT gpointer
  5762. ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
  5763. {
  5764. MONO_ARCH_SAVE_REGS;
  5765. return mono_compile_method (method);
  5766. }
  5767. ICALL_EXPORT MonoString *
  5768. ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
  5769. {
  5770. MonoString *mcpath;
  5771. gchar *path;
  5772. MONO_ARCH_SAVE_REGS;
  5773. path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
  5774. #if defined (HOST_WIN32)
  5775. /* Avoid mixing '/' and '\\' */
  5776. {
  5777. gint i;
  5778. for (i = strlen (path) - 1; i >= 0; i--)
  5779. if (path [i] == '/')
  5780. path [i] = '\\';
  5781. }
  5782. #endif
  5783. mcpath = mono_string_new (mono_domain_get (), path);
  5784. g_free (path);
  5785. return mcpath;
  5786. }
  5787. static MonoString *
  5788. get_bundled_app_config (void)
  5789. {
  5790. const gchar *app_config;
  5791. MonoDomain *domain;
  5792. MonoString *file;
  5793. gchar *config_file_name, *config_file_path;
  5794. gsize len;
  5795. gchar *module;
  5796. MONO_ARCH_SAVE_REGS;
  5797. domain = mono_domain_get ();
  5798. file = domain->setup->configuration_file;
  5799. if (!file)
  5800. return NULL;
  5801. // Retrieve config file and remove the extension
  5802. config_file_name = mono_string_to_utf8 (file);
  5803. config_file_path = mono_portability_find_file (config_file_name, TRUE);
  5804. if (!config_file_path)
  5805. config_file_path = config_file_name;
  5806. len = strlen (config_file_path) - strlen (".config");
  5807. module = g_malloc0 (len + 1);
  5808. memcpy (module, config_file_path, len);
  5809. // Get the config file from the module name
  5810. app_config = mono_config_string_for_assembly_file (module);
  5811. // Clean-up
  5812. g_free (module);
  5813. if (config_file_name != config_file_path)
  5814. g_free (config_file_name);
  5815. g_free (config_file_path);
  5816. if (!app_config)
  5817. return NULL;
  5818. return mono_string_new (mono_domain_get (), app_config);
  5819. }
  5820. static MonoString *
  5821. get_bundled_machine_config (void)
  5822. {
  5823. const gchar *machine_config;
  5824. MONO_ARCH_SAVE_REGS;
  5825. machine_config = mono_get_machine_config ();
  5826. if (!machine_config)
  5827. return NULL;
  5828. return mono_string_new (mono_domain_get (), machine_config);
  5829. }
  5830. ICALL_EXPORT MonoString *
  5831. ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
  5832. {
  5833. MonoString *ipath;
  5834. gchar *path;
  5835. MONO_ARCH_SAVE_REGS;
  5836. path = g_path_get_dirname (mono_get_config_dir ());
  5837. #if defined (HOST_WIN32)
  5838. /* Avoid mixing '/' and '\\' */
  5839. {
  5840. gint i;
  5841. for (i = strlen (path) - 1; i >= 0; i--)
  5842. if (path [i] == '/')
  5843. path [i] = '\\';
  5844. }
  5845. #endif
  5846. ipath = mono_string_new (mono_domain_get (), path);
  5847. g_free (path);
  5848. return ipath;
  5849. }
  5850. ICALL_EXPORT gboolean
  5851. ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
  5852. {
  5853. MonoPEResourceDataEntry *entry;
  5854. MonoImage *image;
  5855. MONO_ARCH_SAVE_REGS;
  5856. if (!assembly || !result || !size)
  5857. return FALSE;
  5858. *result = NULL;
  5859. *size = 0;
  5860. image = assembly->assembly->image;
  5861. entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
  5862. if (!entry)
  5863. return FALSE;
  5864. *result = mono_image_rva_map (image, entry->rde_data_offset);
  5865. if (!(*result)) {
  5866. g_free (entry);
  5867. return FALSE;
  5868. }
  5869. *size = entry->rde_size;
  5870. g_free (entry);
  5871. return TRUE;
  5872. }
  5873. ICALL_EXPORT MonoBoolean
  5874. ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
  5875. {
  5876. return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
  5877. }
  5878. ICALL_EXPORT MonoBoolean
  5879. ves_icall_System_Diagnostics_Debugger_IsLogging (void)
  5880. {
  5881. if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
  5882. return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
  5883. else
  5884. return FALSE;
  5885. }
  5886. ICALL_EXPORT void
  5887. ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
  5888. {
  5889. if (mono_get_runtime_callbacks ()->debug_log)
  5890. mono_get_runtime_callbacks ()->debug_log (level, category, message);
  5891. }
  5892. ICALL_EXPORT void
  5893. ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
  5894. {
  5895. #if defined (HOST_WIN32)
  5896. OutputDebugString (mono_string_chars (message));
  5897. #else
  5898. g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
  5899. #endif
  5900. }
  5901. /* Only used for value types */
  5902. ICALL_EXPORT MonoObject *
  5903. ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
  5904. {
  5905. MonoClass *klass;
  5906. MonoDomain *domain;
  5907. MONO_ARCH_SAVE_REGS;
  5908. domain = mono_object_domain (type);
  5909. klass = mono_class_from_mono_type (type->type);
  5910. mono_class_init_or_throw (klass);
  5911. if (mono_class_is_nullable (klass))
  5912. /* No arguments -> null */
  5913. return NULL;
  5914. return mono_object_new (domain, klass);
  5915. }
  5916. ICALL_EXPORT MonoReflectionMethod *
  5917. ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
  5918. {
  5919. MonoClass *klass, *parent;
  5920. MonoMethod *method = m->method;
  5921. MonoMethod *result = NULL;
  5922. int slot;
  5923. MONO_ARCH_SAVE_REGS;
  5924. if (method->klass == NULL)
  5925. return m;
  5926. if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
  5927. MONO_CLASS_IS_INTERFACE (method->klass) ||
  5928. method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
  5929. return m;
  5930. slot = mono_method_get_vtable_slot (method);
  5931. if (slot == -1)
  5932. return m;
  5933. klass = method->klass;
  5934. if (klass->generic_class)
  5935. klass = klass->generic_class->container_class;
  5936. if (definition) {
  5937. /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
  5938. for (parent = klass->parent; parent != NULL; parent = parent->parent) {
  5939. mono_class_setup_vtable (parent);
  5940. if (parent->vtable_size <= slot)
  5941. break;
  5942. klass = parent;
  5943. }
  5944. } else {
  5945. klass = klass->parent;
  5946. if (!klass)
  5947. return m;
  5948. }
  5949. if (klass == method->klass)
  5950. return m;
  5951. /*This is possible if definition == FALSE.
  5952. * Do it here to be really sure we don't read invalid memory.
  5953. */
  5954. if (slot >= klass->vtable_size)
  5955. return m;
  5956. mono_class_setup_vtable (klass);
  5957. result = klass->vtable [slot];
  5958. if (result == NULL) {
  5959. /* It is an abstract method */
  5960. gpointer iter = NULL;
  5961. while ((result = mono_class_get_methods (klass, &iter)))
  5962. if (result->slot == slot)
  5963. break;
  5964. }
  5965. if (result == NULL)
  5966. return m;
  5967. return mono_method_get_object (mono_domain_get (), result, NULL);
  5968. }
  5969. ICALL_EXPORT MonoString*
  5970. ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
  5971. {
  5972. MonoMethod *method = m->method;
  5973. MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
  5974. return m->name;
  5975. }
  5976. ICALL_EXPORT void
  5977. mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
  5978. {
  5979. MONO_ARCH_SAVE_REGS;
  5980. iter->sig = *(MonoMethodSignature**)argsp;
  5981. g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
  5982. g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
  5983. iter->next_arg = 0;
  5984. /* FIXME: it's not documented what start is exactly... */
  5985. if (start) {
  5986. iter->args = start;
  5987. } else {
  5988. iter->args = argsp + sizeof (gpointer);
  5989. }
  5990. iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
  5991. /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
  5992. }
  5993. ICALL_EXPORT MonoTypedRef
  5994. mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
  5995. {
  5996. guint32 i, arg_size;
  5997. gint32 align;
  5998. MonoTypedRef res;
  5999. MONO_ARCH_SAVE_REGS;
  6000. i = iter->sig->sentinelpos + iter->next_arg;
  6001. g_assert (i < iter->sig->param_count);
  6002. res.type = iter->sig->params [i];
  6003. res.klass = mono_class_from_mono_type (res.type);
  6004. arg_size = mono_type_stack_size (res.type, &align);
  6005. #if defined(__arm__) || defined(__mips__)
  6006. iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
  6007. #endif
  6008. res.value = iter->args;
  6009. #if G_BYTE_ORDER != G_LITTLE_ENDIAN
  6010. if (arg_size <= sizeof (gpointer)) {
  6011. int dummy;
  6012. int padding = arg_size - mono_type_size (res.type, &dummy);
  6013. res.value = (guint8*)res.value + padding;
  6014. }
  6015. #endif
  6016. iter->args = (char*)iter->args + arg_size;
  6017. iter->next_arg++;
  6018. /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
  6019. return res;
  6020. }
  6021. ICALL_EXPORT MonoTypedRef
  6022. mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
  6023. {
  6024. guint32 i, arg_size;
  6025. gint32 align;
  6026. MonoTypedRef res;
  6027. MONO_ARCH_SAVE_REGS;
  6028. i = iter->sig->sentinelpos + iter->next_arg;
  6029. g_assert (i < iter->sig->param_count);
  6030. while (i < iter->sig->param_count) {
  6031. if (!mono_metadata_type_equal (type, iter->sig->params [i]))
  6032. continue;
  6033. res.type = iter->sig->params [i];
  6034. res.klass = mono_class_from_mono_type (res.type);
  6035. /* FIXME: endianess issue... */
  6036. arg_size = mono_type_stack_size (res.type, &align);
  6037. #if defined(__arm__) || defined(__mips__)
  6038. iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
  6039. #endif
  6040. res.value = iter->args;
  6041. iter->args = (char*)iter->args + arg_size;
  6042. iter->next_arg++;
  6043. /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
  6044. return res;
  6045. }
  6046. /* g_print ("arg type 0x%02x not found\n", res.type->type); */
  6047. res.type = NULL;
  6048. res.value = NULL;
  6049. res.klass = NULL;
  6050. return res;
  6051. }
  6052. ICALL_EXPORT MonoType*
  6053. mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
  6054. {
  6055. gint i;
  6056. MONO_ARCH_SAVE_REGS;
  6057. i = iter->sig->sentinelpos + iter->next_arg;
  6058. g_assert (i < iter->sig->param_count);
  6059. return iter->sig->params [i];
  6060. }
  6061. ICALL_EXPORT MonoObject*
  6062. mono_TypedReference_ToObject (MonoTypedRef tref)
  6063. {
  6064. MONO_ARCH_SAVE_REGS;
  6065. if (MONO_TYPE_IS_REFERENCE (tref.type)) {
  6066. MonoObject** objp = tref.value;
  6067. return *objp;
  6068. }
  6069. return mono_value_box (mono_domain_get (), tref.klass, tref.value);
  6070. }
  6071. ICALL_EXPORT MonoObject*
  6072. mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
  6073. {
  6074. MONO_ARCH_SAVE_REGS;
  6075. if (MONO_TYPE_IS_REFERENCE (type)) {
  6076. MonoObject** objp = value;
  6077. return *objp;
  6078. }
  6079. return mono_value_box (mono_domain_get (), klass, value);
  6080. }
  6081. static void
  6082. prelink_method (MonoMethod *method)
  6083. {
  6084. const char *exc_class, *exc_arg;
  6085. if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
  6086. return;
  6087. mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
  6088. if (exc_class) {
  6089. mono_raise_exception(
  6090. mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
  6091. }
  6092. /* create the wrapper, too? */
  6093. }
  6094. ICALL_EXPORT void
  6095. ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
  6096. {
  6097. MONO_ARCH_SAVE_REGS;
  6098. prelink_method (method->method);
  6099. }
  6100. ICALL_EXPORT void
  6101. ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
  6102. {
  6103. MonoClass *klass = mono_class_from_mono_type (type->type);
  6104. MonoMethod* m;
  6105. gpointer iter = NULL;
  6106. MONO_ARCH_SAVE_REGS;
  6107. mono_class_init_or_throw (klass);
  6108. while ((m = mono_class_get_methods (klass, &iter)))
  6109. prelink_method (m);
  6110. }
  6111. /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
  6112. ICALL_EXPORT void
  6113. ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
  6114. gint32 const **exponents,
  6115. gunichar2 const **digitLowerTable,
  6116. gunichar2 const **digitUpperTable,
  6117. gint64 const **tenPowersList,
  6118. gint32 const **decHexDigits)
  6119. {
  6120. *mantissas = Formatter_MantissaBitsTable;
  6121. *exponents = Formatter_TensExponentTable;
  6122. *digitLowerTable = Formatter_DigitLowerTable;
  6123. *digitUpperTable = Formatter_DigitUpperTable;
  6124. *tenPowersList = Formatter_TenPowersList;
  6125. *decHexDigits = Formatter_DecHexDigits;
  6126. }
  6127. ICALL_EXPORT void
  6128. get_category_data (int version,
  6129. guint8 const **category_data,
  6130. guint16 const **category_astral_index)
  6131. {
  6132. *category_astral_index = NULL;
  6133. #ifndef DISABLE_NET_4_0
  6134. if (version == 4) {
  6135. *category_data = CategoryData_v4;
  6136. #ifndef DISABLE_ASTRAL
  6137. *category_astral_index = CategoryData_v4_astral_index;
  6138. #endif
  6139. return;
  6140. }
  6141. #endif
  6142. *category_data = CategoryData_v2;
  6143. #ifndef DISABLE_ASTRAL
  6144. *category_astral_index = CategoryData_v2_astral_index;
  6145. #endif
  6146. }
  6147. /* These parameters are "readonly" in corlib/System/Char.cs */
  6148. ICALL_EXPORT void
  6149. ves_icall_System_Char_GetDataTablePointers (int category_data_version,
  6150. guint8 const **category_data,
  6151. guint16 const **category_astral_index,
  6152. guint8 const **numeric_data,
  6153. gdouble const **numeric_data_values,
  6154. guint16 const **to_lower_data_low,
  6155. guint16 const **to_lower_data_high,
  6156. guint16 const **to_upper_data_low,
  6157. guint16 const **to_upper_data_high)
  6158. {
  6159. get_category_data (category_data_version, category_data, category_astral_index);
  6160. *numeric_data = NumericData;
  6161. *numeric_data_values = NumericDataValues;
  6162. *to_lower_data_low = ToLowerDataLow;
  6163. *to_lower_data_high = ToLowerDataHigh;
  6164. *to_upper_data_low = ToUpperDataLow;
  6165. *to_upper_data_high = ToUpperDataHigh;
  6166. }
  6167. ICALL_EXPORT gint32
  6168. ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
  6169. {
  6170. return method->method->token;
  6171. }
  6172. /*
  6173. * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
  6174. * and avoid useless allocations.
  6175. */
  6176. static MonoArray*
  6177. type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
  6178. {
  6179. MonoArray *res;
  6180. int i, count = 0;
  6181. for (i = 0; i < type->num_mods; ++i) {
  6182. if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
  6183. count++;
  6184. }
  6185. if (!count)
  6186. return NULL;
  6187. res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
  6188. count = 0;
  6189. for (i = 0; i < type->num_mods; ++i) {
  6190. if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
  6191. MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
  6192. mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
  6193. count++;
  6194. }
  6195. }
  6196. return res;
  6197. }
  6198. ICALL_EXPORT MonoArray*
  6199. param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
  6200. {
  6201. MonoType *type = param->ClassImpl->type;
  6202. MonoClass *member_class = mono_object_class (param->MemberImpl);
  6203. MonoMethod *method = NULL;
  6204. MonoImage *image;
  6205. int pos;
  6206. MonoMethodSignature *sig;
  6207. if (mono_class_is_reflection_method_or_constructor (member_class)) {
  6208. MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
  6209. method = rmethod->method;
  6210. } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
  6211. MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
  6212. if (!(method = prop->property->get))
  6213. method = prop->property->set;
  6214. g_assert (method);
  6215. } else {
  6216. char *type_name = mono_type_get_full_name (member_class);
  6217. char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
  6218. MonoException *ex = mono_get_exception_not_supported (msg);
  6219. g_free (type_name);
  6220. g_free (msg);
  6221. mono_raise_exception (ex);
  6222. }
  6223. image = method->klass->image;
  6224. pos = param->PositionImpl;
  6225. sig = mono_method_signature (method);
  6226. if (pos == -1)
  6227. type = sig->ret;
  6228. else
  6229. type = sig->params [pos];
  6230. return type_array_from_modifiers (image, type, optional);
  6231. }
  6232. static MonoType*
  6233. get_property_type (MonoProperty *prop)
  6234. {
  6235. MonoMethodSignature *sig;
  6236. if (prop->get) {
  6237. sig = mono_method_signature (prop->get);
  6238. return sig->ret;
  6239. } else if (prop->set) {
  6240. sig = mono_method_signature (prop->set);
  6241. return sig->params [sig->param_count - 1];
  6242. }
  6243. return NULL;
  6244. }
  6245. ICALL_EXPORT MonoArray*
  6246. property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
  6247. {
  6248. MonoType *type = get_property_type (property->property);
  6249. MonoImage *image = property->klass->image;
  6250. if (!type)
  6251. return NULL;
  6252. return type_array_from_modifiers (image, type, optional);
  6253. }
  6254. /*
  6255. *Construct a MonoType suited to be used to decode a constant blob object.
  6256. *
  6257. * @type is the target type which will be constructed
  6258. * @blob_type is the blob type, for example, that comes from the constant table
  6259. * @real_type is the expected constructed type.
  6260. */
  6261. static void
  6262. mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
  6263. {
  6264. type->type = blob_type;
  6265. type->data.klass = NULL;
  6266. if (blob_type == MONO_TYPE_CLASS)
  6267. type->data.klass = mono_defaults.object_class;
  6268. else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
  6269. /* For enums, we need to use the base type */
  6270. type->type = MONO_TYPE_VALUETYPE;
  6271. type->data.klass = mono_class_from_mono_type (real_type);
  6272. } else
  6273. type->data.klass = mono_class_from_mono_type (real_type);
  6274. }
  6275. ICALL_EXPORT MonoObject*
  6276. property_info_get_default_value (MonoReflectionProperty *property)
  6277. {
  6278. MonoType blob_type;
  6279. MonoProperty *prop = property->property;
  6280. MonoType *type = get_property_type (prop);
  6281. MonoDomain *domain = mono_object_domain (property);
  6282. MonoTypeEnum def_type;
  6283. const char *def_value;
  6284. MonoObject *o;
  6285. mono_class_init (prop->parent);
  6286. if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
  6287. mono_raise_exception (mono_get_exception_invalid_operation (NULL));
  6288. def_value = mono_class_get_property_default_value (prop, &def_type);
  6289. mono_type_from_blob_type (&blob_type, def_type, type);
  6290. o = mono_get_object_from_blob (domain, &blob_type, def_value);
  6291. return o;
  6292. }
  6293. ICALL_EXPORT MonoBoolean
  6294. custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
  6295. {
  6296. MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
  6297. MonoCustomAttrInfo *cinfo;
  6298. gboolean found;
  6299. mono_class_init_or_throw (attr_class);
  6300. cinfo = mono_reflection_get_custom_attrs_info (obj);
  6301. if (!cinfo)
  6302. return FALSE;
  6303. found = mono_custom_attrs_has_attr (cinfo, attr_class);
  6304. if (!cinfo->cached)
  6305. mono_custom_attrs_free (cinfo);
  6306. return found;
  6307. }
  6308. ICALL_EXPORT MonoArray*
  6309. custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
  6310. {
  6311. MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
  6312. MonoArray *res;
  6313. MonoError error;
  6314. if (attr_class)
  6315. mono_class_init_or_throw (attr_class);
  6316. res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
  6317. if (!mono_error_ok (&error))
  6318. mono_error_raise_exception (&error);
  6319. if (mono_loader_get_last_error ()) {
  6320. mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
  6321. g_assert_not_reached ();
  6322. /* Not reached */
  6323. return NULL;
  6324. } else {
  6325. return res;
  6326. }
  6327. }
  6328. ICALL_EXPORT MonoString*
  6329. ves_icall_Mono_Runtime_GetDisplayName (void)
  6330. {
  6331. char *info;
  6332. MonoString *display_name;
  6333. info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
  6334. display_name = mono_string_new (mono_domain_get (), info);
  6335. g_free (info);
  6336. return display_name;
  6337. }
  6338. ICALL_EXPORT MonoString*
  6339. ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
  6340. {
  6341. MonoString *message;
  6342. guint32 ret;
  6343. gunichar2 buf[256];
  6344. ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
  6345. FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
  6346. buf, 255, NULL);
  6347. if (ret == 0) {
  6348. message = mono_string_new (mono_domain_get (), "Error looking up error string");
  6349. } else {
  6350. message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
  6351. }
  6352. return message;
  6353. }
  6354. const static guchar
  6355. dbase64 [] = {
  6356. 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  6357. 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  6358. 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
  6359. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
  6360. 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  6361. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
  6362. 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  6363. 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
  6364. };
  6365. static MonoArray *
  6366. base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
  6367. {
  6368. gint ignored;
  6369. gint i;
  6370. gunichar2 c;
  6371. gunichar2 last, prev_last, prev2_last;
  6372. gint olength;
  6373. MonoArray *result;
  6374. guchar *res_ptr;
  6375. gint a [4], b [4];
  6376. MonoException *exc;
  6377. int havePadding = 0;
  6378. ignored = 0;
  6379. last = prev_last = 0, prev2_last = 0;
  6380. for (i = 0; i < ilength; i++) {
  6381. c = start [i];
  6382. if (c >= sizeof (dbase64)) {
  6383. exc = mono_exception_from_name_msg (mono_get_corlib (),
  6384. "System", "FormatException",
  6385. "Invalid character found.");
  6386. mono_raise_exception (exc);
  6387. } else if (isspace (c)) {
  6388. ignored++;
  6389. } else if (havePadding && c != '=') {
  6390. exc = mono_exception_from_name_msg (mono_get_corlib (),
  6391. "System", "FormatException",
  6392. "Invalid character found.");
  6393. mono_raise_exception (exc);
  6394. } else {
  6395. if (c == '=') havePadding = 1;
  6396. prev2_last = prev_last;
  6397. prev_last = last;
  6398. last = c;
  6399. }
  6400. }
  6401. olength = ilength - ignored;
  6402. if (allowWhitespaceOnly && olength == 0) {
  6403. return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
  6404. }
  6405. if ((olength & 3) != 0 || olength <= 0) {
  6406. exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
  6407. "FormatException", "Invalid length.");
  6408. mono_raise_exception (exc);
  6409. }
  6410. if (prev2_last == '=') {
  6411. exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
  6412. mono_raise_exception (exc);
  6413. }
  6414. olength = (olength * 3) / 4;
  6415. if (last == '=')
  6416. olength--;
  6417. if (prev_last == '=')
  6418. olength--;
  6419. result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
  6420. res_ptr = mono_array_addr (result, guchar, 0);
  6421. for (i = 0; i < ilength; ) {
  6422. int k;
  6423. for (k = 0; k < 4 && i < ilength;) {
  6424. c = start [i++];
  6425. if (isspace (c))
  6426. continue;
  6427. a [k] = (guchar) c;
  6428. if (((b [k] = dbase64 [c]) & 0x80) != 0) {
  6429. exc = mono_exception_from_name_msg (mono_get_corlib (),
  6430. "System", "FormatException",
  6431. "Invalid character found.");
  6432. mono_raise_exception (exc);
  6433. }
  6434. k++;
  6435. }
  6436. *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
  6437. if (a [2] != '=')
  6438. *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
  6439. if (a [3] != '=')
  6440. *res_ptr++ = (b [2] << 6) | b [3];
  6441. while (i < ilength && isspace (start [i]))
  6442. i++;
  6443. }
  6444. return result;
  6445. }
  6446. ICALL_EXPORT MonoArray *
  6447. InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
  6448. {
  6449. MONO_ARCH_SAVE_REGS;
  6450. return base64_to_byte_array (mono_string_chars (str),
  6451. mono_string_length (str), allowWhitespaceOnly);
  6452. }
  6453. ICALL_EXPORT MonoArray *
  6454. InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
  6455. {
  6456. MONO_ARCH_SAVE_REGS;
  6457. return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
  6458. length, FALSE);
  6459. }
  6460. #ifndef DISABLE_ICALL_TABLES
  6461. #define ICALL_TYPE(id,name,first)
  6462. #define ICALL(id,name,func) Icall_ ## id,
  6463. enum {
  6464. #include "metadata/icall-def.h"
  6465. Icall_last
  6466. };
  6467. #undef ICALL_TYPE
  6468. #undef ICALL
  6469. #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
  6470. #define ICALL(id,name,func)
  6471. enum {
  6472. #include "metadata/icall-def.h"
  6473. Icall_type_num
  6474. };
  6475. #undef ICALL_TYPE
  6476. #undef ICALL
  6477. #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
  6478. #define ICALL(id,name,func)
  6479. typedef struct {
  6480. guint16 first_icall;
  6481. } IcallTypeDesc;
  6482. static const IcallTypeDesc
  6483. icall_type_descs [] = {
  6484. #include "metadata/icall-def.h"
  6485. {Icall_last}
  6486. };
  6487. #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
  6488. #undef ICALL_TYPE
  6489. #define ICALL_TYPE(id,name,first)
  6490. #undef ICALL
  6491. #ifdef HAVE_ARRAY_ELEM_INIT
  6492. #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
  6493. #define MSGSTRFIELD1(line) str##line
  6494. static const struct msgstrtn_t {
  6495. #define ICALL(id,name,func)
  6496. #undef ICALL_TYPE
  6497. #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
  6498. #include "metadata/icall-def.h"
  6499. #undef ICALL_TYPE
  6500. } icall_type_names_str = {
  6501. #define ICALL_TYPE(id,name,first) (name),
  6502. #include "metadata/icall-def.h"
  6503. #undef ICALL_TYPE
  6504. };
  6505. static const guint16 icall_type_names_idx [] = {
  6506. #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
  6507. #include "metadata/icall-def.h"
  6508. #undef ICALL_TYPE
  6509. };
  6510. #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
  6511. static const struct msgstr_t {
  6512. #undef ICALL
  6513. #define ICALL_TYPE(id,name,first)
  6514. #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
  6515. #include "metadata/icall-def.h"
  6516. #undef ICALL
  6517. } icall_names_str = {
  6518. #define ICALL(id,name,func) (name),
  6519. #include "metadata/icall-def.h"
  6520. #undef ICALL
  6521. };
  6522. static const guint16 icall_names_idx [] = {
  6523. #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
  6524. #include "metadata/icall-def.h"
  6525. #undef ICALL
  6526. };
  6527. #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
  6528. #else
  6529. #undef ICALL_TYPE
  6530. #undef ICALL
  6531. #define ICALL_TYPE(id,name,first) name,
  6532. #define ICALL(id,name,func)
  6533. static const char* const
  6534. icall_type_names [] = {
  6535. #include "metadata/icall-def.h"
  6536. NULL
  6537. };
  6538. #define icall_type_name_get(id) (icall_type_names [(id)])
  6539. #undef ICALL_TYPE
  6540. #undef ICALL
  6541. #define ICALL_TYPE(id,name,first)
  6542. #define ICALL(id,name,func) name,
  6543. static const char* const
  6544. icall_names [] = {
  6545. #include "metadata/icall-def.h"
  6546. NULL
  6547. };
  6548. #define icall_name_get(id) icall_names [(id)]
  6549. #endif /* !HAVE_ARRAY_ELEM_INIT */
  6550. #undef ICALL_TYPE
  6551. #undef ICALL
  6552. #define ICALL_TYPE(id,name,first)
  6553. #define ICALL(id,name,func) func,
  6554. static const gconstpointer
  6555. icall_functions [] = {
  6556. #include "metadata/icall-def.h"
  6557. NULL
  6558. };
  6559. #ifdef ENABLE_ICALL_SYMBOL_MAP
  6560. #undef ICALL_TYPE
  6561. #undef ICALL
  6562. #define ICALL_TYPE(id,name,first)
  6563. #define ICALL(id,name,func) #func,
  6564. static const gconstpointer
  6565. icall_symbols [] = {
  6566. #include "metadata/icall-def.h"
  6567. NULL
  6568. };
  6569. #endif
  6570. #endif /* DISABLE_ICALL_TABLES */
  6571. static GHashTable *icall_hash = NULL;
  6572. static GHashTable *jit_icall_hash_name = NULL;
  6573. static GHashTable *jit_icall_hash_addr = NULL;
  6574. void
  6575. mono_icall_init (void)
  6576. {
  6577. #ifndef DISABLE_ICALL_TABLES
  6578. int i = 0;
  6579. /* check that tables are sorted: disable in release */
  6580. if (TRUE) {
  6581. int j;
  6582. const char *prev_class = NULL;
  6583. const char *prev_method;
  6584. for (i = 0; i < Icall_type_num; ++i) {
  6585. const IcallTypeDesc *desc;
  6586. int num_icalls;
  6587. prev_method = NULL;
  6588. if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
  6589. g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
  6590. prev_class = icall_type_name_get (i);
  6591. desc = &icall_type_descs [i];
  6592. num_icalls = icall_desc_num_icalls (desc);
  6593. /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
  6594. for (j = 0; j < num_icalls; ++j) {
  6595. const char *methodn = icall_name_get (desc->first_icall + j);
  6596. if (prev_method && strcmp (prev_method, methodn) >= 0)
  6597. g_print ("method %s should come before method %s\n", methodn, prev_method);
  6598. prev_method = methodn;
  6599. }
  6600. }
  6601. }
  6602. #endif
  6603. icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
  6604. }
  6605. void
  6606. mono_icall_cleanup (void)
  6607. {
  6608. g_hash_table_destroy (icall_hash);
  6609. g_hash_table_destroy (jit_icall_hash_name);
  6610. g_hash_table_destroy (jit_icall_hash_addr);
  6611. }
  6612. void
  6613. mono_add_internal_call (const char *name, gconstpointer method)
  6614. {
  6615. mono_loader_lock ();
  6616. g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
  6617. mono_loader_unlock ();
  6618. }
  6619. #ifndef DISABLE_ICALL_TABLES
  6620. #ifdef HAVE_ARRAY_ELEM_INIT
  6621. static int
  6622. compare_method_imap (const void *key, const void *elem)
  6623. {
  6624. const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
  6625. return strcmp (key, method_name);
  6626. }
  6627. static gpointer
  6628. find_method_icall (const IcallTypeDesc *imap, const char *name)
  6629. {
  6630. const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
  6631. if (!nameslot)
  6632. return NULL;
  6633. return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
  6634. }
  6635. static int
  6636. compare_class_imap (const void *key, const void *elem)
  6637. {
  6638. const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
  6639. return strcmp (key, class_name);
  6640. }
  6641. static const IcallTypeDesc*
  6642. find_class_icalls (const char *name)
  6643. {
  6644. const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
  6645. if (!nameslot)
  6646. return NULL;
  6647. return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
  6648. }
  6649. #else /* HAVE_ARRAY_ELEM_INIT */
  6650. static int
  6651. compare_method_imap (const void *key, const void *elem)
  6652. {
  6653. const char** method_name = (const char**)elem;
  6654. return strcmp (key, *method_name);
  6655. }
  6656. static gpointer
  6657. find_method_icall (const IcallTypeDesc *imap, const char *name)
  6658. {
  6659. const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
  6660. if (!nameslot)
  6661. return NULL;
  6662. return (gpointer)icall_functions [(nameslot - icall_names)];
  6663. }
  6664. static int
  6665. compare_class_imap (const void *key, const void *elem)
  6666. {
  6667. const char** class_name = (const char**)elem;
  6668. return strcmp (key, *class_name);
  6669. }
  6670. static const IcallTypeDesc*
  6671. find_class_icalls (const char *name)
  6672. {
  6673. const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
  6674. if (!nameslot)
  6675. return NULL;
  6676. return &icall_type_descs [nameslot - icall_type_names];
  6677. }
  6678. #endif /* HAVE_ARRAY_ELEM_INIT */
  6679. #endif /* DISABLE_ICALL_TABLES */
  6680. /*
  6681. * we should probably export this as an helper (handle nested types).
  6682. * Returns the number of chars written in buf.
  6683. */
  6684. static int
  6685. concat_class_name (char *buf, int bufsize, MonoClass *klass)
  6686. {
  6687. int nspacelen, cnamelen;
  6688. nspacelen = strlen (klass->name_space);
  6689. cnamelen = strlen (klass->name);
  6690. if (nspacelen + cnamelen + 2 > bufsize)
  6691. return 0;
  6692. if (nspacelen) {
  6693. memcpy (buf, klass->name_space, nspacelen);
  6694. buf [nspacelen ++] = '.';
  6695. }
  6696. memcpy (buf + nspacelen, klass->name, cnamelen);
  6697. buf [nspacelen + cnamelen] = 0;
  6698. return nspacelen + cnamelen;
  6699. }
  6700. #ifdef DISABLE_ICALL_TABLES
  6701. static void
  6702. no_icall_table (void)
  6703. {
  6704. g_assert_not_reached ();
  6705. }
  6706. #endif
  6707. gpointer
  6708. mono_lookup_internal_call (MonoMethod *method)
  6709. {
  6710. char *sigstart;
  6711. char *tmpsig;
  6712. char mname [2048];
  6713. int typelen = 0, mlen, siglen;
  6714. gpointer res;
  6715. #ifndef DISABLE_ICALL_TABLES
  6716. const IcallTypeDesc *imap = NULL;
  6717. #endif
  6718. g_assert (method != NULL);
  6719. if (method->is_inflated)
  6720. method = ((MonoMethodInflated *) method)->declaring;
  6721. if (method->klass->nested_in) {
  6722. int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
  6723. if (!pos)
  6724. return NULL;
  6725. mname [pos++] = '/';
  6726. mname [pos] = 0;
  6727. typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
  6728. if (!typelen)
  6729. return NULL;
  6730. typelen += pos;
  6731. } else {
  6732. typelen = concat_class_name (mname, sizeof (mname), method->klass);
  6733. if (!typelen)
  6734. return NULL;
  6735. }
  6736. #ifndef DISABLE_ICALL_TABLES
  6737. imap = find_class_icalls (mname);
  6738. #endif
  6739. mname [typelen] = ':';
  6740. mname [typelen + 1] = ':';
  6741. mlen = strlen (method->name);
  6742. memcpy (mname + typelen + 2, method->name, mlen);
  6743. sigstart = mname + typelen + 2 + mlen;
  6744. *sigstart = 0;
  6745. tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
  6746. siglen = strlen (tmpsig);
  6747. if (typelen + mlen + siglen + 6 > sizeof (mname))
  6748. return NULL;
  6749. sigstart [0] = '(';
  6750. memcpy (sigstart + 1, tmpsig, siglen);
  6751. sigstart [siglen + 1] = ')';
  6752. sigstart [siglen + 2] = 0;
  6753. g_free (tmpsig);
  6754. mono_loader_lock ();
  6755. res = g_hash_table_lookup (icall_hash, mname);
  6756. if (res) {
  6757. mono_loader_unlock ();
  6758. return res;
  6759. }
  6760. /* try without signature */
  6761. *sigstart = 0;
  6762. res = g_hash_table_lookup (icall_hash, mname);
  6763. if (res) {
  6764. mono_loader_unlock ();
  6765. return res;
  6766. }
  6767. #ifdef DISABLE_ICALL_TABLES
  6768. mono_loader_unlock ();
  6769. /* Fail only when the result is actually used */
  6770. /* mono_marshal_get_native_wrapper () depends on this */
  6771. if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
  6772. return ves_icall_System_String_ctor_RedirectToCreateString;
  6773. else
  6774. return no_icall_table;
  6775. #else
  6776. /* it wasn't found in the static call tables */
  6777. if (!imap) {
  6778. mono_loader_unlock ();
  6779. return NULL;
  6780. }
  6781. res = find_method_icall (imap, sigstart - mlen);
  6782. if (res) {
  6783. mono_loader_unlock ();
  6784. return res;
  6785. }
  6786. /* try _with_ signature */
  6787. *sigstart = '(';
  6788. res = find_method_icall (imap, sigstart - mlen);
  6789. if (res) {
  6790. mono_loader_unlock ();
  6791. return res;
  6792. }
  6793. g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
  6794. g_print ("\nYour mono runtime and class libraries are out of sync.\n");
  6795. g_print ("The out of sync library is: %s\n", method->klass->image->name);
  6796. g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
  6797. 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");
  6798. g_print ("If you see other errors or faults after this message they are probably related\n");
  6799. g_print ("and you need to fix your mono install first.\n");
  6800. mono_loader_unlock ();
  6801. return NULL;
  6802. #endif
  6803. }
  6804. #ifdef ENABLE_ICALL_SYMBOL_MAP
  6805. static int
  6806. func_cmp (gconstpointer key, gconstpointer p)
  6807. {
  6808. return (gsize)key - (gsize)*(gsize*)p;
  6809. }
  6810. #endif
  6811. /*
  6812. * mono_lookup_icall_symbol:
  6813. *
  6814. * Given the icall METHOD, returns its C symbol.
  6815. */
  6816. const char*
  6817. mono_lookup_icall_symbol (MonoMethod *m)
  6818. {
  6819. #ifdef DISABLE_ICALL_TABLES
  6820. g_assert_not_reached ();
  6821. return NULL;
  6822. #else
  6823. #ifdef ENABLE_ICALL_SYMBOL_MAP
  6824. gpointer func;
  6825. int i;
  6826. gpointer slot;
  6827. static gconstpointer *functions_sorted;
  6828. static const char**symbols_sorted;
  6829. static gboolean inited;
  6830. if (!inited) {
  6831. gboolean changed;
  6832. functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
  6833. memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
  6834. symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
  6835. memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
  6836. /* Bubble sort the two arrays */
  6837. changed = TRUE;
  6838. while (changed) {
  6839. changed = FALSE;
  6840. for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
  6841. if (functions_sorted [i] > functions_sorted [i + 1]) {
  6842. gconstpointer tmp;
  6843. tmp = functions_sorted [i];
  6844. functions_sorted [i] = functions_sorted [i + 1];
  6845. functions_sorted [i + 1] = tmp;
  6846. tmp = symbols_sorted [i];
  6847. symbols_sorted [i] = symbols_sorted [i + 1];
  6848. symbols_sorted [i + 1] = tmp;
  6849. changed = TRUE;
  6850. }
  6851. }
  6852. }
  6853. }
  6854. func = mono_lookup_internal_call (m);
  6855. if (!func)
  6856. return NULL;
  6857. slot = bsearch (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
  6858. if (!slot)
  6859. return NULL;
  6860. g_assert (slot);
  6861. return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
  6862. #else
  6863. fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
  6864. g_assert_not_reached ();
  6865. return 0;
  6866. #endif
  6867. #endif
  6868. }
  6869. static MonoType*
  6870. type_from_typename (char *typename)
  6871. {
  6872. MonoClass *klass = NULL; /* assignment to shut GCC warning up */
  6873. if (!strcmp (typename, "int"))
  6874. klass = mono_defaults.int_class;
  6875. else if (!strcmp (typename, "ptr"))
  6876. klass = mono_defaults.int_class;
  6877. else if (!strcmp (typename, "void"))
  6878. klass = mono_defaults.void_class;
  6879. else if (!strcmp (typename, "int32"))
  6880. klass = mono_defaults.int32_class;
  6881. else if (!strcmp (typename, "uint32"))
  6882. klass = mono_defaults.uint32_class;
  6883. else if (!strcmp (typename, "int8"))
  6884. klass = mono_defaults.sbyte_class;
  6885. else if (!strcmp (typename, "uint8"))
  6886. klass = mono_defaults.byte_class;
  6887. else if (!strcmp (typename, "int16"))
  6888. klass = mono_defaults.int16_class;
  6889. else if (!strcmp (typename, "uint16"))
  6890. klass = mono_defaults.uint16_class;
  6891. else if (!strcmp (typename, "long"))
  6892. klass = mono_defaults.int64_class;
  6893. else if (!strcmp (typename, "ulong"))
  6894. klass = mono_defaults.uint64_class;
  6895. else if (!strcmp (typename, "float"))
  6896. klass = mono_defaults.single_class;
  6897. else if (!strcmp (typename, "double"))
  6898. klass = mono_defaults.double_class;
  6899. else if (!strcmp (typename, "object"))
  6900. klass = mono_defaults.object_class;
  6901. else if (!strcmp (typename, "obj"))
  6902. klass = mono_defaults.object_class;
  6903. else if (!strcmp (typename, "string"))
  6904. klass = mono_defaults.string_class;
  6905. else if (!strcmp (typename, "bool"))
  6906. klass = mono_defaults.boolean_class;
  6907. else if (!strcmp (typename, "boolean"))
  6908. klass = mono_defaults.boolean_class;
  6909. else {
  6910. g_error ("%s", typename);
  6911. g_assert_not_reached ();
  6912. }
  6913. return &klass->byval_arg;
  6914. }
  6915. MonoMethodSignature*
  6916. mono_create_icall_signature (const char *sigstr)
  6917. {
  6918. gchar **parts;
  6919. int i, len;
  6920. gchar **tmp;
  6921. MonoMethodSignature *res;
  6922. mono_loader_lock ();
  6923. res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
  6924. if (res) {
  6925. mono_loader_unlock ();
  6926. return res;
  6927. }
  6928. parts = g_strsplit (sigstr, " ", 256);
  6929. tmp = parts;
  6930. len = 0;
  6931. while (*tmp) {
  6932. len ++;
  6933. tmp ++;
  6934. }
  6935. res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
  6936. res->pinvoke = 1;
  6937. #ifdef HOST_WIN32
  6938. /*
  6939. * Under windows, the default pinvoke calling convention is STDCALL but
  6940. * we need CDECL.
  6941. */
  6942. res->call_convention = MONO_CALL_C;
  6943. #endif
  6944. res->ret = type_from_typename (parts [0]);
  6945. for (i = 1; i < len; ++i) {
  6946. res->params [i - 1] = type_from_typename (parts [i]);
  6947. }
  6948. g_strfreev (parts);
  6949. g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
  6950. mono_loader_unlock ();
  6951. return res;
  6952. }
  6953. MonoJitICallInfo *
  6954. mono_find_jit_icall_by_name (const char *name)
  6955. {
  6956. MonoJitICallInfo *info;
  6957. g_assert (jit_icall_hash_name);
  6958. mono_loader_lock ();
  6959. info = g_hash_table_lookup (jit_icall_hash_name, name);
  6960. mono_loader_unlock ();
  6961. return info;
  6962. }
  6963. MonoJitICallInfo *
  6964. mono_find_jit_icall_by_addr (gconstpointer addr)
  6965. {
  6966. MonoJitICallInfo *info;
  6967. g_assert (jit_icall_hash_addr);
  6968. mono_loader_lock ();
  6969. info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
  6970. mono_loader_unlock ();
  6971. return info;
  6972. }
  6973. /*
  6974. * mono_get_jit_icall_info:
  6975. *
  6976. * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
  6977. * caller should access it while holding the loader lock.
  6978. */
  6979. GHashTable*
  6980. mono_get_jit_icall_info (void)
  6981. {
  6982. return jit_icall_hash_name;
  6983. }
  6984. /*
  6985. * mono_lookup_jit_icall_symbol:
  6986. *
  6987. * Given the jit icall NAME, returns its C symbol if possible, or NULL.
  6988. */
  6989. const char*
  6990. mono_lookup_jit_icall_symbol (const char *name)
  6991. {
  6992. MonoJitICallInfo *info;
  6993. const char *res = NULL;
  6994. mono_loader_lock ();
  6995. info = g_hash_table_lookup (jit_icall_hash_name, name);
  6996. if (info)
  6997. res = info->c_symbol;
  6998. mono_loader_unlock ();
  6999. return res;
  7000. }
  7001. void
  7002. mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
  7003. {
  7004. mono_loader_lock ();
  7005. g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
  7006. mono_loader_unlock ();
  7007. }
  7008. MonoJitICallInfo *
  7009. mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
  7010. {
  7011. MonoJitICallInfo *info;
  7012. g_assert (func);
  7013. g_assert (name);
  7014. mono_loader_lock ();
  7015. if (!jit_icall_hash_name) {
  7016. jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
  7017. jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
  7018. }
  7019. if (g_hash_table_lookup (jit_icall_hash_name, name)) {
  7020. g_warning ("jit icall already defined \"%s\"\n", name);
  7021. g_assert_not_reached ();
  7022. }
  7023. info = g_new0 (MonoJitICallInfo, 1);
  7024. info->name = name;
  7025. info->func = func;
  7026. info->sig = sig;
  7027. info->c_symbol = c_symbol;
  7028. if (is_save) {
  7029. info->wrapper = func;
  7030. } else {
  7031. info->wrapper = NULL;
  7032. }
  7033. g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
  7034. g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
  7035. mono_loader_unlock ();
  7036. return info;
  7037. }
  7038. MonoJitICallInfo *
  7039. mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
  7040. {
  7041. return mono_register_jit_icall_full (func, name, sig, is_save, NULL);
  7042. }