diff options
-rw-r--r-- | lldb/include/lldb/Symbol/FuncUnwinders.h | 13 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp | 35 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h | 7 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp | 3 | ||||
-rw-r--r-- | lldb/source/Symbol/FuncUnwinders.cpp | 94 |
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 () { |