Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Target/ThreadPlan.cpp
39587 views
1
//===-- ThreadPlan.cpp ----------------------------------------------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
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/LLDBLog.h"
16
#include "lldb/Utility/Log.h"
17
#include "lldb/Utility/State.h"
18
19
using namespace lldb;
20
using namespace lldb_private;
21
22
// ThreadPlan constructor
23
ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
24
Vote report_stop_vote, Vote report_run_vote)
25
: m_process(*thread.GetProcess().get()), m_tid(thread.GetID()),
26
m_report_stop_vote(report_stop_vote), m_report_run_vote(report_run_vote),
27
m_takes_iteration_count(false), m_could_not_resolve_hw_bp(false),
28
m_thread(&thread), m_kind(kind), m_name(name), m_plan_complete_mutex(),
29
m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),
30
m_plan_private(false), m_okay_to_discard(true),
31
m_is_controlling_plan(false), m_plan_succeeded(true) {
32
SetID(GetNextID());
33
}
34
35
// Destructor
36
ThreadPlan::~ThreadPlan() = default;
37
38
Target &ThreadPlan::GetTarget() { return m_process.GetTarget(); }
39
40
const Target &ThreadPlan::GetTarget() const { return m_process.GetTarget(); }
41
42
Thread &ThreadPlan::GetThread() {
43
if (m_thread)
44
return *m_thread;
45
46
ThreadSP thread_sp = m_process.GetThreadList().FindThreadByID(m_tid);
47
m_thread = thread_sp.get();
48
return *m_thread;
49
}
50
51
bool ThreadPlan::PlanExplainsStop(Event *event_ptr) {
52
if (m_cached_plan_explains_stop == eLazyBoolCalculate) {
53
bool actual_value = DoPlanExplainsStop(event_ptr);
54
CachePlanExplainsStop(actual_value);
55
return actual_value;
56
} else {
57
return m_cached_plan_explains_stop == eLazyBoolYes;
58
}
59
}
60
61
bool ThreadPlan::IsPlanComplete() {
62
std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
63
return m_plan_complete;
64
}
65
66
void ThreadPlan::SetPlanComplete(bool success) {
67
std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
68
m_plan_complete = true;
69
m_plan_succeeded = success;
70
}
71
72
bool ThreadPlan::MischiefManaged() {
73
std::lock_guard<std::recursive_mutex> guard(m_plan_complete_mutex);
74
// Mark the plan is complete, but don't override the success flag.
75
m_plan_complete = true;
76
return true;
77
}
78
79
Vote ThreadPlan::ShouldReportStop(Event *event_ptr) {
80
Log *log = GetLog(LLDBLog::Step);
81
82
if (m_report_stop_vote == eVoteNoOpinion) {
83
ThreadPlan *prev_plan = GetPreviousPlan();
84
if (prev_plan) {
85
Vote prev_vote = prev_plan->ShouldReportStop(event_ptr);
86
LLDB_LOG(log, "returning previous thread plan vote: {0}", prev_vote);
87
return prev_vote;
88
}
89
}
90
LLDB_LOG(log, "Returning vote: {0}", m_report_stop_vote);
91
return m_report_stop_vote;
92
}
93
94
Vote ThreadPlan::ShouldReportRun(Event *event_ptr) {
95
if (m_report_run_vote == eVoteNoOpinion) {
96
ThreadPlan *prev_plan = GetPreviousPlan();
97
if (prev_plan)
98
return prev_plan->ShouldReportRun(event_ptr);
99
}
100
return m_report_run_vote;
101
}
102
103
void ThreadPlan::ClearThreadCache() { m_thread = nullptr; }
104
105
bool ThreadPlan::StopOthers() {
106
ThreadPlan *prev_plan;
107
prev_plan = GetPreviousPlan();
108
return (prev_plan == nullptr) ? false : prev_plan->StopOthers();
109
}
110
111
void ThreadPlan::SetStopOthers(bool new_value) {
112
// SetStopOthers doesn't work up the hierarchy. You have to set the explicit
113
// ThreadPlan you want to affect.
114
}
115
116
bool ThreadPlan::WillResume(StateType resume_state, bool current_plan) {
117
m_cached_plan_explains_stop = eLazyBoolCalculate;
118
119
if (current_plan) {
120
Log *log = GetLog(LLDBLog::Step);
121
122
if (log) {
123
RegisterContext *reg_ctx = GetThread().GetRegisterContext().get();
124
assert(reg_ctx);
125
addr_t pc = reg_ctx->GetPC();
126
addr_t sp = reg_ctx->GetSP();
127
addr_t fp = reg_ctx->GetFP();
128
LLDB_LOGF(
129
log,
130
"%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64
131
", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "
132
"plan = '%s', state = %s, stop others = %d",
133
__FUNCTION__, GetThread().GetIndexID(),
134
static_cast<void *>(&GetThread()), m_tid, static_cast<uint64_t>(pc),
135
static_cast<uint64_t>(sp), static_cast<uint64_t>(fp), m_name.c_str(),
136
StateAsCString(resume_state), StopOthers());
137
}
138
}
139
bool success = DoWillResume(resume_state, current_plan);
140
ClearThreadCache(); // We don't cache the thread pointer over resumes. This
141
// Thread might go away, and another Thread represent
142
// the same underlying object on a later stop.
143
return success;
144
}
145
146
lldb::user_id_t ThreadPlan::GetNextID() {
147
static uint32_t g_nextPlanID = 0;
148
return ++g_nextPlanID;
149
}
150
151
void ThreadPlan::DidPush() {}
152
153
void ThreadPlan::DidPop() {}
154
155
bool ThreadPlan::OkayToDiscard() {
156
return IsControllingPlan() ? m_okay_to_discard : true;
157
}
158
159
lldb::StateType ThreadPlan::RunState() {
160
if (m_tracer_sp && m_tracer_sp->TracingEnabled())
161
return eStateStepping;
162
else
163
return GetPlanRunState();
164
}
165
166
bool ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason) {
167
switch (reason) {
168
case eStopReasonWatchpoint:
169
case eStopReasonSignal:
170
case eStopReasonException:
171
case eStopReasonExec:
172
case eStopReasonThreadExiting:
173
case eStopReasonInstrumentation:
174
case eStopReasonFork:
175
case eStopReasonVFork:
176
case eStopReasonVForkDone:
177
return true;
178
default:
179
return false;
180
}
181
}
182
183
// ThreadPlanNull
184
185
ThreadPlanNull::ThreadPlanNull(Thread &thread)
186
: ThreadPlan(ThreadPlan::eKindNull, "Null Thread Plan", thread,
187
eVoteNoOpinion, eVoteNoOpinion) {}
188
189
ThreadPlanNull::~ThreadPlanNull() = default;
190
191
void ThreadPlanNull::GetDescription(Stream *s, lldb::DescriptionLevel level) {
192
s->PutCString("Null thread plan - thread has been destroyed.");
193
}
194
195
bool ThreadPlanNull::ValidatePlan(Stream *error) {
196
#ifdef LLDB_CONFIGURATION_DEBUG
197
fprintf(stderr,
198
"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
199
", ptid = 0x%" PRIx64 ")",
200
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
201
#else
202
Log *log = GetLog(LLDBLog::Thread);
203
if (log)
204
log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
205
", ptid = 0x%" PRIx64 ")",
206
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
207
#endif
208
return true;
209
}
210
211
bool ThreadPlanNull::ShouldStop(Event *event_ptr) {
212
#ifdef LLDB_CONFIGURATION_DEBUG
213
fprintf(stderr,
214
"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
215
", ptid = 0x%" PRIx64 ")",
216
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
217
#else
218
Log *log = GetLog(LLDBLog::Thread);
219
if (log)
220
log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
221
", ptid = 0x%" PRIx64 ")",
222
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
223
#endif
224
return true;
225
}
226
227
bool ThreadPlanNull::WillStop() {
228
#ifdef LLDB_CONFIGURATION_DEBUG
229
fprintf(stderr,
230
"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
231
", ptid = 0x%" PRIx64 ")",
232
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
233
#else
234
Log *log = GetLog(LLDBLog::Thread);
235
if (log)
236
log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
237
", ptid = 0x%" PRIx64 ")",
238
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
239
#endif
240
return true;
241
}
242
243
bool ThreadPlanNull::DoPlanExplainsStop(Event *event_ptr) {
244
#ifdef LLDB_CONFIGURATION_DEBUG
245
fprintf(stderr,
246
"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
247
", ptid = 0x%" PRIx64 ")",
248
LLVM_PRETTY_FUNCTION, GetThread().GetID(), GetThread().GetProtocolID());
249
#else
250
Log *log = GetLog(LLDBLog::Thread);
251
if (log)
252
log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
253
", ptid = 0x%" PRIx64 ")",
254
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
255
#endif
256
return true;
257
}
258
259
// The null plan is never done.
260
bool ThreadPlanNull::MischiefManaged() {
261
// The null plan is never done.
262
#ifdef LLDB_CONFIGURATION_DEBUG
263
fprintf(stderr,
264
"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
265
", ptid = 0x%" PRIx64 ")",
266
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
267
#else
268
Log *log = GetLog(LLDBLog::Thread);
269
if (log)
270
log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
271
", ptid = 0x%" PRIx64 ")",
272
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
273
#endif
274
return false;
275
}
276
277
lldb::StateType ThreadPlanNull::GetPlanRunState() {
278
// Not sure what to return here. This is a dead thread.
279
#ifdef LLDB_CONFIGURATION_DEBUG
280
fprintf(stderr,
281
"error: %s called on thread that has been destroyed (tid = 0x%" PRIx64
282
", ptid = 0x%" PRIx64 ")",
283
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
284
#else
285
Log *log = GetLog(LLDBLog::Thread);
286
if (log)
287
log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64
288
", ptid = 0x%" PRIx64 ")",
289
LLVM_PRETTY_FUNCTION, m_tid, GetThread().GetProtocolID());
290
#endif
291
return eStateRunning;
292
}
293
294