https://github.com/korli created https://github.com/llvm/llvm-project/pull/115462
* Signal frame unwinding on x86_64 from X512 * Header search for commpage_defs.h on non-standard paths Unwind supported tests pass on Haiku x86_64 From faa99ee1a06a8139995bba31e6d783df164fb45d Mon Sep 17 00:00:00 2001 From: Trung Nguyen <trungnt282...@gmail.com> Date: Thu, 7 Jul 2022 22:19:34 +0700 Subject: [PATCH] [libunwind][Haiku] Improve support * Signal frame unwinding on x86_64 from X512 * Header search for commpage_defs.h on non-standard paths --- libunwind/src/CMakeLists.txt | 16 ++++++++ libunwind/src/UnwindCursor.hpp | 71 ++++++++++++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/libunwind/src/CMakeLists.txt b/libunwind/src/CMakeLists.txt index 2e18b109656331..e7ea57734cca97 100644 --- a/libunwind/src/CMakeLists.txt +++ b/libunwind/src/CMakeLists.txt @@ -113,6 +113,22 @@ if (HAIKU) add_compile_flags("-D_DEFAULT_SOURCE") add_compile_flags("-DPT_GNU_EH_FRAME=PT_EH_FRAME") + + find_path(LIBUNWIND_HAIKU_PRIVATE_HEADERS + "commpage_defs.h" + PATHS ${CMAKE_SYSTEM_INCLUDE_PATH} + PATH_SUFFIXES "/private/system" + NO_DEFAULT_PATH + REQUIRED) + + include_directories(SYSTEM "${LIBUNWIND_HAIKU_PRIVATE_HEADERS}") + if (LIBUNWIND_TARGET_TRIPLE) + if (${LIBUNWIND_TARGET_TRIPLE} MATCHES "^x86_64") + include_directories(SYSTEM "${LIBUNWIND_HAIKU_PRIVATE_HEADERS}/arch/x86_64") + endif() + else() + include_directories(SYSTEM "${LIBUNWIND_HAIKU_PRIVATE_HEADERS}/arch/${CMAKE_SYSTEM_PROCESSOR}") + endif() endif () string(REPLACE ";" " " LIBUNWIND_COMPILE_FLAGS "${LIBUNWIND_COMPILE_FLAGS}") diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index 32e6fb43d988ff..0019c1e62a7a65 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -1010,6 +1010,9 @@ class UnwindCursor : public AbstractUnwindCursor{ template <typename Registers> int stepThroughSigReturn(Registers &) { return UNW_STEP_END; } +#elif defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64) + bool setInfoForSigReturn(); + int stepThroughSigReturn(); #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) @@ -1313,7 +1316,8 @@ class UnwindCursor : public AbstractUnwindCursor{ unw_proc_info_t _info; bool _unwindInfoMissing; bool _isSignalFrame; -#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ + (defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)) bool _isSigReturn = false; #endif }; @@ -2549,7 +2553,8 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable, template <typename A, typename R> void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { -#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ + (defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)) _isSigReturn = false; #endif @@ -2673,7 +2678,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { } #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ + (defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)) if (setInfoForSigReturn()) return; #endif @@ -2749,6 +2755,62 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) { _isSignalFrame = true; return UNW_STEP_SUCCESS; } +#elif defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64) + +#include <commpage_defs.h> +#include <signal.h> + +extern "C" { +extern void *__gCommPageAddress; +} + +template <typename A, typename R> +bool UnwindCursor<A, R>::setInfoForSigReturn() { +#if defined(_LIBUNWIND_TARGET_X86_64) + addr_t signal_handler = (((addr_t*)__gCommPageAddress)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] + + (addr_t)__gCommPageAddress); + addr_t signal_handler_ret = signal_handler + 45; +#endif + pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); + if (pc == signal_handler_ret) { + _info = {}; + _info.start_ip = signal_handler; + _info.end_ip = signal_handler_ret; + _isSigReturn = true; + return true; + } + return false; +} + +template <typename A, typename R> +int UnwindCursor<A, R>::stepThroughSigReturn() { + _isSignalFrame = true; + pint_t sp = _registers.getSP(); +#if defined(_LIBUNWIND_TARGET_X86_64) + vregs *regs = (vregs*)(sp + 0x70); + + _registers.setRegister(UNW_REG_IP, regs->rip); + _registers.setRegister(UNW_REG_SP, regs->rsp); + _registers.setRegister(UNW_X86_64_RAX, regs->rax); + _registers.setRegister(UNW_X86_64_RDX, regs->rdx); + _registers.setRegister(UNW_X86_64_RCX, regs->rcx); + _registers.setRegister(UNW_X86_64_RBX, regs->rbx); + _registers.setRegister(UNW_X86_64_RSI, regs->rsi); + _registers.setRegister(UNW_X86_64_RDI, regs->rdi); + _registers.setRegister(UNW_X86_64_RBP, regs->rbp); + _registers.setRegister(UNW_X86_64_R8, regs->r8); + _registers.setRegister(UNW_X86_64_R9, regs->r9); + _registers.setRegister(UNW_X86_64_R10, regs->r10); + _registers.setRegister(UNW_X86_64_R11, regs->r11); + _registers.setRegister(UNW_X86_64_R12, regs->r12); + _registers.setRegister(UNW_X86_64_R13, regs->r13); + _registers.setRegister(UNW_X86_64_R14, regs->r14); + _registers.setRegister(UNW_X86_64_R15, regs->r15); + // TODO: XMM +#endif + + return UNW_STEP_SUCCESS; +} #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && // defined(_LIBUNWIND_TARGET_AARCH64) @@ -2917,7 +2979,8 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) { // Use unwinding info to modify register set as if function returned. int result; -#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) +#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ + (defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)) if (_isSigReturn) { result = this->stepThroughSigReturn(); } else _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits