aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamas Berghammer <tberghammer@google.com>2015-08-20 09:09:01 +0000
committerTamas Berghammer <tberghammer@google.com>2015-08-20 09:09:01 +0000
commit6c727b4e70e97f64028d3301fa11f50040149ec1 (patch)
treef436ee8af336c2afb785dc4853523ab9461b3622
parent101511676406c47a58e587deafb81fbf4e2c079b (diff)
downloadlldb-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
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp11
-rw-r--r--source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp10
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp13
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 (&reg_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 (&reg_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!");
}
}
}