[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