Author: jmolenda Date: Tue Jan 13 01:39:03 2015 New Revision: 225773 URL: http://llvm.org/viewvc/llvm-project?rev=225773&view=rev Log: 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>
Modified: lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp Modified: lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp?rev=225773&r1=225772&r2=225773&view=diff ============================================================================== --- lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp (original) +++ lldb/trunk/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp Tue Jan 13 01:39:03 2015 @@ -818,10 +818,19 @@ AssemblyParse_x86::get_non_call_site_unw 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_f 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_f 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_f 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_f 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::AugmentUnwindPlanFro } - // 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()) { _______________________________________________ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits