01-exception-backtraces.patch 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. commit 6a570ad85b81eb53f0245268c7315409de2520e0
  2. merge: b38db0d0c3651fa83d5bc81f795fde7680f72033 45a49d9b4df748ab9f2b1267f8183b6574fea206
  3. author: eeight
  4. date: 2021-02-24T23:44:48+03:00
  5. revision: 7897977
  6. IGNIETFERRO-603 Record exception backtraces during stack unwinding
  7. REVIEW: 1637486
  8. --- a/include/unwind.h
  9. +++ b/include/unwind.h
  10. @@ -396,6 +396,21 @@ extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc,
  11. _Unwind_Personality_Fn pers);
  12. #endif
  13. +#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
  14. +
  15. +#define _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_SIZE 128
  16. +// NB. How to compute:
  17. +// offsetof(__cxa_exception, unwindHeader) + (sizeof(_Unwind_Backtrace_Buffer) + 15) / 16 * 16 - sizeof(_Unwind_Backtrace_Buffer)
  18. +// Correctness of this value is static_assert'd in contrib/libs/cxxsupp/libcxxrta/exception.cc
  19. +#define _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_MAGIC_OFFSET 104
  20. +#define _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_PRIMARY_CLASS 0xacadacadull
  21. +#define _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_DEPENDENT_CLASS 0xddddacadull
  22. +
  23. +typedef struct _Unwind_Backtrace_Buffer {
  24. + size_t size;
  25. + void* backtrace[_YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_SIZE];
  26. +} _Unwind_Backtrace_Buffer;
  27. +#endif
  28. #ifdef __cplusplus
  29. }
  30. #endif
  31. --- a/src/UnwindLevel1.c
  32. +++ b/src/UnwindLevel1.c
  33. @@ -38,6 +38,15 @@ static _Unwind_Reason_Code
  34. unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
  35. __unw_init_local(cursor, uc);
  36. +#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
  37. + _Unwind_Backtrace_Buffer* backtrace_buffer =
  38. + exception_object->exception_class == _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_PRIMARY_CLASS ||
  39. + exception_object->exception_class == _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_DEPENDENT_CLASS ?
  40. + (_Unwind_Backtrace_Buffer *)(
  41. + (char*)exception_object - _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_MAGIC_OFFSET) - 1
  42. + : NULL;
  43. +#endif
  44. +
  45. // Walk each frame looking for a place to stop.
  46. while (true) {
  47. // Ask libunwind to get next frame (skip over first which is
  48. @@ -57,6 +66,14 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
  49. return _URC_FATAL_PHASE1_ERROR;
  50. }
  51. +#ifdef _YNDX_LIBUNWIND_ENABLE_EXCEPTION_BACKTRACE
  52. + if (backtrace_buffer && backtrace_buffer->size < _YNDX_LIBUNWIND_EXCEPTION_BACKTRACE_SIZE) {
  53. + unw_word_t pc;
  54. + __unw_get_reg(cursor, UNW_REG_IP, &pc);
  55. + backtrace_buffer->backtrace[backtrace_buffer->size++] = (void *)pc;
  56. + }
  57. +#endif
  58. +
  59. // See if frame has code to run (has personality routine).
  60. unw_proc_info_t frameInfo;
  61. unw_word_t sp;