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.
@@ -3041,7 +3080,7 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
3041
3080
// Use unwinding info to modify register set as if function returned.
3042
3081
int result;
3043
3082
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
3044
- defined (_LIBUNWIND_TARGET_HAIKU )
3083
+ defined (_LIBUNWIND_CHECK_HAIKU_SIGRETURN )
3045
3084
if (_isSigReturn) {
3046
3085
result = this ->stepThroughSigReturn ();
3047
3086
} else
0 commit comments