[PATCH] D106626: [libunwind] Allow restoring SP while unwinding.

Marco Vanotti via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 22 18:09:09 PDT 2021


charco created this revision.
Herald added a project: libunwind.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libunwind.
charco requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

This commit modified 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 such situation in where that is false, is for example if you have
switched stacks and are in an interrupt frame. 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 stack 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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D106626

Files:
  libunwind/src/DwarfInstructions.hpp


Index: libunwind/src/DwarfInstructions.hpp
===================================================================
--- libunwind/src/DwarfInstructions.hpp
+++ libunwind/src/DwarfInstructions.hpp
@@ -167,6 +167,16 @@
 
        // restore registers that DWARF says were saved
       R newRegisters = registers;
+
+      // Typically, the CFA is the stack pointer at the call site in
+      // the previous frame. However, there are scenarios in which this is not
+      // true. For example, if we switched to a new stack. In that case, the
+      // value of the previous SP might be indicated by a CFI directive.
+      //
+      // We set the SP here to the CFA, allowing for it to be overridden
+      // by a CFI directive later on.
+      newRegisters.setSP(cfa);
+
       pint_t returnAddress = 0;
       const int lastReg = R::lastDwarfRegNum();
       assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&
@@ -200,10 +210,6 @@
         }
       }
 
-      // By definition, the CFA is the stack pointer at the call site, so
-      // restoring SP means setting it to CFA.
-      newRegisters.setSP(cfa);
-
       isSignalFrame = cieInfo.isSignalFrame;
 
 #if defined(_LIBUNWIND_TARGET_AARCH64)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D106626.361054.patch
Type: text/x-patch
Size: 1216 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210723/d9748f26/attachment.bin>


More information about the llvm-commits mailing list