diff --git a/src/DwarfInstructions.hpp b/src/DwarfInstructions.hpp
index 96744e5..8955248 100644
--- a/src/DwarfInstructions.hpp
+++ b/src/DwarfInstructions.hpp
@@ -379,16 +379,8 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc,
#endif
// Return address is address after call site instruction, so setting IP to
- // that simulates a return.
- //
- // The +-1 situation is subtle.
- // Return address points to the next instruction after the `call`
- // instruction, but logically we're "inside" the call instruction, and
- // FDEs are constructed accordingly.
- // So our FDE parsing implicitly subtracts 1 from the address.
- // But for signal return, there's no `call` instruction, and
- // subtracting 1 would be incorrect. So we add 1 here to compensate.
- newRegisters.setIP(returnAddress + cieInfo.isSignalFrame);
+ // that does simulates a return.
+ newRegisters.setIP(returnAddress);
// Simulate the step by replacing the register set with the new ones.
registers = newRegisters;
diff --git a/src/DwarfParser.hpp b/src/DwarfParser.hpp
index 488043d..7adf96a 100644
--- a/src/DwarfParser.hpp
+++ b/src/DwarfParser.hpp
@@ -452,14 +452,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace,
")\n",
static_cast(instructionsEnd));
- // see DWARF Spec, section 6.4.2 for details on unwind opcodes;
- //
- // Note that we're looking for the PrologInfo for address `codeOffset - 1`,
- // hence '<' instead of '<=" in `codeOffset < pcoffset`
- // (compare to DWARF Spec section 6.4.3 "Call Frame Instruction Usage").
- // The -1 accounts for the fact that function return address points to the
- // next instruction *after* the `call` instruction, while control is
- // logically "inside" the `call` instruction.
+ // see DWARF Spec, section 6.4.2 for details on unwind opcodes
while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
uint64_t reg;
uint64_t reg2;
diff --git a/src/UnwindCursor.hpp b/src/UnwindCursor.hpp
index 11fc03f..21c9b3b 100644
--- a/src/UnwindCursor.hpp
+++ b/src/UnwindCursor.hpp
@@ -2605,6 +2605,14 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) {
--pc;
#endif
+#if !(defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32))
+ // In case of this is frame of signal handler, the IP saved in the signal
+ // handler points to first non-executed instruction, while FDE/CIE expects IP
+ // to be after the first non-executed instruction.
+ if (_isSignalFrame)
+ ++pc;
+#endif
+
// Ask address space object to find unwind sections for this pc.
UnwindInfoSections sects;
if (_addressSpace.findUnwindSections(pc, sects)) {
@@ -2760,15 +2768,7 @@ int UnwindCursor::stepThroughSigReturn(Registers_arm64 &) {
_registers.setRegister(UNW_AARCH64_X0 + i, value);
}
_registers.setSP(_addressSpace.get64(sigctx + kOffsetSp));
-
- // The +1 story is the same as in DwarfInstructions::stepWithDwarf()
- // (search for "returnAddress + cieInfo.isSignalFrame" or "Return address points to the next instruction").
- // This is probably not the right place for this because this function is not necessarily used
- // with DWARF. Need to research whether the other unwind methods have the same +-1 situation or
- // are off by one.
- pint_t returnAddress = _addressSpace.get64(sigctx + kOffsetPc);
- _registers.setIP(returnAddress + 1);
-
+ _registers.setIP(_addressSpace.get64(sigctx + kOffsetPc));
_isSignalFrame = true;
return UNW_STEP_SUCCESS;
}