From 31d7ad4ecff690d83f404e49662b5edc9d95ae53 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Fri, 21 Feb 2014 05:20:25 +0000 Subject: Add a new idea of a "fallback" UnwindPlan to the RegisterContextLLDB class. If we try to unwind a stack frame to find a caller stack frame, and we fail to get a valid-looking frame, AND if the UnwindPlan we used is an assembly-inspection based UnwindPlan, then we should throw away the assembly-inspection UnwindPlan and try unwinding with the architectural default UnwindPlan. This code path won't be taken if eh_frame unwind instructions are available - lldb will always prefer those once it's off the zeroth frame. The problem I'm trying to fix here is the class of unwind failures that happen when we have hand-written assembly on the stack, with no eh_frame, and lldb's assembly parser fails to understand the assembly. People usually write their hand-written assembly to follow the frame-pointer-preserving conventions of the platform so the architectural default UnwindPlan will often work. We won't have the spill location for most of the non-volatile registers if we fall back to this, but it's better than stopping the unwind prematurely. This is a bit of a tricky change that I believe is correct, but if we get unwinds that go of into the weeds / unwind bogus frames at the end of the stack, I'll need to revisit it. llvm-svn: 201839 --- lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp') diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp index a3a7002ea09..5db08e5c26d 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -158,6 +158,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) if (reg_ctx_sp.get() == NULL) { + // 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()) + { + return AddOneMoreFrame (abi); + } if (log) log->Printf ("%*sFrame %d did not get a RegisterContext, stopping.", cur_idx < 100 ? cur_idx : 100, "", cur_idx); @@ -166,6 +172,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) if (!reg_ctx_sp->IsValid()) { + // 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()) + { + return AddOneMoreFrame (abi); + } if (log) { log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk", @@ -175,6 +187,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) } if (!reg_ctx_sp->GetCFA (cursor_sp->cfa)) { + // 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()) + { + return AddOneMoreFrame (abi); + } if (log) { log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk", @@ -189,6 +207,12 @@ 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()) + { + return AddOneMoreFrame (abi); + } if (log) { log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk", @@ -199,6 +223,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) } if (!reg_ctx_sp->ReadPC (cursor_sp->start_pc)) { + // 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()) + { + return AddOneMoreFrame (abi); + } if (log) { log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk", @@ -208,6 +238,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) } if (abi && !abi->CodeAddressIsValid (cursor_sp->start_pc)) { + // 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()) + { + return AddOneMoreFrame (abi); + } if (log) { log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk", -- cgit v1.2.3