summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
diff options
context:
space:
mode:
authorTodd Fiala <tfiala@google.com>2014-02-01 00:48:34 +0000
committerTodd Fiala <tfiala@google.com>2014-02-01 00:48:34 +0000
commit31cb474e2d0dea9eb4298b6cbfe5887bbde7e3cf (patch)
treeccfb5d10950f628a68fe1dacc2f8d9cf4a6d41d1 /lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
parentc5326ca9bb107a309a886481b5e3cd1a5c3dd28e (diff)
downloadbcm5719-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.cpp41
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;
OpenPOWER on IntegriCloud