backtrace_linux.cpp 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #include "backtrace_lib.h"
  2. #include <libunwind.h>
  3. #include <signal.h>
  4. #include <util/system/backtrace.h>
  5. namespace {
  6. size_t BackTrace(void** p, size_t len, ucontext_t* con) {
  7. unw_context_t context;
  8. unw_cursor_t cursor;
  9. if (unw_getcontext(&context)) {
  10. return 0;
  11. }
  12. if (unw_init_local(&cursor, &context)) {
  13. return 0;
  14. }
  15. const sigcontext* signal_mcontext = (const sigcontext*)&(con->uc_mcontext);
  16. unw_set_reg(&cursor, UNW_X86_64_RSI, signal_mcontext->rsi);
  17. unw_set_reg(&cursor, UNW_X86_64_RDI, signal_mcontext->rdi);
  18. unw_set_reg(&cursor, UNW_X86_64_RBP, signal_mcontext->rbp);
  19. unw_set_reg(&cursor, UNW_X86_64_RAX, signal_mcontext->rax);
  20. unw_set_reg(&cursor, UNW_X86_64_RBX, signal_mcontext->rbx);
  21. unw_set_reg(&cursor, UNW_X86_64_RCX, signal_mcontext->rcx);
  22. unw_set_reg(&cursor, UNW_X86_64_R8, signal_mcontext->r8);
  23. unw_set_reg(&cursor, UNW_X86_64_R9, signal_mcontext->r9);
  24. unw_set_reg(&cursor, UNW_X86_64_R10, signal_mcontext->r10);
  25. unw_set_reg(&cursor, UNW_X86_64_R11, signal_mcontext->r11);
  26. unw_set_reg(&cursor, UNW_X86_64_R12, signal_mcontext->r12);
  27. unw_set_reg(&cursor, UNW_X86_64_R13, signal_mcontext->r13);
  28. unw_set_reg(&cursor, UNW_X86_64_R14, signal_mcontext->r14);
  29. unw_set_reg(&cursor, UNW_X86_64_R15, signal_mcontext->r15);
  30. unw_set_reg(&cursor, UNW_X86_64_RSP, signal_mcontext->rsp);
  31. unw_set_reg(&cursor, UNW_REG_SP, signal_mcontext->rsp);
  32. unw_set_reg(&cursor, UNW_REG_IP, signal_mcontext->rip);
  33. size_t pos = 0;
  34. p[pos++] = (void*)signal_mcontext->rip;
  35. while (pos < len && unw_step(&cursor) > 0) {
  36. unw_word_t ip = 0;
  37. unw_get_reg(&cursor, UNW_REG_IP, &ip);
  38. if (unw_is_signal_frame(&cursor)) {
  39. continue;
  40. }
  41. p[pos++] = (void*)ip;
  42. }
  43. return pos;
  44. }
  45. }
  46. namespace NYql {
  47. namespace NBacktrace {
  48. size_t CollectBacktrace(void** addresses, size_t limit, void* data) {
  49. if (!data) {
  50. return BackTrace(addresses, limit);
  51. }
  52. return BackTrace(addresses, limit, reinterpret_cast<ucontext_t*>(data));
  53. }
  54. }
  55. }