forked from OSchip/llvm-project
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 llvm-svn: 245546
This commit is contained in:
parent
0e1d729b75
commit
99c40e673a
|
|
@ -578,7 +578,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco
|
||||||
{
|
{
|
||||||
if (BitIsSet (registers, i))
|
if (BitIsSet (registers, i))
|
||||||
{
|
{
|
||||||
context.SetRegisterPlusOffset (sp_reg, addr - sp);
|
context.SetAddress(addr);
|
||||||
data = MemARead(context, addr, 4, 0, &success);
|
data = MemARead(context, addr, 4, 0, &success);
|
||||||
if (!success)
|
if (!success)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -2214,7 +2214,7 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc
|
||||||
for (i=0; i<regs; ++i)
|
for (i=0; i<regs; ++i)
|
||||||
{
|
{
|
||||||
GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
|
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);
|
data = MemARead(context, addr, reg_byte_size, 0, &success);
|
||||||
if (!success)
|
if (!success)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -3516,7 +3516,10 @@ EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding enco
|
||||||
context.type = EmulateInstruction::eContextRegisterPlusOffset;
|
context.type = EmulateInstruction::eContextRegisterPlusOffset;
|
||||||
context.SetRegisterPlusOffset (dwarf_reg, offset);
|
context.SetRegisterPlusOffset (dwarf_reg, offset);
|
||||||
if (wback && (n == 13)) // Pop Instruction
|
if (wback && (n == 13)) // Pop Instruction
|
||||||
|
{
|
||||||
context.type = EmulateInstruction::eContextPopRegisterOffStack;
|
context.type = EmulateInstruction::eContextPopRegisterOffStack;
|
||||||
|
context.SetAddress(base_address + offset);
|
||||||
|
}
|
||||||
|
|
||||||
// R[i] = MemA [address, 4]; address = address + 4;
|
// R[i] = MemA [address, 4]; address = address + 4;
|
||||||
uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
|
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;
|
context.type = eContextPopRegisterOffStack;
|
||||||
else
|
else
|
||||||
context.type = eContextRegisterLoad;
|
context.type = eContextRegisterLoad;
|
||||||
context.SetRegisterPlusOffset (base_reg, address - Rn);
|
context.SetAddress(address);
|
||||||
|
|
||||||
const uint32_t addr_byte_size = GetAddressByteSize();
|
const uint32_t addr_byte_size = GetAddressByteSize();
|
||||||
uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
|
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;
|
context.type = eContextPopRegisterOffStack;
|
||||||
else
|
else
|
||||||
context.type = eContextRegisterLoad;
|
context.type = eContextRegisterLoad;
|
||||||
context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
|
context.SetAddress(address);
|
||||||
|
|
||||||
// R[t] = MemA[address,4];
|
// R[t] = MemA[address,4];
|
||||||
const uint32_t addr_byte_size = GetAddressByteSize();
|
const uint32_t addr_byte_size = GetAddressByteSize();
|
||||||
|
|
|
||||||
|
|
@ -768,8 +768,6 @@ EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode)
|
||||||
Context context_t;
|
Context context_t;
|
||||||
Context context_t2;
|
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];
|
uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
|
||||||
Error error;
|
Error error;
|
||||||
|
|
||||||
|
|
@ -787,6 +785,8 @@ EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode)
|
||||||
context_t.type = eContextRegisterStore;
|
context_t.type = eContextRegisterStore;
|
||||||
context_t2.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))
|
if (!ReadRegister (®_info_Rt, data_Rt))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -820,6 +820,8 @@ EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode)
|
||||||
context_t.type = eContextRegisterLoad;
|
context_t.type = eContextRegisterLoad;
|
||||||
context_t2.type = eContextRegisterLoad;
|
context_t2.type = eContextRegisterLoad;
|
||||||
}
|
}
|
||||||
|
context_t.SetAddress(address);
|
||||||
|
context_t2.SetAddress(address + size);
|
||||||
|
|
||||||
if (rt_unknown)
|
if (rt_unknown)
|
||||||
memset (buffer, 'U', reg_info_Rt.byte_size);
|
memset (buffer, 'U', reg_info_Rt.byte_size);
|
||||||
|
|
@ -950,8 +952,6 @@ EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Context context;
|
Context context;
|
||||||
context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset);
|
|
||||||
|
|
||||||
switch (memop)
|
switch (memop)
|
||||||
{
|
{
|
||||||
case MemOp_STORE:
|
case MemOp_STORE:
|
||||||
|
|
@ -959,6 +959,7 @@ EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode)
|
||||||
context.type = eContextPushRegisterOnStack;
|
context.type = eContextPushRegisterOnStack;
|
||||||
else
|
else
|
||||||
context.type = eContextRegisterStore;
|
context.type = eContextRegisterStore;
|
||||||
|
context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset);
|
||||||
|
|
||||||
if (!ReadRegister (®_info_Rt, data_Rt))
|
if (!ReadRegister (®_info_Rt, data_Rt))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -975,6 +976,7 @@ EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode)
|
||||||
context.type = eContextPopRegisterOffStack;
|
context.type = eContextPopRegisterOffStack;
|
||||||
else
|
else
|
||||||
context.type = eContextRegisterLoad;
|
context.type = eContextRegisterLoad;
|
||||||
|
context.SetAddress(address);
|
||||||
|
|
||||||
if (!ReadMemory (context, address, buffer, reg_info_Rt.byte_size))
|
if (!ReadMemory (context, address, buffer, reg_info_Rt.byte_size))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -579,11 +579,20 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
|
||||||
const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
|
const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
|
||||||
const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
|
const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
|
||||||
if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
|
if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
|
||||||
|
{
|
||||||
|
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->SetRegisterLocationToSame (reg_num, /*must_replace*/ false);
|
||||||
m_curr_row_modified = true;
|
m_curr_row_modified = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
assert (!"unhandled case, add code to handle this!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue