@@ -230,8 +230,8 @@ void DwarfFDECache<A>::iterateCacheEntries(void (*func)(
230230}
231231#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
232232
233-
234- # define arrayoffsetof ( type, index, field ) (( size_t )(&(( type *) 0 )[index]. field))
233+ # define arrayoffsetof ( type, index, field ) \
234+ ( sizeof ( type) * (index) + offsetof( type, field))
235235
236236#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
237237template <typename A> class UnwindSectionHeader {
@@ -1010,6 +1010,9 @@ class UnwindCursor : public AbstractUnwindCursor{
10101010 template <typename Registers> int stepThroughSigReturn (Registers &) {
10111011 return UNW_STEP_END;
10121012 }
1013+ #elif defined(_LIBUNWIND_TARGET_HAIKU)
1014+ bool setInfoForSigReturn ();
1015+ int stepThroughSigReturn ();
10131016#endif
10141017
10151018#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
@@ -1313,7 +1316,8 @@ class UnwindCursor : public AbstractUnwindCursor{
13131316 unw_proc_info_t _info;
13141317 bool _unwindInfoMissing;
13151318 bool _isSignalFrame;
1316- #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
1319+ #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
1320+ defined (_LIBUNWIND_TARGET_HAIKU)
13171321 bool _isSigReturn = false;
13181322#endif
13191323};
@@ -2033,7 +2037,6 @@ typedef _Unwind_Reason_Code __xlcxx_personality_v0_t(int, _Unwind_Action,
20332037 uint64_t ,
20342038 _Unwind_Exception *,
20352039 struct _Unwind_Context *);
2036- __attribute__ ((__weak__)) __xlcxx_personality_v0_t __xlcxx_personality_v0;
20372040}
20382041
20392042static __xlcxx_personality_v0_t *xlcPersonalityV0;
@@ -2126,42 +2129,35 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R ®isters) {
21262129 // function __xlcxx_personality_v0(), which is the personality for the state
21272130 // table and is exported from libc++abi, is directly assigned as the
21282131 // handler here. When a legacy XLC++ frame is encountered, the symbol
2129- // is resolved dynamically using dlopen() to avoid hard dependency from
2130- // libunwind on libc++abi.
2132+ // is resolved dynamically using dlopen() to avoid a hard dependency of
2133+ // libunwind on libc++abi in cases such as non-C++ applications .
21312134
21322135 // Resolve the function pointer to the state table personality if it has
2133- // not already.
2136+ // not already been done .
21342137 if (xlcPersonalityV0 == NULL ) {
21352138 xlcPersonalityV0InitLock.lock ();
21362139 if (xlcPersonalityV0 == NULL ) {
2137- // If libc++abi is statically linked in, symbol __xlcxx_personality_v0
2138- // has been resolved at the link time.
2139- xlcPersonalityV0 = &__xlcxx_personality_v0;
2140+ // Resolve __xlcxx_personality_v0 using dlopen().
2141+ const char *libcxxabi = " libc++abi.a(libc++abi.so.1)" ;
2142+ void *libHandle;
2143+ // The AIX dlopen() sets errno to 0 when it is successful, which
2144+ // clobbers the value of errno from the user code. This is an AIX
2145+ // bug because according to POSIX it should not set errno to 0. To
2146+ // workaround before AIX fixes the bug, errno is saved and restored.
2147+ int saveErrno = errno;
2148+ libHandle = dlopen (libcxxabi, RTLD_MEMBER | RTLD_NOW);
2149+ if (libHandle == NULL ) {
2150+ _LIBUNWIND_TRACE_UNWINDING (" dlopen() failed with errno=%d\n " , errno);
2151+ assert (0 && " dlopen() failed" );
2152+ }
2153+ xlcPersonalityV0 = reinterpret_cast <__xlcxx_personality_v0_t *>(
2154+ dlsym (libHandle, " __xlcxx_personality_v0" ));
21402155 if (xlcPersonalityV0 == NULL ) {
2141- // libc++abi is dynamically linked. Resolve __xlcxx_personality_v0
2142- // using dlopen().
2143- const char libcxxabi[] = " libc++abi.a(libc++abi.so.1)" ;
2144- void *libHandle;
2145- // The AIX dlopen() sets errno to 0 when it is successful, which
2146- // clobbers the value of errno from the user code. This is an AIX
2147- // bug because according to POSIX it should not set errno to 0. To
2148- // workaround before AIX fixes the bug, errno is saved and restored.
2149- int saveErrno = errno;
2150- libHandle = dlopen (libcxxabi, RTLD_MEMBER | RTLD_NOW);
2151- if (libHandle == NULL ) {
2152- _LIBUNWIND_TRACE_UNWINDING (" dlopen() failed with errno=%d\n " ,
2153- errno);
2154- assert (0 && " dlopen() failed" );
2155- }
2156- xlcPersonalityV0 = reinterpret_cast <__xlcxx_personality_v0_t *>(
2157- dlsym (libHandle, " __xlcxx_personality_v0" ));
2158- if (xlcPersonalityV0 == NULL ) {
2159- _LIBUNWIND_TRACE_UNWINDING (" dlsym() failed with errno=%d\n " , errno);
2160- assert (0 && " dlsym() failed" );
2161- }
2156+ _LIBUNWIND_TRACE_UNWINDING (" dlsym() failed with errno=%d\n " , errno);
21622157 dlclose (libHandle);
2163- errno = saveErrno ;
2158+ assert ( 0 && " dlsym() failed " ) ;
21642159 }
2160+ errno = saveErrno;
21652161 }
21662162 xlcPersonalityV0InitLock.unlock ();
21672163 }
@@ -2557,7 +2553,8 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
25572553
25582554template <typename A, typename R>
25592555void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2560- #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2556+ #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
2557+ defined (_LIBUNWIND_TARGET_HAIKU)
25612558 _isSigReturn = false ;
25622559#endif
25632560
@@ -2681,7 +2678,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
26812678 }
26822679#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
26832680
2684- #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2681+ #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
2682+ defined (_LIBUNWIND_TARGET_HAIKU)
26852683 if (setInfoForSigReturn ())
26862684 return ;
26872685#endif
@@ -2757,6 +2755,63 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
27572755 _isSignalFrame = true ;
27582756 return UNW_STEP_SUCCESS;
27592757}
2758+
2759+ #elif defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)
2760+ #include < commpage_defs.h>
2761+ #include < signal.h>
2762+
2763+ extern " C" {
2764+ extern void *__gCommPageAddress;
2765+ }
2766+
2767+ template <typename A, typename R>
2768+ bool UnwindCursor<A, R>::setInfoForSigReturn() {
2769+ #if defined(_LIBUNWIND_TARGET_X86_64)
2770+ addr_t signal_handler =
2771+ (((addr_t *)__gCommPageAddress)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] +
2772+ (addr_t )__gCommPageAddress);
2773+ addr_t signal_handler_ret = signal_handler + 45 ;
2774+ #endif
2775+ pint_t pc = static_cast <pint_t >(this ->getReg (UNW_REG_IP));
2776+ if (pc == signal_handler_ret) {
2777+ _info = {};
2778+ _info.start_ip = signal_handler;
2779+ _info.end_ip = signal_handler_ret;
2780+ _isSigReturn = true ;
2781+ return true ;
2782+ }
2783+ return false ;
2784+ }
2785+
2786+ template <typename A, typename R>
2787+ int UnwindCursor<A, R>::stepThroughSigReturn() {
2788+ _isSignalFrame = true ;
2789+ pint_t sp = _registers.getSP ();
2790+ #if defined(_LIBUNWIND_TARGET_X86_64)
2791+ vregs *regs = (vregs *)(sp + 0x70 );
2792+
2793+ _registers.setRegister (UNW_REG_IP, regs->rip );
2794+ _registers.setRegister (UNW_REG_SP, regs->rsp );
2795+ _registers.setRegister (UNW_X86_64_RAX, regs->rax );
2796+ _registers.setRegister (UNW_X86_64_RDX, regs->rdx );
2797+ _registers.setRegister (UNW_X86_64_RCX, regs->rcx );
2798+ _registers.setRegister (UNW_X86_64_RBX, regs->rbx );
2799+ _registers.setRegister (UNW_X86_64_RSI, regs->rsi );
2800+ _registers.setRegister (UNW_X86_64_RDI, regs->rdi );
2801+ _registers.setRegister (UNW_X86_64_RBP, regs->rbp );
2802+ _registers.setRegister (UNW_X86_64_R8, regs->r8 );
2803+ _registers.setRegister (UNW_X86_64_R9, regs->r9 );
2804+ _registers.setRegister (UNW_X86_64_R10, regs->r10 );
2805+ _registers.setRegister (UNW_X86_64_R11, regs->r11 );
2806+ _registers.setRegister (UNW_X86_64_R12, regs->r12 );
2807+ _registers.setRegister (UNW_X86_64_R13, regs->r13 );
2808+ _registers.setRegister (UNW_X86_64_R14, regs->r14 );
2809+ _registers.setRegister (UNW_X86_64_R15, regs->r15 );
2810+ // TODO: XMM
2811+ #endif
2812+
2813+ return UNW_STEP_SUCCESS;
2814+ }
27602815#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
27612816 // defined(_LIBUNWIND_TARGET_AARCH64)
27622817
@@ -2925,7 +2980,8 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
29252980
29262981 // Use unwinding info to modify register set as if function returned.
29272982 int result;
2928- #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2983+ #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
2984+ defined (_LIBUNWIND_TARGET_HAIKU)
29292985 if (_isSigReturn) {
29302986 result = this ->stepThroughSigReturn ();
29312987 } else
0 commit comments