diff options
author | Jason Molenda <jmolenda@apple.com> | 2015-01-13 07:39:03 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 2015-01-13 07:39:03 +0000 |
commit | 30cab7eca247a6d9ed1398d35c613554cabb905a (patch) | |
tree | c41884ead7dcf0ee3d8f4a0986b3255137ad4c59 | |
parent | fcb91c19dc22f7637e0b2bc2d2008743eb384062 (diff) |
Enhance the eh_frame unwind instruction augmenter so that
it will do the right thing on x86 routines with a mid-function
epilogue sequence (where the unwind rules need to be reinstalled
after the epilogue has completed).
<rdar://problem/19417410>
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@225773 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp index f86c56b44..fa83c19e9 100644 --- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp +++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp @@ -818,10 +818,19 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan) row_updated = true; } - // FIXME recognize the i386 picbase setup instruction sequence, - // 0x1f16: call 0x1f1b ; main + 11 at /private/tmp/a.c:3 - // 0x1f1b: popl %eax - // and record the temporary stack movements if the CFA is not expressed in terms of ebp. + // call next instruction + // call 0 + // => pop %ebx + // This is used in i386 programs to get the PIC base address for finding global data + else if (call_next_insn_pattern_p ()) + { + current_sp_bytes_offset_from_cfa += m_wordsize; + if (row->GetCFARegister() == m_lldb_sp_regnum) + { + row->SetCFAOffset (current_sp_bytes_offset_from_cfa); + row_updated = true; + } + } if (row_updated) { @@ -884,12 +893,20 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin if (cfa_reg != m_lldb_sp_regnum || first_row->GetCFAOffset() != m_wordsize) return false; + UnwindPlan::RowSP original_last_row = unwind_plan.GetRowForFunctionOffset (-1); + Target *target = m_exe_ctx.GetTargetPtr(); m_cur_insn = func.GetBaseAddress(); uint64_t offset = 0; int row_id = 1; bool unwind_plan_updated = false; UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row)); + + // After a mid-function epilogue we will need to re-insert the original unwind rules + // so unwinds work for the remainder of the function. These aren't common with clang/gcc + // on x86 but it is possible. + bool reinstate_unwind_state = false; + while (func.ContainsFileAddress (m_cur_insn)) { int insn_len; @@ -912,6 +929,23 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin offset += insn_len; m_cur_insn.SetOffset(m_cur_insn.GetOffset() + insn_len); + if (reinstate_unwind_state) + { + // that was the last instruction of this function + if (func.ContainsFileAddress (m_cur_insn) == false) + continue; + + UnwindPlan::RowSP new_row(new UnwindPlan::Row()); + *new_row = *original_last_row; + new_row->SetOffset (offset); + unwind_plan.AppendRow (new_row); + row.reset (new UnwindPlan::Row()); + *row = *new_row; + reinstate_unwind_state = false; + unwind_plan_updated = true; + continue; + } + // If we already have one row for this instruction, we can continue. while (row_id < unwind_plan.GetRowCount() && unwind_plan.GetRowAtIndex (row_id)->GetOffset() <= offset) @@ -1016,6 +1050,11 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin unwind_plan_updated = true; continue; } + if (ret_pattern_p ()) + { + reinstate_unwind_state = true; + continue; + } } else if (cfa_reg == m_lldb_fp_regnum) { @@ -1037,6 +1076,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow (new_row); unwind_plan_updated = true; + reinstate_unwind_state = true; continue; } } @@ -1260,8 +1300,8 @@ UnwindAssembly_x86::AugmentUnwindPlanFromCallSite (AddressRange& func, Thread& t } - // It looks like the prologue is described. Now check to see if the epilogue has the same - // unwind state. + // It looks like the prologue is described. + // Is the epilogue described? If it is, no need to do any augmentation. if (first_row != last_row && first_row->GetOffset() != last_row->GetOffset()) { |