1 //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Target/ThreadPlan.h"
10 #include "lldb/Core/Debugger.h"
11 #include "lldb/Target/Process.h"
12 #include "lldb/Target/RegisterContext.h"
13 #include "lldb/Target/Target.h"
14 #include "lldb/Target/Thread.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/State.h"
19 using namespace lldb_private;
21 // ThreadPlan constructor
22 ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
23 Vote stop_vote, Vote run_vote)
24 : m_thread(thread), m_stop_vote(stop_vote), m_run_vote(run_vote),
25 m_takes_iteration_count(false), m_could_not_resolve_hw_bp(false),
26 m_kind(kind), m_name(name), m_plan_complete_mutex(),
27 m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),
28 m_plan_private(false), m_okay_to_discard(true), m_is_master_plan(false),
29 m_plan_succeeded(true) {
34 ThreadPlan::~ThreadPlan() = default;
36 bool ThreadPlan::PlanExplainsStop(Event *event_ptr) {
37 if (m_cached_plan_explains_stop == eLazyBoolCalculate) {
38 bool actual_value = DoPlanExplainsStop(event_ptr);
39 m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
42 return m_cached_plan_explains_stop == eLazyBoolYes;
46 bool ThreadPlan::IsPlanComplete() {
47 std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
48 return m_plan_complete;
51 void ThreadPlan::SetPlanComplete(bool success) {
52 std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
53 m_plan_complete = true;
54 m_plan_succeeded = success;
57 bool ThreadPlan::MischiefManaged() {
58 std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
59 // Mark the plan is complete, but don't override the success flag.
60 m_plan_complete = true;
64 Vote ThreadPlan::ShouldReportStop(Event *event_ptr) {
65 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
67 if (m_stop_vote == eVoteNoOpinion) {
68 ThreadPlan *prev_plan = GetPreviousPlan();
70 Vote prev_vote = prev_plan->ShouldReportStop(event_ptr);
71 LLDB_LOG(log, "returning previous thread plan vote: {0}", prev_vote);
75 LLDB_LOG(log, "Returning vote: {0}", m_stop_vote);
79 Vote ThreadPlan::ShouldReportRun(Event *event_ptr) {
80 if (m_run_vote == eVoteNoOpinion) {
81 ThreadPlan *prev_plan = GetPreviousPlan();
83 return prev_plan->ShouldReportRun(event_ptr);
88 bool ThreadPlan::StopOthers() {
89 ThreadPlan *prev_plan;
90 prev_plan = GetPreviousPlan();
91 return (prev_plan == nullptr) ? false : prev_plan->StopOthers();
94 void ThreadPlan::SetStopOthers(bool new_value) {
95 // SetStopOthers doesn't work up the hierarchy. You have to set the explicit
96 // ThreadPlan you want to affect.
99 bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) {
100 m_cached_plan_explains_stop = eLazyBoolCalculate;
103 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
106 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
108 addr_t pc = reg_ctx->GetPC();
109 addr_t sp = reg_ctx->GetSP();
110 addr_t fp = reg_ctx->GetFP();
112 "%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64
113 ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "
114 "plan = '%s', state = %s, stop others = %d",
115 __FUNCTION__, m_thread.GetIndexID(), static_cast<void *>(&m_thread),
116 m_thread.GetID(), static_cast<uint64_t>(pc),
117 static_cast<uint64_t>(sp), static_cast<uint64_t>(fp), m_name.c_str(),
118 StateAsCString(resume_state), StopOthers());
121 return DoWillResume(resume_state, current_plan);
124 lldb::user_id_t ThreadPlan::GetNextID() {
125 static uint32_t g_nextPlanID = 0;
126 return ++g_nextPlanID;
129 void ThreadPlan::DidPush() {}
131 void ThreadPlan::WillPop() {}
133 bool ThreadPlan::OkayToDiscard() {
134 return IsMasterPlan() ? m_okay_to_discard : true;
137 lldb::StateType ThreadPlan::RunState() {
138 if (m_tracer_sp && m_tracer_sp->TracingEnabled() &&
139 m_tracer_sp->SingleStepEnabled())
140 return eStateStepping;
142 return GetPlanRunState();
145 bool ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason) {
147 case eStopReasonWatchpoint:
148 case eStopReasonSignal:
149 case eStopReasonException:
150 case eStopReasonExec:
151 case eStopReasonThreadExiting:
152 case eStopReasonInstrumentation:
161 ThreadPlanNull::ThreadPlanNull(Thread &thread)
162 : ThreadPlan(ThreadPlan::eKindNull, "Null Thread Plan", thread,
163 eVoteNoOpinion, eVoteNoOpinion) {}
165 ThreadPlanNull::~ThreadPlanNull() = default;
167 void ThreadPlanNull::GetDescription(Stream *s, lldb::DescriptionLevel level) {
168 s->PutCString("Null thread plan - thread has been destroyed.");
171 bool ThreadPlanNull::ValidatePlan(Stream *error) {
172 #ifdef LLDB_CONFIGURATION_DEBUG
174 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
175 ", ptid = 0x%" PRIx64 ")",
176 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
178 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
180 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
181 ", ptid = 0x%" PRIx64 ")",
182 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
183 m_thread.GetProtocolID());
188 bool ThreadPlanNull::ShouldStop(Event *event_ptr) {
189 #ifdef LLDB_CONFIGURATION_DEBUG
191 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
192 ", ptid = 0x%" PRIx64 ")",
193 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
195 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
197 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
198 ", ptid = 0x%" PRIx64 ")",
199 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
200 m_thread.GetProtocolID());
205 bool ThreadPlanNull::WillStop() {
206 #ifdef LLDB_CONFIGURATION_DEBUG
208 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
209 ", ptid = 0x%" PRIx64 ")",
210 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
212 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
214 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
215 ", ptid = 0x%" PRIx64 ")",
216 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
217 m_thread.GetProtocolID());
222 bool ThreadPlanNull::DoPlanExplainsStop(Event *event_ptr) {
223 #ifdef LLDB_CONFIGURATION_DEBUG
225 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
226 ", ptid = 0x%" PRIx64 ")",
227 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
229 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
231 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
232 ", ptid = 0x%" PRIx64 ")",
233 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
234 m_thread.GetProtocolID());
239 // The null plan is never done.
240 bool ThreadPlanNull::MischiefManaged() {
241 // The null plan is never done.
242 #ifdef LLDB_CONFIGURATION_DEBUG
244 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
245 ", ptid = 0x%" PRIx64 ")",
246 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
248 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
250 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
251 ", ptid = 0x%" PRIx64 ")",
252 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
253 m_thread.GetProtocolID());
258 lldb::StateType ThreadPlanNull::GetPlanRunState() {
259 // Not sure what to return here. This is a dead thread.
260 #ifdef LLDB_CONFIGURATION_DEBUG
262 "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
263 ", ptid = 0x%" PRIx64 ")",
264 LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
266 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
268 log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
269 ", ptid = 0x%" PRIx64 ")",
270 LLVM_PRETTY_FUNCTION, m_thread.GetID(),
271 m_thread.GetProtocolID());
273 return eStateRunning;