LLDB mainline
SBThreadPlan.cpp
Go to the documentation of this file.
1//===-- SBThreadPlan.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/API/SBThread.h"
11
12#include "lldb/API/SBFileSpec.h"
13#include "lldb/API/SBStream.h"
17#include "lldb/Core/Debugger.h"
22#include "lldb/Target/Process.h"
23#include "lldb/Target/Queue.h"
27#include "lldb/Target/Target.h"
28#include "lldb/Target/Thread.h"
34#include "lldb/Utility/State.h"
35#include "lldb/Utility/Stream.h"
37
38#include "lldb/API/SBAddress.h"
39#include "lldb/API/SBDebugger.h"
40#include "lldb/API/SBEvent.h"
41#include "lldb/API/SBFrame.h"
42#include "lldb/API/SBProcess.h"
44#include "lldb/API/SBValue.h"
45
46#include <memory>
47
48using namespace lldb;
49using namespace lldb_private;
50
51// Constructors
53
55 : m_opaque_wp(lldb_object_sp) {
56 LLDB_INSTRUMENT_VA(this, lldb_object_sp);
57}
58
60 : m_opaque_wp(rhs.m_opaque_wp) {
61 LLDB_INSTRUMENT_VA(this, rhs);
62}
63
64SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name) {
65 LLDB_INSTRUMENT_VA(this, sb_thread, class_name);
66
67 Thread *thread = sb_thread.get();
68 if (thread)
69 m_opaque_wp = std::make_shared<ScriptedThreadPlan>(*thread, class_name,
71}
72
73SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name,
74 lldb::SBStructuredData &args_data) {
75 LLDB_INSTRUMENT_VA(this, sb_thread, class_name, args_data);
76
77 Thread *thread = sb_thread.get();
78 if (thread)
79 m_opaque_wp = std::make_shared<ScriptedThreadPlan>(*thread, class_name,
80 *args_data.m_impl_up);
81}
82
83// Assignment operator
84
86 LLDB_INSTRUMENT_VA(this, rhs);
87
88 if (this != &rhs)
90 return *this;
91}
92// Destructor
94
97 return this->operator bool();
98}
99SBThreadPlan::operator bool() const {
100 LLDB_INSTRUMENT_VA(this);
101
102 return static_cast<bool>(GetSP());
103}
104
106 LLDB_INSTRUMENT_VA(this);
107
108 m_opaque_wp.reset();
109}
110
112 LLDB_INSTRUMENT_VA(this);
113
114 return eStopReasonNone;
115}
116
118 LLDB_INSTRUMENT_VA(this);
119
120 return 0;
121}
122
124 LLDB_INSTRUMENT_VA(this, idx);
125
126 return 0;
127}
128
130 LLDB_INSTRUMENT_VA(this);
131
132 ThreadPlanSP thread_plan_sp(GetSP());
133 if (thread_plan_sp) {
134 return SBThread(thread_plan_sp->GetThread().shared_from_this());
135 } else
136 return SBThread();
137}
138
140 LLDB_INSTRUMENT_VA(this, description);
141
142 ThreadPlanSP thread_plan_sp(GetSP());
143 if (thread_plan_sp) {
144 thread_plan_sp->GetDescription(description.get(), eDescriptionLevelFull);
145 } else {
146 description.Printf("Empty SBThreadPlan");
147 }
148 return true;
149}
150
151void SBThreadPlan::SetThreadPlan(const ThreadPlanSP &lldb_object_wp) {
152 m_opaque_wp = lldb_object_wp;
153}
154
156 LLDB_INSTRUMENT_VA(this, success);
157
158 ThreadPlanSP thread_plan_sp(GetSP());
159 if (thread_plan_sp)
160 thread_plan_sp->SetPlanComplete(success);
161}
162
164 LLDB_INSTRUMENT_VA(this);
165
166 ThreadPlanSP thread_plan_sp(GetSP());
167 if (thread_plan_sp)
168 return thread_plan_sp->IsPlanComplete();
169 return true;
170}
171
173 LLDB_INSTRUMENT_VA(this);
174
175 ThreadPlanSP thread_plan_sp(GetSP());
176 if (thread_plan_sp)
177 return thread_plan_sp->IsPlanStale();
178 return true;
179}
180
182 LLDB_INSTRUMENT_VA(this);
183
184 ThreadPlanSP thread_plan_sp(GetSP());
185 if (thread_plan_sp)
186 return thread_plan_sp->ValidatePlan(nullptr);
187 return false;
188}
189
191 LLDB_INSTRUMENT_VA(this);
192
193 ThreadPlanSP thread_plan_sp(GetSP());
194 if (thread_plan_sp)
195 return thread_plan_sp->StopOthers();
196 return false;
197}
198
199void SBThreadPlan::SetStopOthers(bool stop_others) {
200 LLDB_INSTRUMENT_VA(this, stop_others);
201
202 ThreadPlanSP thread_plan_sp(GetSP());
203 if (thread_plan_sp)
204 thread_plan_sp->SetStopOthers(stop_others);
205}
206
207// This section allows an SBThreadPlan to push another of the common types of
208// plans...
209//
210// FIXME, you should only be able to queue thread plans from inside the methods
211// of a Scripted Thread Plan. Need a way to enforce that.
212
215 lldb::addr_t size) {
216 LLDB_INSTRUMENT_VA(this, sb_start_address, size);
217
219 return QueueThreadPlanForStepOverRange(sb_start_address, size, error);
220}
221
223 SBAddress &sb_start_address, lldb::addr_t size, SBError &error) {
224 LLDB_INSTRUMENT_VA(this, sb_start_address, size, error);
225
226 ThreadPlanSP thread_plan_sp(GetSP());
227 if (thread_plan_sp) {
228 Address *start_address = sb_start_address.get();
229 if (!start_address) {
230 return SBThreadPlan();
231 }
232
233 AddressRange range(*start_address, size);
234 SymbolContext sc;
235 start_address->CalculateSymbolContext(&sc);
236 Status plan_status;
237
239 thread_plan_sp->GetThread().QueueThreadPlanForStepOverRange(
240 false, range, sc, eAllThreads, plan_status));
241
242 if (plan_status.Fail())
243 error.SetErrorString(plan_status.AsCString());
244 else
245 plan.GetSP()->SetPrivate(true);
246
247 return plan;
248 }
249 return SBThreadPlan();
250}
251
254 lldb::addr_t size) {
255 LLDB_INSTRUMENT_VA(this, sb_start_address, size);
256
258 return QueueThreadPlanForStepInRange(sb_start_address, size, error);
259}
260
263 lldb::addr_t size, SBError &error) {
264 LLDB_INSTRUMENT_VA(this, sb_start_address, size, error);
265
266 ThreadPlanSP thread_plan_sp(GetSP());
267 if (thread_plan_sp) {
268 Address *start_address = sb_start_address.get();
269 if (!start_address) {
270 return SBThreadPlan();
271 }
272
273 AddressRange range(*start_address, size);
274 SymbolContext sc;
275 start_address->CalculateSymbolContext(&sc);
276
277 Status plan_status;
278 SBThreadPlan plan =
279 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepInRange(
280 false, range, sc, nullptr, eAllThreads, plan_status));
281
282 if (plan_status.Fail())
283 error.SetErrorString(plan_status.AsCString());
284 else
285 plan.GetSP()->SetPrivate(true);
286
287 return plan;
288 }
289 return SBThreadPlan();
290}
291
293SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
294 bool first_insn) {
295 LLDB_INSTRUMENT_VA(this, frame_idx_to_step_to, first_insn);
296
298 return QueueThreadPlanForStepOut(frame_idx_to_step_to, first_insn, error);
299}
300
302SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
303 bool first_insn, SBError &error) {
304 LLDB_INSTRUMENT_VA(this, frame_idx_to_step_to, first_insn, error);
305
306 ThreadPlanSP thread_plan_sp(GetSP());
307 if (thread_plan_sp) {
308 SymbolContext sc;
309 sc = thread_plan_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext(
310 lldb::eSymbolContextEverything);
311
312 Status plan_status;
313 SBThreadPlan plan =
314 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepOut(
315 false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion,
316 frame_idx_to_step_to, plan_status));
317
318 if (plan_status.Fail())
319 error.SetErrorString(plan_status.AsCString());
320 else
321 plan.GetSP()->SetPrivate(true);
322
323 return plan;
324 }
325 return SBThreadPlan();
326}
327
330 LLDB_INSTRUMENT_VA(this, sb_address);
331
333 return QueueThreadPlanForRunToAddress(sb_address, error);
334}
335
337 SBError &error) {
338 LLDB_INSTRUMENT_VA(this, sb_address, error);
339
340 ThreadPlanSP thread_plan_sp(GetSP());
341 if (thread_plan_sp) {
342 Address *address = sb_address.get();
343 if (!address)
344 return SBThreadPlan();
345
346 Status plan_status;
347 SBThreadPlan plan =
348 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForRunToAddress(
349 false, *address, false, plan_status));
350
351 if (plan_status.Fail())
352 error.SetErrorString(plan_status.AsCString());
353 else
354 plan.GetSP()->SetPrivate(true);
355
356 return plan;
357 }
358 return SBThreadPlan();
359}
360
362SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) {
363 LLDB_INSTRUMENT_VA(this, script_class_name);
364
366 return QueueThreadPlanForStepScripted(script_class_name, error);
367}
368
371 SBError &error) {
372 LLDB_INSTRUMENT_VA(this, script_class_name, error);
373
374 ThreadPlanSP thread_plan_sp(GetSP());
375 if (thread_plan_sp) {
376 Status plan_status;
377 StructuredData::ObjectSP empty_args;
378 SBThreadPlan plan =
379 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted(
380 false, script_class_name, empty_args, false, plan_status));
381
382 if (plan_status.Fail())
383 error.SetErrorString(plan_status.AsCString());
384 else
385 plan.GetSP()->SetPrivate(true);
386
387 return plan;
388 }
389 return SBThreadPlan();
390}
391
394 lldb::SBStructuredData &args_data,
395 SBError &error) {
396 LLDB_INSTRUMENT_VA(this, script_class_name, args_data, error);
397
398 ThreadPlanSP thread_plan_sp(GetSP());
399 if (thread_plan_sp) {
400 Status plan_status;
401 StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP();
402 SBThreadPlan plan =
403 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted(
404 false, script_class_name, args_obj, false, plan_status));
405
406 if (plan_status.Fail())
407 error.SetErrorString(plan_status.AsCString());
408 else
409 plan.GetSP()->SetPrivate(true);
410
411 return plan;
412 } else {
413 return SBThreadPlan();
414 }
415}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_INSTRUMENT_VA(...)
lldb_private::Address * get()
Definition: SBAddress.cpp:186
lldb_private::Stream * get()
Definition: SBStream.cpp:175
StructuredDataImplUP m_impl_up
lldb::StopReason GetStopReason()
SBThreadPlan QueueThreadPlanForStepInRange(SBAddress &start_address, lldb::addr_t range_size)
bool IsValid() const
bool GetDescription(lldb::SBStream &description) const
lldb::ThreadPlanSP GetSP() const
Definition: SBThreadPlan.h:134
void SetThreadPlan(const lldb::ThreadPlanSP &lldb_object_sp)
void SetPlanComplete(bool success)
SBThreadPlan QueueThreadPlanForStepScripted(const char *script_class_name)
void SetStopOthers(bool stop_others)
SBThread GetThread() const
const lldb::SBThreadPlan & operator=(const lldb::SBThreadPlan &rhs)
size_t GetStopReasonDataCount()
Get the number of words associated with the stop reason.
SBThreadPlan QueueThreadPlanForStepOverRange(SBAddress &start_address, lldb::addr_t range_size)
uint64_t GetStopReasonDataAtIndex(uint32_t idx)
Get information associated with a stop reason.
SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address)
lldb::ThreadPlanWP m_opaque_wp
Definition: SBThreadPlan.h:138
SBThreadPlan QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, bool first_insn=false)
lldb_private::Thread * get()
Definition: SBThread.cpp:1352
A section + offset based address range class.
Definition: AddressRange.h:25
A section + offset based address class.
Definition: Address.h:62
uint32_t CalculateSymbolContext(SymbolContext *sc, lldb::SymbolContextItem resolve_scope=lldb::eSymbolContextEverything) const
Reconstruct a symbol context from an address.
Definition: Address.cpp:832
An error handling class.
Definition: Status.h:115
bool Fail() const
Test for error condition.
Definition: Status.cpp:270
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:195
std::shared_ptr< Object > ObjectSP
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:34
A class that represents a running process on the host machine.
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::ThreadPlan > ThreadPlanSP
Definition: lldb-forward.h:453
@ eDescriptionLevelFull
uint64_t addr_t
Definition: lldb-types.h:80
StopReason
Thread stop reasons.