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
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
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 SBError &error) {
331 LLDB_INSTRUMENT_VA(this, step_over, error);
332
333 ThreadPlanSP thread_plan_sp(GetSP());
334 if (thread_plan_sp) {
335 Status plan_status;
336 SBThreadPlan plan(
337 thread_plan_sp->GetThread().QueueThreadPlanForStepSingleInstruction(
338 step_over, false, false, plan_status));
339
340 if (plan_status.Fail())
341 error.SetErrorString(plan_status.AsCString());
342 else
343 plan.GetSP()->SetPrivate(true);
344
345 return plan;
346 }
347
348 return SBThreadPlan();
349}
350
353 LLDB_INSTRUMENT_VA(this, sb_address);
354
356 return QueueThreadPlanForRunToAddress(sb_address, error);
357}
358
360 SBError &error) {
361 LLDB_INSTRUMENT_VA(this, sb_address, error);
362
363 ThreadPlanSP thread_plan_sp(GetSP());
364 if (thread_plan_sp) {
365 Address *address = sb_address.get();
366 if (!address)
367 return SBThreadPlan();
368
369 Status plan_status;
370 SBThreadPlan plan =
371 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForRunToAddress(
372 false, *address, false, plan_status));
373
374 if (plan_status.Fail())
375 error.SetErrorString(plan_status.AsCString());
376 else
377 plan.GetSP()->SetPrivate(true);
378
379 return plan;
380 }
381 return SBThreadPlan();
382}
383
385SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) {
386 LLDB_INSTRUMENT_VA(this, script_class_name);
387
389 return QueueThreadPlanForStepScripted(script_class_name, error);
390}
391
394 SBError &error) {
395 LLDB_INSTRUMENT_VA(this, script_class_name, error);
396
397 ThreadPlanSP thread_plan_sp(GetSP());
398 if (thread_plan_sp) {
399 Status plan_status;
400 StructuredData::ObjectSP empty_args;
401 SBThreadPlan plan =
402 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted(
403 false, script_class_name, empty_args, false, plan_status));
404
405 if (plan_status.Fail())
406 error.SetErrorString(plan_status.AsCString());
407 else
408 plan.GetSP()->SetPrivate(true);
409
410 return plan;
411 }
412 return SBThreadPlan();
413}
414
417 lldb::SBStructuredData &args_data,
418 SBError &error) {
419 LLDB_INSTRUMENT_VA(this, script_class_name, args_data, error);
420
421 ThreadPlanSP thread_plan_sp(GetSP());
422 if (thread_plan_sp) {
423 Status plan_status;
424 StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP();
425 SBThreadPlan plan =
426 SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted(
427 false, script_class_name, args_obj, false, plan_status));
428
429 if (plan_status.Fail())
430 error.SetErrorString(plan_status.AsCString());
431 else
432 plan.GetSP()->SetPrivate(true);
433
434 return plan;
435 } else {
436 return SBThreadPlan();
437 }
438}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_INSTRUMENT_VA(...)
lldb_private::Address * get()
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
void SetThreadPlan(const lldb::ThreadPlanSP &lldb_object_sp)
void SetPlanComplete(bool success)
SBThreadPlan QueueThreadPlanForStepScripted(const char *script_class_name)
void SetStopOthers(bool stop_others)
SBThreadPlan QueueThreadPlanForStepSingleInstruction(bool step_over, SBError &error)
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
SBThreadPlan QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to, bool first_insn=false)
lldb_private::Thread * get()
A section + offset based address range class.
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:820
An error handling class.
Definition Status.h:118
bool Fail() const
Test for error condition.
Definition Status.cpp:294
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.
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::ThreadPlan > ThreadPlanSP
class LLDB_API SBThread
Definition SBDefines.h:115
@ eDescriptionLevelFull
uint64_t addr_t
Definition lldb-types.h:80
StopReason
Thread stop reasons.