PageRenderTime 42ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/mono/mini/mini-exceptions.c

https://bitbucket.org/danipen/mono
C | 2723 lines | 1918 code | 422 blank | 383 comment | 483 complexity | fefd991958de59db90d77e6bfd24ad5b 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. * mini-exceptions.c: generic exception support
  3. *
  4. * Authors:
  5. * Dietmar Maurer (dietmar@ximian.com)
  6. * Mono Team (mono-list@lists.ximian.com)
  7. *
  8. * Copyright 2001-2003 Ximian, Inc.
  9. * Copyright 2003-2008 Novell, Inc.
  10. * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
  11. */
  12. #include <config.h>
  13. #include <glib.h>
  14. #include <signal.h>
  15. #include <string.h>
  16. #ifdef HAVE_EXECINFO_H
  17. #include <execinfo.h>
  18. #endif
  19. #ifdef HAVE_SYS_TYPES_H
  20. #include <sys/types.h>
  21. #endif
  22. #ifdef HAVE_SYS_WAIT_H
  23. #include <sys/wait.h>
  24. #endif
  25. #ifdef HAVE_UNISTD_H
  26. #include <unistd.h>
  27. #endif
  28. #ifdef HAVE_SYS_SYSCALL_H
  29. #include <sys/syscall.h>
  30. #endif
  31. #include <mono/metadata/appdomain.h>
  32. #include <mono/metadata/tabledefs.h>
  33. #include <mono/metadata/threads.h>
  34. #include <mono/metadata/threads-types.h>
  35. #include <mono/metadata/debug-helpers.h>
  36. #include <mono/metadata/exception.h>
  37. #include <mono/metadata/gc-internal.h>
  38. #include <mono/metadata/mono-debug.h>
  39. #include <mono/metadata/profiler.h>
  40. #include <mono/metadata/mono-endian.h>
  41. #include <mono/metadata/environment.h>
  42. #include <mono/utils/mono-mmap.h>
  43. #include <mono/utils/mono-logger-internal.h>
  44. #include "mini.h"
  45. #include "debug-mini.h"
  46. #include "trace.h"
  47. #include "debugger-agent.h"
  48. #ifndef MONO_ARCH_CONTEXT_DEF
  49. #define MONO_ARCH_CONTEXT_DEF
  50. #endif
  51. static gpointer restore_context_func, call_filter_func;
  52. static gpointer throw_exception_func, rethrow_exception_func;
  53. static gpointer throw_corlib_exception_func;
  54. static gpointer try_more_restore_tramp = NULL;
  55. static gpointer restore_stack_protection_tramp = NULL;
  56. static MonoUnhandledExceptionFunc unhandled_exception_hook = NULL;
  57. static gpointer unhandled_exception_hook_data = NULL;
  58. static void try_more_restore (void);
  59. static void restore_stack_protection (void);
  60. static void mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data);
  61. static void mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx);
  62. static void mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data);
  63. void
  64. mono_exceptions_init (void)
  65. {
  66. MonoRuntimeExceptionHandlingCallbacks cbs;
  67. if (mono_aot_only) {
  68. restore_context_func = mono_aot_get_trampoline ("restore_context");
  69. call_filter_func = mono_aot_get_trampoline ("call_filter");
  70. throw_exception_func = mono_aot_get_trampoline ("throw_exception");
  71. rethrow_exception_func = mono_aot_get_trampoline ("rethrow_exception");
  72. } else {
  73. MonoTrampInfo *info;
  74. restore_context_func = mono_arch_get_restore_context (&info, FALSE);
  75. if (info) {
  76. mono_save_trampoline_xdebug_info (info);
  77. mono_tramp_info_free (info);
  78. }
  79. call_filter_func = mono_arch_get_call_filter (&info, FALSE);
  80. if (info) {
  81. mono_save_trampoline_xdebug_info (info);
  82. mono_tramp_info_free (info);
  83. }
  84. throw_exception_func = mono_arch_get_throw_exception (&info, FALSE);
  85. if (info) {
  86. mono_save_trampoline_xdebug_info (info);
  87. mono_tramp_info_free (info);
  88. }
  89. rethrow_exception_func = mono_arch_get_rethrow_exception (&info, FALSE);
  90. if (info) {
  91. mono_save_trampoline_xdebug_info (info);
  92. mono_tramp_info_free (info);
  93. }
  94. }
  95. #ifdef MONO_ARCH_HAVE_RESTORE_STACK_SUPPORT
  96. try_more_restore_tramp = mono_create_specific_trampoline (try_more_restore, MONO_TRAMPOLINE_RESTORE_STACK_PROT, mono_domain_get (), NULL);
  97. restore_stack_protection_tramp = mono_create_specific_trampoline (restore_stack_protection, MONO_TRAMPOLINE_RESTORE_STACK_PROT, mono_domain_get (), NULL);
  98. #endif
  99. #ifdef MONO_ARCH_HAVE_EXCEPTIONS_INIT
  100. mono_arch_exceptions_init ();
  101. #endif
  102. cbs.mono_walk_stack_with_ctx = mono_runtime_walk_stack_with_ctx;
  103. cbs.mono_walk_stack_with_state = mono_walk_stack_with_state;
  104. cbs.mono_raise_exception = mono_get_throw_exception ();
  105. cbs.mono_raise_exception_with_ctx = mono_raise_exception_with_ctx;
  106. cbs.mono_install_handler_block_guard = mono_install_handler_block_guard;
  107. mono_install_eh_callbacks (&cbs);
  108. }
  109. gpointer
  110. mono_get_throw_exception (void)
  111. {
  112. g_assert (throw_exception_func);
  113. return throw_exception_func;
  114. }
  115. gpointer
  116. mono_get_rethrow_exception (void)
  117. {
  118. g_assert (rethrow_exception_func);
  119. return rethrow_exception_func;
  120. }
  121. gpointer
  122. mono_get_call_filter (void)
  123. {
  124. g_assert (call_filter_func);
  125. return call_filter_func;
  126. }
  127. gpointer
  128. mono_get_restore_context (void)
  129. {
  130. g_assert (restore_context_func);
  131. return restore_context_func;
  132. }
  133. gpointer
  134. mono_get_throw_corlib_exception (void)
  135. {
  136. gpointer code = NULL;
  137. MonoTrampInfo *info;
  138. /* This depends on corlib classes so cannot be inited in mono_exceptions_init () */
  139. if (throw_corlib_exception_func)
  140. return throw_corlib_exception_func;
  141. if (mono_aot_only)
  142. code = mono_aot_get_trampoline ("throw_corlib_exception");
  143. else {
  144. code = mono_arch_get_throw_corlib_exception (&info, FALSE);
  145. if (info) {
  146. mono_save_trampoline_xdebug_info (info);
  147. mono_tramp_info_free (info);
  148. }
  149. }
  150. mono_memory_barrier ();
  151. throw_corlib_exception_func = code;
  152. return throw_corlib_exception_func;
  153. }
  154. static gboolean
  155. is_address_protected (MonoJitInfo *ji, MonoJitExceptionInfo *ei, gpointer ip)
  156. {
  157. MonoTryBlockHoleTableJitInfo *table;
  158. int i;
  159. guint32 offset;
  160. guint16 clause;
  161. if (ei->try_start > ip || ip >= ei->try_end)
  162. return FALSE;
  163. if (!ji->has_try_block_holes)
  164. return TRUE;
  165. table = mono_jit_info_get_try_block_hole_table_info (ji);
  166. offset = (guint32)((char*)ip - (char*)ji->code_start);
  167. clause = (guint16)(ei - ji->clauses);
  168. g_assert (clause < ji->num_clauses);
  169. for (i = 0; i < table->num_holes; ++i) {
  170. MonoTryBlockHoleJitInfo *hole = &table->holes [i];
  171. if (hole->clause == clause && hole->offset <= offset && hole->offset + hole->length > offset)
  172. return FALSE;
  173. }
  174. return TRUE;
  175. }
  176. /*
  177. * find_jit_info:
  178. *
  179. * Translate between the mono_arch_find_jit_info function and the old API.
  180. */
  181. static MonoJitInfo *
  182. find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx,
  183. MonoContext *new_ctx, MonoLMF **lmf, gboolean *managed)
  184. {
  185. StackFrameInfo frame;
  186. MonoJitInfo *ji;
  187. gboolean err;
  188. gpointer ip = MONO_CONTEXT_GET_IP (ctx);
  189. /* Avoid costly table lookup during stack overflow */
  190. if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size)))
  191. ji = prev_ji;
  192. else
  193. ji = mini_jit_info_table_find (domain, ip, NULL);
  194. if (managed)
  195. *managed = FALSE;
  196. err = mono_arch_find_jit_info (domain, jit_tls, ji, ctx, new_ctx, lmf, NULL, &frame);
  197. if (!err)
  198. return (gpointer)-1;
  199. /* Convert between the new and the old APIs */
  200. switch (frame.type) {
  201. case FRAME_TYPE_MANAGED:
  202. if (managed)
  203. *managed = TRUE;
  204. return frame.ji;
  205. case FRAME_TYPE_MANAGED_TO_NATIVE:
  206. if (frame.ji)
  207. return frame.ji;
  208. else {
  209. memset (res, 0, sizeof (MonoJitInfo));
  210. res->method = frame.method;
  211. return res;
  212. }
  213. case FRAME_TYPE_DEBUGGER_INVOKE: {
  214. MonoContext tmp_ctx;
  215. /*
  216. * The normal exception handling code can't handle this frame, so just
  217. * skip it.
  218. */
  219. ji = find_jit_info (domain, jit_tls, res, NULL, new_ctx, &tmp_ctx, lmf, managed);
  220. memcpy (new_ctx, &tmp_ctx, sizeof (MonoContext));
  221. return ji;
  222. }
  223. default:
  224. g_assert_not_reached ();
  225. return NULL;
  226. }
  227. }
  228. /* mono_find_jit_info:
  229. *
  230. * This function is used to gather information from @ctx. It return the
  231. * MonoJitInfo of the corresponding function, unwinds one stack frame and
  232. * stores the resulting context into @new_ctx. It also stores a string
  233. * describing the stack location into @trace (if not NULL), and modifies
  234. * the @lmf if necessary. @native_offset return the IP offset from the
  235. * start of the function or -1 if that info is not available.
  236. */
  237. MonoJitInfo *
  238. mono_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInfo *res, MonoJitInfo *prev_ji, MonoContext *ctx,
  239. MonoContext *new_ctx, char **trace, MonoLMF **lmf, int *native_offset,
  240. gboolean *managed)
  241. {
  242. gboolean managed2;
  243. gpointer ip = MONO_CONTEXT_GET_IP (ctx);
  244. MonoJitInfo *ji;
  245. if (trace)
  246. *trace = NULL;
  247. if (native_offset)
  248. *native_offset = -1;
  249. if (managed)
  250. *managed = FALSE;
  251. ji = find_jit_info (domain, jit_tls, res, prev_ji, ctx, new_ctx, lmf, &managed2);
  252. if (ji == (gpointer)-1)
  253. return ji;
  254. if (managed2 || (ji && ji->method->wrapper_type)) {
  255. const char *real_ip, *start;
  256. gint32 offset;
  257. start = (const char *)ji->code_start;
  258. if (!managed2)
  259. /* ctx->ip points into native code */
  260. real_ip = (const char*)MONO_CONTEXT_GET_IP (new_ctx);
  261. else
  262. real_ip = (const char*)ip;
  263. if ((real_ip >= start) && (real_ip <= start + ji->code_size))
  264. offset = real_ip - start;
  265. else
  266. offset = -1;
  267. if (native_offset)
  268. *native_offset = offset;
  269. if (managed)
  270. if (!ji->method->wrapper_type || ji->method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
  271. *managed = TRUE;
  272. if (trace)
  273. *trace = mono_debug_print_stack_frame (ji->method, offset, domain);
  274. } else {
  275. if (trace) {
  276. char *fname = mono_method_full_name (res->method, TRUE);
  277. *trace = g_strdup_printf ("in (unmanaged) %s", fname);
  278. g_free (fname);
  279. }
  280. }
  281. return ji;
  282. }
  283. /*
  284. * mono_find_jit_info_ext:
  285. *
  286. * A version of mono_find_jit_info which returns all data in the StackFrameInfo
  287. * structure.
  288. * A note about frames of type FRAME_TYPE_MANAGED_TO_NATIVE:
  289. * - These frames are used to mark managed-to-native transitions, so CTX will refer to native
  290. * code, and new_ctx will refer to the last managed frame. The caller should unwind once more
  291. * to obtain the last managed frame.
  292. * If SAVE_LOCATIONS is not NULL, it should point to an array of size MONO_MAX_IREGS.
  293. * On return, it will be filled with the locations where callee saved registers are saved
  294. * by the current frame. This is returned outside of StackFrameInfo because it can be
  295. * quite large on some platforms.
  296. */
  297. gboolean
  298. mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,
  299. MonoJitInfo *prev_ji, MonoContext *ctx,
  300. MonoContext *new_ctx, char **trace, MonoLMF **lmf,
  301. mgreg_t **save_locations,
  302. StackFrameInfo *frame)
  303. {
  304. gboolean err;
  305. gpointer ip = MONO_CONTEXT_GET_IP (ctx);
  306. MonoJitInfo *ji;
  307. MonoDomain *target_domain;
  308. if (trace)
  309. *trace = NULL;
  310. /* Avoid costly table lookup during stack overflow */
  311. if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size)))
  312. ji = prev_ji;
  313. else
  314. ji = mini_jit_info_table_find (domain, ip, &target_domain);
  315. if (!target_domain)
  316. target_domain = domain;
  317. if (save_locations)
  318. memset (save_locations, 0, MONO_MAX_IREGS * sizeof (mgreg_t*));
  319. err = mono_arch_find_jit_info (target_domain, jit_tls, ji, ctx, new_ctx, lmf, save_locations, frame);
  320. if (!err)
  321. return FALSE;
  322. if (frame->type == FRAME_TYPE_MANAGED) {
  323. if (!frame->ji->method->wrapper_type || frame->ji->method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
  324. frame->managed = TRUE;
  325. }
  326. if (frame->type == FRAME_TYPE_MANAGED_TO_NATIVE) {
  327. /*
  328. * This type of frame is just a marker, the caller should unwind once more to get the
  329. * last managed frame.
  330. */
  331. frame->ji = NULL;
  332. frame->method = NULL;
  333. }
  334. frame->native_offset = -1;
  335. frame->domain = target_domain;
  336. ji = frame->ji;
  337. if (frame->type == FRAME_TYPE_MANAGED)
  338. frame->method = ji->method;
  339. if (ji && (frame->managed || ji->method->wrapper_type)) {
  340. const char *real_ip, *start;
  341. start = (const char *)ji->code_start;
  342. if (!frame->managed)
  343. /* ctx->ip points into native code */
  344. real_ip = (const char*)MONO_CONTEXT_GET_IP (new_ctx);
  345. else
  346. real_ip = (const char*)ip;
  347. if ((real_ip >= start) && (real_ip <= start + ji->code_size))
  348. frame->native_offset = real_ip - start;
  349. else
  350. frame->native_offset = -1;
  351. if (trace)
  352. *trace = mono_debug_print_stack_frame (ji->method, frame->native_offset, domain);
  353. } else {
  354. if (trace && frame->method) {
  355. char *fname = mono_method_full_name (frame->method, TRUE);
  356. *trace = g_strdup_printf ("in (unmanaged) %s", fname);
  357. g_free (fname);
  358. }
  359. }
  360. return TRUE;
  361. }
  362. static gpointer
  363. get_generic_info_from_stack_frame (MonoJitInfo *ji, MonoContext *ctx)
  364. {
  365. MonoGenericJitInfo *gi;
  366. gpointer info;
  367. if (!ji->has_generic_jit_info)
  368. return NULL;
  369. gi = mono_jit_info_get_generic_jit_info (ji);
  370. if (!gi->has_this)
  371. return NULL;
  372. info = NULL;
  373. /*
  374. * Search location list if available, it contains the precise location of the
  375. * argument for every pc offset, even if the method was interrupted while it was in
  376. * its prolog.
  377. */
  378. if (gi->nlocs) {
  379. int offset = (mgreg_t)MONO_CONTEXT_GET_IP (ctx) - (mgreg_t)ji->code_start;
  380. int i;
  381. for (i = 0; i < gi->nlocs; ++i) {
  382. MonoDwarfLocListEntry *entry = &gi->locations [i];
  383. if (offset >= entry->from && (offset < entry->to || entry->to == 0)) {
  384. if (entry->is_reg)
  385. info = (gpointer)mono_arch_context_get_int_reg (ctx, entry->reg);
  386. else
  387. info = *(gpointer*)(gpointer)((char*)mono_arch_context_get_int_reg (ctx, entry->reg) + entry->offset);
  388. break;
  389. }
  390. }
  391. g_assert (i < gi->nlocs);
  392. } else {
  393. if (gi->this_in_reg)
  394. info = (gpointer)mono_arch_context_get_int_reg (ctx, gi->this_reg);
  395. else
  396. info = *(gpointer*)(gpointer)((char*)mono_arch_context_get_int_reg (ctx, gi->this_reg) +
  397. gi->this_offset);
  398. }
  399. if (mono_method_get_context (ji->method)->method_inst) {
  400. return info;
  401. } else if ((ji->method->flags & METHOD_ATTRIBUTE_STATIC) || ji->method->klass->valuetype) {
  402. return info;
  403. } else {
  404. /* Avoid returning a managed object */
  405. MonoObject *this_obj = info;
  406. return this_obj->vtable->klass;
  407. }
  408. }
  409. static MonoGenericContext
  410. get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
  411. {
  412. MonoGenericContext context = { NULL, NULL };
  413. MonoClass *class, *method_container_class;
  414. g_assert (generic_info);
  415. g_assert (ji->method->is_inflated);
  416. if (mono_method_get_context (ji->method)->method_inst) {
  417. MonoMethodRuntimeGenericContext *mrgctx = generic_info;
  418. class = mrgctx->class_vtable->klass;
  419. context.method_inst = mrgctx->method_inst;
  420. g_assert (context.method_inst);
  421. } else if ((ji->method->flags & METHOD_ATTRIBUTE_STATIC) || ji->method->klass->valuetype) {
  422. MonoVTable *vtable = generic_info;
  423. class = vtable->klass;
  424. } else {
  425. class = generic_info;
  426. }
  427. //g_assert (!ji->method->klass->generic_container);
  428. if (ji->method->klass->generic_class)
  429. method_container_class = ji->method->klass->generic_class->container_class;
  430. else
  431. method_container_class = ji->method->klass;
  432. /* class might refer to a subclass of ji->method's class */
  433. while (!(class == ji->method->klass || (class->generic_class && class->generic_class->container_class == method_container_class))) {
  434. class = class->parent;
  435. g_assert (class);
  436. }
  437. if (class->generic_class || class->generic_container)
  438. context.class_inst = mini_class_get_context (class)->class_inst;
  439. if (class->generic_class)
  440. g_assert (mono_class_has_parent_and_ignore_generics (class->generic_class->container_class, method_container_class));
  441. else
  442. g_assert (mono_class_has_parent_and_ignore_generics (class, method_container_class));
  443. return context;
  444. }
  445. static MonoMethod*
  446. get_method_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
  447. {
  448. MonoGenericContext context;
  449. MonoMethod *method;
  450. if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
  451. return ji->method;
  452. context = get_generic_context_from_stack_frame (ji, generic_info);
  453. method = mono_method_get_declaring_generic_method (ji->method);
  454. method = mono_class_inflate_generic_method (method, &context);
  455. return method;
  456. }
  457. /**
  458. * mono_exception_walk_native_trace:
  459. * @ex: The exception object whose frames should be walked
  460. * @func: callback to call for each stack frame
  461. * @user_data: data passed to the callback
  462. *
  463. * This function walks the stacktrace of an exception. For
  464. * each frame the callback function is called with the relevant info.
  465. * The walk ends when no more stack frames are found or when the callback
  466. * returns a TRUE value.
  467. */
  468. gboolean
  469. mono_exception_walk_trace (MonoException *ex, MonoExceptionFrameWalk func, gpointer user_data)
  470. {
  471. MonoDomain *domain = mono_domain_get ();
  472. MonoArray *ta = ex->trace_ips;
  473. int len, i;
  474. if (ta == NULL)
  475. return FALSE;
  476. len = mono_array_length (ta) >> 1;
  477. for (i = 0; i < len; i++) {
  478. gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0);
  479. gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1);
  480. MonoJitInfo *ji = mono_jit_info_table_find (domain, ip);
  481. if (ji == NULL) {
  482. if (func (NULL, ip, 0, FALSE, user_data))
  483. return TRUE;
  484. } else {
  485. MonoMethod *method = get_method_from_stack_frame (ji, generic_info);
  486. if (func (method, ji->code_start, (char *) ip - (char *) ji->code_start, TRUE, user_data))
  487. return TRUE;
  488. }
  489. }
  490. return len > 0;
  491. }
  492. MonoString *
  493. ves_icall_System_Exception_get_trace (MonoException *ex)
  494. {
  495. MonoDomain *domain = mono_domain_get ();
  496. MonoString *res;
  497. MonoArray *ta = ex->trace_ips;
  498. int i, len;
  499. GString *trace_str;
  500. if (ta == NULL)
  501. /* Exception is not thrown yet */
  502. return NULL;
  503. len = mono_array_length (ta) >> 1;
  504. trace_str = g_string_new ("");
  505. for (i = 0; i < len; i++) {
  506. MonoJitInfo *ji;
  507. gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0);
  508. gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1);
  509. ji = mono_jit_info_table_find (domain, ip);
  510. if (ji == NULL) {
  511. /* Unmanaged frame */
  512. g_string_append_printf (trace_str, "in (unmanaged) %p\n", ip);
  513. } else {
  514. gchar *location;
  515. gint32 address;
  516. MonoMethod *method = get_method_from_stack_frame (ji, generic_info);
  517. address = (char *)ip - (char *)ji->code_start;
  518. location = mono_debug_print_stack_frame (
  519. method, address, ex->object.vtable->domain);
  520. g_string_append_printf (trace_str, "%s\n", location);
  521. g_free (location);
  522. }
  523. }
  524. res = mono_string_new (ex->object.vtable->domain, trace_str->str);
  525. g_string_free (trace_str, TRUE);
  526. return res;
  527. }
  528. MonoArray *
  529. ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info)
  530. {
  531. MonoDomain *domain = mono_domain_get ();
  532. MonoArray *res;
  533. MonoArray *ta = exc->trace_ips;
  534. MonoDebugSourceLocation *location;
  535. int i, len;
  536. if (ta == NULL) {
  537. /* Exception is not thrown yet */
  538. return mono_array_new (domain, mono_defaults.stack_frame_class, 0);
  539. }
  540. len = mono_array_length (ta) >> 1;
  541. res = mono_array_new (domain, mono_defaults.stack_frame_class, len > skip ? len - skip : 0);
  542. for (i = skip; i < len; i++) {
  543. MonoJitInfo *ji;
  544. MonoStackFrame *sf = (MonoStackFrame *)mono_object_new (domain, mono_defaults.stack_frame_class);
  545. gpointer ip = mono_array_get (ta, gpointer, i * 2 + 0);
  546. gpointer generic_info = mono_array_get (ta, gpointer, i * 2 + 1);
  547. MonoMethod *method;
  548. ji = mono_jit_info_table_find (domain, ip);
  549. if (ji == NULL) {
  550. /* Unmanaged frame */
  551. mono_array_setref (res, i, sf);
  552. continue;
  553. }
  554. g_assert (ji != NULL);
  555. method = get_method_from_stack_frame (ji, generic_info);
  556. if (ji->method->wrapper_type) {
  557. char *s;
  558. sf->method = NULL;
  559. s = mono_method_full_name (method, TRUE);
  560. MONO_OBJECT_SETREF (sf, internal_method_name, mono_string_new (domain, s));
  561. g_free (s);
  562. }
  563. else
  564. MONO_OBJECT_SETREF (sf, method, mono_method_get_object (domain, method, NULL));
  565. sf->native_offset = (char *)ip - (char *)ji->code_start;
  566. /*
  567. * mono_debug_lookup_source_location() returns both the file / line number information
  568. * and the IL offset. Note that computing the IL offset is already an expensive
  569. * operation, so we shouldn't call this method twice.
  570. */
  571. location = mono_debug_lookup_source_location (ji->method, sf->native_offset, domain);
  572. if (location)
  573. sf->il_offset = location->il_offset;
  574. else
  575. sf->il_offset = 0;
  576. if (need_file_info) {
  577. if (location && location->source_file) {
  578. MONO_OBJECT_SETREF (sf, filename, mono_string_new (domain, location->source_file));
  579. sf->line = location->row;
  580. sf->column = location->column;
  581. } else {
  582. sf->line = sf->column = 0;
  583. sf->filename = NULL;
  584. }
  585. }
  586. mono_debug_free_source_location (location);
  587. mono_array_setref (res, i, sf);
  588. }
  589. return res;
  590. }
  591. static void
  592. mono_runtime_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
  593. {
  594. if (!start_ctx) {
  595. MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  596. if (jit_tls && jit_tls->orig_ex_ctx_set)
  597. start_ctx = &jit_tls->orig_ex_ctx;
  598. }
  599. mono_walk_stack_with_ctx (func, start_ctx, unwind_options, user_data);
  600. }
  601. /**
  602. * mono_walk_stack_with_ctx:
  603. *
  604. * Unwind the current thread starting at @start_ctx.
  605. *
  606. * If @start_ctx is null, we capture the current context.
  607. */
  608. void
  609. mono_walk_stack_with_ctx (MonoJitStackWalk func, MonoContext *start_ctx, MonoUnwindOptions unwind_options, void *user_data)
  610. {
  611. MonoContext extra_ctx;
  612. MonoInternalThread *thread = mono_thread_internal_current ();
  613. MONO_ARCH_CONTEXT_DEF
  614. if (!thread || !thread->jit_data)
  615. return;
  616. if (!start_ctx) {
  617. mono_arch_flush_register_windows ();
  618. #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
  619. MONO_INIT_CONTEXT_FROM_CURRENT (&extra_ctx);
  620. #else
  621. MONO_INIT_CONTEXT_FROM_FUNC (&extra_ctx, mono_walk_stack_with_ctx);
  622. #endif
  623. start_ctx = &extra_ctx;
  624. }
  625. mono_walk_stack_full (func, start_ctx, mono_domain_get (), thread->jit_data, mono_get_lmf (), unwind_options, user_data);
  626. }
  627. /**
  628. * mono_walk_stack_with_state:
  629. *
  630. * Unwind a thread described by @state.
  631. *
  632. * State must be valid (state->valid == TRUE).
  633. *
  634. * If you are using this function to unwind another thread, make sure it is suspended.
  635. *
  636. * If @state is null, we capture the current context.
  637. */
  638. void
  639. mono_walk_stack_with_state (MonoJitStackWalk func, MonoThreadUnwindState *state, MonoUnwindOptions unwind_options, void *user_data)
  640. {
  641. MonoThreadUnwindState extra_state;
  642. if (!state) {
  643. if (!mono_thread_state_init_from_current (&extra_state))
  644. return;
  645. state = &extra_state;
  646. }
  647. g_assert (state->valid);
  648. mono_walk_stack_full (func,
  649. &state->ctx,
  650. state->unwind_data [MONO_UNWIND_DATA_DOMAIN],
  651. state->unwind_data [MONO_UNWIND_DATA_JIT_TLS],
  652. state->unwind_data [MONO_UNWIND_DATA_LMF],
  653. unwind_options, user_data);
  654. }
  655. void
  656. mono_walk_stack (MonoJitStackWalk func, MonoUnwindOptions options, void *user_data)
  657. {
  658. MonoThreadUnwindState state;
  659. if (!mono_thread_state_init_from_current (&state))
  660. return;
  661. mono_walk_stack_with_state (func, &state, options, user_data);
  662. }
  663. /**
  664. * mono_walk_stack_full:
  665. * @func: callback to call for each stack frame
  666. * @domain: starting appdomain, can be NULL to use the current domain
  667. * @unwind_options: what extra information the unwinder should gather
  668. * @start_ctx: starting state of the stack walk, can be NULL.
  669. * @thread: the thread whose stack to walk, can be NULL to use the current thread
  670. * @lmf: the LMF of @thread, can be NULL to use the LMF of the current thread
  671. * @user_data: data passed to the callback
  672. *
  673. * This function walks the stack of a thread, starting from the state
  674. * represented by start_ctx. For each frame the callback
  675. * function is called with the relevant info. The walk ends when no more
  676. * managed stack frames are found or when the callback returns a TRUE value.
  677. */
  678. static void
  679. mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain *domain, MonoJitTlsData *jit_tls, MonoLMF *lmf, MonoUnwindOptions unwind_options, gpointer user_data)
  680. {
  681. gint il_offset, i;
  682. MonoContext ctx, new_ctx;
  683. StackFrameInfo frame;
  684. gboolean res;
  685. mgreg_t *reg_locations [MONO_MAX_IREGS];
  686. mgreg_t *new_reg_locations [MONO_MAX_IREGS];
  687. gboolean get_reg_locations = unwind_options & MONO_UNWIND_REG_LOCATIONS;
  688. g_assert (start_ctx);
  689. g_assert (domain);
  690. g_assert (jit_tls);
  691. /*The LMF will be null if the target have no managed frames.*/
  692. /* g_assert (lmf); */
  693. memcpy (&ctx, start_ctx, sizeof (MonoContext));
  694. memset (reg_locations, 0, sizeof (reg_locations));
  695. while (MONO_CONTEXT_GET_SP (&ctx) < jit_tls->end_of_stack) {
  696. frame.lmf = lmf;
  697. res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, get_reg_locations ? new_reg_locations : NULL, &frame);
  698. if (!res)
  699. return;
  700. if ((unwind_options & MONO_UNWIND_LOOKUP_IL_OFFSET) && frame.ji) {
  701. MonoDebugSourceLocation *source;
  702. source = mono_debug_lookup_source_location (frame.ji->method, frame.native_offset, domain);
  703. il_offset = source ? source->il_offset : -1;
  704. mono_debug_free_source_location (source);
  705. } else
  706. il_offset = -1;
  707. frame.il_offset = il_offset;
  708. if ((unwind_options & MONO_UNWIND_LOOKUP_ACTUAL_METHOD) && frame.ji) {
  709. frame.actual_method = get_method_from_stack_frame (frame.ji, get_generic_info_from_stack_frame (frame.ji, &ctx));
  710. } else {
  711. frame.actual_method = frame.method;
  712. }
  713. if (get_reg_locations)
  714. frame.reg_locations = reg_locations;
  715. if (func (&frame, &ctx, user_data))
  716. return;
  717. if (get_reg_locations) {
  718. for (i = 0; i < MONO_MAX_IREGS; ++i)
  719. if (new_reg_locations [i])
  720. reg_locations [i] = new_reg_locations [i];
  721. }
  722. ctx = new_ctx;
  723. }
  724. }
  725. MonoBoolean
  726. ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
  727. MonoReflectionMethod **method,
  728. gint32 *iloffset, gint32 *native_offset,
  729. MonoString **file, gint32 *line, gint32 *column)
  730. {
  731. MonoDomain *domain = mono_domain_get ();
  732. MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  733. MonoLMF *lmf = mono_get_lmf ();
  734. MonoJitInfo *ji = NULL;
  735. MonoContext ctx, new_ctx;
  736. MonoDebugSourceLocation *location;
  737. MonoMethod *actual_method;
  738. StackFrameInfo frame;
  739. gboolean res;
  740. MONO_ARCH_CONTEXT_DEF;
  741. mono_arch_flush_register_windows ();
  742. #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
  743. MONO_INIT_CONTEXT_FROM_CURRENT (&ctx);
  744. #else
  745. MONO_INIT_CONTEXT_FROM_FUNC (&ctx, ves_icall_get_frame_info);
  746. #endif
  747. new_ctx = ctx;
  748. do {
  749. ctx = new_ctx;
  750. res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, &frame);
  751. if (!res)
  752. return FALSE;
  753. if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE || frame.type == FRAME_TYPE_DEBUGGER_INVOKE)
  754. continue;
  755. ji = frame.ji;
  756. *native_offset = frame.native_offset;
  757. /* The skip count passed by the caller depends on us not filtering out MANAGED_TO_NATIVE */
  758. if (ji->method->wrapper_type != MONO_WRAPPER_NONE && ji->method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && ji->method->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE)
  759. continue;
  760. skip--;
  761. } while (skip >= 0);
  762. actual_method = get_method_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, &ctx));
  763. mono_gc_wbarrier_generic_store (method, (MonoObject*) mono_method_get_object (domain, actual_method, NULL));
  764. location = mono_debug_lookup_source_location (ji->method, *native_offset, domain);
  765. if (location)
  766. *iloffset = location->il_offset;
  767. else
  768. *iloffset = 0;
  769. if (need_file_info) {
  770. if (location) {
  771. mono_gc_wbarrier_generic_store (file, (MonoObject*) mono_string_new (domain, location->source_file));
  772. *line = location->row;
  773. *column = location->column;
  774. } else {
  775. *file = NULL;
  776. *line = *column = 0;
  777. }
  778. }
  779. mono_debug_free_source_location (location);
  780. return TRUE;
  781. }
  782. typedef struct {
  783. guint32 skips;
  784. MonoSecurityFrame *frame;
  785. } MonoFrameSecurityInfo;
  786. static gboolean
  787. callback_get_first_frame_security_info (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
  788. {
  789. MonoFrameSecurityInfo *si = (MonoFrameSecurityInfo*) data;
  790. MonoJitInfo *ji = frame->ji;
  791. if (!ji)
  792. return FALSE;
  793. /* FIXME: skip all wrappers ?? probably not - case by case testing is required */
  794. if (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
  795. ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
  796. ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
  797. ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
  798. ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) {
  799. return FALSE;
  800. }
  801. if (si->skips > 0) {
  802. si->skips--;
  803. return FALSE;
  804. }
  805. si->frame = mono_declsec_create_frame (frame->domain, ji);
  806. /* Stop - we only want the first frame (e.g. LinkDemand and InheritanceDemand) */
  807. return TRUE;
  808. }
  809. /**
  810. * ves_icall_System_Security_SecurityFrame_GetSecurityFrame:
  811. * @skip: the number of stack frames to skip
  812. *
  813. * This function returns a the security informations of a single stack frame
  814. * (after the skipped ones). This is required for [NonCas]LinkDemand[Choice]
  815. * and [NonCas]InheritanceDemand[Choice] as only the caller security is
  816. * evaluated.
  817. */
  818. MonoSecurityFrame*
  819. ves_icall_System_Security_SecurityFrame_GetSecurityFrame (gint32 skip)
  820. {
  821. MonoFrameSecurityInfo si;
  822. si.skips = skip;
  823. si.frame = NULL;
  824. mono_walk_stack (callback_get_first_frame_security_info, MONO_UNWIND_DEFAULT, &si);
  825. return (si.skips == 0) ? si.frame : NULL;
  826. }
  827. typedef struct {
  828. guint32 skips;
  829. MonoArray *stack;
  830. guint32 count;
  831. guint32 maximum;
  832. } MonoSecurityStack;
  833. static void
  834. grow_array (MonoSecurityStack *stack)
  835. {
  836. MonoDomain *domain = mono_domain_get ();
  837. guint32 newsize = (stack->maximum << 1);
  838. MonoArray *newstack = mono_array_new (domain, mono_defaults.runtimesecurityframe_class, newsize);
  839. int i;
  840. for (i=0; i < stack->maximum; i++) {
  841. gpointer frame = mono_array_get (stack->stack, gpointer, i);
  842. mono_array_setref (newstack, i, frame);
  843. }
  844. stack->maximum = newsize;
  845. stack->stack = newstack;
  846. }
  847. static gboolean
  848. callback_get_stack_frames_security_info (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
  849. {
  850. MonoSecurityStack *ss = (MonoSecurityStack*) data;
  851. MonoJitInfo *ji = frame->ji;
  852. if (!ji)
  853. return FALSE;
  854. /* FIXME: skip all wrappers ?? probably not - case by case testing is required */
  855. if (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
  856. ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
  857. ji->method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
  858. ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
  859. ji->method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) {
  860. return FALSE;
  861. }
  862. if (ss->skips > 0) {
  863. ss->skips--;
  864. return FALSE;
  865. }
  866. if (ss->count == ss->maximum)
  867. grow_array (ss);
  868. mono_array_setref (ss->stack, ss->count++, mono_declsec_create_frame (frame->domain, ji));
  869. /* continue down the stack */
  870. return FALSE;
  871. }
  872. static MonoArray *
  873. glist_to_array (GList *list, MonoClass *eclass)
  874. {
  875. MonoDomain *domain = mono_domain_get ();
  876. MonoArray *res;
  877. int len, i;
  878. if (!list)
  879. return NULL;
  880. len = g_list_length (list);
  881. res = mono_array_new (domain, eclass, len);
  882. for (i = 0; list; list = list->next, i++)
  883. mono_array_set (res, gpointer, i, list->data);
  884. return res;
  885. }
  886. /**
  887. * ves_icall_System_Security_SecurityFrame_GetSecurityStack:
  888. * @skip: the number of stack frames to skip
  889. *
  890. * This function returns an managed array of containing the security
  891. * informations for each frame (after the skipped ones). This is used for
  892. * [NonCas]Demand[Choice] where the complete evaluation of the stack is
  893. * required.
  894. */
  895. MonoArray*
  896. ves_icall_System_Security_SecurityFrame_GetSecurityStack (gint32 skip)
  897. {
  898. MonoSecurityStack ss;
  899. #if defined(__ia64__) || defined(__s390__) || defined(__s390x__)
  900. skip--;
  901. #endif
  902. ss.skips = skip;
  903. ss.count = 0;
  904. ss.maximum = MONO_CAS_INITIAL_STACK_SIZE;
  905. ss.stack = mono_array_new (mono_domain_get (), mono_defaults.runtimesecurityframe_class, ss.maximum);
  906. mono_walk_stack (callback_get_stack_frames_security_info, MONO_UNWIND_DEFAULT, &ss);
  907. /* g_warning ("STACK RESULT: %d out of %d", ss.count, ss.maximum); */
  908. return ss.stack;
  909. }
  910. static MonoClass*
  911. get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx)
  912. {
  913. MonoClass *catch_class = ei->data.catch_class;
  914. MonoType *inflated_type;
  915. MonoGenericContext context;
  916. /*MonoJitExceptionInfo::data is an union used by filter and finally clauses too.*/
  917. if (!catch_class || ei->flags != MONO_EXCEPTION_CLAUSE_NONE)
  918. return NULL;
  919. if (!ji->has_generic_jit_info || !mono_jit_info_get_generic_jit_info (ji)->has_this)
  920. return catch_class;
  921. context = get_generic_context_from_stack_frame (ji, get_generic_info_from_stack_frame (ji, ctx));
  922. /* FIXME: we shouldn't inflate but instead put the
  923. type in the rgctx and fetch it from there. It
  924. might be a good idea to do this lazily, i.e. only
  925. when the exception is actually thrown, so as not to
  926. waste space for exception clauses which might never
  927. be encountered. */
  928. inflated_type = mono_class_inflate_generic_type (&catch_class->byval_arg, &context);
  929. catch_class = mono_class_from_mono_type (inflated_type);
  930. mono_metadata_free_type (inflated_type);
  931. return catch_class;
  932. }
  933. /*
  934. * mini_jit_info_table_find:
  935. *
  936. * Same as mono_jit_info_table_find, but search all the domains of the current thread
  937. * if ADDR is not found in DOMAIN. The domain where the method was found is stored into
  938. * OUT_DOMAIN if it is not NULL.
  939. */
  940. MonoJitInfo*
  941. mini_jit_info_table_find (MonoDomain *domain, char *addr, MonoDomain **out_domain)
  942. {
  943. MonoJitInfo *ji;
  944. MonoInternalThread *t = mono_thread_internal_current ();
  945. gpointer *refs;
  946. if (out_domain)
  947. *out_domain = NULL;
  948. ji = mono_jit_info_table_find (domain, addr);
  949. if (ji) {
  950. if (out_domain)
  951. *out_domain = domain;
  952. return ji;
  953. }
  954. /* maybe it is shared code, so we also search in the root domain */
  955. if (domain != mono_get_root_domain ()) {
  956. ji = mono_jit_info_table_find (mono_get_root_domain (), addr);
  957. if (ji) {
  958. if (out_domain)
  959. *out_domain = mono_get_root_domain ();
  960. return ji;
  961. }
  962. }
  963. refs = (t->appdomain_refs) ? *(gpointer *) t->appdomain_refs : NULL;
  964. for (; refs && *refs; refs++) {
  965. if (*refs != domain && *refs != mono_get_root_domain ()) {
  966. ji = mono_jit_info_table_find ((MonoDomain*) *refs, addr);
  967. if (ji) {
  968. if (out_domain)
  969. *out_domain = (MonoDomain*) *refs;
  970. return ji;
  971. }
  972. }
  973. }
  974. return NULL;
  975. }
  976. /*
  977. * wrap_non_exception_throws:
  978. *
  979. * Determine whenever M's assembly has a RuntimeCompatibilityAttribute with the
  980. * WrapNonExceptionThrows flag set.
  981. */
  982. static gboolean
  983. wrap_non_exception_throws (MonoMethod *m)
  984. {
  985. MonoAssembly *ass = m->klass->image->assembly;
  986. MonoCustomAttrInfo* attrs;
  987. static MonoClass *klass;
  988. int i;
  989. gboolean val = FALSE;
  990. g_assert (ass);
  991. if (ass->wrap_non_exception_throws_inited)
  992. return ass->wrap_non_exception_throws;
  993. klass = mono_class_from_name_cached (mono_defaults.corlib, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
  994. attrs = mono_custom_attrs_from_assembly (ass);
  995. if (attrs) {
  996. for (i = 0; i < attrs->num_attrs; ++i) {
  997. MonoCustomAttrEntry *attr = &attrs->attrs [i];
  998. const gchar *p;
  999. int len, num_named, named_type, data_type, name_len;
  1000. char *name;
  1001. if (!attr->ctor || attr->ctor->klass != klass)
  1002. continue;
  1003. /* Decode the RuntimeCompatibilityAttribute. See reflection.c */
  1004. len = attr->data_size;
  1005. p = (const char*)attr->data;
  1006. g_assert (read16 (p) == 0x0001);
  1007. p += 2;
  1008. num_named = read16 (p);
  1009. if (num_named != 1)
  1010. continue;
  1011. p += 2;
  1012. named_type = *p;
  1013. p ++;
  1014. data_type = *p;
  1015. p ++;
  1016. /* Property */
  1017. if (named_type != 0x54)
  1018. continue;
  1019. name_len = mono_metadata_decode_blob_size (p, &p);
  1020. name = g_malloc (name_len + 1);
  1021. memcpy (name, p, name_len);
  1022. name [name_len] = 0;
  1023. p += name_len;
  1024. g_assert (!strcmp (name, "WrapNonExceptionThrows"));
  1025. g_free (name);
  1026. /* The value is a BOOLEAN */
  1027. val = *p;
  1028. }
  1029. mono_custom_attrs_free (attrs);
  1030. }
  1031. ass->wrap_non_exception_throws = val;
  1032. mono_memory_barrier ();
  1033. ass->wrap_non_exception_throws_inited = TRUE;
  1034. return val;
  1035. }
  1036. #ifndef MONO_ARCH_STACK_GROWS_UP
  1037. #define DOES_STACK_GROWS_UP 1
  1038. #else
  1039. #define DOES_STACK_GROWS_UP 0
  1040. #endif
  1041. #define MAX_UNMANAGED_BACKTRACE 128
  1042. static MonoArray*
  1043. build_native_trace (void)
  1044. {
  1045. /* This puppy only makes sense on mobile, IOW, ARM. */
  1046. #if defined (HAVE_BACKTRACE_SYMBOLS) && defined (TARGET_ARM)
  1047. MonoArray *res;
  1048. void *native_trace [MAX_UNMANAGED_BACKTRACE];
  1049. int size = backtrace (native_trace, MAX_UNMANAGED_BACKTRACE);
  1050. int i;
  1051. if (!size)
  1052. return NULL;
  1053. res = mono_array_new (mono_domain_get (), mono_defaults.int_class, size);
  1054. for (i = 0; i < size; i++)
  1055. mono_array_set (res, gpointer, i, native_trace [i]);
  1056. return res;
  1057. #else
  1058. return NULL;
  1059. #endif
  1060. }
  1061. #define setup_managed_stacktrace_information() do { \
  1062. if (mono_ex && !initial_trace_ips) { \
  1063. trace_ips = g_list_reverse (trace_ips); \
  1064. MONO_OBJECT_SETREF (mono_ex, trace_ips, glist_to_array (trace_ips, mono_defaults.int_class)); \
  1065. MONO_OBJECT_SETREF (mono_ex, native_trace_ips, build_native_trace ()); \
  1066. if (has_dynamic_methods) \
  1067. /* These methods could go away anytime, so compute the stack trace now */ \
  1068. MONO_OBJECT_SETREF (mono_ex, stack_trace, ves_icall_System_Exception_get_trace (mono_ex)); \
  1069. } \
  1070. g_list_free (trace_ips); \
  1071. trace_ips = NULL; \
  1072. } while (0)
  1073. /*
  1074. * mono_handle_exception_internal_first_pass:
  1075. *
  1076. * The first pass of exception handling. Unwind the stack until a catch clause which can catch
  1077. * OBJ is found. Run the index of the filter clause which caught the exception into
  1078. * OUT_FILTER_IDX. Return TRUE if the exception is caught, FALSE otherwise.
  1079. */
  1080. static gboolean
  1081. mono_handle_exception_internal_first_pass (MonoContext *ctx, gpointer obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoObject *non_exception)
  1082. {
  1083. MonoDomain *domain = mono_domain_get ();
  1084. MonoJitInfo *ji;
  1085. static int (*call_filter) (MonoContext *, gpointer) = NULL;
  1086. MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  1087. MonoLMF *lmf = mono_get_lmf ();
  1088. MonoArray *initial_trace_ips = NULL;
  1089. GList *trace_ips = NULL;
  1090. MonoException *mono_ex;
  1091. gboolean stack_overflow = FALSE;
  1092. MonoContext initial_ctx;
  1093. int frame_count = 0;
  1094. gboolean has_dynamic_methods = FALSE;
  1095. gint32 filter_idx;
  1096. int i;
  1097. MonoObject *ex_obj;
  1098. g_assert (ctx != NULL);
  1099. if (obj == domain->stack_overflow_ex)
  1100. stack_overflow = TRUE;
  1101. mono_ex = (MonoException*)obj;
  1102. initial_trace_ips = mono_ex->trace_ips;
  1103. if (mono_object_isinst (obj, mono_defaults.exception_class)) {
  1104. mono_ex = (MonoException*)obj;
  1105. initial_trace_ips = mono_ex->trace_ips;
  1106. } else {
  1107. mono_ex = NULL;
  1108. }
  1109. if (!call_filter)
  1110. call_filter = mono_get_call_filter ();
  1111. g_assert (jit_tls->end_of_stack);
  1112. g_assert (jit_tls->abort_func);
  1113. if (out_filter_idx)
  1114. *out_filter_idx = -1;
  1115. if (out_ji)
  1116. *out_ji = NULL;
  1117. filter_idx = 0;
  1118. initial_ctx = *ctx;
  1119. while (1) {
  1120. MonoContext new_ctx;
  1121. guint32 free_stack;
  1122. int clause_index_start = 0;
  1123. gboolean unwind_res = TRUE;
  1124. StackFrameInfo frame;
  1125. unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
  1126. if (unwind_res) {
  1127. if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
  1128. *ctx = new_ctx;
  1129. continue;
  1130. }
  1131. g_assert (frame.type == FRAME_TYPE_MANAGED);
  1132. ji = frame.ji;
  1133. }
  1134. if (!unwind_res) {
  1135. setup_managed_stacktrace_information ();
  1136. return FALSE;
  1137. }
  1138. frame_count ++;
  1139. //printf ("M: %s %d.\n", mono_method_full_name (ji->method, TRUE), frame_count);
  1140. if (mini_get_debug_options ()->reverse_pinvoke_exceptions && ji->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
  1141. g_error ("A native frame was found while unwinding the stack after an exception.\n"
  1142. "The native frame called the managed method:\n%s\n",
  1143. mono_method_full_name (ji->method, TRUE));
  1144. }
  1145. if (ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
  1146. /*
  1147. * Avoid overwriting the stack trace if the exception is
  1148. * rethrown. Also avoid giant stack traces during a stack
  1149. * overflow.
  1150. */
  1151. if (!initial_trace_ips && (frame_count < 1000)) {
  1152. trace_ips = g_list_prepend (trace_ips, MONO_CONTEXT_GET_IP (ctx));
  1153. trace_ips = g_list_prepend (trace_ips,
  1154. get_generic_info_from_stack_frame (ji, ctx));
  1155. }
  1156. }
  1157. if (ji->method->dynamic)
  1158. has_dynamic_methods = TRUE;
  1159. if (stack_overflow) {
  1160. if (DOES_STACK_GROWS_UP)
  1161. free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
  1162. else
  1163. free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
  1164. } else {
  1165. free_stack = 0xffffff;
  1166. }
  1167. for (i = clause_index_start; i < ji->num_clauses; i++) {
  1168. MonoJitExceptionInfo *ei = &ji->clauses [i];
  1169. gboolean filtered = FALSE;
  1170. /*
  1171. * During stack overflow, wait till the unwinding frees some stack
  1172. * space before running handlers/finalizers.
  1173. */
  1174. if (free_stack <= (64 * 1024))
  1175. continue;
  1176. if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
  1177. /* catch block */
  1178. MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
  1179. /*
  1180. * Have to unwrap RuntimeWrappedExceptions if the
  1181. * method's assembly doesn't have a RuntimeCompatibilityAttribute.
  1182. */
  1183. if (non_exception && !wrap_non_exception_throws (ji->method))
  1184. ex_obj = non_exception;
  1185. else
  1186. ex_obj = obj;
  1187. if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
  1188. gboolean is_user_frame = ji->method->wrapper_type == MONO_WRAPPER_NONE || ji->method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD;
  1189. #ifndef DISABLE_PERFCOUNTERS
  1190. mono_perfcounters->exceptions_filters++;
  1191. #endif
  1192. mono_debugger_call_exception_handler (ei->data.filter, MONO_CONTEXT_GET_SP (ctx), ex_obj);
  1193. /*
  1194. Here's the thing, if this is a filter clause done by a wrapper like runtime invoke, we don't want to
  1195. trim the stackframe since if it returns FALSE we lose information.
  1196. FIXME Not 100% sure if it's a good idea even with user clauses.
  1197. */
  1198. if (is_user_frame)
  1199. setup_managed_stacktrace_information ();
  1200. if (ji->from_llvm) {
  1201. #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
  1202. MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
  1203. #else
  1204. g_assert_not_reached ();
  1205. #endif
  1206. } else {
  1207. /* store the exception object in bp + ei->exvar_offset */
  1208. *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
  1209. }
  1210. mono_debugger_agent_begin_exception_filter (mono_ex, ctx, &initial_ctx);
  1211. filtered = call_filter (ctx, ei->data.filter);
  1212. mono_debugger_agent_end_exception_filter (mono_ex, ctx, &initial_ctx);
  1213. if (filtered && out_filter_idx)
  1214. *out_filter_idx = filter_idx;
  1215. if (out_ji)
  1216. *out_ji = ji;
  1217. filter_idx ++;
  1218. if (filtered) {
  1219. if (!is_user_frame)
  1220. setup_managed_stacktrace_information ();
  1221. /* mono_debugger_agent_handle_exception () needs this */
  1222. MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
  1223. return TRUE;
  1224. }
  1225. }
  1226. if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (ex_obj, catch_class)) {
  1227. setup_managed_stacktrace_information ();
  1228. if (out_ji)
  1229. *out_ji = ji;
  1230. /* mono_debugger_agent_handle_exception () needs this */
  1231. MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
  1232. return TRUE;
  1233. }
  1234. }
  1235. }
  1236. *ctx = new_ctx;
  1237. }
  1238. g_assert_not_reached ();
  1239. }
  1240. /**
  1241. * mono_handle_exception_internal:
  1242. * @ctx: saved processor state
  1243. * @obj: the exception object
  1244. * @resume: whenever to resume unwinding based on the state in MonoJitTlsData.
  1245. */
  1246. static gboolean
  1247. mono_handle_exception_internal (MonoContext *ctx, gpointer obj, gboolean resume, MonoJitInfo **out_ji)
  1248. {
  1249. MonoDomain *domain = mono_domain_get ();
  1250. MonoJitInfo *ji;
  1251. static int (*call_filter) (MonoContext *, gpointer) = NULL;
  1252. static void (*restore_context) (void *);
  1253. MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  1254. MonoLMF *lmf = mono_get_lmf ();
  1255. MonoException *mono_ex;
  1256. gboolean stack_overflow = FALSE;
  1257. MonoContext initial_ctx;
  1258. int frame_count = 0;
  1259. gint32 filter_idx, first_filter_idx;
  1260. int i;
  1261. MonoObject *ex_obj;
  1262. MonoObject *non_exception = NULL;
  1263. g_assert (ctx != NULL);
  1264. if (!obj) {
  1265. MonoException *ex = mono_get_exception_null_reference ();
  1266. MONO_OBJECT_SETREF (ex, message, mono_string_new (domain, "Object reference not set to an instance of an object"));
  1267. obj = (MonoObject *)ex;
  1268. }
  1269. /*
  1270. * Allocate a new exception object instead of the preconstructed ones.
  1271. */
  1272. if (obj == domain->stack_overflow_ex) {
  1273. /*
  1274. * It is not a good idea to try and put even more pressure on the little stack available.
  1275. * obj = mono_get_exception_stack_overflow ();
  1276. */
  1277. stack_overflow = TRUE;
  1278. }
  1279. else if (obj == domain->null_reference_ex) {
  1280. obj = mono_get_exception_null_reference ();
  1281. }
  1282. if (!mono_object_isinst (obj, mono_defaults.exception_class)) {
  1283. non_exception = obj;
  1284. obj = mono_get_exception_runtime_wrapped (obj);
  1285. }
  1286. mono_ex = (MonoException*)obj;
  1287. if (mono_object_isinst (obj, mono_defaults.exception_class)) {
  1288. mono_ex = (MonoException*)obj;
  1289. } else {
  1290. mono_ex = NULL;
  1291. }
  1292. if (mono_ex && jit_tls->class_cast_from) {
  1293. if (!strcmp (mono_ex->object.vtable->klass->name, "InvalidCastException")) {
  1294. char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
  1295. char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
  1296. char *msg = g_strdup_printf ("Unable to cast object of type '%s' to type '%s'.", from_name, to_name);
  1297. mono_ex->message = mono_string_new (domain, msg);
  1298. g_free (from_name);
  1299. g_free (to_name);
  1300. g_free (msg);
  1301. }
  1302. if (!strcmp (mono_ex->object.vtable->klass->name, "ArrayTypeMismatchException")) {
  1303. char *from_name = mono_type_get_full_name (jit_tls->class_cast_from);
  1304. char *to_name = mono_type_get_full_name (jit_tls->class_cast_to);
  1305. char *msg = g_strdup_printf ("Source array of type '%s' cannot be cast to destination array type '%s'.", from_name, to_name);
  1306. mono_ex->message = mono_string_new (domain, msg);
  1307. g_free (from_name);
  1308. g_free (to_name);
  1309. g_free (msg);
  1310. }
  1311. }
  1312. if (!call_filter)
  1313. call_filter = mono_get_call_filter ();
  1314. if (!restore_context)
  1315. restore_context = mono_get_restore_context ();
  1316. g_assert (jit_tls->end_of_stack);
  1317. g_assert (jit_tls->abort_func);
  1318. /*
  1319. * We set orig_ex_ctx_set to TRUE/FALSE around profiler calls to make sure it doesn't
  1320. * end up being TRUE on any code path.
  1321. */
  1322. memcpy (&jit_tls->orig_ex_ctx, ctx, sizeof (MonoContext));
  1323. if (!resume) {
  1324. gboolean res;
  1325. MonoContext ctx_cp = *ctx;
  1326. if (mono_trace_is_enabled ()) {
  1327. MonoMethod *system_exception_get_message = mono_class_get_method_from_name (mono_defaults.exception_class, "get_Message", 0);
  1328. MonoMethod *get_message = system_exception_get_message == NULL ? NULL : mono_object_get_virtual_method (obj, system_exception_get_message);
  1329. MonoObject *message;
  1330. const char *type_name = mono_class_get_name (mono_object_class (mono_ex));
  1331. char *msg = NULL;
  1332. MonoObject *exc = NULL;
  1333. if (get_message == NULL) {
  1334. message = NULL;
  1335. } else if (!strcmp (type_name, "OutOfMemoryException") || !strcmp (type_name, "StackOverflowException")) {
  1336. message = NULL;
  1337. msg = g_strdup_printf ("(No exception message for: %s)\n", type_name);
  1338. } else {
  1339. message = mono_runtime_invoke (get_message, obj, NULL, &exc);
  1340. }
  1341. if (msg == NULL) {
  1342. msg = message ? mono_string_to_utf8 ((MonoString *) message) : g_strdup ("(System.Exception.Message property not available)");
  1343. }
  1344. g_print ("[%p:] EXCEPTION handling: %s.%s: %s\n", (void*)GetCurrentThreadId (), mono_object_class (obj)->name_space, mono_object_class (obj)->name, msg);
  1345. g_free (msg);
  1346. if (mono_ex && mono_trace_eval_exception (mono_object_class (mono_ex)))
  1347. mono_print_thread_dump_from_ctx (ctx);
  1348. }
  1349. jit_tls->orig_ex_ctx_set = TRUE;
  1350. mono_profiler_exception_thrown (obj);
  1351. jit_tls->orig_ex_ctx_set = FALSE;
  1352. res = mono_handle_exception_internal_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, non_exception);
  1353. if (!res) {
  1354. if (mini_get_debug_options ()->break_on_exc)
  1355. G_BREAKPOINT ();
  1356. mono_debugger_agent_handle_exception (obj, ctx, NULL);
  1357. if (mini_get_debug_options ()->suspend_on_unhandled) {
  1358. mono_runtime_printf_err ("Unhandled exception, suspending...");
  1359. while (1)
  1360. ;
  1361. }
  1362. // FIXME: This runs managed code so it might cause another stack overflow when
  1363. // we are handling a stack overflow
  1364. mono_unhandled_exception (obj);
  1365. } else {
  1366. //
  1367. // Treat exceptions that are "handled" by mono_runtime_invoke() as unhandled.
  1368. // See bug #669836.
  1369. //
  1370. if (ji && ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE)
  1371. mono_debugger_agent_handle_exception (obj, ctx, NULL);
  1372. else
  1373. mono_debugger_agent_handle_exception (obj, ctx, &ctx_cp);
  1374. }
  1375. }
  1376. if (out_ji)
  1377. *out_ji = NULL;
  1378. filter_idx = 0;
  1379. initial_ctx = *ctx;
  1380. while (1) {
  1381. MonoContext new_ctx;
  1382. guint32 free_stack;
  1383. int clause_index_start = 0;
  1384. gboolean unwind_res = TRUE;
  1385. if (resume) {
  1386. resume = FALSE;
  1387. ji = jit_tls->resume_state.ji;
  1388. new_ctx = jit_tls->resume_state.new_ctx;
  1389. clause_index_start = jit_tls->resume_state.clause_index;
  1390. lmf = jit_tls->resume_state.lmf;
  1391. first_filter_idx = jit_tls->resume_state.first_filter_idx;
  1392. filter_idx = jit_tls->resume_state.filter_idx;
  1393. } else {
  1394. StackFrameInfo frame;
  1395. unwind_res = mono_find_jit_info_ext (domain, jit_tls, NULL, ctx, &new_ctx, NULL, &lmf, NULL, &frame);
  1396. if (unwind_res) {
  1397. if (frame.type == FRAME_TYPE_DEBUGGER_INVOKE || frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
  1398. *ctx = new_ctx;
  1399. continue;
  1400. }
  1401. g_assert (frame.type == FRAME_TYPE_MANAGED);
  1402. ji = frame.ji;
  1403. }
  1404. }
  1405. if (!unwind_res) {
  1406. *(mono_get_lmf_addr ()) = lmf;
  1407. jit_tls->abort_func (obj);
  1408. g_assert_not_reached ();
  1409. }
  1410. frame_count ++;
  1411. //printf ("M: %s %d.\n", mono_method_full_name (ji->method, TRUE), frame_count);
  1412. if (stack_overflow) {
  1413. if (DOES_STACK_GROWS_UP)
  1414. free_stack = (guint8*)(MONO_CONTEXT_GET_SP (ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx));
  1415. else
  1416. free_stack = (guint8*)(MONO_CONTEXT_GET_SP (&initial_ctx)) - (guint8*)(MONO_CONTEXT_GET_SP (ctx));
  1417. } else {
  1418. free_stack = 0xffffff;
  1419. }
  1420. for (i = clause_index_start; i < ji->num_clauses; i++) {
  1421. MonoJitExceptionInfo *ei = &ji->clauses [i];
  1422. gboolean filtered = FALSE;
  1423. /*
  1424. * During stack overflow, wait till the unwinding frees some stack
  1425. * space before running handlers/finalizers.
  1426. */
  1427. if (free_stack <= (64 * 1024))
  1428. continue;
  1429. if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx))) {
  1430. /* catch block */
  1431. MonoClass *catch_class = get_exception_catch_class (ei, ji, ctx);
  1432. /*
  1433. * Have to unwrap RuntimeWrappedExceptions if the
  1434. * method's assembly doesn't have a RuntimeCompatibilityAttribute.
  1435. */
  1436. if (non_exception && !wrap_non_exception_throws (ji->method))
  1437. ex_obj = non_exception;
  1438. else
  1439. ex_obj = obj;
  1440. if (((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER))) {
  1441. if (ji->from_llvm) {
  1442. #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
  1443. MONO_CONTEXT_SET_LLVM_EXC_REG (ctx, ex_obj);
  1444. #else
  1445. g_assert_not_reached ();
  1446. #endif
  1447. } else {
  1448. /* store the exception object in bp + ei->exvar_offset */
  1449. *((gpointer *)(gpointer)((char *)MONO_CONTEXT_GET_BP (ctx) + ei->exvar_offset)) = ex_obj;
  1450. }
  1451. }
  1452. if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
  1453. /*
  1454. * Filter clauses should only be run in the
  1455. * first pass of exception handling.
  1456. */
  1457. filtered = (filter_idx == first_filter_idx);
  1458. filter_idx ++;
  1459. }
  1460. if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE &&
  1461. mono_object_isinst (ex_obj, catch_class)) || filtered) {
  1462. /*
  1463. * This guards against the situation that we abort a thread that is executing a finally clause
  1464. * that was called by the EH machinery. It won't have a guard trampoline installed, so we must
  1465. * check for this situation here and resume interruption if we are below the guarded block.
  1466. */
  1467. if (G_UNLIKELY (jit_tls->handler_block_return_address)) {
  1468. gboolean is_outside = FALSE;
  1469. gpointer prot_bp = MONO_CONTEXT_GET_BP (&jit_tls->handler_block_context);
  1470. gpointer catch_bp = MONO_CONTEXT_GET_BP (ctx);
  1471. //FIXME make this stack direction aware
  1472. if (catch_bp > prot_bp) {
  1473. is_outside = TRUE;
  1474. } else if (catch_bp == prot_bp) {
  1475. /* Can be either try { try { } catch {} } finally {} or try { try { } finally {} } catch {}
  1476. * So we check if the catch handler_start is protected by the guarded handler protected region
  1477. *
  1478. * Assumptions:
  1479. * If there is an outstanding guarded_block return address, it means the current thread must be aborted.
  1480. * This is the only way to reach out the guarded block as other cases are handled by the trampoline.
  1481. * There aren't any further finally/fault handler blocks down the stack over this exception.
  1482. * This must be ensured by the code that installs the guard trampoline.
  1483. */
  1484. g_assert (ji == mini_jit_info_table_find (domain, MONO_CONTEXT_GET_IP (&jit_tls->handler_block_context), NULL));
  1485. if (!is_address_protected (ji, jit_tls->handler_block, ei->handler_start)) {
  1486. is_outside = TRUE;
  1487. }
  1488. }
  1489. if (is_outside) {
  1490. jit_tls->handler_block_return_address = NULL;
  1491. jit_tls->handler_block = NULL;
  1492. mono_thread_resume_interruption (); /*We ignore the exception here, it will be raised later*/
  1493. }
  1494. }
  1495. if (mono_trace_is_enabled () && mono_trace_eval (ji->method))
  1496. g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
  1497. jit_tls->orig_ex_ctx_set = TRUE;
  1498. mono_profiler_exception_clause_handler (ji->method, ei->flags, i);
  1499. jit_tls->orig_ex_ctx_set = FALSE;
  1500. mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
  1501. MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
  1502. *(mono_get_lmf_addr ()) = lmf;
  1503. #ifndef DISABLE_PERFCOUNTERS
  1504. mono_perfcounters->exceptions_depth += frame_count;
  1505. #endif
  1506. if (obj == domain->stack_overflow_ex)
  1507. jit_tls->handling_stack_ovf = FALSE;
  1508. return 0;
  1509. }
  1510. if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
  1511. (ei->flags == MONO_EXCEPTION_CLAUSE_FAULT)) {
  1512. if (mono_trace_is_enabled () && mono_trace_eval (ji->method))
  1513. g_print ("EXCEPTION: fault clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
  1514. jit_tls->orig_ex_ctx_set = TRUE;
  1515. mono_profiler_exception_clause_handler (ji->method, ei->flags, i);
  1516. jit_tls->orig_ex_ctx_set = FALSE;
  1517. mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
  1518. call_filter (ctx, ei->handler_start);
  1519. }
  1520. if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
  1521. (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY)) {
  1522. if (mono_trace_is_enabled () && mono_trace_eval (ji->method))
  1523. g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
  1524. jit_tls->orig_ex_ctx_set = TRUE;
  1525. mono_profiler_exception_clause_handler (ji->method, ei->flags, i);
  1526. jit_tls->orig_ex_ctx_set = FALSE;
  1527. mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
  1528. #ifndef DISABLE_PERFCOUNTERS
  1529. mono_perfcounters->exceptions_finallys++;
  1530. #endif
  1531. *(mono_get_lmf_addr ()) = lmf;
  1532. if (ji->from_llvm) {
  1533. /*
  1534. * LLVM compiled finally handlers follow the design
  1535. * of the c++ ehabi, i.e. they call a resume function
  1536. * at the end instead of returning to the caller.
  1537. * So save the exception handling state,
  1538. * mono_resume_unwind () will call us again to continue
  1539. * the unwinding.
  1540. */
  1541. jit_tls->resume_state.ex_obj = obj;
  1542. jit_tls->resume_state.ji = ji;
  1543. jit_tls->resume_state.clause_index = i + 1;
  1544. jit_tls->resume_state.ctx = *ctx;
  1545. jit_tls->resume_state.new_ctx = new_ctx;
  1546. jit_tls->resume_state.lmf = lmf;
  1547. jit_tls->resume_state.first_filter_idx = first_filter_idx;
  1548. jit_tls->resume_state.filter_idx = filter_idx;
  1549. MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
  1550. return 0;
  1551. } else {
  1552. call_filter (ctx, ei->handler_start);
  1553. }
  1554. }
  1555. }
  1556. }
  1557. jit_tls->orig_ex_ctx_set = TRUE;
  1558. mono_profiler_exception_method_leave (ji->method);
  1559. jit_tls->orig_ex_ctx_set = FALSE;
  1560. *ctx = new_ctx;
  1561. }
  1562. g_assert_not_reached ();
  1563. }
  1564. /*
  1565. * mono_debugger_handle_exception:
  1566. *
  1567. * Notify the debugger about exceptions. Returns TRUE if the debugger wants us to stop
  1568. * at the exception and FALSE to resume with the normal exception handling.
  1569. *
  1570. * The arch code is responsible to setup @ctx in a way that MONO_CONTEXT_GET_IP () and
  1571. * MONO_CONTEXT_GET_SP () point to the throw instruction; ie. before executing the
  1572. * `callq throw' instruction.
  1573. */
  1574. gboolean
  1575. mono_debugger_handle_exception (MonoContext *ctx, MonoObject *obj)
  1576. {
  1577. MonoDebuggerExceptionAction action;
  1578. if (!mono_debug_using_mono_debugger ())
  1579. return FALSE;
  1580. if (!obj) {
  1581. MonoException *ex = mono_get_exception_null_reference ();
  1582. MONO_OBJECT_SETREF (ex, message, mono_string_new (mono_domain_get (), "Object reference not set to an instance of an object"));
  1583. obj = (MonoObject *)ex;
  1584. }
  1585. action = _mono_debugger_throw_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj);
  1586. if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP) {
  1587. /*
  1588. * The debugger wants us to stop on the `throw' instruction.
  1589. * By the time we get here, it already inserted a breakpoint there.
  1590. */
  1591. return TRUE;
  1592. } else if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED) {
  1593. MonoContext ctx_cp = *ctx;
  1594. MonoJitInfo *ji = NULL;
  1595. gboolean ret;
  1596. /*
  1597. * The debugger wants us to stop only if this exception is user-unhandled.
  1598. */
  1599. ret = mono_handle_exception_internal_first_pass (&ctx_cp, obj, NULL, &ji, NULL);
  1600. if (ret && (ji != NULL) && (ji->method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE)) {
  1601. /*
  1602. * The exception is handled in a runtime-invoke wrapper, that means that it's unhandled
  1603. * inside the method being invoked, so we handle it like a user-unhandled exception.
  1604. */
  1605. ret = FALSE;
  1606. }
  1607. if (!ret) {
  1608. /*
  1609. * The exception is user-unhandled - tell the debugger to stop.
  1610. */
  1611. return _mono_debugger_unhandled_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj);
  1612. }
  1613. /*
  1614. * The exception is catched somewhere - resume with the normal exception handling and don't
  1615. * stop in the debugger.
  1616. */
  1617. }
  1618. return FALSE;
  1619. }
  1620. /**
  1621. * mono_debugger_run_finally:
  1622. * @start_ctx: saved processor state
  1623. *
  1624. * This method is called by the Mono Debugger to call all `finally' clauses of the
  1625. * current stack frame. It's used when the user issues a `return' command to make
  1626. * the current stack frame return. After returning from this method, the debugger
  1627. * unwinds the stack one frame and gives control back to the user.
  1628. *
  1629. * NOTE: This method is only used when running inside the Mono Debugger.
  1630. */
  1631. void
  1632. mono_debugger_run_finally (MonoContext *start_ctx)
  1633. {
  1634. static int (*call_filter) (MonoContext *, gpointer) = NULL;
  1635. MonoDomain *domain = mono_domain_get ();
  1636. MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  1637. MonoLMF *lmf = mono_get_lmf ();
  1638. MonoContext ctx, new_ctx;
  1639. MonoJitInfo *ji, rji;
  1640. int i;
  1641. ctx = *start_ctx;
  1642. ji = mono_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, NULL, NULL);
  1643. if (!ji || ji == (gpointer)-1)
  1644. return;
  1645. if (!call_filter)
  1646. call_filter = mono_get_call_filter ();
  1647. for (i = 0; i < ji->num_clauses; i++) {
  1648. MonoJitExceptionInfo *ei = &ji->clauses [i];
  1649. if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (&ctx)) &&
  1650. (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
  1651. call_filter (&ctx, ei->handler_start);
  1652. }
  1653. }
  1654. }
  1655. /**
  1656. * mono_handle_exception:
  1657. * @ctx: saved processor state
  1658. * @obj: the exception object
  1659. */
  1660. gboolean
  1661. mono_handle_exception (MonoContext *ctx, gpointer obj)
  1662. {
  1663. #ifndef DISABLE_PERFCOUNTERS
  1664. mono_perfcounters->exceptions_thrown++;
  1665. #endif
  1666. return mono_handle_exception_internal (ctx, obj, FALSE, NULL);
  1667. }
  1668. #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
  1669. #ifndef MONO_ARCH_USE_SIGACTION
  1670. #error "Can't use sigaltstack without sigaction"
  1671. #endif
  1672. #define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
  1673. void
  1674. mono_setup_altstack (MonoJitTlsData *tls)
  1675. {
  1676. size_t stsize = 0;
  1677. stack_t sa;
  1678. guint8 *staddr = NULL;
  1679. if (mono_running_on_valgrind ())
  1680. return;
  1681. mono_thread_get_stack_bounds (&staddr, &stsize);
  1682. g_assert (staddr);
  1683. tls->end_of_stack = staddr + stsize;
  1684. tls->stack_size = stsize;
  1685. /*g_print ("thread %p, stack_base: %p, stack_size: %d\n", (gpointer)pthread_self (), staddr, stsize);*/
  1686. tls->stack_ovf_guard_base = staddr + mono_pagesize ();
  1687. tls->stack_ovf_guard_size = ALIGN_TO (8 * 4096, mono_pagesize ());
  1688. g_assert ((guint8*)&sa >= (guint8*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size);
  1689. if (mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE)) {
  1690. /* mprotect can fail for the main thread stack */
  1691. gpointer gaddr = mono_valloc (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON|MONO_MMAP_FIXED);
  1692. g_assert (gaddr == tls->stack_ovf_guard_base);
  1693. tls->stack_ovf_valloced = TRUE;
  1694. }
  1695. /* Setup an alternate signal stack */
  1696. tls->signal_stack = mono_valloc (0, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON);
  1697. tls->signal_stack_size = MONO_ARCH_SIGNAL_STACK_SIZE;
  1698. g_assert (tls->signal_stack);
  1699. sa.ss_sp = tls->signal_stack;
  1700. sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
  1701. #if __APPLE__
  1702. sa.ss_flags = 0;
  1703. #else
  1704. sa.ss_flags = SS_ONSTACK;
  1705. #endif
  1706. g_assert (sigaltstack (&sa, NULL) == 0);
  1707. mono_gc_register_altstack ((char*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size, (char*)staddr + stsize - ((char*)tls->stack_ovf_guard_base + tls->stack_ovf_guard_size), tls->signal_stack, tls->signal_stack_size);
  1708. }
  1709. void
  1710. mono_free_altstack (MonoJitTlsData *tls)
  1711. {
  1712. stack_t sa;
  1713. int err;
  1714. sa.ss_sp = tls->signal_stack;
  1715. sa.ss_size = MONO_ARCH_SIGNAL_STACK_SIZE;
  1716. sa.ss_flags = SS_DISABLE;
  1717. err = sigaltstack (&sa, NULL);
  1718. g_assert (err == 0);
  1719. if (tls->signal_stack)
  1720. mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE);
  1721. if (tls->stack_ovf_valloced)
  1722. mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size);
  1723. else
  1724. mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
  1725. }
  1726. #else /* !MONO_ARCH_SIGSEGV_ON_ALTSTACK */
  1727. void
  1728. mono_setup_altstack (MonoJitTlsData *tls)
  1729. {
  1730. }
  1731. void
  1732. mono_free_altstack (MonoJitTlsData *tls)
  1733. {
  1734. }
  1735. #endif /* MONO_ARCH_SIGSEGV_ON_ALTSTACK */
  1736. static gboolean
  1737. try_restore_stack_protection (MonoJitTlsData *jit_tls, int extra_bytes)
  1738. {
  1739. gint32 unprotect_size = jit_tls->stack_ovf_guard_size;
  1740. /* we need to leave some room for throwing the exception */
  1741. while (unprotect_size >= 0 && (char*)jit_tls->stack_ovf_guard_base + unprotect_size > ((char*)&unprotect_size - extra_bytes))
  1742. unprotect_size -= mono_pagesize ();
  1743. /* at this point we could try and build a new domain->stack_overflow_ex, but only if there
  1744. * is sufficient stack
  1745. */
  1746. //fprintf (stderr, "restoring stack protection: %p-%p (%d)\n", jit_tls->stack_ovf_guard_base, (char*)jit_tls->stack_ovf_guard_base + unprotect_size, unprotect_size);
  1747. if (unprotect_size)
  1748. mono_mprotect (jit_tls->stack_ovf_guard_base, unprotect_size, MONO_MMAP_NONE);
  1749. return unprotect_size == jit_tls->stack_ovf_guard_size;
  1750. }
  1751. static G_GNUC_UNUSED void
  1752. try_more_restore (void)
  1753. {
  1754. MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  1755. if (try_restore_stack_protection (jit_tls, 500))
  1756. jit_tls->restore_stack_prot = NULL;
  1757. }
  1758. static G_GNUC_UNUSED void
  1759. restore_stack_protection (void)
  1760. {
  1761. MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  1762. MonoException *ex = mono_domain_get ()->stack_overflow_ex;
  1763. /* if we can't restore the stack protection, keep a callback installed so
  1764. * we'll try to restore as much stack as we can at each return from unmanaged
  1765. * code.
  1766. */
  1767. if (try_restore_stack_protection (jit_tls, 4096))
  1768. jit_tls->restore_stack_prot = NULL;
  1769. else
  1770. jit_tls->restore_stack_prot = try_more_restore_tramp;
  1771. /* here we also throw a stack overflow exception */
  1772. ex->trace_ips = NULL;
  1773. ex->stack_trace = NULL;
  1774. mono_raise_exception (ex);
  1775. }
  1776. gpointer
  1777. mono_altstack_restore_prot (mgreg_t *regs, guint8 *code, gpointer *tramp_data, guint8* tramp)
  1778. {
  1779. void (*func)(void) = (gpointer)tramp_data;
  1780. func ();
  1781. return NULL;
  1782. }
  1783. gboolean
  1784. mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
  1785. {
  1786. /* we got a stack overflow in the soft-guard pages
  1787. * There are two cases:
  1788. * 1) managed code caused the overflow: we unprotect the soft-guard page
  1789. * and let the arch-specific code trigger the exception handling mechanism
  1790. * in the thread stack. The soft-guard pages will be protected again as the stack is unwound.
  1791. * 2) unmanaged code caused the overflow: we unprotect the soft-guard page
  1792. * and hope we can continue with those enabled, at least until the hard-guard page
  1793. * is hit. The alternative to continuing here is to just print a message and abort.
  1794. * We may add in the future the code to protect the pages again in the codepath
  1795. * when we return from unmanaged to managed code.
  1796. */
  1797. if (jit_tls->stack_ovf_guard_size && fault_addr >= (guint8*)jit_tls->stack_ovf_guard_base &&
  1798. fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size) {
  1799. /* we unprotect the minimum amount we can */
  1800. guint32 guard_size;
  1801. gboolean handled = FALSE;
  1802. guard_size = jit_tls->stack_ovf_guard_size - (mono_pagesize () * SIZEOF_VOID_P / 4);
  1803. while (guard_size && fault_addr < (guint8*)jit_tls->stack_ovf_guard_base + guard_size) {
  1804. guard_size -= mono_pagesize ();
  1805. }
  1806. guard_size = jit_tls->stack_ovf_guard_size - guard_size;
  1807. /*fprintf (stderr, "unprotecting: %d\n", guard_size);*/
  1808. mono_mprotect ((char*)jit_tls->stack_ovf_guard_base + jit_tls->stack_ovf_guard_size - guard_size, guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
  1809. #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
  1810. if (ji) {
  1811. mono_arch_handle_altstack_exception (ctx, fault_addr, TRUE);
  1812. handled = TRUE;
  1813. }
  1814. #endif
  1815. if (!handled) {
  1816. /* We print a message: after this even managed stack overflows
  1817. * may crash the runtime
  1818. */
  1819. mono_runtime_printf_err ("Stack overflow in unmanaged: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
  1820. if (!jit_tls->handling_stack_ovf) {
  1821. jit_tls->restore_stack_prot = restore_stack_protection_tramp;
  1822. jit_tls->handling_stack_ovf = 1;
  1823. } else {
  1824. /*fprintf (stderr, "Already handling stack overflow\n");*/
  1825. }
  1826. }
  1827. return TRUE;
  1828. }
  1829. return FALSE;
  1830. }
  1831. typedef struct {
  1832. MonoMethod *omethod;
  1833. int count;
  1834. } PrintOverflowUserData;
  1835. static gboolean
  1836. print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
  1837. {
  1838. MonoMethod *method = NULL;
  1839. PrintOverflowUserData *user_data = data;
  1840. gchar *location;
  1841. if (frame->ji)
  1842. method = frame->ji->method;
  1843. if (method) {
  1844. if (user_data->count == 0) {
  1845. /* The first frame is in its prolog, so a line number cannot be computed */
  1846. user_data->count ++;
  1847. return FALSE;
  1848. }
  1849. /* If this is a one method overflow, skip the other instances */
  1850. if (method == user_data->omethod)
  1851. return FALSE;
  1852. location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
  1853. mono_runtime_printf_err (" %s", location);
  1854. g_free (location);
  1855. if (user_data->count == 1) {
  1856. mono_runtime_printf_err (" <...>");
  1857. user_data->omethod = method;
  1858. } else {
  1859. user_data->omethod = NULL;
  1860. }
  1861. user_data->count ++;
  1862. } else
  1863. mono_runtime_printf_err (" at <unknown> <0x%05x>", frame->native_offset);
  1864. return FALSE;
  1865. }
  1866. void
  1867. mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
  1868. {
  1869. PrintOverflowUserData ud;
  1870. MonoContext mctx;
  1871. /* we don't do much now, but we can warn the user with a useful message */
  1872. mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
  1873. #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
  1874. mono_arch_sigctx_to_monoctx (ctx, &mctx);
  1875. mono_runtime_printf_err ("Stacktrace:");
  1876. memset (&ud, 0, sizeof (ud));
  1877. mono_walk_stack_with_ctx (print_overflow_stack_frame, &mctx, MONO_UNWIND_LOOKUP_ACTUAL_METHOD, &ud);
  1878. #else
  1879. if (ji && ji->method)
  1880. mono_runtime_printf_err ("At %s", mono_method_full_name (ji->method, TRUE));
  1881. else
  1882. mono_runtime_printf_err ("At <unmanaged>.");
  1883. #endif
  1884. _exit (1);
  1885. }
  1886. static gboolean
  1887. print_stack_frame_to_stderr (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
  1888. {
  1889. MonoMethod *method = NULL;
  1890. if (frame->ji)
  1891. method = frame->ji->method;
  1892. if (method) {
  1893. gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
  1894. mono_runtime_printf_err (" %s", location);
  1895. g_free (location);
  1896. } else
  1897. mono_runtime_printf_err (" at <unknown> <0x%05x>", frame->native_offset);
  1898. return FALSE;
  1899. }
  1900. static G_GNUC_UNUSED gboolean
  1901. print_stack_frame_to_string (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
  1902. {
  1903. GString *p = (GString*)data;
  1904. MonoMethod *method = NULL;
  1905. if (frame->ji)
  1906. method = frame->ji->method;
  1907. if (method) {
  1908. gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, mono_domain_get ());
  1909. g_string_append_printf (p, " %s\n", location);
  1910. g_free (location);
  1911. } else
  1912. g_string_append_printf (p, " at <unknown> <0x%05x>\n", frame->native_offset);
  1913. return FALSE;
  1914. }
  1915. static gboolean handling_sigsegv = FALSE;
  1916. /*
  1917. * mono_handle_native_sigsegv:
  1918. *
  1919. * Handle a SIGSEGV received while in native code by printing diagnostic
  1920. * information and aborting.
  1921. */
  1922. void
  1923. mono_handle_native_sigsegv (int signal, void *ctx)
  1924. {
  1925. #ifdef MONO_ARCH_USE_SIGACTION
  1926. struct sigaction sa;
  1927. #endif
  1928. MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  1929. const char *signal_str = (signal == SIGSEGV) ? "SIGSEGV" : "SIGABRT";
  1930. if (handling_sigsegv)
  1931. return;
  1932. if (mini_get_debug_options ()->suspend_on_sigsegv) {
  1933. mono_runtime_printf_err ("Received SIGSEGV, suspending...");
  1934. while (1)
  1935. ;
  1936. }
  1937. /* To prevent infinite loops when the stack walk causes a crash */
  1938. handling_sigsegv = TRUE;
  1939. /* !jit_tls means the thread was not registered with the runtime */
  1940. if (jit_tls && mono_thread_internal_current ()) {
  1941. mono_runtime_printf_err ("Stacktrace:\n");
  1942. mono_walk_stack (print_stack_frame_to_stderr, TRUE, NULL);
  1943. }
  1944. #ifdef HAVE_BACKTRACE_SYMBOLS
  1945. {
  1946. void *array [256];
  1947. char **names;
  1948. int i, size;
  1949. mono_runtime_printf_err ("\nNative stacktrace:\n");
  1950. size = backtrace (array, 256);
  1951. names = backtrace_symbols (array, size);
  1952. for (i =0; i < size; ++i) {
  1953. mono_runtime_printf_err ("\t%s", names [i]);
  1954. }
  1955. free (names);
  1956. /* Try to get more meaningful information using gdb */
  1957. #if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
  1958. if (!mini_get_debug_options ()->no_gdb_backtrace && !mono_debug_using_mono_debugger ()) {
  1959. /* From g_spawn_command_line_sync () in eglib */
  1960. pid_t pid;
  1961. int status;
  1962. pid_t crashed_pid = getpid ();
  1963. //pid = fork ();
  1964. /*
  1965. * glibc fork acquires some locks, so if the crash happened inside malloc/free,
  1966. * it will deadlock. Call the syscall directly instead.
  1967. */
  1968. pid = mono_runtime_syscall_fork ();
  1969. if (pid == 0) {
  1970. dup2 (STDERR_FILENO, STDOUT_FILENO);
  1971. mono_gdb_render_native_backtraces (crashed_pid);
  1972. exit (1);
  1973. }
  1974. mono_runtime_printf_err ("\nDebug info from gdb:\n");
  1975. waitpid (pid, &status, 0);
  1976. }
  1977. #endif
  1978. }
  1979. #endif
  1980. /*
  1981. * A SIGSEGV indicates something went very wrong so we can no longer depend
  1982. * on anything working. So try to print out lots of diagnostics, starting
  1983. * with ones which have a greater chance of working.
  1984. */
  1985. mono_runtime_printf_err (
  1986. "\n"
  1987. "=================================================================\n"
  1988. "Got a %s while executing native code. This usually indicates\n"
  1989. "a fatal error in the mono runtime or one of the native libraries \n"
  1990. "used by your application.\n"
  1991. "=================================================================\n",
  1992. signal_str);
  1993. #ifdef MONO_ARCH_USE_SIGACTION
  1994. /* Remove our SIGABRT handler */
  1995. sa.sa_handler = SIG_DFL;
  1996. sigemptyset (&sa.sa_mask);
  1997. sa.sa_flags = 0;
  1998. g_assert (sigaction (SIGABRT, &sa, NULL) != -1);
  1999. #endif
  2000. /*Android abort is a fluke, it doesn't abort, it triggers another segv. */
  2001. #if defined (PLATFORM_ANDROID)
  2002. exit (-1);
  2003. #else
  2004. abort ();
  2005. #endif
  2006. }
  2007. static void
  2008. mono_print_thread_dump_internal (void *sigctx, MonoContext *start_ctx)
  2009. {
  2010. MonoInternalThread *thread = mono_thread_internal_current ();
  2011. #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
  2012. MonoContext ctx;
  2013. #endif
  2014. GString* text = g_string_new (0);
  2015. char *name, *wapi_desc;
  2016. GError *error = NULL;
  2017. if (thread->name) {
  2018. name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
  2019. g_assert (!error);
  2020. g_string_append_printf (text, "\n\"%s\"", name);
  2021. g_free (name);
  2022. }
  2023. else if (thread->threadpool_thread)
  2024. g_string_append (text, "\n\"<threadpool thread>\"");
  2025. else
  2026. g_string_append (text, "\n\"<unnamed thread>\"");
  2027. #ifndef HOST_WIN32
  2028. wapi_desc = wapi_current_thread_desc ();
  2029. g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread, wapi_desc);
  2030. free (wapi_desc);
  2031. #endif
  2032. #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
  2033. if (start_ctx) {
  2034. memcpy (&ctx, start_ctx, sizeof (MonoContext));
  2035. } else if (!sigctx)
  2036. MONO_INIT_CONTEXT_FROM_FUNC (&ctx, mono_print_thread_dump);
  2037. else
  2038. mono_arch_sigctx_to_monoctx (sigctx, &ctx);
  2039. mono_walk_stack_with_ctx (print_stack_frame_to_string, &ctx, MONO_UNWIND_LOOKUP_ALL, text);
  2040. #else
  2041. mono_runtime_printf ("\t<Stack traces in thread dumps not supported on this platform>");
  2042. #endif
  2043. mono_runtime_printf ("%s", text->str);
  2044. #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
  2045. OutputDebugStringA(text->str);
  2046. #endif
  2047. g_string_free (text, TRUE);
  2048. mono_runtime_stdout_fflush ();
  2049. }
  2050. /*
  2051. * mono_print_thread_dump:
  2052. *
  2053. * Print information about the current thread to stdout.
  2054. * SIGCTX can be NULL, allowing this to be called from gdb.
  2055. */
  2056. void
  2057. mono_print_thread_dump (void *sigctx)
  2058. {
  2059. mono_print_thread_dump_internal (sigctx, NULL);
  2060. }
  2061. void
  2062. mono_print_thread_dump_from_ctx (MonoContext *ctx)
  2063. {
  2064. mono_print_thread_dump_internal (NULL, ctx);
  2065. }
  2066. /*
  2067. * mono_resume_unwind:
  2068. *
  2069. * This is called by a trampoline from LLVM compiled finally clauses to continue
  2070. * unwinding.
  2071. */
  2072. void
  2073. mono_resume_unwind (MonoContext *ctx)
  2074. {
  2075. MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  2076. static void (*restore_context) (MonoContext *);
  2077. MonoContext new_ctx;
  2078. MONO_CONTEXT_SET_IP (ctx, MONO_CONTEXT_GET_IP (&jit_tls->resume_state.ctx));
  2079. MONO_CONTEXT_SET_SP (ctx, MONO_CONTEXT_GET_SP (&jit_tls->resume_state.ctx));
  2080. new_ctx = *ctx;
  2081. mono_handle_exception_internal (&new_ctx, jit_tls->resume_state.ex_obj, TRUE, NULL);
  2082. if (!restore_context)
  2083. restore_context = mono_get_restore_context ();
  2084. restore_context (&new_ctx);
  2085. }
  2086. #ifdef MONO_ARCH_HAVE_HANDLER_BLOCK_GUARD
  2087. typedef struct {
  2088. MonoJitInfo *ji;
  2089. MonoContext ctx;
  2090. MonoJitExceptionInfo *ei;
  2091. } FindHandlerBlockData;
  2092. static gboolean
  2093. find_last_handler_block (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
  2094. {
  2095. int i;
  2096. gpointer ip;
  2097. FindHandlerBlockData *pdata = data;
  2098. MonoJitInfo *ji = frame->ji;
  2099. if (!ji)
  2100. return FALSE;
  2101. if (ji->method->wrapper_type)
  2102. return FALSE;
  2103. ip = MONO_CONTEXT_GET_IP (ctx);
  2104. for (i = 0; i < ji->num_clauses; ++i) {
  2105. MonoJitExceptionInfo *ei = ji->clauses + i;
  2106. if (ei->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
  2107. continue;
  2108. /*If ip points to the first instruction it means the handler block didn't start
  2109. so we can leave its execution to the EH machinery*/
  2110. if (ei->handler_start < ip && ip < ei->data.handler_end) {
  2111. pdata->ji = ji;
  2112. pdata->ei = ei;
  2113. pdata->ctx = *ctx;
  2114. break;
  2115. }
  2116. }
  2117. return FALSE;
  2118. }
  2119. static gpointer
  2120. install_handler_block_guard (MonoJitInfo *ji, MonoContext *ctx)
  2121. {
  2122. int i;
  2123. MonoJitExceptionInfo *clause = NULL;
  2124. gpointer ip;
  2125. ip = MONO_CONTEXT_GET_IP (ctx);
  2126. for (i = 0; i < ji->num_clauses; ++i) {
  2127. clause = &ji->clauses [i];
  2128. if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY)
  2129. continue;
  2130. if (clause->handler_start < ip && clause->data.handler_end > ip)
  2131. break;
  2132. }
  2133. /*no matching finally */
  2134. if (i == ji->num_clauses)
  2135. return NULL;
  2136. /*If we stopped on the instruction right before the try, we haven't actually started executing it*/
  2137. if (ip == clause->handler_start)
  2138. return NULL;
  2139. return mono_arch_install_handler_block_guard (ji, clause, ctx, mono_create_handler_block_trampoline ());
  2140. }
  2141. /*
  2142. * Finds the bottom handler block running and install a block guard if needed.
  2143. * FIXME add full-aot support.
  2144. */
  2145. gboolean
  2146. mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
  2147. {
  2148. FindHandlerBlockData data = { 0 };
  2149. MonoJitTlsData *jit_tls = ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS];
  2150. gpointer resume_ip;
  2151. /* FIXME */
  2152. if (mono_aot_only)
  2153. return FALSE;
  2154. /* Guard against a null MonoJitTlsData. This can happens if the thread receives the
  2155. * interrupt signal before the JIT has time to initialize its TLS data for the given thread.
  2156. */
  2157. if (!jit_tls || jit_tls->handler_block_return_address)
  2158. return FALSE;
  2159. mono_walk_stack_with_state (find_last_handler_block, ctx, MONO_UNWIND_SIGNAL_SAFE, &data);
  2160. if (!data.ji)
  2161. return FALSE;
  2162. memcpy (&jit_tls->handler_block_context, &data.ctx, sizeof (MonoContext));
  2163. resume_ip = install_handler_block_guard (data.ji, &data.ctx);
  2164. if (resume_ip == NULL)
  2165. return FALSE;
  2166. jit_tls->handler_block_return_address = resume_ip;
  2167. jit_tls->handler_block = data.ei;
  2168. return TRUE;
  2169. }
  2170. #else
  2171. gboolean
  2172. mono_install_handler_block_guard (MonoThreadUnwindState *ctx)
  2173. {
  2174. return FALSE;
  2175. }
  2176. #endif
  2177. void
  2178. mono_set_cast_details (MonoClass *from, MonoClass *to)
  2179. {
  2180. MonoJitTlsData *jit_tls = NULL;
  2181. if (mini_get_debug_options ()->better_cast_details) {
  2182. jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  2183. jit_tls->class_cast_from = from;
  2184. jit_tls->class_cast_to = to;
  2185. }
  2186. }
  2187. /*returns false if the thread is not attached*/
  2188. gboolean
  2189. mono_thread_state_init_from_sigctx (MonoThreadUnwindState *ctx, void *sigctx)
  2190. {
  2191. #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
  2192. MonoInternalThread *thread = mono_thread_internal_current ();
  2193. if (!thread || !thread->jit_data) {
  2194. ctx->valid = FALSE;
  2195. return FALSE;
  2196. }
  2197. if (sigctx)
  2198. mono_arch_sigctx_to_monoctx (sigctx, &ctx->ctx);
  2199. else
  2200. #if MONO_ARCH_HAS_MONO_CONTEXT && !defined(MONO_CROSS_COMPILE)
  2201. MONO_CONTEXT_GET_CURRENT (ctx->ctx);
  2202. #else
  2203. g_error ("Use a null sigctx requires a working mono-context");
  2204. #endif
  2205. ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
  2206. ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
  2207. ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
  2208. ctx->valid = TRUE;
  2209. return TRUE;
  2210. #else
  2211. g_error ("Implement mono_arch_sigctx_to_monoctx for the current target");
  2212. return FALSE;
  2213. #endif
  2214. }
  2215. gboolean
  2216. mono_thread_state_init_from_monoctx (MonoThreadUnwindState *ctx, MonoContext *mctx)
  2217. {
  2218. MonoInternalThread *thread = mono_thread_internal_current ();
  2219. if (!thread || !thread->jit_data) {
  2220. ctx->valid = FALSE;
  2221. return FALSE;
  2222. }
  2223. ctx->ctx = *mctx;
  2224. ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
  2225. ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
  2226. ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
  2227. ctx->valid = TRUE;
  2228. return TRUE;
  2229. }
  2230. /*returns false if the thread is not attached*/
  2231. gboolean
  2232. mono_thread_state_init_from_current (MonoThreadUnwindState *ctx)
  2233. {
  2234. MonoInternalThread *thread = mono_thread_internal_current ();
  2235. MONO_ARCH_CONTEXT_DEF
  2236. mono_arch_flush_register_windows ();
  2237. if (!thread || !thread->jit_data) {
  2238. ctx->valid = FALSE;
  2239. return FALSE;
  2240. }
  2241. #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
  2242. MONO_INIT_CONTEXT_FROM_CURRENT (&ctx->ctx);
  2243. #else
  2244. MONO_INIT_CONTEXT_FROM_FUNC (&ctx->ctx, mono_thread_state_init_from_current);
  2245. #endif
  2246. ctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
  2247. ctx->unwind_data [MONO_UNWIND_DATA_LMF] = mono_get_lmf ();
  2248. ctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = thread->jit_data;
  2249. ctx->valid = TRUE;
  2250. return TRUE;
  2251. }
  2252. static void
  2253. mono_raise_exception_with_ctx (MonoException *exc, MonoContext *ctx)
  2254. {
  2255. void (*restore_context) (MonoContext *);
  2256. restore_context = mono_get_restore_context ();
  2257. mono_handle_exception (ctx, exc);
  2258. restore_context (ctx);
  2259. }
  2260. /*FIXME Move all monoctx -> sigctx conversion to signal handlers once all archs support utils/mono-context */
  2261. void
  2262. mono_setup_async_callback (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data)
  2263. {
  2264. #ifdef MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK
  2265. MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
  2266. jit_tls->ex_ctx = *ctx;
  2267. mono_arch_setup_async_callback (ctx, async_cb, user_data);
  2268. #else
  2269. g_error ("This target doesn't support mono_arch_setup_async_callback");
  2270. #endif
  2271. }
  2272. void
  2273. mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, gpointer user_data)
  2274. {
  2275. unhandled_exception_hook = func;
  2276. unhandled_exception_hook_data = user_data;
  2277. }
  2278. void
  2279. mono_invoke_unhandled_exception_hook (MonoObject *exc)
  2280. {
  2281. if (unhandled_exception_hook) {
  2282. unhandled_exception_hook (exc, unhandled_exception_hook_data);
  2283. } else {
  2284. MonoObject *other = NULL;
  2285. MonoString *str = mono_object_to_string (exc, &other);
  2286. char *msg = NULL;
  2287. if (str)
  2288. msg = mono_string_to_utf8 (str);
  2289. else
  2290. msg = g_strdup ("Nested exception trying to figure out what went wrong");
  2291. mono_runtime_printf_err ("[ERROR] FATAL UNHANDLED EXCEPTION: %s", msg);
  2292. g_free (msg);
  2293. #if defined(__APPLE__) && defined(__arm__)
  2294. g_assertion_message ("Terminating runtime due to unhandled exception");
  2295. #else
  2296. exit (mono_environment_exitcode_get ());
  2297. #endif
  2298. }
  2299. g_assert_not_reached ();
  2300. }