Skip to content

Commit 6cf1345

Browse files
lemulemaste
authored andcommitted
[libunwind] Unwind through aarch64/FreeBSD sigreturn frame
Similar to D90898 (Linux Aarch64). Differential Revision: https://reviews.llvm.org/D155066
1 parent 19ca79e commit 6cf1345

File tree

2 files changed

+84
-6
lines changed

2 files changed

+84
-6
lines changed

libunwind/include/__libunwind_config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
# if defined(__HAIKU__)
4040
# define _LIBUNWIND_TARGET_HAIKU 1
4141
# endif
42+
#if defined(__FreeBSD__)
43+
#define _LIBUNWIND_TARGET_FREEBSD 1
44+
#endif
4245
# if defined(__i386__)
4346
# define _LIBUNWIND_TARGET_I386
4447
# define _LIBUNWIND_CONTEXT_SIZE 8
@@ -73,6 +76,8 @@
7376
# define _LIBUNWIND_CONTEXT_SIZE 66
7477
# if defined(__SEH__)
7578
# define _LIBUNWIND_CURSOR_SIZE 164
79+
#elif defined(_LIBUNWIND_TARGET_FREEBSD)
80+
#define _LIBUNWIND_CURSOR_SIZE 80
7681
# else
7782
# define _LIBUNWIND_CURSOR_SIZE 78
7883
# endif

libunwind/src/UnwindCursor.hpp

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@
3939
#include <sys/uio.h>
4040
#include <unistd.h>
4141
#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
42+
#define _LIBUNWIND_CHECK_SIGRETURN 1
43+
#endif
44+
45+
#if defined(_LIBUNWIND_TARGET_FREEBSD) && defined(_LIBUNWIND_TARGET_AARCH64)
46+
#include <machine/frame.h>
47+
#include <sys/sysctl.h>
48+
#include <sys/ucontext.h>
49+
#include <sys/user.h>
50+
#include <unistd.h>
51+
#define _LIBUNWIND_CHECK_FREEBSD_SIGRETURN 1
52+
#define _LIBUNWIND_CHECK_SIGRETURN 1
4253
#endif
4354

4455
#include "AddressSpace.hpp"
@@ -983,7 +994,7 @@ class UnwindCursor : public AbstractUnwindCursor{
983994
}
984995
#endif
985996

986-
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
997+
#if defined(_LIBUNWIND_CHECK_SIGRETURN)
987998
bool setInfoForSigReturn() {
988999
R dummy;
9891000
return setInfoForSigReturn(dummy);
@@ -1011,7 +1022,7 @@ class UnwindCursor : public AbstractUnwindCursor{
10111022
template <typename Registers> int stepThroughSigReturn(Registers &) {
10121023
return UNW_STEP_END;
10131024
}
1014-
#endif
1025+
#endif // defined(_LIBUNWIND_CHECK_SIGRETURN)
10151026

10161027
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
10171028
bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo,
@@ -1314,9 +1325,14 @@ class UnwindCursor : public AbstractUnwindCursor{
13141325
unw_proc_info_t _info;
13151326
bool _unwindInfoMissing;
13161327
bool _isSignalFrame;
1317-
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
1328+
#if defined(_LIBUNWIND_CHECK_SIGRETURN)
13181329
bool _isSigReturn = false;
1330+
#if defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN)
1331+
bool _isSigTrampDetermined = false;
1332+
pint_t _sigTrampStart;
1333+
pint_t _sigTrampEnd;
13191334
#endif
1335+
#endif // defined(_LIBUNWIND_CHECK_SIGRETURN)
13201336
};
13211337

13221338

@@ -2558,7 +2574,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
25582574

25592575
template <typename A, typename R>
25602576
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2561-
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2577+
#if defined(_LIBUNWIND_CHECK_SIGRETURN)
25622578
_isSigReturn = false;
25632579
#endif
25642580

@@ -2673,7 +2689,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
26732689
}
26742690
#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
26752691

2676-
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2692+
#if defined(_LIBUNWIND_CHECK_SIGRETURN)
26772693
if (setInfoForSigReturn())
26782694
return;
26792695
#endif
@@ -2909,6 +2925,63 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
29092925
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
29102926
// defined(_LIBUNWIND_TARGET_S390X)
29112927

2928+
#if defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN) && \
2929+
defined(_LIBUNWIND_TARGET_AARCH64)
2930+
template <typename A, typename R>
2931+
bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
2932+
// Look for the sigreturn trampoline.
2933+
//
2934+
// https://cgit.freebsd.org/src/tree/sys/arm64/arm64/sigtramp.S
2935+
const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
2936+
2937+
if (_isSigTrampDetermined == false) {
2938+
struct kinfo_sigtramp kst = {0};
2939+
size_t len = sizeof(kst);
2940+
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP, getpid()};
2941+
if (sysctl(mib, 4, &kst, &len, NULL, 0) == 0) {
2942+
_isSigTrampDetermined = true;
2943+
_sigTrampStart = reinterpret_cast<pint_t>(kst.ksigtramp_start);
2944+
_sigTrampEnd = reinterpret_cast<pint_t>(kst.ksigtramp_end);
2945+
}
2946+
}
2947+
2948+
if (_isSigTrampDetermined == false ||
2949+
(pc < _sigTrampStart || pc >= _sigTrampEnd))
2950+
return false;
2951+
2952+
_info = {};
2953+
_info.start_ip = _sigTrampStart;
2954+
_info.end_ip = _sigTrampEnd;
2955+
_isSigReturn = true;
2956+
return true;
2957+
}
2958+
2959+
template <typename A, typename R>
2960+
int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
2961+
// In the signal trampoline frame, sp points to a sigframe
2962+
const pint_t kOffsetSpToSigcontext =
2963+
offsetof(struct sigframe, sf_uc) + offsetof(ucontext_t, uc_mcontext);
2964+
2965+
// Offsets from mcontext_t to each register.
2966+
const pint_t kOffsetGprs = offsetof(struct gpregs, gp_x[0]);
2967+
const pint_t kOffsetSp = offsetof(struct gpregs, gp_sp);
2968+
const pint_t kOffsetPc = offsetof(struct gpregs, gp_lr);
2969+
2970+
pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
2971+
2972+
for (int i = 0; i <= 29; ++i) {
2973+
uint64_t value =
2974+
_addressSpace.get64(sigctx + kOffsetGprs + static_cast<pint_t>(i * 8));
2975+
_registers.setRegister(UNW_AARCH64_X0 + i, value);
2976+
}
2977+
_registers.setSP(_addressSpace.get64(sigctx + kOffsetSp));
2978+
_registers.setIP(_addressSpace.get64(sigctx + kOffsetPc));
2979+
_isSignalFrame = true;
2980+
return UNW_STEP_SUCCESS;
2981+
}
2982+
#endif // defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN) &&
2983+
// defined(_LIBUNWIND_TARGET_AARCH64)
2984+
29122985
template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
29132986
(void)stage2;
29142987
// Bottom of stack is defined is when unwind info cannot be found.
@@ -2917,7 +2990,7 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
29172990

29182991
// Use unwinding info to modify register set as if function returned.
29192992
int result;
2920-
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2993+
#if defined(_LIBUNWIND_CHECK_SIGRETURN)
29212994
if (_isSigReturn) {
29222995
result = this->stepThroughSigReturn();
29232996
} else

0 commit comments

Comments
 (0)