Path: blob/main/contrib/llvm-project/lldb/source/Target/ThreadPlan.cpp
39587 views
//===-- ThreadPlan.cpp ----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Target/ThreadPlan.h"9#include "lldb/Core/Debugger.h"10#include "lldb/Target/Process.h"11#include "lldb/Target/RegisterContext.h"12#include "lldb/Target/Target.h"13#include "lldb/Target/Thread.h"14#include "lldb/Utility/LLDBLog.h"15#include "lldb/Utility/Log.h"16#include "lldb/Utility/State.h"1718using namespace lldb;19using namespace lldb_private;2021// ThreadPlan constructor22ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,23Vote report_stop_vote, Vote report_run_vote)24: m_process(*thread.GetProcess().get()), m_tid(thread.GetID()),25m_report_stop_vote(report_stop_vote), m_report_run_vote(report_run_vote),26m_takes_iteration_count(false), m_could_not_resolve_hw_bp(false),27m_thread(&thread), m_kind(kind), m_name(name), m_plan_complete_mutex(),28m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),29m_plan_private(false), m_okay_to_discard(true),30m_is_controlling_plan(false), m_plan_succeeded(true) {31SetID(GetNextID());32}3334// Destructor35ThreadPlan::~ThreadPlan() = default;3637Target &ThreadPlan::GetTarget() { return m_process.GetTarget(); }3839const Target &ThreadPlan::GetTarget() const { return m_process.GetTarget(); }4041Thread &ThreadPlan::GetThread() {42if (m_thread)43return *m_thread;4445ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(m_tid);46m_thread = thread_sp.get();47return *m_thread;48}4950bool ThreadPlan::PlanExplainsStop(Event *event_ptr) {51if (m_cached_plan_explains_stop == eLazyBoolCalculate) {52bool actual_value = DoPlanExplainsStop(event_ptr);53CachePlanExplainsStop(actual_value);54return actual_value;55} else {56return m_cached_plan_explains_stop == eLazyBoolYes;57}58}5960bool ThreadPlan::IsPlanComplete() {61std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);62return m_plan_complete;63}6465void ThreadPlan::SetPlanComplete(bool success) {66std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);67m_plan_complete = true;68m_plan_succeeded = success;69}7071bool ThreadPlan::MischiefManaged() {72std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);73// Mark the plan is complete, but don't override the success flag.74m_plan_complete = true;75return true;76}7778Vote ThreadPlan::ShouldReportStop(Event *event_ptr) {79Log *log = GetLog(LLDBLog::Step);8081if (m_report_stop_vote == eVoteNoOpinion) {82ThreadPlan *prev_plan = GetPreviousPlan();83if (prev_plan) {84Vote prev_vote = prev_plan->ShouldReportStop(event_ptr);85LLDB_LOG(log, "returning previous thread plan vote: {0}", prev_vote);86return prev_vote;87}88}89LLDB_LOG(log, "Returning vote: {0}", m_report_stop_vote);90return m_report_stop_vote;91}9293Vote ThreadPlan::ShouldReportRun(Event *event_ptr) {94if (m_report_run_vote == eVoteNoOpinion) {95ThreadPlan *prev_plan = GetPreviousPlan();96if (prev_plan)97return prev_plan->ShouldReportRun(event_ptr);98}99return m_report_run_vote;100}101102void ThreadPlan::ClearThreadCache() { m_thread = nullptr; }103104bool ThreadPlan::StopOthers() {105ThreadPlan *prev_plan;106prev_plan = GetPreviousPlan();107return (prev_plan == nullptr) ? false : prev_plan->StopOthers();108}109110void ThreadPlan::SetStopOthers(bool new_value) {111// SetStopOthers doesn't work up the hierarchy. You have to set the explicit112// ThreadPlan you want to affect.113}114115bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) {116m_cached_plan_explains_stop = eLazyBoolCalculate;117118if (current_plan) {119Log *log = GetLog(LLDBLog::Step);120121if (log) {122RegisterContext *reg_ctx = GetThread().GetRegisterContext().get();123assert(reg_ctx);124addr_t pc = reg_ctx->GetPC();125addr_t sp = reg_ctx->GetSP();126addr_t fp = reg_ctx->GetFP();127LLDB_LOGF(128log,129"%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64130", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "131"plan = '%s', state = %s, stop others = %d",132__FUNCTION__, GetThread().GetIndexID(),133static_cast<void *>(&GetThread()), m_tid, static_cast<uint64_t>(pc),134static_cast<uint64_t>(sp), static_cast<uint64_t>(fp), m_name.c_str(),135StateAsCString(resume_state), StopOthers());136}137}138bool success = DoWillResume(resume_state, current_plan);139ClearThreadCache(); // We don't cache the thread pointer over resumes. This140// Thread might go away, and another Thread represent141// the same underlying object on a later stop.142return success;143}144145lldb::user_id_t ThreadPlan::GetNextID() {146static uint32_t g_nextPlanID = 0;147return ++g_nextPlanID;148}149150void ThreadPlan::DidPush() {}151152void ThreadPlan::DidPop() {}153154bool ThreadPlan::OkayToDiscard() {155return IsControllingPlan() ? m_okay_to_discard : true;156}157158lldb::StateType ThreadPlan::RunState() {159if (m_tracer_sp && m_tracer_sp->TracingEnabled())160return eStateStepping;161else162return GetPlanRunState();163}164165bool ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason) {166switch (reason) {167case eStopReasonWatchpoint:168case eStopReasonSignal:169case eStopReasonException:170case eStopReasonExec:171case eStopReasonThreadExiting:172case eStopReasonInstrumentation:173case eStopReasonFork:174case eStopReasonVFork:175case eStopReasonVForkDone:176return true;177default:178return false;179}180}181182// ThreadPlanNull183184ThreadPlanNull::ThreadPlanNull(Thread &thread)185: ThreadPlan(ThreadPlan::eKindNull, "Null Thread Plan", thread,186eVoteNoOpinion, eVoteNoOpinion) {}187188ThreadPlanNull::~ThreadPlanNull() = default;189190void ThreadPlanNull::GetDescription(Stream *s, lldb::DescriptionLevel level) {191s->PutCString("Null thread plan - thread has been destroyed.");192}193194bool ThreadPlanNull::ValidatePlan(Stream *error) {195#ifdef LLDB_CONFIGURATION_DEBUG196fprintf(stderr,197"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64198", ptid = 0x%" PRIx64 ")",199LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());200#else201Log *log = GetLog(LLDBLog::Thread);202if (log)203log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64204", ptid = 0x%" PRIx64 ")",205LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());206#endif207return true;208}209210bool ThreadPlanNull::ShouldStop(Event *event_ptr) {211#ifdef LLDB_CONFIGURATION_DEBUG212fprintf(stderr,213"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64214", ptid = 0x%" PRIx64 ")",215LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());216#else217Log *log = GetLog(LLDBLog::Thread);218if (log)219log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64220", ptid = 0x%" PRIx64 ")",221LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());222#endif223return true;224}225226bool ThreadPlanNull::WillStop() {227#ifdef LLDB_CONFIGURATION_DEBUG228fprintf(stderr,229"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64230", ptid = 0x%" PRIx64 ")",231LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());232#else233Log *log = GetLog(LLDBLog::Thread);234if (log)235log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64236", ptid = 0x%" PRIx64 ")",237LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());238#endif239return true;240}241242bool ThreadPlanNull::DoPlanExplainsStop(Event *event_ptr) {243#ifdef LLDB_CONFIGURATION_DEBUG244fprintf(stderr,245"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64246", ptid = 0x%" PRIx64 ")",247LLVM_PRETTY_FUNCTION, GetThread().GetID(), GetThread().GetProtocolID());248#else249Log *log = GetLog(LLDBLog::Thread);250if (log)251log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64252", ptid = 0x%" PRIx64 ")",253LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());254#endif255return true;256}257258// The null plan is never done.259bool ThreadPlanNull::MischiefManaged() {260// The null plan is never done.261#ifdef LLDB_CONFIGURATION_DEBUG262fprintf(stderr,263"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64264", ptid = 0x%" PRIx64 ")",265LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());266#else267Log *log = GetLog(LLDBLog::Thread);268if (log)269log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64270", ptid = 0x%" PRIx64 ")",271LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());272#endif273return false;274}275276lldb::StateType ThreadPlanNull::GetPlanRunState() {277// Not sure what to return here. This is a dead thread.278#ifdef LLDB_CONFIGURATION_DEBUG279fprintf(stderr,280"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64281", ptid = 0x%" PRIx64 ")",282LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());283#else284Log *log = GetLog(LLDBLog::Thread);285if (log)286log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64287", ptid = 0x%" PRIx64 ")",288LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());289#endif290return eStateRunning;291}292293294