summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Symbol/FuncUnwinders.h13
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp35
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h7
-rw-r--r--lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp3
-rw-r--r--lldb/source/Symbol/FuncUnwinders.cpp94
5 files changed, 24 insertions, 128 deletions
diff --git a/lldb/include/lldb/Symbol/FuncUnwinders.h b/lldb/include/lldb/Symbol/FuncUnwinders.h
index 0cf584239f9..8e29e4e48da 100644
--- a/lldb/include/lldb/Symbol/FuncUnwinders.h
+++ b/lldb/include/lldb/Symbol/FuncUnwinders.h
@@ -16,7 +16,8 @@ public:
// FuncUnwinders objects are used to track UnwindPlans for a function
// (named or not - really just an address range)
- // We'll record three different UnwindPlans for each address range:
+ // We'll record four different UnwindPlans for each address range:
+ //
// 1. Unwinding from a call site (a valid exception throw location)
// This is often sourced from the eh_frame exception handling info
// 2. Unwinding from a non-call site (any location in the function)
@@ -67,14 +68,6 @@ public:
return m_range.ContainsFileAddress (addr);
}
- // When we're doing an unwind using the UnwindPlanAtNonCallSite and we find an
- // impossible unwind condition, we know that the UnwindPlan is invalid. Calling
- // this method on the FuncUnwinder will tell it to replace that UnwindPlan with
- // the architectural default UnwindPlan so hopefully our stack walk will get past
- // this frame.
- void
- InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& Thread);
-
private:
lldb::UnwindAssemblySP
@@ -90,6 +83,8 @@ private:
lldb::UnwindPlanSP m_unwind_plan_arch_default_sp;
lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp;
+ // Fetching the UnwindPlans can be expensive - if we've already attempted
+ // to get one & failed, don't try again.
bool m_tried_unwind_at_call_site:1,
m_tried_unwind_at_non_call_site:1,
m_tried_unwind_fast:1,
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 88bb608ea9e..92e378979be 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -62,8 +62,7 @@ RegisterContextLLDB::RegisterContextLLDB
m_sym_ctx_valid (false),
m_frame_number (frame_number),
m_registers(),
- m_parent_unwind (unwind_lldb),
- m_completed_stack_walk (false)
+ m_parent_unwind (unwind_lldb)
{
m_sym_ctx.Clear(false);
m_sym_ctx_valid = false;
@@ -307,7 +306,6 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (pc == 0)
{
m_frame_type = eNotAValidFrame;
- m_completed_stack_walk = true;
UnwindLogMsg ("this frame has a pc of 0x0");
return;
}
@@ -388,10 +386,6 @@ RegisterContextLLDB::InitializeNonZerothFrame()
{
UnwindLogMsg ("could not find a valid cfa address");
m_frame_type = eNotAValidFrame;
- if (cfa_regval == 0 || cfa_regval == 1)
- {
- m_completed_stack_walk = true;
- }
return;
}
@@ -588,10 +582,6 @@ RegisterContextLLDB::InitializeNonZerothFrame()
{
UnwindLogMsg ("could not find a valid cfa address");
m_frame_type = eNotAValidFrame;
- if (cfa_regval == 0 || cfa_regval == 1)
- {
- m_completed_stack_walk = true;
- }
return;
}
@@ -1040,11 +1030,10 @@ RegisterContextLLDB::IsValid () const
return m_frame_type != eNotAValidFrame;
}
-bool
-RegisterContextLLDB::IsCompletedStackWalk () const
-{
- return m_completed_stack_walk;
-}
+// After the final stack frame in a stack walk we'll get one invalid (eNotAValidFrame) stack frame --
+// one past the end of the stack walk. But higher-level code will need to tell the differnece between
+// "the unwind plan below this frame failed" versus "we successfully completed the stack walk" so
+// this method helps to disambiguate that.
bool
RegisterContextLLDB::IsTrapHandlerFrame () const
@@ -1420,15 +1409,6 @@ RegisterContextLLDB::TryFallbackUnwindPlan ()
if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
{
- FuncUnwindersSP func_unwinders_sp;
- if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule())
- {
- func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
- if (func_unwinders_sp)
- {
- func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread);
- }
- }
m_registers.clear();
m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
addr_t cfa_regval = LLDB_INVALID_ADDRESS;
@@ -1437,8 +1417,9 @@ RegisterContextLLDB::TryFallbackUnwindPlan ()
m_cfa = cfa_regval + active_row->GetCFAOffset ();
}
- UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.",
- original_full_unwind_plan_sp->GetSourceName().GetCString(), m_fallback_unwind_plan_sp->GetSourceName().GetCString());
+ 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());
m_fallback_unwind_plan_sp.reset();
}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
index d272073de55..ff0b77488eb 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -73,9 +73,6 @@ public:
IsValid () const;
bool
- IsCompletedStackWalk () const;
-
- bool
IsTrapHandlerFrame () const;
bool
@@ -243,10 +240,6 @@ private:
lldb_private::UnwindLLDB& m_parent_unwind; // The UnwindLLDB that is creating this RegisterContextLLDB
- bool m_completed_stack_walk; // indicates that we completed a full stack walk
- // (this frame is likely eNotAValidFrame aka !IsValid())
- // and we should not continue trying to unwind
-
//------------------------------------------------------------------
// For RegisterContextLLDB only
//------------------------------------------------------------------
diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
index b61819af0d8..37fd4f48955 100644
--- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -174,8 +174,7 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
{
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
- if (reg_ctx_sp->IsCompletedStackWalk() == false
- && m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ if (m_frames[cur_idx - 1]->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
{
return AddOneMoreFrame (abi);
}
diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp
index 95fc8174785..bee84cba748 100644
--- a/lldb/source/Symbol/FuncUnwinders.cpp
+++ b/lldb/source/Symbol/FuncUnwinders.cpp
@@ -25,13 +25,9 @@ using namespace lldb;
using namespace lldb_private;
-FuncUnwinders::FuncUnwinders
-(
- UnwindTable& unwind_table,
- AddressRange range
-) :
- m_unwind_table(unwind_table),
- m_range(range),
+FuncUnwinders::FuncUnwinders (UnwindTable& unwind_table, AddressRange range) :
+ m_unwind_table (unwind_table),
+ m_range (range),
m_mutex (Mutex::eMutexTypeRecursive),
m_unwind_plan_call_site_sp (),
m_unwind_plan_non_call_site_sp (),
@@ -42,29 +38,17 @@ FuncUnwinders::FuncUnwinders
m_tried_unwind_fast (false),
m_tried_unwind_arch_default (false),
m_tried_unwind_arch_default_at_func_entry (false),
- m_first_non_prologue_insn()
+ m_first_non_prologue_insn ()
{
}
-FuncUnwinders::~FuncUnwinders ()
+FuncUnwinders::~FuncUnwinders ()
{
}
UnwindPlanSP
FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
{
- // Lock the mutex to ensure we can always give out the most appropriate
- // information. We want to make sure if someone requests a call site unwind
- // plan, that they get one and don't run into a race condition where one
- // thread has started to create the unwind plan and has put it into
- // m_unwind_plan_call_site_sp, and have another thread enter this function
- // and return the partially filled in m_unwind_plan_call_site_sp pointer.
- // We also want to make sure that we lock out other unwind plans from
- // being accessed until this one is done creating itself in case someone
- // had some code like:
- // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
- // if (best_unwind_plan == NULL)
- // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex);
if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == nullptr)
{
@@ -96,18 +80,6 @@ FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
UnwindPlanSP
FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset)
{
- // Lock the mutex to ensure we can always give out the most appropriate
- // information. We want to make sure if someone requests an unwind
- // plan, that they get one and don't run into a race condition where one
- // thread has started to create the unwind plan and has put it into
- // the unique pointer member variable, and have another thread enter this function
- // and return the partially filled pointer contained in the unique pointer.
- // We also want to make sure that we lock out other unwind plans from
- // being accessed until this one is done creating itself in case someone
- // had some code like:
- // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
- // if (best_unwind_plan == NULL)
- // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex);
if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == nullptr)
{
@@ -121,9 +93,11 @@ FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int c
// For 0th frame on i386 & x86_64, we fetch eh_frame and try using assembly profiler
// to augment it into asynchronous unwind table.
GetUnwindPlanAtCallSite(current_offset);
- if (m_unwind_plan_call_site_sp) {
+ if (m_unwind_plan_call_site_sp)
+ {
UnwindPlan* plan = new UnwindPlan (*m_unwind_plan_call_site_sp);
- if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *plan)) {
+ if (assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *plan))
+ {
m_unwind_plan_non_call_site_sp.reset (plan);
return m_unwind_plan_non_call_site_sp;
}
@@ -141,18 +115,6 @@ FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int c
UnwindPlanSP
FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
{
- // Lock the mutex to ensure we can always give out the most appropriate
- // information. We want to make sure if someone requests an unwind
- // plan, that they get one and don't run into a race condition where one
- // thread has started to create the unwind plan and has put it into
- // the unique pointer member variable, and have another thread enter this function
- // and return the partially filled pointer contained in the unique pointer.
- // We also want to make sure that we lock out other unwind plans from
- // being accessed until this one is done creating itself in case someone
- // had some code like:
- // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
- // if (best_unwind_plan == NULL)
- // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex);
if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == nullptr)
{
@@ -171,18 +133,6 @@ FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
UnwindPlanSP
FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
{
- // Lock the mutex to ensure we can always give out the most appropriate
- // information. We want to make sure if someone requests an unwind
- // plan, that they get one and don't run into a race condition where one
- // thread has started to create the unwind plan and has put it into
- // the unique pointer member variable, and have another thread enter this function
- // and return the partially filled pointer contained in the unique pointer.
- // We also want to make sure that we lock out other unwind plans from
- // being accessed until this one is done creating itself in case someone
- // had some code like:
- // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
- // if (best_unwind_plan == NULL)
- // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex);
if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == nullptr)
{
@@ -207,20 +157,9 @@ FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
UnwindPlanSP
FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread)
{
- // Lock the mutex to ensure we can always give out the most appropriate
- // information. We want to make sure if someone requests an unwind
- // plan, that they get one and don't run into a race condition where one
- // thread has started to create the unwind plan and has put it into
- // the unique pointer member variable, and have another thread enter this function
- // and return the partially filled pointer contained in the unique pointer.
- // We also want to make sure that we lock out other unwind plans from
- // being accessed until this one is done creating itself in case someone
- // had some code like:
- // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...)
- // if (best_unwind_plan == NULL)
- // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex);
- if (m_tried_unwind_arch_default_at_func_entry == false && m_unwind_plan_arch_default_at_func_entry_sp.get() == nullptr)
+ if (m_tried_unwind_arch_default_at_func_entry == false
+ && m_unwind_plan_arch_default_at_func_entry_sp.get() == nullptr)
{
m_tried_unwind_arch_default_at_func_entry = true;
Address current_pc;
@@ -249,7 +188,6 @@ FuncUnwinders::GetFirstNonPrologueInsn (Target& target)
ExecutionContext exe_ctx (target.shared_from_this(), false);
UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler());
if (assembly_profiler_sp)
- if (assembly_profiler_sp)
assembly_profiler_sp->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn);
return m_first_non_prologue_insn;
}
@@ -260,16 +198,6 @@ FuncUnwinders::GetFunctionStartAddress () const
return m_range.GetBaseAddress();
}
-void
-FuncUnwinders::InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& thread)
-{
- UnwindPlanSP arch_default = GetUnwindPlanArchitectureDefault (thread);
- if (arch_default && m_tried_unwind_at_call_site)
- {
- m_unwind_plan_call_site_sp = arch_default;
- }
-}
-
lldb::UnwindAssemblySP
FuncUnwinders::GetUnwindAssemblyProfiler ()
{
OpenPOWER on IntegriCloud