1 //===-- SBThreadPlan.cpp --------------------------------------------------===//
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/API/SBThread.h"
10 #include "lldb/Utility/Instrumentation.h"
12 #include "lldb/API/SBFileSpec.h"
13 #include "lldb/API/SBStream.h"
14 #include "lldb/API/SBStructuredData.h"
15 #include "lldb/API/SBSymbolContext.h"
16 #include "lldb/Breakpoint/BreakpointLocation.h"
17 #include "lldb/Core/Debugger.h"
18 #include "lldb/Core/StructuredDataImpl.h"
19 #include "lldb/Interpreter/CommandInterpreter.h"
20 #include "lldb/Symbol/CompileUnit.h"
21 #include "lldb/Symbol/SymbolContext.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/Queue.h"
24 #include "lldb/Target/ScriptedThreadPlan.h"
25 #include "lldb/Target/StopInfo.h"
26 #include "lldb/Target/SystemRuntime.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Target/Thread.h"
29 #include "lldb/Target/ThreadPlan.h"
30 #include "lldb/Target/ThreadPlanStepInRange.h"
31 #include "lldb/Target/ThreadPlanStepInstruction.h"
32 #include "lldb/Target/ThreadPlanStepOut.h"
33 #include "lldb/Target/ThreadPlanStepRange.h"
34 #include "lldb/Utility/State.h"
35 #include "lldb/Utility/Stream.h"
36 #include "lldb/Utility/StructuredData.h"
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"
43 #include "lldb/API/SBThreadPlan.h"
44 #include "lldb/API/SBValue.h"
49 using namespace lldb_private
;
52 SBThreadPlan::SBThreadPlan() { LLDB_INSTRUMENT_VA(this); }
54 SBThreadPlan::SBThreadPlan(const ThreadPlanSP
&lldb_object_sp
)
55 : m_opaque_wp(lldb_object_sp
) {
56 LLDB_INSTRUMENT_VA(this, lldb_object_sp
);
59 SBThreadPlan::SBThreadPlan(const SBThreadPlan
&rhs
)
60 : m_opaque_wp(rhs
.m_opaque_wp
) {
61 LLDB_INSTRUMENT_VA(this, rhs
);
64 SBThreadPlan::SBThreadPlan(lldb::SBThread
&sb_thread
, const char *class_name
) {
65 LLDB_INSTRUMENT_VA(this, sb_thread
, class_name
);
67 Thread
*thread
= sb_thread
.get();
69 m_opaque_wp
= std::make_shared
<ScriptedThreadPlan
>(*thread
, class_name
,
70 StructuredDataImpl());
73 SBThreadPlan::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
);
77 Thread
*thread
= sb_thread
.get();
79 m_opaque_wp
= std::make_shared
<ScriptedThreadPlan
>(*thread
, class_name
,
80 *args_data
.m_impl_up
);
83 // Assignment operator
85 const lldb::SBThreadPlan
&SBThreadPlan::operator=(const SBThreadPlan
&rhs
) {
86 LLDB_INSTRUMENT_VA(this, rhs
);
89 m_opaque_wp
= rhs
.m_opaque_wp
;
93 SBThreadPlan::~SBThreadPlan() = default;
95 bool SBThreadPlan::IsValid() const {
96 LLDB_INSTRUMENT_VA(this);
97 return this->operator bool();
99 SBThreadPlan::operator bool() const {
100 LLDB_INSTRUMENT_VA(this);
102 return static_cast<bool>(GetSP());
105 void SBThreadPlan::Clear() {
106 LLDB_INSTRUMENT_VA(this);
111 lldb::StopReason
SBThreadPlan::GetStopReason() {
112 LLDB_INSTRUMENT_VA(this);
114 return eStopReasonNone
;
117 size_t SBThreadPlan::GetStopReasonDataCount() {
118 LLDB_INSTRUMENT_VA(this);
123 uint64_t SBThreadPlan::GetStopReasonDataAtIndex(uint32_t idx
) {
124 LLDB_INSTRUMENT_VA(this, idx
);
129 SBThread
SBThreadPlan::GetThread() const {
130 LLDB_INSTRUMENT_VA(this);
132 ThreadPlanSP
thread_plan_sp(GetSP());
133 if (thread_plan_sp
) {
134 return SBThread(thread_plan_sp
->GetThread().shared_from_this());
139 bool SBThreadPlan::GetDescription(lldb::SBStream
&description
) const {
140 LLDB_INSTRUMENT_VA(this, description
);
142 ThreadPlanSP
thread_plan_sp(GetSP());
143 if (thread_plan_sp
) {
144 thread_plan_sp
->GetDescription(description
.get(), eDescriptionLevelFull
);
146 description
.Printf("Empty SBThreadPlan");
151 void SBThreadPlan::SetThreadPlan(const ThreadPlanSP
&lldb_object_wp
) {
152 m_opaque_wp
= lldb_object_wp
;
155 void SBThreadPlan::SetPlanComplete(bool success
) {
156 LLDB_INSTRUMENT_VA(this, success
);
158 ThreadPlanSP
thread_plan_sp(GetSP());
160 thread_plan_sp
->SetPlanComplete(success
);
163 bool SBThreadPlan::IsPlanComplete() {
164 LLDB_INSTRUMENT_VA(this);
166 ThreadPlanSP
thread_plan_sp(GetSP());
168 return thread_plan_sp
->IsPlanComplete();
172 bool SBThreadPlan::IsPlanStale() {
173 LLDB_INSTRUMENT_VA(this);
175 ThreadPlanSP
thread_plan_sp(GetSP());
177 return thread_plan_sp
->IsPlanStale();
181 bool SBThreadPlan::IsValid() {
182 LLDB_INSTRUMENT_VA(this);
184 ThreadPlanSP
thread_plan_sp(GetSP());
186 return thread_plan_sp
->ValidatePlan(nullptr);
190 bool SBThreadPlan::GetStopOthers() {
191 LLDB_INSTRUMENT_VA(this);
193 ThreadPlanSP
thread_plan_sp(GetSP());
195 return thread_plan_sp
->StopOthers();
199 void SBThreadPlan::SetStopOthers(bool stop_others
) {
200 LLDB_INSTRUMENT_VA(this, stop_others
);
202 ThreadPlanSP
thread_plan_sp(GetSP());
204 thread_plan_sp
->SetStopOthers(stop_others
);
207 // This section allows an SBThreadPlan to push another of the common types of
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.
214 SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress
&sb_start_address
,
216 LLDB_INSTRUMENT_VA(this, sb_start_address
, size
);
219 return QueueThreadPlanForStepOverRange(sb_start_address
, size
, error
);
222 SBThreadPlan
SBThreadPlan::QueueThreadPlanForStepOverRange(
223 SBAddress
&sb_start_address
, lldb::addr_t size
, SBError
&error
) {
224 LLDB_INSTRUMENT_VA(this, sb_start_address
, size
, error
);
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();
233 AddressRange
range(*start_address
, size
);
235 start_address
->CalculateSymbolContext(&sc
);
238 SBThreadPlan plan
= SBThreadPlan(
239 thread_plan_sp
->GetThread().QueueThreadPlanForStepOverRange(
240 false, range
, sc
, eAllThreads
, plan_status
));
242 if (plan_status
.Fail())
243 error
.SetErrorString(plan_status
.AsCString());
245 plan
.GetSP()->SetPrivate(true);
249 return SBThreadPlan();
253 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress
&sb_start_address
,
255 LLDB_INSTRUMENT_VA(this, sb_start_address
, size
);
258 return QueueThreadPlanForStepInRange(sb_start_address
, size
, error
);
262 SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress
&sb_start_address
,
263 lldb::addr_t size
, SBError
&error
) {
264 LLDB_INSTRUMENT_VA(this, sb_start_address
, size
, error
);
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();
273 AddressRange
range(*start_address
, size
);
275 start_address
->CalculateSymbolContext(&sc
);
279 SBThreadPlan(thread_plan_sp
->GetThread().QueueThreadPlanForStepInRange(
280 false, range
, sc
, nullptr, eAllThreads
, plan_status
));
282 if (plan_status
.Fail())
283 error
.SetErrorString(plan_status
.AsCString());
285 plan
.GetSP()->SetPrivate(true);
289 return SBThreadPlan();
293 SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to
,
295 LLDB_INSTRUMENT_VA(this, frame_idx_to_step_to
, first_insn
);
298 return QueueThreadPlanForStepOut(frame_idx_to_step_to
, first_insn
, error
);
302 SBThreadPlan::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
);
306 ThreadPlanSP
thread_plan_sp(GetSP());
307 if (thread_plan_sp
) {
309 sc
= thread_plan_sp
->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext(
310 lldb::eSymbolContextEverything
);
314 SBThreadPlan(thread_plan_sp
->GetThread().QueueThreadPlanForStepOut(
315 false, &sc
, first_insn
, false, eVoteYes
, eVoteNoOpinion
,
316 frame_idx_to_step_to
, plan_status
));
318 if (plan_status
.Fail())
319 error
.SetErrorString(plan_status
.AsCString());
321 plan
.GetSP()->SetPrivate(true);
325 return SBThreadPlan();
329 SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address
) {
330 LLDB_INSTRUMENT_VA(this, sb_address
);
333 return QueueThreadPlanForRunToAddress(sb_address
, error
);
336 SBThreadPlan
SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address
,
338 LLDB_INSTRUMENT_VA(this, sb_address
, error
);
340 ThreadPlanSP
thread_plan_sp(GetSP());
341 if (thread_plan_sp
) {
342 Address
*address
= sb_address
.get();
344 return SBThreadPlan();
348 SBThreadPlan(thread_plan_sp
->GetThread().QueueThreadPlanForRunToAddress(
349 false, *address
, false, plan_status
));
351 if (plan_status
.Fail())
352 error
.SetErrorString(plan_status
.AsCString());
354 plan
.GetSP()->SetPrivate(true);
358 return SBThreadPlan();
362 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name
) {
363 LLDB_INSTRUMENT_VA(this, script_class_name
);
366 return QueueThreadPlanForStepScripted(script_class_name
, error
);
370 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name
,
372 LLDB_INSTRUMENT_VA(this, script_class_name
, error
);
374 ThreadPlanSP
thread_plan_sp(GetSP());
375 if (thread_plan_sp
) {
377 StructuredData::ObjectSP empty_args
;
379 SBThreadPlan(thread_plan_sp
->GetThread().QueueThreadPlanForStepScripted(
380 false, script_class_name
, empty_args
, false, plan_status
));
382 if (plan_status
.Fail())
383 error
.SetErrorString(plan_status
.AsCString());
385 plan
.GetSP()->SetPrivate(true);
389 return SBThreadPlan();
393 SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name
,
394 lldb::SBStructuredData
&args_data
,
396 LLDB_INSTRUMENT_VA(this, script_class_name
, args_data
, error
);
398 ThreadPlanSP
thread_plan_sp(GetSP());
399 if (thread_plan_sp
) {
401 StructuredData::ObjectSP args_obj
= args_data
.m_impl_up
->GetObjectSP();
403 SBThreadPlan(thread_plan_sp
->GetThread().QueueThreadPlanForStepScripted(
404 false, script_class_name
, args_obj
, false, plan_status
));
406 if (plan_status
.Fail())
407 error
.SetErrorString(plan_status
.AsCString());
409 plan
.GetSP()->SetPrivate(true);
413 return SBThreadPlan();