4141#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
4242#endif
4343
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+
4450#include " AddressSpace.hpp"
4551#include " CompactUnwinder.hpp"
4652#include " config.h"
@@ -1031,7 +1037,7 @@ class UnwindCursor : public AbstractUnwindCursor{
10311037 template <typename Registers> int stepThroughSigReturn (Registers &) {
10321038 return UNW_STEP_END;
10331039 }
1034- #elif defined(_LIBUNWIND_TARGET_HAIKU )
1040+ #elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN )
10351041 bool setInfoForSigReturn ();
10361042 int stepThroughSigReturn ();
10371043#endif
@@ -2630,7 +2636,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
26302636template <typename A, typename R>
26312637void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
26322638#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
2633- defined (_LIBUNWIND_TARGET_HAIKU )
2639+ defined (_LIBUNWIND_CHECK_HAIKU_SIGRETURN )
26342640 _isSigReturn = false ;
26352641#endif
26362642
@@ -2755,7 +2761,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
27552761#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
27562762
27572763#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
2758- defined (_LIBUNWIND_TARGET_HAIKU )
2764+ defined (_LIBUNWIND_CHECK_HAIKU_SIGRETURN )
27592765 if (setInfoForSigReturn ())
27602766 return ;
27612767#endif
@@ -2831,63 +2837,6 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
28312837 _isSignalFrame = true ;
28322838 return UNW_STEP_SUCCESS;
28332839}
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- }
28912840#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
28922841 // defined(_LIBUNWIND_TARGET_AARCH64)
28932842
@@ -3103,6 +3052,96 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
31033052#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
31043053 // defined(_LIBUNWIND_TARGET_S390X)
31053054
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+
31063145template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
31073146 (void )stage2;
31083147 // 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) {
31123151 // Use unwinding info to modify register set as if function returned.
31133152 int result;
31143153#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
3115- defined (_LIBUNWIND_TARGET_HAIKU )
3154+ defined (_LIBUNWIND_CHECK_HAIKU_SIGRETURN )
31163155 if (_isSigReturn) {
31173156 result = this ->stepThroughSigReturn ();
31183157 } else
0 commit comments