Author: jmolenda
Date: Fri Nov 21 19:52:03 2014
New Revision: 222601
URL: http://llvm.org/viewvc/llvm-project?rev=222601&view=rev
Log:
When a RegisterContext produces an invalid CFA address, change
UnwindLLDB::AddOneMoreFrame to try the fallback unwind plan on
that same stack frame before it tries the fallback unwind plan
on the "next" or callee frame.
In RegisterContextLLDB::TryFallbackUnwindPlan, when we're
trying the fallback unwind plan to see if it is valid, make
sure we change all of the object ivars that might be used in
the process of fetching the CFA & caller's saved pc value
and restore those if we decide not to use the fallback
unwindplan.
<rdar://problem/19035079>
Modified:
lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp
Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp?rev=222601&r1=222600&r2=222601&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Fri Nov
21 19:52:03 2014
@@ -1528,7 +1528,17 @@ RegisterContextLLDB::TryFallbackUnwindPl
if (m_fallback_unwind_plan_sp.get() == nullptr)
return true;
+
+ // Switch the full UnwindPlan to be the fallback UnwindPlan. If we decide
this isn't
+ // working, we need to restore.
+ // We'll also need to save & restore the value of the m_cfa ivar. Save is
down below a bit in 'old_cfa'.
UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
+ addr_t old_cfa = m_cfa;
+
+ m_registers.clear();
+
+ m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
+
UnwindPlan::RowSP active_row =
m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
@@ -1539,11 +1549,12 @@ RegisterContextLLDB::TryFallbackUnwindPl
{
UnwindLogMsg ("failed to get cfa with fallback unwindplan");
m_fallback_unwind_plan_sp.reset();
+ m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+ m_cfa = old_cfa;
return false;
}
+ m_cfa = new_cfa;
- m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
- m_registers.clear();
if (SavedLocationForRegister (pc_regnum.GetAsKind (eRegisterKindLLDB),
regloc) == UnwindLLDB::RegisterSearchResult::eRegisterFound)
{
const RegisterInfo *reg_info =
GetRegisterInfoAtIndex(pc_regnum.GetAsKind (eRegisterKindLLDB));
@@ -1557,12 +1568,13 @@ RegisterContextLLDB::TryFallbackUnwindPl
}
}
- m_full_unwind_plan_sp = original_full_unwind_plan_sp;
if (new_caller_pc_value == LLDB_INVALID_ADDRESS)
{
UnwindLogMsg ("failed to get a pc value for the caller frame with
the fallback unwind plan");
m_fallback_unwind_plan_sp.reset();
+ m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+ m_cfa = old_cfa;
return false;
}
@@ -1572,14 +1584,12 @@ RegisterContextLLDB::TryFallbackUnwindPl
{
UnwindLogMsg ("fallback unwind plan got the same values for
this frame CFA and caller frame pc, not using");
m_fallback_unwind_plan_sp.reset();
+ m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+ m_cfa = old_cfa;
return false;
}
}
- m_registers.clear();
- m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
- m_cfa = new_cfa;
-
UnwindLogMsg ("trying to unwind from this function with the UnwindPlan
'%s' because UnwindPlan '%s' failed.",
m_fallback_unwind_plan_sp->GetSourceName().GetCString(),
original_full_unwind_plan_sp->GetSourceName().GetCString());
Modified: lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp
URL:
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp?rev=222601&r1=222600&r2=222601&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp Fri Nov 21
19:52:03 2014
@@ -208,18 +208,35 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
// these.
if (reg_ctx_sp->IsTrapHandlerFrame() == false)
{
- // If the RegisterContextLLDB has a fallback UnwindPlan, it will
switch to that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return
false.
- if (m_frames[cur_idx -
1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ // See if we can find a fallback unwind plan for THIS frame. It
may be
+ // that the UnwindPlan we're using for THIS frame was bad and gave
us a
+ // bad CFA.
+ // If that's not it, then see if we can change the UnwindPlan for
the frame
+ // below us ("NEXT") -- see if using that other UnwindPlan gets us
a better
+ // unwind state.
+ if (reg_ctx_sp->TryFallbackUnwindPlan() == false
+ || reg_ctx_sp->GetCFA (cursor_sp->cfa) == false
+ || abi->CallFrameAddressIsValid(cursor_sp->cfa) == false)
{
- return AddOneMoreFrame (abi);
+ if (m_frames[cur_idx -
1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ return AddOneMoreFrame (abi);
+ }
+ if (log)
+ {
+ log->Printf("%*sFrame %d did not get a valid CFA for this
frame, stopping stack walk",
+ cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+ }
+ goto unwind_done;
}
- if (log)
+ else
{
- log->Printf("%*sFrame %d did not get a valid CFA for this
frame, stopping stack walk",
- cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+ if (log)
+ {
+ log->Printf("%*sFrame %d had a bad CFA value but we
switched the UnwindPlan being used and got one that looks more realistic.",
+ cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+ }
}
- goto unwind_done;
}
}
if (!reg_ctx_sp->ReadPC (cursor_sp->start_pc))
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits