diff options
author | Tamas Berghammer <tberghammer@google.com> | 2015-03-25 10:46:45 +0000 |
---|---|---|
committer | Tamas Berghammer <tberghammer@google.com> | 2015-03-25 10:46:45 +0000 |
commit | 86e7018e79cbab56f3e9861c6d2aa2aa7bb41b23 (patch) | |
tree | 2e90b95088defbfa72ba4e7bf2c69c8913f03f74 | |
parent | 6373cee3b6599e585ff77c5f5e8827ac6427ef49 (diff) | |
download | bcm5719-llvm-86e7018e79cbab56f3e9861c6d2aa2aa7bb41b23.tar.gz bcm5719-llvm-86e7018e79cbab56f3e9861c6d2aa2aa7bb41b23.zip |
Add support for 'leal' instruction to UnwindAssembly-x86
Gcc for android use the leal instruction to substract from the stack
pointer in the prologue of a function call. This patch add basic support
for evaluating this instruction to support stack unwinding on
android-x86.
Differential revision: http://reviews.llvm.org/D8583
llvm-svn: 233178
-rw-r--r-- | lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp index 91f60069996..7e4c696a36d 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp +++ b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp @@ -148,6 +148,7 @@ private: bool mov_rsp_rbp_pattern_p (); bool sub_rsp_pattern_p (int& amount); bool add_rsp_pattern_p (int& amount); + bool lea_rsp_pattern_p (int& amount); bool push_reg_p (int& regno); bool pop_reg_p (int& regno); bool push_imm_pattern_p (); @@ -410,6 +411,36 @@ AssemblyParse_x86::add_rsp_pattern_p (int& amount) return false; } +// lea esp, [esp - 0x28] +// lea esp, [esp + 0x28] +bool +AssemblyParse_x86::lea_rsp_pattern_p (int& amount) +{ + uint8_t *p = m_cur_insn_bytes; + if (m_wordsize == 8 && *p == 0x48) + p++; + + // Check opcode + if (*p != 0x8d) + return false; + + // 8 bit displacement + if (*(p + 1) == 0x64 && (*(p + 2) & 0x3f) == 0x24) + { + amount = (int8_t) *(p + 3); + return true; + } + + // 32 bit displacement + if (*(p + 1) == 0xa4 && (*(p + 2) & 0x3f) == 0x24) + { + amount = (int32_t) extract_4 (p + 3); + return true; + } + + return false; +} + // pushq %rbx // pushl %ebx bool @@ -808,6 +839,18 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan) in_epilogue = true; } + else if (lea_rsp_pattern_p (stack_offset)) + { + current_sp_bytes_offset_from_cfa -= stack_offset; + if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) + { + row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa); + row_updated = true; + } + if (stack_offset > 0) + in_epilogue = true; + } + else if (ret_pattern_p () && prologue_completed_row.get()) { // Reinstate the saved prologue setup for any instructions @@ -1068,6 +1111,19 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin unwind_plan_updated = true; continue; } + + // lea %rsp, [%rsp + $offset] + if (lea_rsp_pattern_p (amount)) + { + row->SetOffset (offset); + row->GetCFAValue().IncOffset (-amount); + + UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); + unwind_plan.InsertRow (new_row); + unwind_plan_updated = true; + continue; + } + if (ret_pattern_p ()) { reinstate_unwind_state = true; @@ -1234,7 +1290,8 @@ AssemblyParse_x86::find_first_non_prologue_insn (Address &address) } if (push_rbp_pattern_p () || mov_rsp_rbp_pattern_p () || sub_rsp_pattern_p (offset) - || push_reg_p (regno) || mov_reg_to_local_stack_frame_p (regno, offset)) + || push_reg_p (regno) || mov_reg_to_local_stack_frame_p (regno, offset) + || (lea_rsp_pattern_p (offset) && offset < 0)) { m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len); continue; |