diff options
author | Todd Fiala <tfiala@google.com> | 2014-02-01 00:48:34 +0000 |
---|---|---|
committer | Todd Fiala <tfiala@google.com> | 2014-02-01 00:48:34 +0000 |
commit | 31cb474e2d0dea9eb4298b6cbfe5887bbde7e3cf (patch) | |
tree | ccfb5d10950f628a68fe1dacc2f8d9cf4a6d41d1 /lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp | |
parent | c5326ca9bb107a309a886481b5e3cd1a5c3dd28e (diff) | |
download | bcm5719-llvm-31cb474e2d0dea9eb4298b6cbfe5887bbde7e3cf.tar.gz bcm5719-llvm-31cb474e2d0dea9eb4298b6cbfe5887bbde7e3cf.zip |
Fix for failure to unwind Linux stack frames with call in final position.
Fixes http://llvm.org/bugs/show_bug.cgi?id=18656.
Note this exposes a failure on Linux of
TestInferiorAssert.test_inferior_asserting_disassemble, similar to how
it fails on FreeBSD. I'll file a bug for this next. We're now getting
another frame beyond where we used to prior to this fix, so the fix is
exposing failures in previosly not-reachable frames.
Much thanks to Jason Molenda, who had much to do with helping figure
out where unwinding was breaking.
llvm-svn: 200600
Diffstat (limited to 'lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 899c8c2f20d..954bf7b724c 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -83,6 +83,37 @@ RegisterContextLLDB::RegisterContextLLDB } } +bool +RegisterContextLLDB::IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset) +{ + if (!unwind_plan_sp) + return false; + + // check if m_current_pc is valid + if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) + { + // yes - current offset can be used as is + valid_pc_offset = m_current_offset; + return true; + } + + // if m_current_offset <= 0, we've got nothing else to try + if (m_current_offset <= 0) + return false; + + // check pc - 1 to see if it's valid + Address pc_minus_one (m_current_pc); + pc_minus_one.SetOffset(m_current_pc.GetOffset() - 1); + if (unwind_plan_sp->PlanValidAtAddress(pc_minus_one)) + { + // *valid_pc_offset = m_current_offset - 1; + valid_pc_offset = m_current_pc.GetOffset() - 1; + return true; + } + + return false; +} + // Initialize a RegisterContextLLDB which is the first frame of a stack -- the zeroth frame or currently // executing frame. @@ -500,9 +531,10 @@ RegisterContextLLDB::InitializeNonZerothFrame() else { m_full_unwind_plan_sp = GetFullUnwindPlanForFrame (); - if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc)) + int valid_offset = -1; + if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset)) { - active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); + active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (valid_offset); row_register_kind = m_full_unwind_plan_sp->GetRegisterKind (); if (active_row.get() && log) { @@ -769,7 +801,8 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // Typically this is unwind info from an eh_frame section intended for exception handling; only valid at call sites unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one); - if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) + int valid_offset = -1; + if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); return unwind_plan_sp; @@ -778,7 +811,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've // struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible. unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread); - if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) + if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); return unwind_plan_sp; |