-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libunwind] Unwind through loongarch64/Linux sigreturn frame #123682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-libunwind Author: None (Ami-zhang) ChangesSimilar 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 <[email protected]> Full diff: https://github.com/llvm/llvm-project/pull/123682.diff 3 Files Affected:
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index 3831d8e071ef3a..c074497f85d3b8 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -32,7 +32,7 @@
#if defined(_LIBUNWIND_TARGET_LINUX) && \
(defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \
- defined(_LIBUNWIND_TARGET_S390X))
+ defined(_LIBUNWIND_TARGET_S390X) || defined(_LIBUNWIND_TARGET_LOONGARCH))
#include <errno.h>
#include <signal.h>
#include <sys/syscall.h>
@@ -1000,6 +1000,10 @@ class UnwindCursor : public AbstractUnwindCursor{
bool setInfoForSigReturn(Registers_riscv &);
int stepThroughSigReturn(Registers_riscv &);
#endif
+#if defined(_LIBUNWIND_TARGET_LOONGARCH)
+ bool setInfoForSigReturn(Registers_loongarch &);
+ int stepThroughSigReturn(Registers_loongarch &);
+#endif
#if defined(_LIBUNWIND_TARGET_S390X)
bool setInfoForSigReturn(Registers_s390x &);
int stepThroughSigReturn(Registers_s390x &);
@@ -2868,6 +2872,61 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_riscv &) {
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
// defined(_LIBUNWIND_TARGET_RISCV)
+#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_RISCV)
+
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
defined(_LIBUNWIND_TARGET_S390X)
template <typename A, typename R>
diff --git a/libunwind/test/signal_unwind.pass.cpp b/libunwind/test/signal_unwind.pass.cpp
index 1c1566415a4d4b..4de271ecb886bd 100644
--- a/libunwind/test/signal_unwind.pass.cpp
+++ b/libunwind/test/signal_unwind.pass.cpp
@@ -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
diff --git a/libunwind/test/unwind_leaffunction.pass.cpp b/libunwind/test/unwind_leaffunction.pass.cpp
index 98de7dc43260c2..d336c159c131b5 100644
--- a/libunwind/test/unwind_leaffunction.pass.cpp
+++ b/libunwind/test/unwind_leaffunction.pass.cpp
@@ -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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move loongarch code before riscv for an alphabetical order.
libunwind/src/UnwindCursor.hpp
Outdated
return UNW_STEP_SUCCESS; | ||
} | ||
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && | ||
// defined(_LIBUNWIND_TARGET_RISCV) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// defined(_LIBUNWIND_TARGET_RISCV) | |
// defined(_LIBUNWIND_TARGET_LOONGARCH) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
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 <[email protected]>
Ping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…3682) 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 <[email protected]> Co-authored-by: zhuqizheng <[email protected]>
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 [email protected]