[Lldb-commits] [lldb] r221866 - A pretty big overhaul of the TryFallbackUnwindPlan method in
Jason Molenda
jmolenda at apple.com
Wed Nov 12 23:31:46 PST 2014
Author: jmolenda
Date: Thu Nov 13 01:31:45 2014
New Revision: 221866
URL: http://llvm.org/viewvc/llvm-project?rev=221866&view=rev
Log:
A pretty big overhaul of the TryFallbackUnwindPlan method in
RegisterContextLLDB. I have core files of half a dozen tricky
unwind situations on x86/arm and they're all working pretty much
correctly at this point, but we'll need to keep an eye out for
unwinder regressions for a little while; it's tricky to get these
heuristics completely correct in all unwind situations.
<rdar://problem/18937193>
Modified:
lldb/trunk/include/lldb/Symbol/UnwindPlan.h
lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp
Modified: lldb/trunk/include/lldb/Symbol/UnwindPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/UnwindPlan.h?rev=221866&r1=221865&r2=221866&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/UnwindPlan.h (original)
+++ lldb/trunk/include/lldb/Symbol/UnwindPlan.h Thu Nov 13 01:31:45 2014
@@ -359,7 +359,9 @@ public:
CFAType m_cfa_type;
- // If m_cfa_type == CFAIsRegisterPlusOffset, the following ivars are used
+ // If m_cfa_type == CFAIsRegisterPlusOffset, the CFA address is computed as m_cfa_reg_num + m_cfa_offset
+ // If m_cfa_type == CFAIsRegisterDereferenced, the CFA address is computed as *(m_cfa_reg_num) - i.e. the
+ // address in m_cfa_reg_num is dereferenced and the pointer value read is the CFA addr.
uint32_t m_cfa_reg_num; // The Call Frame Address register number
int32_t m_cfa_offset; // The offset from the CFA for this row
Modified: lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp?rev=221866&r1=221865&r2=221866&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp Thu Nov 13 01:31:45 2014
@@ -694,10 +694,21 @@ void
PlatformDarwinKernel::CalculateTrapHandlerSymbolNames ()
{
m_trap_handlers.push_back(ConstString ("trap_from_kernel"));
+ m_trap_handlers.push_back(ConstString ("hndl_machine_check"));
m_trap_handlers.push_back(ConstString ("hndl_double_fault"));
m_trap_handlers.push_back(ConstString ("hndl_allintrs"));
m_trap_handlers.push_back(ConstString ("hndl_alltraps"));
m_trap_handlers.push_back(ConstString ("interrupt"));
+ m_trap_handlers.push_back(ConstString ("fleh_prefabt"));
+ m_trap_handlers.push_back(ConstString ("ExceptionVectorsBase"));
+ m_trap_handlers.push_back(ConstString ("ExceptionVectorsTable"));
+ m_trap_handlers.push_back(ConstString ("fleh_undef"));
+ m_trap_handlers.push_back(ConstString ("fleh_dataabt"));
+ m_trap_handlers.push_back(ConstString ("fleh_irq"));
+ m_trap_handlers.push_back(ConstString ("fleh_decirq"));
+ m_trap_handlers.push_back(ConstString ("fleh_fiq_generic"));
+ m_trap_handlers.push_back(ConstString ("fleh_dec"));
+
}
#else // __APPLE__
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=221866&r1=221865&r2=221866&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Thu Nov 13 01:31:45 2014
@@ -311,12 +311,19 @@ RegisterContextLLDB::InitializeNonZeroth
UnwindLogMsg ("sp = 0x%" PRIx64, reg_val);
}
- // A pc of 0x0 means it's the end of the stack crawl
- if (pc == 0)
+ // A pc of 0x0 means it's the end of the stack crawl unless we're above a trap handler function
+ bool above_trap_handler = false;
+ if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsTrapHandlerFrame())
+ above_trap_handler = true;
+
+ if (pc == 0 || pc == 0x1)
{
- m_frame_type = eNotAValidFrame;
- UnwindLogMsg ("this frame has a pc of 0x0");
- return;
+ if (above_trap_handler == false)
+ {
+ m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("this frame has a pc of 0x0");
+ return;
+ }
}
ExecutionContext exe_ctx(m_thread.shared_from_this());
@@ -381,7 +388,7 @@ RegisterContextLLDB::InitializeNonZeroth
UnwindLogMsg ("failed to get cfa value");
if (m_frame_type != eSkipFrame) // don't override eSkipFrame
{
- m_frame_type = eNormalFrame;
+ m_frame_type = eNotAValidFrame;
}
return;
}
@@ -550,7 +557,6 @@ RegisterContextLLDB::InitializeNonZeroth
m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
UnwindPlan::RowSP active_row;
- int cfa_offset = 0;
RegisterKind row_register_kind = eRegisterKindGeneric;
// Try to get by with just the fast UnwindPlan if possible - the full UnwindPlan may be expensive to get
@@ -598,17 +604,7 @@ RegisterContextLLDB::InitializeNonZeroth
return;
}
- cfa_offset = active_row->GetCFAOffset ();
-
- UnwindLogMsg ("m_cfa = 0x%" PRIx64 " (cfa_offset = %i)", m_cfa, cfa_offset);
-
- // A couple of sanity checks..
- if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == (addr_t)cfa_offset || m_cfa == (addr_t)cfa_offset + 1)
- {
- UnwindLogMsg ("could not find a valid cfa address");
- m_frame_type = eNotAValidFrame;
- return;
- }
+ UnwindLogMsg ("m_cfa = 0x%" PRIx64, m_cfa);
if (CheckIfLoopingStack ())
{
@@ -1269,7 +1265,7 @@ RegisterContextLLDB::SavedLocationForReg
m_full_unwind_plan_sp->GetSourceName().GetCString());
// Throw away the full unwindplan; install the arch default unwindplan
- if (TryFallbackUnwindPlan())
+ if (ForceSwitchToFallbackUnwindPlan())
{
// Now re-fetch the pc value we're searching for
RegisterNumber arch_default_pc_reg (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
@@ -1357,8 +1353,9 @@ RegisterContextLLDB::SavedLocationForReg
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
regloc.location.inferred_value = m_cfa + offset;
m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
- UnwindLogMsg ("supplying caller's register %s (%d), value is CFA plus offset %d",
- regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), offset);
+ UnwindLogMsg ("supplying caller's register %s (%d), value is CFA plus offset %d [value is 0x%" PRIx64 "]",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB),
+ offset, regloc.location.inferred_value);
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
@@ -1368,8 +1365,9 @@ RegisterContextLLDB::SavedLocationForReg
regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
regloc.location.target_memory_location = m_cfa + offset;
m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc;
- UnwindLogMsg ("supplying caller's register %s (%d) from the stack, saved at CFA plus offset %d",
- regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), offset);
+ UnwindLogMsg ("supplying caller's register %s (%d) from the stack, saved at CFA plus offset %d [saved at 0x%" PRIx64 "]",
+ regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB),
+ offset, regloc.location.target_memory_location);
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
@@ -1438,42 +1436,132 @@ RegisterContextLLDB::SavedLocationForReg
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
}
-// If the Full unwindplan has been determined to be incorrect, this method will
-// replace it with the architecture's default unwindplan, if one is defined.
-// It will also find the FuncUnwinders object for this function and replace the
-// Full unwind method for the function there so we don't use the errant Full unwindplan
-// again in the future of this debug session.
-// We're most likely doing this because the Full unwindplan was generated by assembly
-// instruction profiling and the profiler got something wrong.
+// TryFallbackUnwindPlan() -- this method is a little tricky.
+//
+// When this is called, the frame above -- the caller frame, the "previous" frame --
+// is invalid or bad.
+//
+// Instead of stopping the stack walk here, we'll try a different UnwindPlan and see
+// if we can get a valid frame above us.
+//
+// This most often happens when an unwind plan based on assembly instruction inspection
+// is not correct -- mostly with hand-written assembly functions or functions where the
+// stack frame is set up "out of band", e.g. the kernel saved the register context and
+// then called an asynchronous trap handler like _sigtramp.
+//
+// Often in these cases, if we just do a dumb stack walk we'll get past this tricky
+// frame and our usual techniques can continue to be used.
bool
RegisterContextLLDB::TryFallbackUnwindPlan ()
{
- UnwindPlan::Row::RegisterLocation unwindplan_regloc;
- if (m_fallback_unwind_plan_sp.get() == NULL)
+ if (m_fallback_unwind_plan_sp.get() == nullptr)
return false;
- if (m_full_unwind_plan_sp.get() == NULL)
+ if (m_full_unwind_plan_sp.get() == nullptr)
+ return false;
+
+ if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get()
+ || m_full_unwind_plan_sp->GetSourceName() == m_fallback_unwind_plan_sp->GetSourceName())
+ {
return false;
+ }
// If a compiler generated unwind plan failed, trying the arch default unwindplan
// isn't going to do any better.
if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes)
return false;
+
+ // Get the caller's pc value and our own CFA value.
+ // Swap in the fallback unwind plan, re-fetch the caller's pc value and CFA value.
+ // If they're the same, then the fallback unwind plan provides no benefit.
+
+ RegisterNumber pc_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+
+ addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS;
+ addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS;
+ addr_t old_this_frame_cfa_value = m_cfa;
+ UnwindLLDB::RegisterLocation regloc;
+ if (SavedLocationForRegister (pc_regnum.GetAsKind (eRegisterKindLLDB), regloc) == UnwindLLDB::RegisterSearchResult::eRegisterFound)
+ {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(pc_regnum.GetAsKind (eRegisterKindLLDB));
+ if (reg_info)
+ {
+ RegisterValue reg_value;
+ if (ReadRegisterValueFromRegisterLocation (regloc, reg_info, reg_value))
+ {
+ old_caller_pc_value = reg_value.GetAsUInt64();
+ }
+ }
+ }
+
+ // This is a tricky wrinkle! If SavedLocationForRegister() detects a really impossible
+ // register location for the full unwind plan, it may call ForceSwitchToFallbackUnwindPlan()
+ // which in turn replaces the full unwindplan with the fallback... in short, we're done,
+ // we're using the fallback UnwindPlan.
+ // We checked if m_fallback_unwind_plan_sp was nullptr at the top -- the only way it
+ // became nullptr since then is via SavedLocationForRegister().
+ if (m_fallback_unwind_plan_sp.get() == nullptr)
+ return true;
+
UnwindPlanSP original_full_unwind_plan_sp = m_full_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)
{
+ addr_t new_cfa;
+ if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa)
+ || new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS)
+ {
+ UnwindLogMsg ("failed to get cfa with fallback unwindplan");
+ m_fallback_unwind_plan_sp.reset();
+ return false;
+ }
+
+ 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));
+ if (reg_info)
+ {
+ RegisterValue reg_value;
+ if (ReadRegisterValueFromRegisterLocation (regloc, reg_info, reg_value))
+ {
+ new_caller_pc_value = reg_value.GetAsUInt64();
+ }
+ }
+ }
+
+ 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();
+ return false;
+ }
+
+ if (old_caller_pc_value != LLDB_INVALID_ADDRESS)
+ {
+ if (old_caller_pc_value == new_caller_pc_value && new_cfa == old_this_frame_cfa_value)
+ {
+ UnwindLogMsg ("fallback unwind plan got the same values for this frame CFA and caller frame pc, not using");
+ m_fallback_unwind_plan_sp.reset();
+ return false;
+ }
+ }
+
m_registers.clear();
m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
- m_cfa = LLDB_INVALID_ADDRESS;
- ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, m_cfa);
+ 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());
+
+ // We've copied the fallback unwind plan into the full - now clear the fallback.
m_fallback_unwind_plan_sp.reset();
}
@@ -1481,33 +1569,102 @@ RegisterContextLLDB::TryFallbackUnwindPl
}
bool
+RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan ()
+{
+ if (m_fallback_unwind_plan_sp.get() == NULL)
+ return false;
+
+ if (m_full_unwind_plan_sp.get() == NULL)
+ return false;
+
+ if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get()
+ || m_full_unwind_plan_sp->GetSourceName() == m_fallback_unwind_plan_sp->GetSourceName())
+ {
+ return false;
+ }
+
+ UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+
+ if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
+ {
+ addr_t new_cfa;
+ if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa)
+ || new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS)
+ {
+ UnwindLogMsg ("failed to get cfa with fallback unwindplan");
+ m_fallback_unwind_plan_sp.reset();
+ return false;
+ }
+
+ m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
+ m_fallback_unwind_plan_sp.reset();
+
+ m_registers.clear();
+
+ m_cfa = new_cfa;
+
+ UnwindLogMsg ("switched unconditionally to the fallback unwindplan %s", m_full_unwind_plan_sp->GetSourceName().GetCString());
+ return true;
+ }
+ return false;
+}
+
+bool
RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind,
const UnwindPlan::RowSP &row,
- addr_t &value)
+ addr_t &cfa_value)
{
- uint32_t cfa_regnum = row->GetCFARegister();
+ RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFARegister());
RegisterValue reg_value;
- addr_t tmp;
- value = LLDB_INVALID_ADDRESS;
+ cfa_value = LLDB_INVALID_ADDRESS;
+ addr_t cfa_reg_contents;
- if (ReadGPRValue (row_register_kind, cfa_regnum, value))
+ if (ReadGPRValue (cfa_reg, cfa_reg_contents))
{
if (row->GetCFAType() == UnwindPlan::Row::CFAIsRegisterDereferenced)
{
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(cfa_regnum);
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex (cfa_reg.GetAsKind (eRegisterKindLLDB));
RegisterValue reg_value;
- tmp = value;
- Error error = ReadRegisterValueFromMemory(reg_info,
- value,
- reg_info->byte_size,
- reg_value);
- value = reg_value.GetAsUInt64();
- UnwindLogMsg("dereferenced address: 0x%" PRIx64 " yields: %" PRIx64, tmp, value);
- return error.Success();
+ if (reg_info)
+ {
+ Error error = ReadRegisterValueFromMemory(reg_info,
+ cfa_reg_contents,
+ reg_info->byte_size,
+ reg_value);
+ if (error.Success ())
+ {
+ cfa_value = reg_value.GetAsUInt64();
+ UnwindLogMsg ("CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64 ", CFA value is 0x%" PRIx64,
+ cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
+ cfa_reg_contents, cfa_value);
+ return true;
+ }
+ else
+ {
+ UnwindLogMsg ("Tried to deref reg %s (%d) [0x%" PRIx64 "] but memory read failed.",
+ cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
+ cfa_reg_contents);
+ }
+ }
+ }
+ else
+ {
+ if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || cfa_reg_contents == 1)
+ {
+ UnwindLogMsg ("Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64,
+ cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
+ cfa_reg_contents);
+ cfa_reg_contents = LLDB_INVALID_ADDRESS;
+ return false;
+ }
+ cfa_value = cfa_reg_contents + row->GetCFAOffset ();
+ UnwindLogMsg ("CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 ", offset is %d",
+ cfa_value,
+ cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
+ cfa_reg_contents, row->GetCFAOffset ());
+ return true;
}
- value = value + row->GetCFAOffset ();
- return true;
}
return false;
}
@@ -1580,6 +1737,12 @@ RegisterContextLLDB::ReadGPRValue (lldb:
return false;
}
+bool
+RegisterContextLLDB::ReadGPRValue (const RegisterNumber ®num, addr_t &value)
+{
+ return ReadGPRValue (regnum.GetRegisterKind(), regnum.GetRegisterNumber(), value);
+}
+
// Find the value of a register in THIS frame
bool
@@ -1702,6 +1865,10 @@ RegisterContextLLDB::ReadPC (addr_t& pc)
if (!IsValid())
return false;
+ bool above_trap_handler = false;
+ if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsTrapHandlerFrame())
+ above_trap_handler = true;
+
if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc))
{
// A pc value of 0 or 1 is impossible in the middle of the stack -- it indicates the end of a stack walk.
@@ -1710,6 +1877,7 @@ RegisterContextLLDB::ReadPC (addr_t& pc)
// find the bug.
if (m_all_registers_available == false
+ && above_trap_handler == false
&& (pc == 0 || pc == 1))
{
return false;
Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h?rev=221866&r1=221865&r2=221866&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h Thu Nov 13 01:31:45 2014
@@ -217,6 +217,18 @@ private:
return output_regnum;
}
+ uint32_t
+ GetRegisterNumber () const
+ {
+ return m_regnum;
+ }
+
+ lldb::RegisterKind
+ GetRegisterKind () const
+ {
+ return m_kind;
+ }
+
const char *
GetName ()
{
@@ -328,11 +340,26 @@ private:
bool
TryFallbackUnwindPlan ();
+ //------------------------------------------------------------------
+ /// Switch to the fallback unwind plan unconditionally without any safety
+ /// checks that it is providing better results than the normal unwind plan.
+ ///
+ /// The only time it is valid to call this method is if the full unwindplan is
+ /// found to be fundamentally incorrect/impossible.
+ ///
+ /// Returns true if it was able to install the fallback unwind plan.
+ //------------------------------------------------------------------
+ bool
+ ForceSwitchToFallbackUnwindPlan ();
+
// Get the contents of a general purpose (address-size) register for this frame
// (usually retrieved from the next frame)
bool
ReadGPRValue (lldb::RegisterKind register_kind, uint32_t regnum, lldb::addr_t &value);
+ bool
+ ReadGPRValue (const RegisterNumber ®_num, lldb::addr_t &value);
+
// Get the CFA register for a given frame.
bool
ReadCFAValueForRow (lldb::RegisterKind register_kind, const UnwindPlan::RowSP &row, lldb::addr_t &value);
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=221866&r1=221865&r2=221866&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/UnwindLLDB.cpp Thu Nov 13 01:31:45 2014
@@ -172,8 +172,9 @@ 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.
+ // We failed to get a valid RegisterContext.
+ // See if the regctx below this on the stack has a fallback unwind plan it can use.
+ // Subsequent calls to TryFallbackUnwindPlan() will return false.
if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
{
return AddOneMoreFrame (abi);
More information about the lldb-commits
mailing list