diff options
author | Tamas Berghammer <tberghammer@google.com> | 2015-08-20 09:09:01 +0000 |
---|---|---|
committer | Tamas Berghammer <tberghammer@google.com> | 2015-08-20 09:09:01 +0000 |
commit | 6c727b4e70e97f64028d3301fa11f50040149ec1 (patch) | |
tree | f436ee8af336c2afb785dc4853523ab9461b3622 | |
parent | 101511676406c47a58e587deafb81fbf4e2c079b (diff) | |
download | lldb-6c727b4e70e97f64028d3301fa11f50040149ec1.tar.gz |
Improve instruction emulation based stack unwinding
On ARM there is no difference petween a pop and a load instruction so
a register can be loaded multiple times during the function. Add check
to threat the load as a restore only if it do the restore from the
same location where the register was saved.
Differential revision: http://reviews.llvm.org/D11947
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@245546 91177308-0d34-0410-b5e6-96231b3b80d8
3 files changed, 24 insertions, 10 deletions
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index c8fc9f86c..638a88c95 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -578,7 +578,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco { if (BitIsSet (registers, i)) { - context.SetRegisterPlusOffset (sp_reg, addr - sp); + context.SetAddress(addr); data = MemARead(context, addr, 4, 0, &success); if (!success) return false; @@ -2214,7 +2214,7 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc for (i=0; i<regs; ++i) { GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg); - context.SetRegisterPlusOffset (sp_reg, addr - sp); + context.SetAddress(addr); data = MemARead(context, addr, reg_byte_size, 0, &success); if (!success) return false; @@ -3516,7 +3516,10 @@ EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding enco context.type = EmulateInstruction::eContextRegisterPlusOffset; context.SetRegisterPlusOffset (dwarf_reg, offset); if (wback && (n == 13)) // Pop Instruction + { context.type = EmulateInstruction::eContextPopRegisterOffStack; + context.SetAddress(base_address + offset); + } // R[i] = MemA [address, 4]; address = address + 4; uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); @@ -10307,7 +10310,7 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc context.type = eContextPopRegisterOffStack; else context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); + context.SetAddress(address); const uint32_t addr_byte_size = GetAddressByteSize(); uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); @@ -10437,7 +10440,7 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco context.type = eContextPopRegisterOffStack; else context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); + context.SetAddress(address); // R[t] = MemA[address,4]; const uint32_t addr_byte_size = GetAddressByteSize(); diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index 99ff07e13..14e084657 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -768,8 +768,6 @@ EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode) Context context_t; Context context_t2; - context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0); - context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size); uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; Error error; @@ -787,6 +785,8 @@ EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode) context_t.type = eContextRegisterStore; context_t2.type = eContextRegisterStore; } + context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0); + context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size); if (!ReadRegister (®_info_Rt, data_Rt)) return false; @@ -820,6 +820,8 @@ EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode) context_t.type = eContextRegisterLoad; context_t2.type = eContextRegisterLoad; } + context_t.SetAddress(address); + context_t2.SetAddress(address + size); if (rt_unknown) memset (buffer, 'U', reg_info_Rt.byte_size); @@ -950,8 +952,6 @@ EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode) return false; Context context; - context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset); - switch (memop) { case MemOp_STORE: @@ -959,6 +959,7 @@ EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode) context.type = eContextPushRegisterOnStack; else context.type = eContextRegisterStore; + context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset); if (!ReadRegister (®_info_Rt, data_Rt)) return false; @@ -975,6 +976,7 @@ EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode) context.type = eContextPopRegisterOffStack; else context.type = eContextRegisterLoad; + context.SetAddress(address); if (!ReadMemory (context, address, buffer, reg_info_Rt.byte_size)) return false; diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 5c016d04e..a7e98be9e 100644 --- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -580,8 +580,17 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric]; if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) { - m_curr_row->SetRegisterLocationToSame (reg_num, /*must_replace*/ false); - m_curr_row_modified = true; + if (context.info_type == EmulateInstruction::eInfoTypeAddress) + { + if (m_pushed_regs.find (reg_num) != m_pushed_regs.end () && + context.info.address == m_pushed_regs[reg_num]) + { + m_curr_row->SetRegisterLocationToSame (reg_num, /*must_replace*/ false); + m_curr_row_modified = true; + } + } + else + assert (!"unhandled case, add code to handle this!"); } } } |