[libunwind] Unwind through loongarch64/Linux sigreturn frame (#123682)
Similar to D90898 (Linux AArch64), D124765 (SystemZ), and D148499 (RISCV). In this commit, I enabled two test cases, while zhuqizheng supported with the source code development. Co-Authored-By: zhuqizheng <zhuqizheng@loongson.cn> Co-authored-by: zhuqizheng <zhuqizheng@loongson.cn>
This commit is contained in:
parent
51ba9819b4
commit
12a154a94a
@ -31,8 +31,9 @@
|
||||
#endif
|
||||
|
||||
#if defined(_LIBUNWIND_TARGET_LINUX) && \
|
||||
(defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \
|
||||
defined(_LIBUNWIND_TARGET_S390X))
|
||||
(defined(_LIBUNWIND_TARGET_AARCH64) || \
|
||||
defined(_LIBUNWIND_TARGET_LOONGARCH) || \
|
||||
defined(_LIBUNWIND_TARGET_RISCV) || defined(_LIBUNWIND_TARGET_S390X))
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/syscall.h>
|
||||
@ -996,6 +997,10 @@ private:
|
||||
bool setInfoForSigReturn(Registers_arm64 &);
|
||||
int stepThroughSigReturn(Registers_arm64 &);
|
||||
#endif
|
||||
#if defined(_LIBUNWIND_TARGET_LOONGARCH)
|
||||
bool setInfoForSigReturn(Registers_loongarch &);
|
||||
int stepThroughSigReturn(Registers_loongarch &);
|
||||
#endif
|
||||
#if defined(_LIBUNWIND_TARGET_RISCV)
|
||||
bool setInfoForSigReturn(Registers_riscv &);
|
||||
int stepThroughSigReturn(Registers_riscv &);
|
||||
@ -2815,6 +2820,61 @@ int UnwindCursor<A, R>::stepThroughSigReturn() {
|
||||
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
|
||||
// defined(_LIBUNWIND_TARGET_AARCH64)
|
||||
|
||||
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
|
||||
defined(_LIBUNWIND_TARGET_LOONGARCH)
|
||||
template <typename A, typename R>
|
||||
bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_loongarch &) {
|
||||
const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
|
||||
// The PC might contain an invalid address if the unwind info is bad, so
|
||||
// directly accessing it could cause a SIGSEGV.
|
||||
if (!isReadableAddr(pc))
|
||||
return false;
|
||||
const auto *instructions = reinterpret_cast<const uint32_t *>(pc);
|
||||
// Look for the two instructions used in the sigreturn trampoline
|
||||
// __vdso_rt_sigreturn:
|
||||
//
|
||||
// 0x03822c0b li a7,0x8b
|
||||
// 0x002b0000 syscall 0
|
||||
if (instructions[0] != 0x03822c0b || instructions[1] != 0x002b0000)
|
||||
return false;
|
||||
|
||||
_info = {};
|
||||
_info.start_ip = pc;
|
||||
_info.end_ip = pc + 4;
|
||||
_isSigReturn = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
int UnwindCursor<A, R>::stepThroughSigReturn(Registers_loongarch &) {
|
||||
// In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
|
||||
// - 128-byte siginfo struct
|
||||
// - ucontext_t struct:
|
||||
// - 8-byte long (__uc_flags)
|
||||
// - 8-byte pointer (*uc_link)
|
||||
// - 24-byte uc_stack
|
||||
// - 8-byte uc_sigmask
|
||||
// - 120-byte of padding to allow sigset_t to be expanded in the future
|
||||
// - 8 bytes of padding because sigcontext has 16-byte alignment
|
||||
// - struct sigcontext uc_mcontext
|
||||
// [1]
|
||||
// https://github.com/torvalds/linux/blob/master/arch/loongarch/kernel/signal.c
|
||||
const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128;
|
||||
|
||||
const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
|
||||
_registers.setIP(_addressSpace.get64(sigctx));
|
||||
for (int i = UNW_LOONGARCH_R1; i <= UNW_LOONGARCH_R31; ++i) {
|
||||
// skip R0
|
||||
uint64_t value =
|
||||
_addressSpace.get64(sigctx + static_cast<pint_t>((i + 1) * 8));
|
||||
_registers.setRegister(i, value);
|
||||
}
|
||||
_isSignalFrame = true;
|
||||
return UNW_STEP_SUCCESS;
|
||||
}
|
||||
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
|
||||
// defined(_LIBUNWIND_TARGET_LOONGARCH)
|
||||
|
||||
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
|
||||
defined(_LIBUNWIND_TARGET_RISCV)
|
||||
template <typename A, typename R>
|
||||
|
@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Ensure that the unwinder can cope with the signal handler.
|
||||
// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+linux.*}}
|
||||
// REQUIRES: target={{(aarch64|loongarch64|riscv64|s390x|x86_64)-.+linux.*}}
|
||||
|
||||
// TODO: Figure out why this fails with Memory Sanitizer.
|
||||
// XFAIL: msan
|
||||
|
@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Ensure that leaf function can be unwund.
|
||||
// REQUIRES: target={{(aarch64|riscv64|s390x|x86_64)-.+linux.*}}
|
||||
// REQUIRES: target={{(aarch64|loongarch64|riscv64|s390x|x86_64)-.+linux.*}}
|
||||
|
||||
// TODO: Figure out why this fails with Memory Sanitizer.
|
||||
// XFAIL: msan
|
||||
|
Loading…
x
Reference in New Issue
Block a user