Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit a085c23

Browse files
committed
[libunwind] Allow restoring SP while unwinding.
This commit modifies stepWithDwarf allowing for CFI directives to specify the value of the stack pointer. Previously, the SP would be unconditionally set to the CFA, because it (wrongly) stated that the CFA is the stack pointer at the call site of a function, but that is not always true. One situation in which that is false, is for example if you have switched stacks. In that case if you set the CFA to the SP before switching the stack, the CFA would be far away from where the current call frame is located. The CFA always points to the current call frame, and that call frame could have a CFI directive that specifies how to restore the stack pointer. If not, it is OK to fallback and set the SP = CFA. This change sets SP = CFA before restoring the registers during unwinding, allowing the stack frame to be restored with a value different than the CFA. Reviewed By: #libunwind, phosek Differential Revision: https://reviews.llvm.org/D106626
1 parent aee8457 commit a085c23

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

libunwind/src/DwarfInstructions.hpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,16 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
167167

168168
// restore registers that DWARF says were saved
169169
R newRegisters = registers;
170+
171+
// Typically, the CFA is the stack pointer at the call site in
172+
// the previous frame. However, there are scenarios in which this is not
173+
// true. For example, if we switched to a new stack. In that case, the
174+
// value of the previous SP might be indicated by a CFI directive.
175+
//
176+
// We set the SP here to the CFA, allowing for it to be overridden
177+
// by a CFI directive later on.
178+
newRegisters.setSP(cfa);
179+
170180
pint_t returnAddress = 0;
171181
const int lastReg = R::lastDwarfRegNum();
172182
assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&
@@ -200,10 +210,6 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
200210
}
201211
}
202212

203-
// By definition, the CFA is the stack pointer at the call site, so
204-
// restoring SP means setting it to CFA.
205-
newRegisters.setSP(cfa);
206-
207213
isSignalFrame = cieInfo.isSignalFrame;
208214

209215
#if defined(_LIBUNWIND_TARGET_AARCH64)

0 commit comments

Comments
 (0)