[libunwind] 0c1a135 - [libunwind][RISCV] Track PC separately from RA

Amanieu d'Antras via cfe-commits cfe-commits at lists.llvm.org
Sat Jun 13 00:15:48 PDT 2020


Author: Amanieu d'Antras
Date: 2020-06-13T08:15:40+01:00
New Revision: 0c1a135adae530b88f68c9425fb85bd8fb9152ca

URL: https://github.com/llvm/llvm-project/commit/0c1a135adae530b88f68c9425fb85bd8fb9152ca
DIFF: https://github.com/llvm/llvm-project/commit/0c1a135adae530b88f68c9425fb85bd8fb9152ca.diff

LOG: [libunwind][RISCV] Track PC separately from RA

Summary:
This allows unwinding to work across signal handler frames where the IP of the previous frame is not the same as the current value of the RA register. This is particularly useful for acquiring backtraces from signal handlers.

I kept the size of the context structure the same to avoid ABI breakage; the PC is stored in the previously unused slot for register 0.

Reviewers: #libunwind, mhorne, lenary, luismarques, arichardson, compnerd

Reviewed By: #libunwind, mhorne, lenary, compnerd

Subscribers: kamleshbhalui, jrtc27, bsdjhb, arichardson, compnerd, simoncook, kito-cheng, shiva0217, rogfer01, rkruppe, psnobl, benna, Jim, s.egerton, sameer.abuasal, evandro, llvm-commits, libcxx-commits

Tags: #libunwind, #llvm

Differential Revision: https://reviews.llvm.org/D78931

Added: 
    

Modified: 
    libunwind/src/Registers.hpp
    libunwind/src/UnwindRegistersRestore.S
    libunwind/src/UnwindRegistersSave.S

Removed: 
    


################################################################################
diff  --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp
index 26a0fa8f338e..c76b05bf314e 100644
--- a/libunwind/src/Registers.hpp
+++ b/libunwind/src/Registers.hpp
@@ -3734,11 +3734,11 @@ class _LIBUNWIND_HIDDEN Registers_riscv {
 
   uint64_t  getSP() const         { return _registers[2]; }
   void      setSP(uint64_t value) { _registers[2] = value; }
-  uint64_t  getIP() const         { return _registers[1]; }
-  void      setIP(uint64_t value) { _registers[1] = value; }
+  uint64_t  getIP() const         { return _registers[0]; }
+  void      setIP(uint64_t value) { _registers[0] = value; }
 
 private:
-
+  // _registers[0] holds the pc
   uint64_t _registers[32];
   double   _floats[32];
 };
@@ -3773,7 +3773,7 @@ inline bool Registers_riscv::validRegister(int regNum) const {
 
 inline uint64_t Registers_riscv::getRegister(int regNum) const {
   if (regNum == UNW_REG_IP)
-    return _registers[1];
+    return _registers[0];
   if (regNum == UNW_REG_SP)
     return _registers[2];
   if (regNum == UNW_RISCV_X0)
@@ -3785,7 +3785,7 @@ inline uint64_t Registers_riscv::getRegister(int regNum) const {
 
 inline void Registers_riscv::setRegister(int regNum, uint64_t value) {
   if (regNum == UNW_REG_IP)
-    _registers[1] = value;
+    _registers[0] = value;
   else if (regNum == UNW_REG_SP)
     _registers[2] = value;
   else if (regNum == UNW_RISCV_X0)

diff  --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S
index 9ad521591918..5d5443215286 100644
--- a/libunwind/src/UnwindRegistersRestore.S
+++ b/libunwind/src/UnwindRegistersRestore.S
@@ -1117,7 +1117,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv)
 #endif
 
   // x0 is zero
-  ld    x1, (8 * 1)(a0)
+  ld    x1, (8 * 0)(a0) // restore pc into ra
   ld    x2, (8 * 2)(a0)
   ld    x3, (8 * 3)(a0)
   ld    x4, (8 * 4)(a0)

diff  --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S
index 9e52c4c9b772..51bb9b0688fd 100644
--- a/libunwind/src/UnwindRegistersSave.S
+++ b/libunwind/src/UnwindRegistersSave.S
@@ -1030,7 +1030,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
 #  thread_state pointer is in a0
 #
 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
-  // x0 is zero
+  sd    x1, (8 * 0)(a0) // store ra as pc
   sd    x1, (8 * 1)(a0)
   sd    x2, (8 * 2)(a0)
   sd    x3, (8 * 3)(a0)


        


More information about the cfe-commits mailing list