Add support for the LEAVE x86 instruction to AssemblyParse_x86.

llvm-svn: 257209
This commit is contained in:
Jason Molenda 2016-01-08 21:13:26 +00:00
parent 256c457170
commit dae3c57189
1 changed files with 38 additions and 7 deletions

View File

@ -155,6 +155,7 @@ private:
bool mov_reg_to_local_stack_frame_p (int& regno, int& fp_offset);
bool ret_pattern_p ();
bool pop_rbp_pattern_p ();
bool leave_pattern_p ();
bool call_next_insn_pattern_p();
uint32_t extract_4 (uint8_t *b);
bool machine_regno_to_lldb_regno (int machine_regno, uint32_t& lldb_regno);
@ -492,6 +493,14 @@ AssemblyParse_x86::pop_rbp_pattern_p ()
return (*p == 0x5d);
}
// leave [0xc9]
bool
AssemblyParse_x86::leave_pattern_p ()
{
uint8_t *p = m_cur_insn_bytes;
return (*p == 0xc9);
}
// call $0 [0xe8 0x0 0x0 0x0 0x0]
bool
AssemblyParse_x86::call_next_insn_pattern_p ()
@ -780,8 +789,7 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
if (machine_regno == (int)m_machine_fp_regnum)
{
row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum,
row->GetCFAValue().GetOffset());
row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
}
in_epilogue = true;
@ -792,12 +800,35 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
// we need to add a new row of instructions.
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum)
{
row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum,
current_sp_bytes_offset_from_cfa);
row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
row_updated = true;
}
}
// The LEAVE instruction moves the value from rbp into rsp and pops
// a value off the stack into rbp (restoring the caller's rbp value).
// It is the opposite of ENTER, or 'push rbp, mov rsp rbp'.
else if (leave_pattern_p ())
{
// We're going to copy the value in rbp into rsp, so re-set the sp offset
// based on the CFAValue. Also, adjust it to recognize that we're popping
// the saved rbp value off the stack.
current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset();
current_sp_bytes_offset_from_cfa -= m_wordsize;
row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
// rbp is restored to the caller's value
saved_registers[m_machine_fp_regnum] = false;
row->RemoveRegisterInfo (m_lldb_fp_regnum);
// cfa is now in terms of rsp again.
row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
in_epilogue = true;
row_updated = true;
}
else if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset)
&& nonvolatile_reg_p (machine_regno)
&& machine_regno_to_lldb_regno (machine_regno, lldb_regno)
@ -1137,15 +1168,15 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
// The only case we care about is epilogue:
// [0x5d] pop %rbp/%ebp
// => [0xc3] ret
if (pop_rbp_pattern_p ())
if (pop_rbp_pattern_p () || leave_pattern_p ())
{
if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes,
1, error) != static_cast<size_t>(-1)
&& ret_pattern_p ())
{
row->SetOffset (offset);
row->GetCFAValue().SetIsRegisterPlusOffset (
first_row->GetCFAValue().GetRegisterNumber(), m_wordsize);
row->GetCFAValue().SetIsRegisterPlusOffset (first_row->GetCFAValue().GetRegisterNumber(),
m_wordsize);
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
unwind_plan.InsertRow (new_row);