|
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 <OS.h> |
| 46 | +#include <signal.h> |
| 47 | +#define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1 |
| 48 | +#endif |
| 49 | + |
44 | 50 | #include "AddressSpace.hpp"
|
45 | 51 | #include "CompactUnwinder.hpp"
|
46 | 52 | #include "config.h"
|
@@ -1015,7 +1021,7 @@ class UnwindCursor : public AbstractUnwindCursor{
|
1015 | 1021 | template <typename Registers> int stepThroughSigReturn(Registers &) {
|
1016 | 1022 | return UNW_STEP_END;
|
1017 | 1023 | }
|
1018 |
| -#elif defined(_LIBUNWIND_TARGET_HAIKU) |
| 1024 | +#elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
1019 | 1025 | bool setInfoForSigReturn();
|
1020 | 1026 | int stepThroughSigReturn();
|
1021 | 1027 | #endif
|
@@ -2559,7 +2565,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
|
2559 | 2565 | template <typename A, typename R>
|
2560 | 2566 | void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
|
2561 | 2567 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
|
2562 |
| - defined(_LIBUNWIND_TARGET_HAIKU) |
| 2568 | + defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
2563 | 2569 | _isSigReturn = false;
|
2564 | 2570 | #endif
|
2565 | 2571 |
|
@@ -2684,7 +2690,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
|
2684 | 2690 | #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
|
2685 | 2691 |
|
2686 | 2692 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
|
2687 |
| - defined(_LIBUNWIND_TARGET_HAIKU) |
| 2693 | + defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
2688 | 2694 | if (setInfoForSigReturn())
|
2689 | 2695 | return;
|
2690 | 2696 | #endif
|
@@ -2760,63 +2766,6 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
|
2760 | 2766 | _isSignalFrame = true;
|
2761 | 2767 | return UNW_STEP_SUCCESS;
|
2762 | 2768 | }
|
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 | 2769 | #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
|
2821 | 2770 | // defined(_LIBUNWIND_TARGET_AARCH64)
|
2822 | 2771 |
|
@@ -3032,6 +2981,96 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
|
3032 | 2981 | #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
|
3033 | 2982 | // defined(_LIBUNWIND_TARGET_S390X)
|
3034 | 2983 |
|
| 2984 | +#if defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
| 2985 | +template <typename A, typename R> |
| 2986 | +bool UnwindCursor<A, R>::setInfoForSigReturn() { |
| 2987 | + Dl_info dlinfo; |
| 2988 | + const auto isSignalHandler = [&](pint_t addr) { |
| 2989 | + if (!dladdr(reinterpret_cast<void *>(addr), &dlinfo)) |
| 2990 | + return false; |
| 2991 | + if (strcmp(dlinfo.dli_fname, "commpage")) |
| 2992 | + return false; |
| 2993 | + if (dlinfo.dli_sname == NULL || |
| 2994 | + strcmp(dlinfo.dli_sname, "commpage_signal_handler")) |
| 2995 | + return false; |
| 2996 | + return true; |
| 2997 | + }; |
| 2998 | + |
| 2999 | + pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); |
| 3000 | + if (!isSignalHandler(pc)) |
| 3001 | + return false; |
| 3002 | + |
| 3003 | + pint_t start = reinterpret_cast<pint_t>(dlinfo.dli_saddr); |
| 3004 | + |
| 3005 | + static size_t signalHandlerSize = 0; |
| 3006 | + if (signalHandlerSize == 0) { |
| 3007 | + size_t boundLow = 0; |
| 3008 | + size_t boundHigh = static_cast<size_t>(-1); |
| 3009 | + |
| 3010 | + area_info areaInfo; |
| 3011 | + if (get_area_info(area_for(dlinfo.dli_saddr), &areaInfo) == B_OK) |
| 3012 | + boundHigh = areaInfo.size; |
| 3013 | + |
| 3014 | + while (boundLow < boundHigh) { |
| 3015 | + size_t boundMid = boundLow + ((boundHigh - boundLow) / 2); |
| 3016 | + pint_t test = start + boundMid; |
| 3017 | + if (test >= start && isSignalHandler(test)) |
| 3018 | + boundLow = boundMid + 1; |
| 3019 | + else |
| 3020 | + boundHigh = boundMid; |
| 3021 | + } |
| 3022 | + |
| 3023 | + signalHandlerSize = boundHigh; |
| 3024 | + } |
| 3025 | + |
| 3026 | + _info = {}; |
| 3027 | + _info.start_ip = start; |
| 3028 | + _info.end_ip = start + signalHandlerSize; |
| 3029 | + _isSigReturn = true; |
| 3030 | + |
| 3031 | + return true; |
| 3032 | +} |
| 3033 | + |
| 3034 | +template <typename A, typename R> |
| 3035 | +int UnwindCursor<A, R>::stepThroughSigReturn() { |
| 3036 | + _isSignalFrame = true; |
| 3037 | + |
| 3038 | +#if defined(_LIBUNWIND_TARGET_X86_64) |
| 3039 | + // Layout of the stack before function call: |
| 3040 | + // - signal_frame_data |
| 3041 | + // + siginfo_t (public struct, fairly stable) |
| 3042 | + // + ucontext_t (public struct, fairly stable) |
| 3043 | + // - mcontext_t -> Offset 0x70, this is what we want. |
| 3044 | + // - frame->ip (8 bytes) |
| 3045 | + // - frame->bp (8 bytes). Not written by the kernel, |
| 3046 | + // but the signal handler has a "push %rbp" instruction. |
| 3047 | + pint_t bp = this->getReg(UNW_X86_64_RBP); |
| 3048 | + vregs *regs = (vregs *)(bp + 0x70); |
| 3049 | + |
| 3050 | + _registers.setRegister(UNW_REG_IP, regs->rip); |
| 3051 | + _registers.setRegister(UNW_REG_SP, regs->rsp); |
| 3052 | + _registers.setRegister(UNW_X86_64_RAX, regs->rax); |
| 3053 | + _registers.setRegister(UNW_X86_64_RDX, regs->rdx); |
| 3054 | + _registers.setRegister(UNW_X86_64_RCX, regs->rcx); |
| 3055 | + _registers.setRegister(UNW_X86_64_RBX, regs->rbx); |
| 3056 | + _registers.setRegister(UNW_X86_64_RSI, regs->rsi); |
| 3057 | + _registers.setRegister(UNW_X86_64_RDI, regs->rdi); |
| 3058 | + _registers.setRegister(UNW_X86_64_RBP, regs->rbp); |
| 3059 | + _registers.setRegister(UNW_X86_64_R8, regs->r8); |
| 3060 | + _registers.setRegister(UNW_X86_64_R9, regs->r9); |
| 3061 | + _registers.setRegister(UNW_X86_64_R10, regs->r10); |
| 3062 | + _registers.setRegister(UNW_X86_64_R11, regs->r11); |
| 3063 | + _registers.setRegister(UNW_X86_64_R12, regs->r12); |
| 3064 | + _registers.setRegister(UNW_X86_64_R13, regs->r13); |
| 3065 | + _registers.setRegister(UNW_X86_64_R14, regs->r14); |
| 3066 | + _registers.setRegister(UNW_X86_64_R15, regs->r15); |
| 3067 | + // TODO: XMM |
| 3068 | +#endif // defined(_LIBUNWIND_TARGET_X86_64) |
| 3069 | + |
| 3070 | + return UNW_STEP_SUCCESS; |
| 3071 | +} |
| 3072 | +#endif // defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
| 3073 | + |
3035 | 3074 | template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
|
3036 | 3075 | (void)stage2;
|
3037 | 3076 | // Bottom of stack is defined is when unwind info cannot be found.
|
|
0 commit comments