Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 62 additions & 2 deletions libunwind/src/UnwindCursor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -996,6 +997,10 @@ class UnwindCursor : public AbstractUnwindCursor{
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 &);
Expand Down Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion libunwind/test/signal_unwind.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion libunwind/test/unwind_leaffunction.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading