From 73bcca5b3dd8fcd1bb62a256473d559488d6729f Mon Sep 17 00:00:00 2001 From: Tamas Berghammer Date: Fri, 19 Feb 2016 10:59:25 +0000 Subject: Stack unwinding emulation: handle adjustment of FP This change is improving the instruction emulation based unwinding to handle when the frame pointer is adjusted (increment/decrement) after it has been initialized. The situation can occur in the prologue of some function where FP is adjusted before it is copied back to SP. Example code (thumb, generated by gcc 4.8): < +0>: push {r4, r7, lr} < +2>: sub sp, #0x14 < +4>: add r7, sp, #0x0 ... <+50>: adds r7, #0x14 ; The CL fixes the handling of this instruction <+52>: mov sp, r7 ; Previously unwinding from here was broken <+54>: pop {r4, r7, pc} Differential revision: http://reviews.llvm.org/D17295 llvm-svn: 261318 --- .../InstEmulation/UnwindAssemblyInstEmulation.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'lldb/source/Plugins') diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 28e411e62c2..e168add266b 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -554,7 +554,6 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, case EmulateInstruction::eContextTableBranchReadMemory: case EmulateInstruction::eContextWriteRegisterRandomBits: case EmulateInstruction::eContextWriteMemoryRandomBits: - case EmulateInstruction::eContextArithmetic: case EmulateInstruction::eContextAdvancePC: case EmulateInstruction::eContextReturnFromException: case EmulateInstruction::eContextPushRegisterOnStack: @@ -573,6 +572,22 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, // } break; + case EmulateInstruction::eContextArithmetic: + { + // If we adjusted the current frame pointer by a constant then adjust the CFA offset + // with the same amount. + lldb::RegisterKind kind = m_unwind_plan_ptr->GetRegisterKind(); + if (m_fp_is_cfa && reg_info->kinds[kind] == m_cfa_reg_info.kinds[kind] && + context.info_type == EmulateInstruction::eInfoTypeRegisterPlusOffset && + context.info.RegisterPlusOffset.reg.kinds[kind] == m_cfa_reg_info.kinds[kind]) + { + const int64_t offset = context.info.RegisterPlusOffset.signed_offset; + m_curr_row->GetCFAValue().IncOffset(-1 * offset); + m_curr_row_modified = true; + } + } + break; + case EmulateInstruction::eContextAbsoluteBranchRegister: case EmulateInstruction::eContextRelativeBranchImmediate: { -- cgit v1.2.3