interop_x86_64.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include "interop.h"
  2. namespace NYT::NBacktrace {
  3. ////////////////////////////////////////////////////////////////////////////////
  4. TFramePointerCursorContext FramePointerCursorContextFromUcontext(const ucontext_t& ucontext)
  5. {
  6. #if defined(_linux_)
  7. return {
  8. .Rip = static_cast<ui64>(ucontext.uc_mcontext.gregs[REG_RIP]),
  9. .Rsp = static_cast<ui64>(ucontext.uc_mcontext.gregs[REG_RSP]),
  10. .Rbp = static_cast<ui64>(ucontext.uc_mcontext.gregs[REG_RBP]),
  11. };
  12. #elif defined(_darwin_)
  13. return {
  14. .Rip = static_cast<ui64>(ucontext.uc_mcontext->__ss.__rip),
  15. .Rsp = static_cast<ui64>(ucontext.uc_mcontext->__ss.__rsp),
  16. .Rbp = static_cast<ui64>(ucontext.uc_mcontext->__ss.__rbp),
  17. };
  18. #else
  19. #error Unsupported platform
  20. #endif
  21. }
  22. std::optional<unw_context_t> TrySynthesizeLibunwindContextFromMachineContext(
  23. const TContMachineContext& machineContext)
  24. {
  25. unw_context_t unwindContext;
  26. if (unw_getcontext(&unwindContext) != 0) {
  27. return {};
  28. }
  29. // Some dirty hacks follow.
  30. struct TUnwindContextRegisters
  31. {
  32. ui64 Rax;
  33. ui64 Rbx;
  34. ui64 Rcx;
  35. ui64 Rdx;
  36. ui64 Rdi;
  37. ui64 Rsi;
  38. ui64 Rbp;
  39. ui64 Rsp;
  40. ui64 R8;
  41. ui64 R9;
  42. ui64 R10;
  43. ui64 R11;
  44. ui64 R12;
  45. ui64 R13;
  46. ui64 R14;
  47. ui64 R15;
  48. ui64 Rip;
  49. ui64 Rflags;
  50. ui64 CS;
  51. ui64 FS;
  52. ui64 GS;
  53. };
  54. struct TMachineContextRegisters
  55. {
  56. ui64 Rbx;
  57. ui64 Rbp;
  58. ui64 R12;
  59. ui64 R13;
  60. ui64 R14;
  61. ui64 R15;
  62. ui64 Rsp;
  63. ui64 Rip;
  64. };
  65. static_assert(sizeof(TContMachineContext) >= sizeof(TMachineContextRegisters));
  66. static_assert(sizeof(unw_context_t) >= sizeof(TUnwindContextRegisters));
  67. const auto* machineContextRegisters = reinterpret_cast<const TMachineContextRegisters*>(&machineContext);
  68. auto* unwindContextRegisters = reinterpret_cast<TUnwindContextRegisters*>(&unwindContext);
  69. #define XX(register) unwindContextRegisters->register = machineContextRegisters->register;
  70. XX(Rbx)
  71. XX(Rbp)
  72. XX(R12)
  73. XX(R13)
  74. XX(R14)
  75. XX(R15)
  76. XX(Rsp)
  77. XX(Rip)
  78. #undef XX
  79. return unwindContext;
  80. }
  81. TFramePointerCursorContext FramePointerCursorContextFromLibunwindCursor(
  82. const unw_cursor_t& cursor)
  83. {
  84. TFramePointerCursorContext context{};
  85. auto& mutableCursor = const_cast<unw_cursor_t&>(cursor);
  86. YT_VERIFY(unw_get_reg(&mutableCursor, UNW_REG_IP, &context.Rip) == 0);
  87. YT_VERIFY(unw_get_reg(&mutableCursor, UNW_X86_64_RSP, &context.Rsp) == 0);
  88. YT_VERIFY(unw_get_reg(&mutableCursor, UNW_X86_64_RBP, &context.Rbp) == 0);
  89. return context;
  90. }
  91. ////////////////////////////////////////////////////////////////////////////////
  92. } // namespace NYT::NBacktrace