|
41 | 41 | #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1 |
42 | 42 | #endif |
43 | 43 |
|
| 44 | +#if defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64) |
| 45 | +#include <signal.h> |
| 46 | +#define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1 |
| 47 | +#endif |
| 48 | + |
44 | 49 | #include "AddressSpace.hpp" |
45 | 50 | #include "CompactUnwinder.hpp" |
46 | 51 | #include "config.h" |
@@ -1015,7 +1020,7 @@ class UnwindCursor : public AbstractUnwindCursor{ |
1015 | 1020 | template <typename Registers> int stepThroughSigReturn(Registers &) { |
1016 | 1021 | return UNW_STEP_END; |
1017 | 1022 | } |
1018 | | -#elif defined(_LIBUNWIND_TARGET_HAIKU) |
| 1023 | +#elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
1019 | 1024 | bool setInfoForSigReturn(); |
1020 | 1025 | int stepThroughSigReturn(); |
1021 | 1026 | #endif |
@@ -2559,7 +2564,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable, |
2559 | 2564 | template <typename A, typename R> |
2560 | 2565 | void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
2561 | 2566 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ |
2562 | | - defined(_LIBUNWIND_TARGET_HAIKU) |
| 2567 | + defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
2563 | 2568 | _isSigReturn = false; |
2564 | 2569 | #endif |
2565 | 2570 |
|
@@ -2684,7 +2689,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
2684 | 2689 | #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
2685 | 2690 |
|
2686 | 2691 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ |
2687 | | - defined(_LIBUNWIND_TARGET_HAIKU) |
| 2692 | + defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
2688 | 2693 | if (setInfoForSigReturn()) |
2689 | 2694 | return; |
2690 | 2695 | #endif |
@@ -2760,63 +2765,6 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) { |
2760 | 2765 | _isSignalFrame = true; |
2761 | 2766 | return UNW_STEP_SUCCESS; |
2762 | 2767 | } |
2763 | | - |
2764 | | -#elif defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64) |
2765 | | -#include <commpage_defs.h> |
2766 | | -#include <signal.h> |
2767 | | - |
2768 | | -extern "C" { |
2769 | | -extern void *__gCommPageAddress; |
2770 | | -} |
2771 | | - |
2772 | | -template <typename A, typename R> |
2773 | | -bool UnwindCursor<A, R>::setInfoForSigReturn() { |
2774 | | -#if defined(_LIBUNWIND_TARGET_X86_64) |
2775 | | - addr_t signal_handler = |
2776 | | - (((addr_t *)__gCommPageAddress)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] + |
2777 | | - (addr_t)__gCommPageAddress); |
2778 | | - addr_t signal_handler_ret = signal_handler + 45; |
2779 | | -#endif |
2780 | | - pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); |
2781 | | - if (pc == signal_handler_ret) { |
2782 | | - _info = {}; |
2783 | | - _info.start_ip = signal_handler; |
2784 | | - _info.end_ip = signal_handler_ret; |
2785 | | - _isSigReturn = true; |
2786 | | - return true; |
2787 | | - } |
2788 | | - return false; |
2789 | | -} |
2790 | | - |
2791 | | -template <typename A, typename R> |
2792 | | -int UnwindCursor<A, R>::stepThroughSigReturn() { |
2793 | | - _isSignalFrame = true; |
2794 | | - pint_t sp = _registers.getSP(); |
2795 | | -#if defined(_LIBUNWIND_TARGET_X86_64) |
2796 | | - vregs *regs = (vregs *)(sp + 0x70); |
2797 | | - |
2798 | | - _registers.setRegister(UNW_REG_IP, regs->rip); |
2799 | | - _registers.setRegister(UNW_REG_SP, regs->rsp); |
2800 | | - _registers.setRegister(UNW_X86_64_RAX, regs->rax); |
2801 | | - _registers.setRegister(UNW_X86_64_RDX, regs->rdx); |
2802 | | - _registers.setRegister(UNW_X86_64_RCX, regs->rcx); |
2803 | | - _registers.setRegister(UNW_X86_64_RBX, regs->rbx); |
2804 | | - _registers.setRegister(UNW_X86_64_RSI, regs->rsi); |
2805 | | - _registers.setRegister(UNW_X86_64_RDI, regs->rdi); |
2806 | | - _registers.setRegister(UNW_X86_64_RBP, regs->rbp); |
2807 | | - _registers.setRegister(UNW_X86_64_R8, regs->r8); |
2808 | | - _registers.setRegister(UNW_X86_64_R9, regs->r9); |
2809 | | - _registers.setRegister(UNW_X86_64_R10, regs->r10); |
2810 | | - _registers.setRegister(UNW_X86_64_R11, regs->r11); |
2811 | | - _registers.setRegister(UNW_X86_64_R12, regs->r12); |
2812 | | - _registers.setRegister(UNW_X86_64_R13, regs->r13); |
2813 | | - _registers.setRegister(UNW_X86_64_R14, regs->r14); |
2814 | | - _registers.setRegister(UNW_X86_64_R15, regs->r15); |
2815 | | - // TODO: XMM |
2816 | | -#endif |
2817 | | - |
2818 | | - return UNW_STEP_SUCCESS; |
2819 | | -} |
2820 | 2768 | #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && |
2821 | 2769 | // defined(_LIBUNWIND_TARGET_AARCH64) |
2822 | 2770 |
|
@@ -3032,6 +2980,93 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) { |
3032 | 2980 | #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && |
3033 | 2981 | // defined(_LIBUNWIND_TARGET_S390X) |
3034 | 2982 |
|
| 2983 | +#if defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
| 2984 | +static size_t signalHandlerSize = 0; |
| 2985 | + |
| 2986 | +template <typename A, typename R> |
| 2987 | +bool UnwindCursor<A, R>::setInfoForSigReturn() { |
| 2988 | + Dl_info dlinfo; |
| 2989 | + auto isSignalHandler = [&](pint_t addr) { |
| 2990 | + if (!dladdr(reinterpret_cast<void *>(addr), &dlinfo)) |
| 2991 | + return false; |
| 2992 | + if (strcmp(dlinfo.dli_fname, "commpage")) |
| 2993 | + return false; |
| 2994 | + if (dlinfo.dli_sname == NULL || |
| 2995 | + strcmp(dlinfo.dli_sname, "commpage_signal_handler")) |
| 2996 | + return false; |
| 2997 | + return true; |
| 2998 | + }; |
| 2999 | + |
| 3000 | + pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); |
| 3001 | + if (!isSignalHandler(pc)) |
| 3002 | + return false; |
| 3003 | + |
| 3004 | + pint_t start = reinterpret_cast<pint_t>(dlinfo.dli_saddr); |
| 3005 | + |
| 3006 | + if (signalHandlerSize == 0) { |
| 3007 | + size_t boundLow = 0; |
| 3008 | + size_t boundHigh = static_cast<size_t>(-1); |
| 3009 | + |
| 3010 | + while (boundLow < boundHigh) { |
| 3011 | + size_t boundMid = boundLow + ((boundHigh - boundLow) / 2); |
| 3012 | + pint_t test = start + boundMid; |
| 3013 | + if (test >= start && isSignalHandler(test)) |
| 3014 | + boundLow = boundMid + 1; |
| 3015 | + else |
| 3016 | + boundHigh = boundMid; |
| 3017 | + } |
| 3018 | + |
| 3019 | + signalHandlerSize = boundHigh; |
| 3020 | + } |
| 3021 | + |
| 3022 | + _info = {}; |
| 3023 | + _info.start_ip = start; |
| 3024 | + _info.end_ip = start + signalHandlerSize; |
| 3025 | + _isSigReturn = true; |
| 3026 | + |
| 3027 | + return true; |
| 3028 | +} |
| 3029 | + |
| 3030 | +template <typename A, typename R> |
| 3031 | +int UnwindCursor<A, R>::stepThroughSigReturn() { |
| 3032 | + _isSignalFrame = true; |
| 3033 | + |
| 3034 | +#if defined(_LIBUNWIND_TARGET_X86_64) |
| 3035 | + // Layout of the stack before function call: |
| 3036 | + // - signal_frame_data |
| 3037 | + // + siginfo_t (public struct, fairly stable) |
| 3038 | + // + ucontext_t (public struct, fairly stable) |
| 3039 | + // - mcontext_t -> Offset 0x70, this is what we want. |
| 3040 | + // - frame->ip (8 bytes) |
| 3041 | + // - frame->bp (8 bytes). Not written by the kernel, |
| 3042 | + // but the signal handler has a "push %rbp" instruction. |
| 3043 | + pint_t bp = this->getReg(UNW_X86_64_RBP); |
| 3044 | + vregs *regs = (vregs *)(bp + 0x70); |
| 3045 | + |
| 3046 | + _registers.setRegister(UNW_REG_IP, regs->rip); |
| 3047 | + _registers.setRegister(UNW_REG_SP, regs->rsp); |
| 3048 | + _registers.setRegister(UNW_X86_64_RAX, regs->rax); |
| 3049 | + _registers.setRegister(UNW_X86_64_RDX, regs->rdx); |
| 3050 | + _registers.setRegister(UNW_X86_64_RCX, regs->rcx); |
| 3051 | + _registers.setRegister(UNW_X86_64_RBX, regs->rbx); |
| 3052 | + _registers.setRegister(UNW_X86_64_RSI, regs->rsi); |
| 3053 | + _registers.setRegister(UNW_X86_64_RDI, regs->rdi); |
| 3054 | + _registers.setRegister(UNW_X86_64_RBP, regs->rbp); |
| 3055 | + _registers.setRegister(UNW_X86_64_R8, regs->r8); |
| 3056 | + _registers.setRegister(UNW_X86_64_R9, regs->r9); |
| 3057 | + _registers.setRegister(UNW_X86_64_R10, regs->r10); |
| 3058 | + _registers.setRegister(UNW_X86_64_R11, regs->r11); |
| 3059 | + _registers.setRegister(UNW_X86_64_R12, regs->r12); |
| 3060 | + _registers.setRegister(UNW_X86_64_R13, regs->r13); |
| 3061 | + _registers.setRegister(UNW_X86_64_R14, regs->r14); |
| 3062 | + _registers.setRegister(UNW_X86_64_R15, regs->r15); |
| 3063 | + // TODO: XMM |
| 3064 | +#endif // defined(_LIBUNWIND_TARGET_X86_64) |
| 3065 | + |
| 3066 | + return UNW_STEP_SUCCESS; |
| 3067 | +} |
| 3068 | +#endif // defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
| 3069 | + |
3035 | 3070 | template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) { |
3036 | 3071 | (void)stage2; |
3037 | 3072 | // Bottom of stack is defined is when unwind info cannot be found. |
|
0 commit comments