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"
@@ -1031,7 +1037,7 @@ class UnwindCursor : public AbstractUnwindCursor{
1031
1037
template <typename Registers> int stepThroughSigReturn (Registers &) {
1032
1038
return UNW_STEP_END;
1033
1039
}
1034
- #elif defined(_LIBUNWIND_TARGET_HAIKU )
1040
+ #elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN )
1035
1041
bool setInfoForSigReturn ();
1036
1042
int stepThroughSigReturn ();
1037
1043
#endif
@@ -2630,7 +2636,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
2630
2636
template <typename A, typename R>
2631
2637
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2632
2638
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
2633
- defined (_LIBUNWIND_TARGET_HAIKU )
2639
+ defined (_LIBUNWIND_CHECK_HAIKU_SIGRETURN )
2634
2640
_isSigReturn = false ;
2635
2641
#endif
2636
2642
@@ -2755,7 +2761,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2755
2761
#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2756
2762
2757
2763
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
2758
- defined (_LIBUNWIND_TARGET_HAIKU )
2764
+ defined (_LIBUNWIND_CHECK_HAIKU_SIGRETURN )
2759
2765
if (setInfoForSigReturn ())
2760
2766
return ;
2761
2767
#endif
@@ -2831,63 +2837,6 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
2831
2837
_isSignalFrame = true ;
2832
2838
return UNW_STEP_SUCCESS;
2833
2839
}
2834
-
2835
- #elif defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)
2836
- #include < commpage_defs.h>
2837
- #include < signal.h>
2838
-
2839
- extern " C" {
2840
- extern void *__gCommPageAddress;
2841
- }
2842
-
2843
- template <typename A, typename R>
2844
- bool UnwindCursor<A, R>::setInfoForSigReturn() {
2845
- #if defined(_LIBUNWIND_TARGET_X86_64)
2846
- addr_t signal_handler =
2847
- (((addr_t *)__gCommPageAddress)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] +
2848
- (addr_t )__gCommPageAddress);
2849
- addr_t signal_handler_ret = signal_handler + 45 ;
2850
- #endif
2851
- pint_t pc = static_cast <pint_t >(this ->getReg (UNW_REG_IP));
2852
- if (pc == signal_handler_ret) {
2853
- _info = {};
2854
- _info.start_ip = signal_handler;
2855
- _info.end_ip = signal_handler_ret;
2856
- _isSigReturn = true ;
2857
- return true ;
2858
- }
2859
- return false ;
2860
- }
2861
-
2862
- template <typename A, typename R>
2863
- int UnwindCursor<A, R>::stepThroughSigReturn() {
2864
- _isSignalFrame = true ;
2865
- pint_t sp = _registers.getSP ();
2866
- #if defined(_LIBUNWIND_TARGET_X86_64)
2867
- vregs *regs = (vregs *)(sp + 0x70 );
2868
-
2869
- _registers.setRegister (UNW_REG_IP, regs->rip );
2870
- _registers.setRegister (UNW_REG_SP, regs->rsp );
2871
- _registers.setRegister (UNW_X86_64_RAX, regs->rax );
2872
- _registers.setRegister (UNW_X86_64_RDX, regs->rdx );
2873
- _registers.setRegister (UNW_X86_64_RCX, regs->rcx );
2874
- _registers.setRegister (UNW_X86_64_RBX, regs->rbx );
2875
- _registers.setRegister (UNW_X86_64_RSI, regs->rsi );
2876
- _registers.setRegister (UNW_X86_64_RDI, regs->rdi );
2877
- _registers.setRegister (UNW_X86_64_RBP, regs->rbp );
2878
- _registers.setRegister (UNW_X86_64_R8, regs->r8 );
2879
- _registers.setRegister (UNW_X86_64_R9, regs->r9 );
2880
- _registers.setRegister (UNW_X86_64_R10, regs->r10 );
2881
- _registers.setRegister (UNW_X86_64_R11, regs->r11 );
2882
- _registers.setRegister (UNW_X86_64_R12, regs->r12 );
2883
- _registers.setRegister (UNW_X86_64_R13, regs->r13 );
2884
- _registers.setRegister (UNW_X86_64_R14, regs->r14 );
2885
- _registers.setRegister (UNW_X86_64_R15, regs->r15 );
2886
- // TODO: XMM
2887
- #endif
2888
-
2889
- return UNW_STEP_SUCCESS;
2890
- }
2891
2840
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2892
2841
// defined(_LIBUNWIND_TARGET_AARCH64)
2893
2842
@@ -3103,6 +3052,96 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
3103
3052
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
3104
3053
// defined(_LIBUNWIND_TARGET_S390X)
3105
3054
3055
+ #if defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
3056
+ template <typename A, typename R>
3057
+ bool UnwindCursor<A, R>::setInfoForSigReturn() {
3058
+ Dl_info dlinfo;
3059
+ const auto isSignalHandler = [&](pint_t addr) {
3060
+ if (!dladdr (reinterpret_cast <void *>(addr), &dlinfo))
3061
+ return false ;
3062
+ if (strcmp (dlinfo.dli_fname , " commpage" ))
3063
+ return false ;
3064
+ if (dlinfo.dli_sname == NULL ||
3065
+ strcmp (dlinfo.dli_sname , " commpage_signal_handler" ))
3066
+ return false ;
3067
+ return true ;
3068
+ };
3069
+
3070
+ pint_t pc = static_cast <pint_t >(this ->getReg (UNW_REG_IP));
3071
+ if (!isSignalHandler (pc))
3072
+ return false ;
3073
+
3074
+ pint_t start = reinterpret_cast <pint_t >(dlinfo.dli_saddr );
3075
+
3076
+ static size_t signalHandlerSize = 0 ;
3077
+ if (signalHandlerSize == 0 ) {
3078
+ size_t boundLow = 0 ;
3079
+ size_t boundHigh = static_cast <size_t >(-1 );
3080
+
3081
+ area_info areaInfo;
3082
+ if (get_area_info (area_for (dlinfo.dli_saddr ), &areaInfo) == B_OK)
3083
+ boundHigh = areaInfo.size ;
3084
+
3085
+ while (boundLow < boundHigh) {
3086
+ size_t boundMid = boundLow + ((boundHigh - boundLow) / 2 );
3087
+ pint_t test = start + boundMid;
3088
+ if (test >= start && isSignalHandler (test))
3089
+ boundLow = boundMid + 1 ;
3090
+ else
3091
+ boundHigh = boundMid;
3092
+ }
3093
+
3094
+ signalHandlerSize = boundHigh;
3095
+ }
3096
+
3097
+ _info = {};
3098
+ _info.start_ip = start;
3099
+ _info.end_ip = start + signalHandlerSize;
3100
+ _isSigReturn = true ;
3101
+
3102
+ return true ;
3103
+ }
3104
+
3105
+ template <typename A, typename R>
3106
+ int UnwindCursor<A, R>::stepThroughSigReturn() {
3107
+ _isSignalFrame = true ;
3108
+
3109
+ #if defined(_LIBUNWIND_TARGET_X86_64)
3110
+ // Layout of the stack before function call:
3111
+ // - signal_frame_data
3112
+ // + siginfo_t (public struct, fairly stable)
3113
+ // + ucontext_t (public struct, fairly stable)
3114
+ // - mcontext_t -> Offset 0x70, this is what we want.
3115
+ // - frame->ip (8 bytes)
3116
+ // - frame->bp (8 bytes). Not written by the kernel,
3117
+ // but the signal handler has a "push %rbp" instruction.
3118
+ pint_t bp = this ->getReg (UNW_X86_64_RBP);
3119
+ vregs *regs = (vregs *)(bp + 0x70 );
3120
+
3121
+ _registers.setRegister (UNW_REG_IP, regs->rip );
3122
+ _registers.setRegister (UNW_REG_SP, regs->rsp );
3123
+ _registers.setRegister (UNW_X86_64_RAX, regs->rax );
3124
+ _registers.setRegister (UNW_X86_64_RDX, regs->rdx );
3125
+ _registers.setRegister (UNW_X86_64_RCX, regs->rcx );
3126
+ _registers.setRegister (UNW_X86_64_RBX, regs->rbx );
3127
+ _registers.setRegister (UNW_X86_64_RSI, regs->rsi );
3128
+ _registers.setRegister (UNW_X86_64_RDI, regs->rdi );
3129
+ _registers.setRegister (UNW_X86_64_RBP, regs->rbp );
3130
+ _registers.setRegister (UNW_X86_64_R8, regs->r8 );
3131
+ _registers.setRegister (UNW_X86_64_R9, regs->r9 );
3132
+ _registers.setRegister (UNW_X86_64_R10, regs->r10 );
3133
+ _registers.setRegister (UNW_X86_64_R11, regs->r11 );
3134
+ _registers.setRegister (UNW_X86_64_R12, regs->r12 );
3135
+ _registers.setRegister (UNW_X86_64_R13, regs->r13 );
3136
+ _registers.setRegister (UNW_X86_64_R14, regs->r14 );
3137
+ _registers.setRegister (UNW_X86_64_R15, regs->r15 );
3138
+ // TODO: XMM
3139
+ #endif // defined(_LIBUNWIND_TARGET_X86_64)
3140
+
3141
+ return UNW_STEP_SUCCESS;
3142
+ }
3143
+ #endif // defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
3144
+
3106
3145
template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
3107
3146
(void )stage2;
3108
3147
// Bottom of stack is defined is when unwind info cannot be found.
@@ -3112,7 +3151,7 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
3112
3151
// Use unwinding info to modify register set as if function returned.
3113
3152
int result;
3114
3153
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
3115
- defined (_LIBUNWIND_TARGET_HAIKU )
3154
+ defined (_LIBUNWIND_CHECK_HAIKU_SIGRETURN )
3116
3155
if (_isSigReturn) {
3117
3156
result = this ->stepThroughSigReturn ();
3118
3157
} else
0 commit comments