xref: /openbsd-src/gnu/llvm/lldb/source/Target/ThreadPlan.cpp (revision 061da546b983eb767bad15e67af1174fb0bcf31c)
1*061da546Spatrick //===-- ThreadPlan.cpp ------------------------------------------*- C++ -*-===//
2*061da546Spatrick //
3*061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*061da546Spatrick //
7*061da546Spatrick //===----------------------------------------------------------------------===//
8*061da546Spatrick 
9*061da546Spatrick #include "lldb/Target/ThreadPlan.h"
10*061da546Spatrick #include "lldb/Core/Debugger.h"
11*061da546Spatrick #include "lldb/Target/Process.h"
12*061da546Spatrick #include "lldb/Target/RegisterContext.h"
13*061da546Spatrick #include "lldb/Target/Target.h"
14*061da546Spatrick #include "lldb/Target/Thread.h"
15*061da546Spatrick #include "lldb/Utility/Log.h"
16*061da546Spatrick #include "lldb/Utility/State.h"
17*061da546Spatrick 
18*061da546Spatrick using namespace lldb;
19*061da546Spatrick using namespace lldb_private;
20*061da546Spatrick 
21*061da546Spatrick // ThreadPlan constructor
22*061da546Spatrick ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
23*061da546Spatrick                        Vote stop_vote, Vote run_vote)
24*061da546Spatrick     : m_thread(thread), m_stop_vote(stop_vote), m_run_vote(run_vote),
25*061da546Spatrick       m_takes_iteration_count(false), m_could_not_resolve_hw_bp(false),
26*061da546Spatrick       m_kind(kind), m_name(name), m_plan_complete_mutex(),
27*061da546Spatrick       m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),
28*061da546Spatrick       m_plan_private(false), m_okay_to_discard(true), m_is_master_plan(false),
29*061da546Spatrick       m_plan_succeeded(true) {
30*061da546Spatrick   SetID(GetNextID());
31*061da546Spatrick }
32*061da546Spatrick 
33*061da546Spatrick // Destructor
34*061da546Spatrick ThreadPlan::~ThreadPlan() = default;
35*061da546Spatrick 
36*061da546Spatrick bool ThreadPlan::PlanExplainsStop(Event *event_ptr) {
37*061da546Spatrick   if (m_cached_plan_explains_stop == eLazyBoolCalculate) {
38*061da546Spatrick     bool actual_value = DoPlanExplainsStop(event_ptr);
39*061da546Spatrick     m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
40*061da546Spatrick     return actual_value;
41*061da546Spatrick   } else {
42*061da546Spatrick     return m_cached_plan_explains_stop == eLazyBoolYes;
43*061da546Spatrick   }
44*061da546Spatrick }
45*061da546Spatrick 
46*061da546Spatrick bool ThreadPlan::IsPlanComplete() {
47*061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
48*061da546Spatrick   return m_plan_complete;
49*061da546Spatrick }
50*061da546Spatrick 
51*061da546Spatrick void ThreadPlan::SetPlanComplete(bool success) {
52*061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
53*061da546Spatrick   m_plan_complete = true;
54*061da546Spatrick   m_plan_succeeded = success;
55*061da546Spatrick }
56*061da546Spatrick 
57*061da546Spatrick bool ThreadPlan::MischiefManaged() {
58*061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
59*061da546Spatrick   // Mark the plan is complete, but don't override the success flag.
60*061da546Spatrick   m_plan_complete = true;
61*061da546Spatrick   return true;
62*061da546Spatrick }
63*061da546Spatrick 
64*061da546Spatrick Vote ThreadPlan::ShouldReportStop(Event *event_ptr) {
65*061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
66*061da546Spatrick 
67*061da546Spatrick   if (m_stop_vote == eVoteNoOpinion) {
68*061da546Spatrick     ThreadPlan *prev_plan = GetPreviousPlan();
69*061da546Spatrick     if (prev_plan) {
70*061da546Spatrick       Vote prev_vote = prev_plan->ShouldReportStop(event_ptr);
71*061da546Spatrick       LLDB_LOG(log, "returning previous thread plan vote: {0}", prev_vote);
72*061da546Spatrick       return prev_vote;
73*061da546Spatrick     }
74*061da546Spatrick   }
75*061da546Spatrick   LLDB_LOG(log, "Returning vote: {0}", m_stop_vote);
76*061da546Spatrick   return m_stop_vote;
77*061da546Spatrick }
78*061da546Spatrick 
79*061da546Spatrick Vote ThreadPlan::ShouldReportRun(Event *event_ptr) {
80*061da546Spatrick   if (m_run_vote == eVoteNoOpinion) {
81*061da546Spatrick     ThreadPlan *prev_plan = GetPreviousPlan();
82*061da546Spatrick     if (prev_plan)
83*061da546Spatrick       return prev_plan->ShouldReportRun(event_ptr);
84*061da546Spatrick   }
85*061da546Spatrick   return m_run_vote;
86*061da546Spatrick }
87*061da546Spatrick 
88*061da546Spatrick bool ThreadPlan::StopOthers() {
89*061da546Spatrick   ThreadPlan *prev_plan;
90*061da546Spatrick   prev_plan = GetPreviousPlan();
91*061da546Spatrick   return (prev_plan == nullptr) ? false : prev_plan->StopOthers();
92*061da546Spatrick }
93*061da546Spatrick 
94*061da546Spatrick void ThreadPlan::SetStopOthers(bool new_value) {
95*061da546Spatrick   // SetStopOthers doesn't work up the hierarchy.  You have to set the explicit
96*061da546Spatrick   // ThreadPlan you want to affect.
97*061da546Spatrick }
98*061da546Spatrick 
99*061da546Spatrick bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) {
100*061da546Spatrick   m_cached_plan_explains_stop = eLazyBoolCalculate;
101*061da546Spatrick 
102*061da546Spatrick   if (current_plan) {
103*061da546Spatrick     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
104*061da546Spatrick 
105*061da546Spatrick     if (log) {
106*061da546Spatrick       RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
107*061da546Spatrick       assert(reg_ctx);
108*061da546Spatrick       addr_t pc = reg_ctx->GetPC();
109*061da546Spatrick       addr_t sp = reg_ctx->GetSP();
110*061da546Spatrick       addr_t fp = reg_ctx->GetFP();
111*061da546Spatrick       LLDB_LOGF(
112*061da546Spatrick           log,
113*061da546Spatrick           "%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64
114*061da546Spatrick           ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "
115*061da546Spatrick           "plan = '%s', state = %s, stop others = %d",
116*061da546Spatrick           __FUNCTION__, m_thread.GetIndexID(), static_cast<void *>(&m_thread),
117*061da546Spatrick           m_thread.GetID(), static_cast<uint64_t>(pc),
118*061da546Spatrick           static_cast<uint64_t>(sp), static_cast<uint64_t>(fp), m_name.c_str(),
119*061da546Spatrick           StateAsCString(resume_state), StopOthers());
120*061da546Spatrick     }
121*061da546Spatrick   }
122*061da546Spatrick   return DoWillResume(resume_state, current_plan);
123*061da546Spatrick }
124*061da546Spatrick 
125*061da546Spatrick lldb::user_id_t ThreadPlan::GetNextID() {
126*061da546Spatrick   static uint32_t g_nextPlanID = 0;
127*061da546Spatrick   return ++g_nextPlanID;
128*061da546Spatrick }
129*061da546Spatrick 
130*061da546Spatrick void ThreadPlan::DidPush() {}
131*061da546Spatrick 
132*061da546Spatrick void ThreadPlan::WillPop() {}
133*061da546Spatrick 
134*061da546Spatrick bool ThreadPlan::OkayToDiscard() {
135*061da546Spatrick   return IsMasterPlan() ? m_okay_to_discard : true;
136*061da546Spatrick }
137*061da546Spatrick 
138*061da546Spatrick lldb::StateType ThreadPlan::RunState() {
139*061da546Spatrick   if (m_tracer_sp && m_tracer_sp->TracingEnabled() &&
140*061da546Spatrick       m_tracer_sp->SingleStepEnabled())
141*061da546Spatrick     return eStateStepping;
142*061da546Spatrick   else
143*061da546Spatrick     return GetPlanRunState();
144*061da546Spatrick }
145*061da546Spatrick 
146*061da546Spatrick bool ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason) {
147*061da546Spatrick   switch (reason) {
148*061da546Spatrick   case eStopReasonWatchpoint:
149*061da546Spatrick   case eStopReasonSignal:
150*061da546Spatrick   case eStopReasonException:
151*061da546Spatrick   case eStopReasonExec:
152*061da546Spatrick   case eStopReasonThreadExiting:
153*061da546Spatrick   case eStopReasonInstrumentation:
154*061da546Spatrick     return true;
155*061da546Spatrick   default:
156*061da546Spatrick     return false;
157*061da546Spatrick   }
158*061da546Spatrick }
159*061da546Spatrick 
160*061da546Spatrick // ThreadPlanNull
161*061da546Spatrick 
162*061da546Spatrick ThreadPlanNull::ThreadPlanNull(Thread &thread)
163*061da546Spatrick     : ThreadPlan(ThreadPlan::eKindNull, "Null Thread Plan", thread,
164*061da546Spatrick                  eVoteNoOpinion, eVoteNoOpinion) {}
165*061da546Spatrick 
166*061da546Spatrick ThreadPlanNull::~ThreadPlanNull() = default;
167*061da546Spatrick 
168*061da546Spatrick void ThreadPlanNull::GetDescription(Stream *s, lldb::DescriptionLevel level) {
169*061da546Spatrick   s->PutCString("Null thread plan - thread has been destroyed.");
170*061da546Spatrick }
171*061da546Spatrick 
172*061da546Spatrick bool ThreadPlanNull::ValidatePlan(Stream *error) {
173*061da546Spatrick #ifdef LLDB_CONFIGURATION_DEBUG
174*061da546Spatrick   fprintf(stderr,
175*061da546Spatrick           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
176*061da546Spatrick           ", ptid = 0x%" PRIx64 ")",
177*061da546Spatrick           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
178*061da546Spatrick #else
179*061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
180*061da546Spatrick   if (log)
181*061da546Spatrick     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
182*061da546Spatrick                ", ptid = 0x%" PRIx64 ")",
183*061da546Spatrick                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
184*061da546Spatrick                m_thread.GetProtocolID());
185*061da546Spatrick #endif
186*061da546Spatrick   return true;
187*061da546Spatrick }
188*061da546Spatrick 
189*061da546Spatrick bool ThreadPlanNull::ShouldStop(Event *event_ptr) {
190*061da546Spatrick #ifdef LLDB_CONFIGURATION_DEBUG
191*061da546Spatrick   fprintf(stderr,
192*061da546Spatrick           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
193*061da546Spatrick           ", ptid = 0x%" PRIx64 ")",
194*061da546Spatrick           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
195*061da546Spatrick #else
196*061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
197*061da546Spatrick   if (log)
198*061da546Spatrick     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
199*061da546Spatrick                ", ptid = 0x%" PRIx64 ")",
200*061da546Spatrick                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
201*061da546Spatrick                m_thread.GetProtocolID());
202*061da546Spatrick #endif
203*061da546Spatrick   return true;
204*061da546Spatrick }
205*061da546Spatrick 
206*061da546Spatrick bool ThreadPlanNull::WillStop() {
207*061da546Spatrick #ifdef LLDB_CONFIGURATION_DEBUG
208*061da546Spatrick   fprintf(stderr,
209*061da546Spatrick           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
210*061da546Spatrick           ", ptid = 0x%" PRIx64 ")",
211*061da546Spatrick           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
212*061da546Spatrick #else
213*061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
214*061da546Spatrick   if (log)
215*061da546Spatrick     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
216*061da546Spatrick                ", ptid = 0x%" PRIx64 ")",
217*061da546Spatrick                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
218*061da546Spatrick                m_thread.GetProtocolID());
219*061da546Spatrick #endif
220*061da546Spatrick   return true;
221*061da546Spatrick }
222*061da546Spatrick 
223*061da546Spatrick bool ThreadPlanNull::DoPlanExplainsStop(Event *event_ptr) {
224*061da546Spatrick #ifdef LLDB_CONFIGURATION_DEBUG
225*061da546Spatrick   fprintf(stderr,
226*061da546Spatrick           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
227*061da546Spatrick           ", ptid = 0x%" PRIx64 ")",
228*061da546Spatrick           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
229*061da546Spatrick #else
230*061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
231*061da546Spatrick   if (log)
232*061da546Spatrick     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
233*061da546Spatrick                ", ptid = 0x%" PRIx64 ")",
234*061da546Spatrick                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
235*061da546Spatrick                m_thread.GetProtocolID());
236*061da546Spatrick #endif
237*061da546Spatrick   return true;
238*061da546Spatrick }
239*061da546Spatrick 
240*061da546Spatrick // The null plan is never done.
241*061da546Spatrick bool ThreadPlanNull::MischiefManaged() {
242*061da546Spatrick // The null plan is never done.
243*061da546Spatrick #ifdef LLDB_CONFIGURATION_DEBUG
244*061da546Spatrick   fprintf(stderr,
245*061da546Spatrick           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
246*061da546Spatrick           ", ptid = 0x%" PRIx64 ")",
247*061da546Spatrick           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
248*061da546Spatrick #else
249*061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
250*061da546Spatrick   if (log)
251*061da546Spatrick     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
252*061da546Spatrick                ", ptid = 0x%" PRIx64 ")",
253*061da546Spatrick                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
254*061da546Spatrick                m_thread.GetProtocolID());
255*061da546Spatrick #endif
256*061da546Spatrick   return false;
257*061da546Spatrick }
258*061da546Spatrick 
259*061da546Spatrick lldb::StateType ThreadPlanNull::GetPlanRunState() {
260*061da546Spatrick // Not sure what to return here.  This is a dead thread.
261*061da546Spatrick #ifdef LLDB_CONFIGURATION_DEBUG
262*061da546Spatrick   fprintf(stderr,
263*061da546Spatrick           "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
264*061da546Spatrick           ", ptid = 0x%" PRIx64 ")",
265*061da546Spatrick           LLVM_PRETTY_FUNCTION, m_thread.GetID(), m_thread.GetProtocolID());
266*061da546Spatrick #else
267*061da546Spatrick   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
268*061da546Spatrick   if (log)
269*061da546Spatrick     log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
270*061da546Spatrick                ", ptid = 0x%" PRIx64 ")",
271*061da546Spatrick                LLVM_PRETTY_FUNCTION, m_thread.GetID(),
272*061da546Spatrick                m_thread.GetProtocolID());
273*061da546Spatrick #endif
274*061da546Spatrick   return eStateRunning;
275*061da546Spatrick }
276