diff options
Diffstat (limited to 'lldb/source/Target/Thread.cpp')
-rw-r--r-- | lldb/source/Target/Thread.cpp | 551 |
1 files changed, 170 insertions, 381 deletions
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index e12b90501103e..24cf4bf3ee1ed 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -1,4 +1,4 @@ -//===-- Thread.cpp ----------------------------------------------*- C++ -*-===// +//===-- Thread.cpp --------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -7,8 +7,6 @@ //===----------------------------------------------------------------------===// #include "lldb/Target/Thread.h" -#include "Plugins/Process/Utility/UnwindLLDB.h" -#include "Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FormatEntity.h" @@ -35,6 +33,7 @@ #include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Target/ThreadPlanPython.h" #include "lldb/Target/ThreadPlanRunToAddress.h" +#include "lldb/Target/ThreadPlanStack.h" #include "lldb/Target/ThreadPlanStepInRange.h" #include "lldb/Target/ThreadPlanStepInstruction.h" #include "lldb/Target/ThreadPlanStepOut.h" @@ -43,7 +42,7 @@ #include "lldb/Target/ThreadPlanStepThrough.h" #include "lldb/Target/ThreadPlanStepUntil.h" #include "lldb/Target/ThreadSpec.h" -#include "lldb/Target/Unwind.h" +#include "lldb/Target/UnwindLLDB.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/State.h" @@ -230,8 +229,7 @@ Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id) m_index_id(use_invalid_index_id ? LLDB_INVALID_INDEX32 : process.GetNextThreadIndexID(tid)), m_reg_context_sp(), m_state(eStateUnloaded), m_state_mutex(), - m_plan_stack(), m_completed_plan_stack(), m_frame_mutex(), - m_curr_frames_sp(), m_prev_frames_sp(), + m_frame_mutex(), m_curr_frames_sp(), m_prev_frames_sp(), m_resume_signal(LLDB_INVALID_SIGNAL_NUMBER), m_resume_state(eStateRunning), m_temporary_resume_state(eStateRunning), m_unwinder_up(), m_destroy_called(false), @@ -242,8 +240,6 @@ Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id) static_cast<void *>(this), GetID()); CheckInWithManager(); - - QueueFundamentalPlan(true); } Thread::~Thread() { @@ -256,30 +252,7 @@ Thread::~Thread() { } void Thread::DestroyThread() { - // Tell any plans on the plan stacks that the thread is being destroyed since - // any plans that have a thread go away in the middle of might need to do - // cleanup, or in some cases NOT do cleanup... - for (auto plan : m_plan_stack) - plan->ThreadDestroyed(); - - for (auto plan : m_discarded_plan_stack) - plan->ThreadDestroyed(); - - for (auto plan : m_completed_plan_stack) - plan->ThreadDestroyed(); - m_destroy_called = true; - m_plan_stack.clear(); - m_discarded_plan_stack.clear(); - m_completed_plan_stack.clear(); - - // Push a ThreadPlanNull on the plan stack. That way we can continue - // assuming that the plan stack is never empty, but if somebody errantly asks - // questions of a destroyed thread without checking first whether it is - // destroyed, they won't crash. - ThreadPlanSP null_plan_sp(new ThreadPlanNull(*this)); - m_plan_stack.push_back(null_plan_sp); - m_stop_info_sp.reset(); m_reg_context_sp.reset(); m_unwinder_up.reset(); @@ -298,7 +271,7 @@ lldb::StackFrameSP Thread::GetSelectedFrame() { StackFrameListSP stack_frame_list_sp(GetStackFrameList()); StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex( stack_frame_list_sp->GetSelectedFrameIndex()); - FunctionOptimizationWarning(frame_sp.get()); + FrameSelectedCallback(frame_sp.get()); return frame_sp; } @@ -307,7 +280,7 @@ uint32_t Thread::SetSelectedFrame(lldb_private::StackFrame *frame, uint32_t ret_value = GetStackFrameList()->SetSelectedFrame(frame); if (broadcast) BroadcastSelectedFrameChange(frame->GetStackID()); - FunctionOptimizationWarning(frame); + FrameSelectedCallback(frame); return ret_value; } @@ -317,7 +290,7 @@ bool Thread::SetSelectedFrameByIndex(uint32_t frame_idx, bool broadcast) { GetStackFrameList()->SetSelectedFrame(frame_sp.get()); if (broadcast) BroadcastSelectedFrameChange(frame_sp->GetStackID()); - FunctionOptimizationWarning(frame_sp.get()); + FrameSelectedCallback(frame_sp.get()); return true; } else return false; @@ -341,7 +314,7 @@ bool Thread::SetSelectedFrameByIndexNoisily(uint32_t frame_idx, bool show_frame_info = true; bool show_source = !already_shown; - FunctionOptimizationWarning(frame_sp.get()); + FrameSelectedCallback(frame_sp.get()); return frame_sp->GetStatus(output_stream, show_frame_info, show_source); } return false; @@ -349,12 +322,17 @@ bool Thread::SetSelectedFrameByIndexNoisily(uint32_t frame_idx, return false; } -void Thread::FunctionOptimizationWarning(StackFrame *frame) { - if (frame && frame->HasDebugInformation() && - GetProcess()->GetWarningsOptimization()) { +void Thread::FrameSelectedCallback(StackFrame *frame) { + if (!frame) + return; + + if (frame->HasDebugInformation() && + (GetProcess()->GetWarningsOptimization() || + GetProcess()->GetWarningsUnsupportedLanguage())) { SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextModule); GetProcess()->PrintWarningOptimization(sc); + GetProcess()->PrintWarningUnsupportedLanguage(sc); } } @@ -423,7 +401,7 @@ lldb::StopInfoSP Thread::GetPrivateStopInfo() { // "m_stop_info_stop_id != process_stop_id" as the condition for the if // statement below, we must also check the stop info to see if we need to // override it. See the header documentation in - // Process::GetStopInfoOverrideCallback() for more information on the stop + // Architecture::OverrideStopInfo() for more information on the stop // info override callback. if (m_stop_info_override_stop_id != process_stop_id) { m_stop_info_override_stop_id = process_stop_id; @@ -524,7 +502,8 @@ bool Thread::CheckpointThreadState(ThreadStateCheckpoint &saved_state) { if (process_sp) saved_state.orig_stop_id = process_sp->GetStopID(); saved_state.current_inlined_depth = GetCurrentInlinedDepth(); - saved_state.m_completed_plan_stack = m_completed_plan_stack; + saved_state.m_completed_plan_checkpoint = + GetPlans().CheckpointCompletedPlans(); return true; } @@ -558,7 +537,8 @@ bool Thread::RestoreThreadStateFromCheckpoint( SetStopInfo(saved_state.stop_info_sp); GetStackFrameList()->SetCurrentInlinedDepth( saved_state.current_inlined_depth); - m_completed_plan_stack = saved_state.m_completed_plan_stack; + GetPlans().RestoreCompletedPlanCheckpoint( + saved_state.m_completed_plan_checkpoint); return true; } @@ -573,9 +553,68 @@ void Thread::SetState(StateType state) { m_state = state; } +std::string Thread::GetStopDescription() { + StackFrameSP frame_sp = GetStackFrameAtIndex(0); + + if (!frame_sp) + return GetStopDescriptionRaw(); + + auto recognized_frame_sp = frame_sp->GetRecognizedFrame(); + + if (!recognized_frame_sp) + return GetStopDescriptionRaw(); + + std::string recognized_stop_description = + recognized_frame_sp->GetStopDescription(); + + if (!recognized_stop_description.empty()) + return recognized_stop_description; + + return GetStopDescriptionRaw(); +} + +std::string Thread::GetStopDescriptionRaw() { + StopInfoSP stop_info_sp = GetStopInfo(); + std::string raw_stop_description; + if (stop_info_sp && stop_info_sp->IsValid()) { + raw_stop_description = stop_info_sp->GetDescription(); + assert((!raw_stop_description.empty() || + stop_info_sp->GetStopReason() == eStopReasonNone) && + "StopInfo returned an empty description."); + } + return raw_stop_description; +} + +void Thread::SelectMostRelevantFrame() { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD); + + auto frames_list_sp = GetStackFrameList(); + + // Only the top frame should be recognized. + auto frame_sp = frames_list_sp->GetFrameAtIndex(0); + + auto recognized_frame_sp = frame_sp->GetRecognizedFrame(); + + if (!recognized_frame_sp) { + LLDB_LOG(log, "Frame #0 not recognized"); + return; + } + + if (StackFrameSP most_relevant_frame_sp = + recognized_frame_sp->GetMostRelevantFrame()) { + LLDB_LOG(log, "Found most relevant frame at index {0}", + most_relevant_frame_sp->GetFrameIndex()); + SetSelectedFrame(most_relevant_frame_sp.get()); + } else { + LLDB_LOG(log, "No relevant frame!"); + } +} + void Thread::WillStop() { ThreadPlan *current_plan = GetCurrentPlan(); + SelectMostRelevantFrame(); + // FIXME: I may decide to disallow threads with no plans. In which // case this should go to an assert. @@ -632,8 +671,7 @@ void Thread::SetupForResume() { bool Thread::ShouldResume(StateType resume_state) { // At this point clear the completed plan stack. - m_completed_plan_stack.clear(); - m_discarded_plan_stack.clear(); + GetPlans().WillResume(); m_override_should_notify = eLazyBoolCalculate; StateType prev_resume_state = GetTemporaryResumeState(); @@ -744,7 +782,9 @@ bool Thread::ShouldStop(Event *event_ptr) { LLDB_LOGF(log, "^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^"); StreamString s; s.IndentMore(); - DumpThreadPlans(&s); + GetProcess()->DumpThreadPlansForTID( + s, GetID(), eDescriptionLevelVerbose, true /* internal */, + false /* condense_trivial */, true /* skip_unreported */); LLDB_LOGF(log, "Plan stack initial state:\n%s", s.GetData()); } @@ -827,7 +867,7 @@ bool Thread::ShouldStop(Event *event_ptr) { current_plan->GetName(), over_ride_stop); // We're starting from the base plan, so just let it decide; - if (PlanIsBasePlan(current_plan)) { + if (current_plan->IsBasePlan()) { should_stop = current_plan->ShouldStop(event_ptr); LLDB_LOGF(log, "Base plan says should stop: %i.", should_stop); } else { @@ -835,7 +875,7 @@ bool Thread::ShouldStop(Event *event_ptr) { // to do, since presumably if there were other plans they would know what // to do... while (true) { - if (PlanIsBasePlan(current_plan)) + if (current_plan->IsBasePlan()) break; should_stop = current_plan->ShouldStop(event_ptr); @@ -881,7 +921,7 @@ bool Thread::ShouldStop(Event *event_ptr) { // Discard the stale plans and all plans below them in the stack, plus move // the completed plans to the completed plan stack - while (!PlanIsBasePlan(plan_ptr)) { + while (!plan_ptr->IsBasePlan()) { bool stale = plan_ptr->IsPlanStale(); ThreadPlan *examined_plan = plan_ptr; plan_ptr = GetPreviousPlan(examined_plan); @@ -908,7 +948,9 @@ bool Thread::ShouldStop(Event *event_ptr) { if (log) { StreamString s; s.IndentMore(); - DumpThreadPlans(&s); + GetProcess()->DumpThreadPlansForTID( + s, GetID(), eDescriptionLevelVerbose, true /* internal */, + false /* condense_trivial */, true /* skip_unreported */); LLDB_LOGF(log, "Plan stack final state:\n%s", s.GetData()); LLDB_LOGF(log, "vvvvvvvv Thread::ShouldStop End (returning %i) vvvvvvvv", should_stop); @@ -947,13 +989,14 @@ Vote Thread::ShouldReportStop(Event *event_ptr) { return eVoteNoOpinion; } - if (m_completed_plan_stack.size() > 0) { - // Don't use GetCompletedPlan here, since that suppresses private plans. + if (GetPlans().AnyCompletedPlans()) { + // Pass skip_private = false to GetCompletedPlan, since we want to ask + // the last plan, regardless of whether it is private or not. LLDB_LOGF(log, "Thread::ShouldReportStop() tid = 0x%4.4" PRIx64 ": returning vote for complete stack's back plan", GetID()); - return m_completed_plan_stack.back()->ShouldReportStop(event_ptr); + return GetPlans().GetCompletedPlan(false)->ShouldReportStop(event_ptr); } else { Vote thread_vote = eVoteNoOpinion; ThreadPlan *plan_ptr = GetCurrentPlan(); @@ -962,7 +1005,7 @@ Vote Thread::ShouldReportStop(Event *event_ptr) { thread_vote = plan_ptr->ShouldReportStop(event_ptr); break; } - if (PlanIsBasePlan(plan_ptr)) + if (plan_ptr->IsBasePlan()) break; else plan_ptr = GetPreviousPlan(plan_ptr); @@ -984,16 +1027,17 @@ Vote Thread::ShouldReportRun(Event *event_ptr) { } Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (m_completed_plan_stack.size() > 0) { - // Don't use GetCompletedPlan here, since that suppresses private plans. + if (GetPlans().AnyCompletedPlans()) { + // Pass skip_private = false to GetCompletedPlan, since we want to ask + // the last plan, regardless of whether it is private or not. LLDB_LOGF(log, "Current Plan for thread %d(%p) (0x%4.4" PRIx64 ", %s): %s being asked whether we should report run.", GetIndexID(), static_cast<void *>(this), GetID(), StateAsCString(GetTemporaryResumeState()), - m_completed_plan_stack.back()->GetName()); + GetCompletedPlan()->GetName()); - return m_completed_plan_stack.back()->ShouldReportRun(event_ptr); + return GetPlans().GetCompletedPlan(false)->ShouldReportRun(event_ptr); } else { LLDB_LOGF(log, "Current Plan for thread %d(%p) (0x%4.4" PRIx64 @@ -1010,148 +1054,85 @@ bool Thread::MatchesSpec(const ThreadSpec *spec) { return (spec == nullptr) ? true : spec->ThreadPassesBasicTests(*this); } -void Thread::PushPlan(ThreadPlanSP &thread_plan_sp) { - if (thread_plan_sp) { - // If the thread plan doesn't already have a tracer, give it its parent's - // tracer: - if (!thread_plan_sp->GetThreadPlanTracer()) { - assert(!m_plan_stack.empty()); - thread_plan_sp->SetThreadPlanTracer( - m_plan_stack.back()->GetThreadPlanTracer()); - } - m_plan_stack.push_back(thread_plan_sp); +ThreadPlanStack &Thread::GetPlans() const { + ThreadPlanStack *plans = GetProcess()->FindThreadPlans(GetID()); + if (plans) + return *plans; - thread_plan_sp->DidPush(); + // History threads don't have a thread plan, but they do ask get asked to + // describe themselves, which usually involves pulling out the stop reason. + // That in turn will check for a completed plan on the ThreadPlanStack. + // Instead of special-casing at that point, we return a Stack with a + // ThreadPlanNull as its base plan. That will give the right answers to the + // queries GetDescription makes, and only assert if you try to run the thread. + if (!m_null_plan_stack_up) + m_null_plan_stack_up = std::make_unique<ThreadPlanStack>(*this, true); + return *(m_null_plan_stack_up.get()); +} - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) { - StreamString s; - thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull); - LLDB_LOGF(log, "Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 ".", - static_cast<void *>(this), s.GetData(), - thread_plan_sp->GetThread().GetID()); - } +void Thread::PushPlan(ThreadPlanSP thread_plan_sp) { + assert(thread_plan_sp && "Don't push an empty thread plan."); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log) { + StreamString s; + thread_plan_sp->GetDescription(&s, lldb::eDescriptionLevelFull); + LLDB_LOGF(log, "Thread::PushPlan(0x%p): \"%s\", tid = 0x%4.4" PRIx64 ".", + static_cast<void *>(this), s.GetData(), + thread_plan_sp->GetThread().GetID()); } + + GetPlans().PushPlan(std::move(thread_plan_sp)); } void Thread::PopPlan() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - - if (m_plan_stack.size() <= 1) - return; - else { - ThreadPlanSP &plan = m_plan_stack.back(); - if (log) { - LLDB_LOGF(log, "Popping plan: \"%s\", tid = 0x%4.4" PRIx64 ".", - plan->GetName(), plan->GetThread().GetID()); - } - m_completed_plan_stack.push_back(plan); - plan->WillPop(); - m_plan_stack.pop_back(); + ThreadPlanSP popped_plan_sp = GetPlans().PopPlan(); + if (log) { + LLDB_LOGF(log, "Popping plan: \"%s\", tid = 0x%4.4" PRIx64 ".", + popped_plan_sp->GetName(), popped_plan_sp->GetThread().GetID()); } } void Thread::DiscardPlan() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (m_plan_stack.size() > 1) { - ThreadPlanSP &plan = m_plan_stack.back(); - LLDB_LOGF(log, "Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".", - plan->GetName(), plan->GetThread().GetID()); - - m_discarded_plan_stack.push_back(plan); - plan->WillPop(); - m_plan_stack.pop_back(); - } -} + ThreadPlanSP discarded_plan_sp = GetPlans().PopPlan(); -ThreadPlan *Thread::GetCurrentPlan() { - // There will always be at least the base plan. If somebody is mucking with - // a thread with an empty plan stack, we should assert right away. - return m_plan_stack.empty() ? nullptr : m_plan_stack.back().get(); + LLDB_LOGF(log, "Discarding plan: \"%s\", tid = 0x%4.4" PRIx64 ".", + discarded_plan_sp->GetName(), + discarded_plan_sp->GetThread().GetID()); } -ThreadPlanSP Thread::GetCompletedPlan() { - ThreadPlanSP empty_plan_sp; - if (!m_completed_plan_stack.empty()) { - for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--) { - ThreadPlanSP completed_plan_sp; - completed_plan_sp = m_completed_plan_stack[i]; - if (!completed_plan_sp->GetPrivate()) - return completed_plan_sp; - } - } - return empty_plan_sp; +ThreadPlan *Thread::GetCurrentPlan() const { + return GetPlans().GetCurrentPlan().get(); } -ValueObjectSP Thread::GetReturnValueObject() { - if (!m_completed_plan_stack.empty()) { - for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--) { - ValueObjectSP return_valobj_sp; - return_valobj_sp = m_completed_plan_stack[i]->GetReturnValueObject(); - if (return_valobj_sp) - return return_valobj_sp; - } - } - return ValueObjectSP(); +ThreadPlanSP Thread::GetCompletedPlan() const { + return GetPlans().GetCompletedPlan(); } -ExpressionVariableSP Thread::GetExpressionVariable() { - if (!m_completed_plan_stack.empty()) { - for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--) { - ExpressionVariableSP expression_variable_sp; - expression_variable_sp = - m_completed_plan_stack[i]->GetExpressionVariable(); - if (expression_variable_sp) - return expression_variable_sp; - } - } - return ExpressionVariableSP(); +ValueObjectSP Thread::GetReturnValueObject() const { + return GetPlans().GetReturnValueObject(); } -bool Thread::IsThreadPlanDone(ThreadPlan *plan) { - if (!m_completed_plan_stack.empty()) { - for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--) { - if (m_completed_plan_stack[i].get() == plan) - return true; - } - } - return false; +ExpressionVariableSP Thread::GetExpressionVariable() const { + return GetPlans().GetExpressionVariable(); } -bool Thread::WasThreadPlanDiscarded(ThreadPlan *plan) { - if (!m_discarded_plan_stack.empty()) { - for (int i = m_discarded_plan_stack.size() - 1; i >= 0; i--) { - if (m_discarded_plan_stack[i].get() == plan) - return true; - } - } - return false; +bool Thread::IsThreadPlanDone(ThreadPlan *plan) const { + return GetPlans().IsPlanDone(plan); } -bool Thread::CompletedPlanOverridesBreakpoint() { - return (!m_completed_plan_stack.empty()) ; +bool Thread::WasThreadPlanDiscarded(ThreadPlan *plan) const { + return GetPlans().WasPlanDiscarded(plan); } -ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) { - if (current_plan == nullptr) - return nullptr; - - int stack_size = m_completed_plan_stack.size(); - for (int i = stack_size - 1; i > 0; i--) { - if (current_plan == m_completed_plan_stack[i].get()) - return m_completed_plan_stack[i - 1].get(); - } - - if (stack_size > 0 && m_completed_plan_stack[0].get() == current_plan) { - return GetCurrentPlan(); - } +bool Thread::CompletedPlanOverridesBreakpoint() const { + return GetPlans().AnyCompletedPlans(); +} - stack_size = m_plan_stack.size(); - for (int i = stack_size - 1; i > 0; i--) { - if (current_plan == m_plan_stack[i].get()) - return m_plan_stack[i - 1].get(); - } - return nullptr; +ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) const{ + return GetPlans().GetPreviousPlan(current_plan); } Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp, @@ -1185,38 +1166,18 @@ Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp, } void Thread::EnableTracer(bool value, bool single_stepping) { - int stack_size = m_plan_stack.size(); - for (int i = 0; i < stack_size; i++) { - if (m_plan_stack[i]->GetThreadPlanTracer()) { - m_plan_stack[i]->GetThreadPlanTracer()->EnableTracing(value); - m_plan_stack[i]->GetThreadPlanTracer()->EnableSingleStep(single_stepping); - } - } + GetPlans().EnableTracer(value, single_stepping); } void Thread::SetTracer(lldb::ThreadPlanTracerSP &tracer_sp) { - int stack_size = m_plan_stack.size(); - for (int i = 0; i < stack_size; i++) - m_plan_stack[i]->SetThreadPlanTracer(tracer_sp); + GetPlans().SetTracer(tracer_sp); } -bool Thread::DiscardUserThreadPlansUpToIndex(uint32_t thread_index) { +bool Thread::DiscardUserThreadPlansUpToIndex(uint32_t plan_index) { // Count the user thread plans from the back end to get the number of the one // we want to discard: - uint32_t idx = 0; - ThreadPlan *up_to_plan_ptr = nullptr; - - for (ThreadPlanSP plan_sp : m_plan_stack) { - if (plan_sp->GetPrivate()) - continue; - if (idx == thread_index) { - up_to_plan_ptr = plan_sp.get(); - break; - } else - idx++; - } - + ThreadPlan *up_to_plan_ptr = GetPlans().GetPlanByIndex(plan_index).get(); if (up_to_plan_ptr == nullptr) return false; @@ -1234,30 +1195,7 @@ void Thread::DiscardThreadPlansUpToPlan(ThreadPlan *up_to_plan_ptr) { "Discarding thread plans for thread tid = 0x%4.4" PRIx64 ", up to %p", GetID(), static_cast<void *>(up_to_plan_ptr)); - - int stack_size = m_plan_stack.size(); - - // If the input plan is nullptr, discard all plans. Otherwise make sure this - // plan is in the stack, and if so discard up to and including it. - - if (up_to_plan_ptr == nullptr) { - for (int i = stack_size - 1; i > 0; i--) - DiscardPlan(); - } else { - bool found_it = false; - for (int i = stack_size - 1; i > 0; i--) { - if (m_plan_stack[i].get() == up_to_plan_ptr) - found_it = true; - } - if (found_it) { - bool last_one = false; - for (int i = stack_size - 1; i > 0 && !last_one; i--) { - if (GetCurrentPlan() == up_to_plan_ptr) - last_one = true; - DiscardPlan(); - } - } - } + GetPlans().DiscardPlansUpToPlan(up_to_plan_ptr); } void Thread::DiscardThreadPlans(bool force) { @@ -1270,73 +1208,20 @@ void Thread::DiscardThreadPlans(bool force) { } if (force) { - int stack_size = m_plan_stack.size(); - for (int i = stack_size - 1; i > 0; i--) { - DiscardPlan(); - } + GetPlans().DiscardAllPlans(); return; } - - while (true) { - int master_plan_idx; - bool discard = true; - - // Find the first master plan, see if it wants discarding, and if yes - // discard up to it. - for (master_plan_idx = m_plan_stack.size() - 1; master_plan_idx >= 0; - master_plan_idx--) { - if (m_plan_stack[master_plan_idx]->IsMasterPlan()) { - discard = m_plan_stack[master_plan_idx]->OkayToDiscard(); - break; - } - } - - if (discard) { - // First pop all the dependent plans: - for (int i = m_plan_stack.size() - 1; i > master_plan_idx; i--) { - // FIXME: Do we need a finalize here, or is the rule that - // "PrepareForStop" - // for the plan leaves it in a state that it is safe to pop the plan - // with no more notice? - DiscardPlan(); - } - - // Now discard the master plan itself. - // The bottom-most plan never gets discarded. "OkayToDiscard" for it - // means discard it's dependent plans, but not it... - if (master_plan_idx > 0) { - DiscardPlan(); - } - } else { - // If the master plan doesn't want to get discarded, then we're done. - break; - } - } -} - -bool Thread::PlanIsBasePlan(ThreadPlan *plan_ptr) { - if (plan_ptr->IsBasePlan()) - return true; - else if (m_plan_stack.size() == 0) - return false; - else - return m_plan_stack[0].get() == plan_ptr; + GetPlans().DiscardConsultingMasterPlans(); } Status Thread::UnwindInnermostExpression() { Status error; - int stack_size = m_plan_stack.size(); - - // If the input plan is nullptr, discard all plans. Otherwise make sure this - // plan is in the stack, and if so discard up to and including it. - - for (int i = stack_size - 1; i > 0; i--) { - if (m_plan_stack[i]->GetKind() == ThreadPlan::eKindCallFunction) { - DiscardThreadPlansUpToPlan(m_plan_stack[i].get()); - return error; - } - } - error.SetErrorString("No expressions currently active on this thread"); + ThreadPlan *innermost_expr_plan = GetPlans().GetInnermostExpression(); + if (!innermost_expr_plan) { + error.SetErrorString("No expressions currently active on this thread"); + return error; + } + DiscardThreadPlansUpToPlan(innermost_expr_plan); return error; } @@ -1502,73 +1387,6 @@ lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted( uint32_t Thread::GetIndexID() const { return m_index_id; } -static void PrintPlanElement(Stream *s, const ThreadPlanSP &plan, - lldb::DescriptionLevel desc_level, - int32_t elem_idx) { - s->IndentMore(); - s->Indent(); - s->Printf("Element %d: ", elem_idx); - plan->GetDescription(s, desc_level); - s->EOL(); - s->IndentLess(); -} - -static void PrintPlanStack(Stream *s, - const std::vector<lldb::ThreadPlanSP> &plan_stack, - lldb::DescriptionLevel desc_level, - bool include_internal) { - int32_t print_idx = 0; - for (ThreadPlanSP plan_sp : plan_stack) { - if (include_internal || !plan_sp->GetPrivate()) { - PrintPlanElement(s, plan_sp, desc_level, print_idx++); - } - } -} - -void Thread::DumpThreadPlans(Stream *s, lldb::DescriptionLevel desc_level, - bool include_internal, - bool ignore_boring_threads) const { - uint32_t stack_size; - - if (ignore_boring_threads) { - uint32_t stack_size = m_plan_stack.size(); - uint32_t completed_stack_size = m_completed_plan_stack.size(); - uint32_t discarded_stack_size = m_discarded_plan_stack.size(); - if (stack_size == 1 && completed_stack_size == 0 && - discarded_stack_size == 0) { - s->Printf("thread #%u: tid = 0x%4.4" PRIx64 "\n", GetIndexID(), GetID()); - s->IndentMore(); - s->Indent(); - s->Printf("No active thread plans\n"); - s->IndentLess(); - return; - } - } - - s->Indent(); - s->Printf("thread #%u: tid = 0x%4.4" PRIx64 ":\n", GetIndexID(), GetID()); - s->IndentMore(); - s->Indent(); - s->Printf("Active plan stack:\n"); - PrintPlanStack(s, m_plan_stack, desc_level, include_internal); - - stack_size = m_completed_plan_stack.size(); - if (stack_size > 0) { - s->Indent(); - s->Printf("Completed Plan Stack:\n"); - PrintPlanStack(s, m_completed_plan_stack, desc_level, include_internal); - } - - stack_size = m_discarded_plan_stack.size(); - if (stack_size > 0) { - s->Indent(); - s->Printf("Discarded Plan Stack:\n"); - PrintPlanStack(s, m_discarded_plan_stack, desc_level, include_internal); - } - - s->IndentLess(); -} - TargetSP Thread::CalculateTarget() { TargetSP target_sp; ProcessSP process_sp(GetProcess()); @@ -1600,9 +1418,7 @@ StackFrameListSP Thread::GetStackFrameList() { void Thread::ClearStackFrames() { std::lock_guard<std::recursive_mutex> guard(m_frame_mutex); - Unwind *unwinder = GetUnwinder(); - if (unwinder) - unwinder->Clear(); + GetUnwinder().Clear(); // Only store away the old "reference" StackFrameList if we got all its // frames: @@ -1773,7 +1589,7 @@ Status Thread::JumpToLine(const FileSpec &file, uint32_t line, "first location:\n", file.GetFilename().AsCString(), line); DumpAddressList(sstr, candidates, target); - *warnings = sstr.GetString(); + *warnings = std::string(sstr.GetString()); } if (!reg_ctx->SetPC(dest)) @@ -2041,37 +1857,10 @@ size_t Thread::GetStackFrameStatus(Stream &strm, uint32_t first_frame, strm, first_frame, num_frames, show_frame_info, num_frames_with_source); } -Unwind *Thread::GetUnwinder() { - if (!m_unwinder_up) { - const ArchSpec target_arch(CalculateTarget()->GetArchitecture()); - const llvm::Triple::ArchType machine = target_arch.GetMachine(); - switch (machine) { - case llvm::Triple::x86_64: - case llvm::Triple::x86: - case llvm::Triple::arm: - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_32: - case llvm::Triple::thumb: - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::ppc64le: - case llvm::Triple::systemz: - case llvm::Triple::hexagon: - case llvm::Triple::arc: - m_unwinder_up.reset(new UnwindLLDB(*this)); - break; - - default: - if (target_arch.GetTriple().getVendor() == llvm::Triple::Apple) - m_unwinder_up.reset(new UnwindMacOSXFrameBackchain(*this)); - break; - } - } - return m_unwinder_up.get(); +Unwind &Thread::GetUnwinder() { + if (!m_unwinder_up) + m_unwinder_up = std::make_unique<UnwindLLDB>(*this); + return *m_unwinder_up; } void Thread::Flush() { |