Skip to content

[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

Merged
merged 1 commit into from
Feb 8, 2025

Conversation

Ami-zhang
Copy link
Contributor

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]

@Ami-zhang Ami-zhang requested a review from a team as a code owner January 21, 2025 03:55
@llvmbot
Copy link
Member

llvmbot commented Jan 21, 2025

@llvm/pr-subscribers-libunwind

Author: None (Ami-zhang)

Changes

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]>


Full diff: https://github.com/llvm/llvm-project/pull/123682.diff

3 Files Affected:

  • (modified) libunwind/src/UnwindCursor.hpp (+60-1)
  • (modified) libunwind/test/signal_unwind.pass.cpp (+1-1)
  • (modified) libunwind/test/unwind_leaffunction.pass.cpp (+1-1)
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

Copy link
Contributor

@SixWeining SixWeining left a 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.

return UNW_STEP_SUCCESS;
}
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
// defined(_LIBUNWIND_TARGET_RISCV)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// defined(_LIBUNWIND_TARGET_RISCV)
// defined(_LIBUNWIND_TARGET_LOONGARCH)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@SixWeining SixWeining requested a review from MaskRay January 21, 2025 12:13
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]>
@Ami-zhang
Copy link
Contributor Author

Ping

Copy link
Contributor

@SixWeining SixWeining left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Ami-zhang Ami-zhang merged commit 12a154a into llvm:main Feb 8, 2025
73 of 76 checks passed
@Ami-zhang Ami-zhang deleted the libunwind branch February 8, 2025 01:48
Icohedron pushed a commit to Icohedron/llvm-project that referenced this pull request Feb 11, 2025
…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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants