1//===-- SBThread.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"
10#include "Utils.h"
11#include "lldb/API/SBAddress.h"
12#include "lldb/API/SBDebugger.h"
13#include "lldb/API/SBEvent.h"
14#include "lldb/API/SBFileSpec.h"
15#include "lldb/API/SBFormat.h"
16#include "lldb/API/SBFrame.h"
17#include "lldb/API/SBProcess.h"
18#include "lldb/API/SBStream.h"
19#include "lldb/API/SBStructuredData.h"
20#include "lldb/API/SBSymbolContext.h"
21#include "lldb/API/SBThreadCollection.h"
22#include "lldb/API/SBThreadPlan.h"
23#include "lldb/API/SBValue.h"
24#include "lldb/Breakpoint/BreakpointLocation.h"
25#include "lldb/Core/Debugger.h"
26#include "lldb/Core/StructuredDataImpl.h"
27#include "lldb/Interpreter/CommandInterpreter.h"
28#include "lldb/Symbol/CompileUnit.h"
29#include "lldb/Symbol/SymbolContext.h"
30#include "lldb/Target/Process.h"
31#include "lldb/Target/Queue.h"
32#include "lldb/Target/StopInfo.h"
33#include "lldb/Target/SystemRuntime.h"
34#include "lldb/Target/Target.h"
35#include "lldb/Target/Thread.h"
36#include "lldb/Target/ThreadPlan.h"
37#include "lldb/Target/ThreadPlanStepInRange.h"
38#include "lldb/Target/ThreadPlanStepInstruction.h"
39#include "lldb/Target/ThreadPlanStepOut.h"
40#include "lldb/Target/ThreadPlanStepRange.h"
41#include "lldb/Utility/Instrumentation.h"
42#include "lldb/Utility/State.h"
43#include "lldb/Utility/Stream.h"
44#include "lldb/Utility/StructuredData.h"
45#include "lldb/ValueObject/ValueObject.h"
46#include "lldb/lldb-enumerations.h"
47
48#include <memory>
49
50using namespace lldb;
51using namespace lldb_private;
52
53const char *SBThread::GetBroadcasterClassName() {
54 LLDB_INSTRUMENT();
55
56 return ConstString(Thread::GetStaticBroadcasterClass()).AsCString();
57}
58
59// Constructors
60SBThread::SBThread() : m_opaque_sp(new ExecutionContextRef()) {
61 LLDB_INSTRUMENT_VA(this);
62}
63
64SBThread::SBThread(const ThreadSP &lldb_object_sp)
65 : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) {
66 LLDB_INSTRUMENT_VA(this, lldb_object_sp);
67}
68
69SBThread::SBThread(const SBThread &rhs) {
70 LLDB_INSTRUMENT_VA(this, rhs);
71
72 m_opaque_sp = clone(src: rhs.m_opaque_sp);
73}
74
75// Assignment operator
76
77const lldb::SBThread &SBThread::operator=(const SBThread &rhs) {
78 LLDB_INSTRUMENT_VA(this, rhs);
79
80 if (this != &rhs)
81 m_opaque_sp = clone(src: rhs.m_opaque_sp);
82 return *this;
83}
84
85// Destructor
86SBThread::~SBThread() = default;
87
88lldb::SBQueue SBThread::GetQueue() const {
89 LLDB_INSTRUMENT_VA(this);
90
91 SBQueue sb_queue;
92 QueueSP queue_sp;
93 std::unique_lock<std::recursive_mutex> lock;
94 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
95
96 if (exe_ctx.HasThreadScope()) {
97 Process::StopLocker stop_locker;
98 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
99 queue_sp = exe_ctx.GetThreadPtr()->GetQueue();
100 if (queue_sp) {
101 sb_queue.SetQueue(queue_sp);
102 }
103 }
104 }
105
106 return sb_queue;
107}
108
109bool SBThread::IsValid() const {
110 LLDB_INSTRUMENT_VA(this);
111 return this->operator bool();
112}
113SBThread::operator bool() const {
114 LLDB_INSTRUMENT_VA(this);
115
116 std::unique_lock<std::recursive_mutex> lock;
117 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
118
119 Target *target = exe_ctx.GetTargetPtr();
120 Process *process = exe_ctx.GetProcessPtr();
121 if (target && process) {
122 Process::StopLocker stop_locker;
123 if (stop_locker.TryLock(lock: &process->GetRunLock()))
124 return m_opaque_sp->GetThreadSP().get() != nullptr;
125 }
126 // Without a valid target & process, this thread can't be valid.
127 return false;
128}
129
130void SBThread::Clear() {
131 LLDB_INSTRUMENT_VA(this);
132
133 m_opaque_sp->Clear();
134}
135
136StopReason SBThread::GetStopReason() {
137 LLDB_INSTRUMENT_VA(this);
138
139 StopReason reason = eStopReasonInvalid;
140 std::unique_lock<std::recursive_mutex> lock;
141 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
142
143 if (exe_ctx.HasThreadScope()) {
144 Process::StopLocker stop_locker;
145 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
146 return exe_ctx.GetThreadPtr()->GetStopReason();
147 }
148 }
149
150 return reason;
151}
152
153size_t SBThread::GetStopReasonDataCount() {
154 LLDB_INSTRUMENT_VA(this);
155
156 std::unique_lock<std::recursive_mutex> lock;
157 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
158
159 if (exe_ctx.HasThreadScope()) {
160 Process::StopLocker stop_locker;
161 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
162 StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
163 if (stop_info_sp) {
164 StopReason reason = stop_info_sp->GetStopReason();
165 switch (reason) {
166 case eStopReasonInvalid:
167 case eStopReasonNone:
168 case eStopReasonTrace:
169 case eStopReasonExec:
170 case eStopReasonPlanComplete:
171 case eStopReasonThreadExiting:
172 case eStopReasonInstrumentation:
173 case eStopReasonProcessorTrace:
174 case eStopReasonVForkDone:
175 case eStopReasonHistoryBoundary:
176 // There is no data for these stop reasons.
177 return 0;
178
179 case eStopReasonBreakpoint: {
180 break_id_t site_id = stop_info_sp->GetValue();
181 lldb::BreakpointSiteSP bp_site_sp(
182 exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
183 site_id));
184 if (bp_site_sp)
185 return bp_site_sp->GetNumberOfConstituents() * 2;
186 else
187 return 0; // Breakpoint must have cleared itself...
188 } break;
189
190 case eStopReasonWatchpoint:
191 return 1;
192
193 case eStopReasonSignal:
194 return 1;
195
196 case eStopReasonInterrupt:
197 return 1;
198
199 case eStopReasonException:
200 return 1;
201
202 case eStopReasonFork:
203 return 1;
204
205 case eStopReasonVFork:
206 return 1;
207 }
208 }
209 }
210 }
211 return 0;
212}
213
214uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
215 LLDB_INSTRUMENT_VA(this, idx);
216
217 std::unique_lock<std::recursive_mutex> lock;
218 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
219
220 if (exe_ctx.HasThreadScope()) {
221 Process::StopLocker stop_locker;
222 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
223 Thread *thread = exe_ctx.GetThreadPtr();
224 StopInfoSP stop_info_sp = thread->GetStopInfo();
225 if (stop_info_sp) {
226 StopReason reason = stop_info_sp->GetStopReason();
227 switch (reason) {
228 case eStopReasonInvalid:
229 case eStopReasonNone:
230 case eStopReasonTrace:
231 case eStopReasonExec:
232 case eStopReasonPlanComplete:
233 case eStopReasonThreadExiting:
234 case eStopReasonInstrumentation:
235 case eStopReasonProcessorTrace:
236 case eStopReasonVForkDone:
237 case eStopReasonHistoryBoundary:
238 // There is no data for these stop reasons.
239 return 0;
240
241 case eStopReasonBreakpoint: {
242 break_id_t site_id = stop_info_sp->GetValue();
243 lldb::BreakpointSiteSP bp_site_sp(
244 exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
245 site_id));
246 if (bp_site_sp) {
247 uint32_t bp_index = idx / 2;
248 BreakpointLocationSP bp_loc_sp(
249 bp_site_sp->GetConstituentAtIndex(idx: bp_index));
250 if (bp_loc_sp) {
251 if (idx & 1) {
252 // Odd idx, return the breakpoint location ID
253 return bp_loc_sp->GetID();
254 } else {
255 // Even idx, return the breakpoint ID
256 return bp_loc_sp->GetBreakpoint().GetID();
257 }
258 }
259 }
260 return LLDB_INVALID_BREAK_ID;
261 } break;
262
263 case eStopReasonWatchpoint:
264 return stop_info_sp->GetValue();
265
266 case eStopReasonSignal:
267 return stop_info_sp->GetValue();
268
269 case eStopReasonInterrupt:
270 return stop_info_sp->GetValue();
271
272 case eStopReasonException:
273 return stop_info_sp->GetValue();
274
275 case eStopReasonFork:
276 return stop_info_sp->GetValue();
277
278 case eStopReasonVFork:
279 return stop_info_sp->GetValue();
280 }
281 }
282 }
283 }
284 return 0;
285}
286
287bool SBThread::GetStopReasonExtendedInfoAsJSON(lldb::SBStream &stream) {
288 LLDB_INSTRUMENT_VA(this, stream);
289
290 Stream &strm = stream.ref();
291
292 std::unique_lock<std::recursive_mutex> lock;
293 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
294
295 if (!exe_ctx.HasThreadScope())
296 return false;
297
298 StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
299 StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
300 if (!info)
301 return false;
302
303 info->Dump(s&: strm);
304
305 return true;
306}
307
308SBThreadCollection
309SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) {
310 LLDB_INSTRUMENT_VA(this, type);
311
312 SBThreadCollection threads;
313
314 std::unique_lock<std::recursive_mutex> lock;
315 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
316
317 if (!exe_ctx.HasThreadScope())
318 return SBThreadCollection();
319
320 ProcessSP process_sp = exe_ctx.GetProcessSP();
321
322 StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
323 StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
324 if (!info)
325 return threads;
326
327 threads = process_sp->GetInstrumentationRuntime(type)
328 ->GetBacktracesFromExtendedStopInfo(info);
329 return threads;
330}
331
332size_t SBThread::GetStopDescription(char *dst, size_t dst_len) {
333 LLDB_INSTRUMENT_VA(this, dst, dst_len);
334
335 std::unique_lock<std::recursive_mutex> lock;
336 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
337
338 if (dst)
339 *dst = 0;
340
341 if (!exe_ctx.HasThreadScope())
342 return 0;
343
344 Process::StopLocker stop_locker;
345 if (!stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock()))
346 return 0;
347
348 std::string thread_stop_desc = exe_ctx.GetThreadPtr()->GetStopDescription();
349 if (thread_stop_desc.empty())
350 return 0;
351
352 if (dst)
353 return ::snprintf(s: dst, maxlen: dst_len, format: "%s", thread_stop_desc.c_str()) + 1;
354
355 // NULL dst passed in, return the length needed to contain the
356 // description.
357 return thread_stop_desc.size() + 1; // Include the NULL byte for size
358}
359
360SBValue SBThread::GetStopReturnValue() {
361 LLDB_INSTRUMENT_VA(this);
362
363 ValueObjectSP return_valobj_sp;
364 std::unique_lock<std::recursive_mutex> lock;
365 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
366
367 if (exe_ctx.HasThreadScope()) {
368 Process::StopLocker stop_locker;
369 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
370 StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
371 if (stop_info_sp) {
372 return_valobj_sp = StopInfo::GetReturnValueObject(stop_info_sp);
373 }
374 }
375 }
376
377 return SBValue(return_valobj_sp);
378}
379
380void SBThread::SetThread(const ThreadSP &lldb_object_sp) {
381 m_opaque_sp->SetThreadSP(lldb_object_sp);
382}
383
384lldb::tid_t SBThread::GetThreadID() const {
385 LLDB_INSTRUMENT_VA(this);
386
387 ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
388 if (thread_sp)
389 return thread_sp->GetID();
390 return LLDB_INVALID_THREAD_ID;
391}
392
393uint32_t SBThread::GetIndexID() const {
394 LLDB_INSTRUMENT_VA(this);
395
396 ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
397 if (thread_sp)
398 return thread_sp->GetIndexID();
399 return LLDB_INVALID_INDEX32;
400}
401
402const char *SBThread::GetName() const {
403 LLDB_INSTRUMENT_VA(this);
404
405 std::unique_lock<std::recursive_mutex> lock;
406 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
407
408 if (!exe_ctx.HasThreadScope())
409 return nullptr;
410
411 Process::StopLocker stop_locker;
412 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock()))
413 return ConstString(exe_ctx.GetThreadPtr()->GetName()).GetCString();
414
415 return nullptr;
416}
417
418const char *SBThread::GetQueueName() const {
419 LLDB_INSTRUMENT_VA(this);
420
421 std::unique_lock<std::recursive_mutex> lock;
422 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
423
424 if (!exe_ctx.HasThreadScope())
425 return nullptr;
426
427 Process::StopLocker stop_locker;
428 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock()))
429 return ConstString(exe_ctx.GetThreadPtr()->GetQueueName()).GetCString();
430
431 return nullptr;
432}
433
434lldb::queue_id_t SBThread::GetQueueID() const {
435 LLDB_INSTRUMENT_VA(this);
436
437 queue_id_t id = LLDB_INVALID_QUEUE_ID;
438 std::unique_lock<std::recursive_mutex> lock;
439 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
440
441 if (exe_ctx.HasThreadScope()) {
442 Process::StopLocker stop_locker;
443 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
444 id = exe_ctx.GetThreadPtr()->GetQueueID();
445 }
446 }
447
448 return id;
449}
450
451bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
452 LLDB_INSTRUMENT_VA(this, path, strm);
453
454 bool success = false;
455 std::unique_lock<std::recursive_mutex> lock;
456 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
457
458 if (exe_ctx.HasThreadScope()) {
459 Process::StopLocker stop_locker;
460 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
461 Thread *thread = exe_ctx.GetThreadPtr();
462 StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo();
463 if (info_root_sp) {
464 StructuredData::ObjectSP node =
465 info_root_sp->GetObjectForDotSeparatedPath(path);
466 if (node) {
467 if (node->GetType() == eStructuredDataTypeString) {
468 strm.ref() << node->GetAsString()->GetValue();
469 success = true;
470 }
471 if (node->GetType() == eStructuredDataTypeInteger) {
472 strm.Printf(format: "0x%" PRIx64, node->GetUnsignedIntegerValue());
473 success = true;
474 }
475 if (node->GetType() == eStructuredDataTypeFloat) {
476 strm.Printf(format: "0x%f", node->GetAsFloat()->GetValue());
477 success = true;
478 }
479 if (node->GetType() == eStructuredDataTypeBoolean) {
480 if (node->GetAsBoolean()->GetValue())
481 strm.Printf(format: "true");
482 else
483 strm.Printf(format: "false");
484 success = true;
485 }
486 if (node->GetType() == eStructuredDataTypeNull) {
487 strm.Printf(format: "null");
488 success = true;
489 }
490 }
491 }
492 }
493 }
494
495 return success;
496}
497
498SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx,
499 ThreadPlan *new_plan) {
500 SBError sb_error;
501
502 Process *process = exe_ctx.GetProcessPtr();
503 if (!process) {
504 sb_error = Status::FromErrorString(str: "No process in SBThread::ResumeNewPlan");
505 return sb_error;
506 }
507
508 Thread *thread = exe_ctx.GetThreadPtr();
509 if (!thread) {
510 sb_error = Status::FromErrorString(str: "No thread in SBThread::ResumeNewPlan");
511 return sb_error;
512 }
513
514 // User level plans should be Controlling Plans so they can be interrupted,
515 // other plans executed, and then a "continue" will resume the plan.
516 if (new_plan != nullptr) {
517 new_plan->SetIsControllingPlan(true);
518 new_plan->SetOkayToDiscard(false);
519 }
520
521 // Why do we need to set the current thread by ID here???
522 process->GetThreadList().SetSelectedThreadByID(tid: thread->GetID());
523
524 if (process->GetTarget().GetDebugger().GetAsyncExecution())
525 sb_error.ref() = process->Resume();
526 else
527 sb_error.ref() = process->ResumeSynchronous(stream: nullptr);
528
529 return sb_error;
530}
531
532void SBThread::StepOver(lldb::RunMode stop_other_threads) {
533 LLDB_INSTRUMENT_VA(this, stop_other_threads);
534
535 SBError error; // Ignored
536 StepOver(stop_other_threads, error);
537}
538
539void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) {
540 LLDB_INSTRUMENT_VA(this, stop_other_threads, error);
541
542 std::unique_lock<std::recursive_mutex> lock;
543 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
544
545 if (!exe_ctx.HasThreadScope()) {
546 error = Status::FromErrorString(str: "this SBThread object is invalid");
547 return;
548 }
549
550 Thread *thread = exe_ctx.GetThreadPtr();
551 bool abort_other_plans = false;
552 StackFrameSP frame_sp(thread->GetStackFrameAtIndex(idx: 0));
553
554 Status new_plan_status;
555 ThreadPlanSP new_plan_sp;
556 if (frame_sp) {
557 if (frame_sp->HasDebugInformation()) {
558 const LazyBool avoid_no_debug = eLazyBoolCalculate;
559 SymbolContext sc(frame_sp->GetSymbolContext(resolve_scope: eSymbolContextEverything));
560 new_plan_sp = thread->QueueThreadPlanForStepOverRange(
561 abort_other_plans, line_entry: sc.line_entry, addr_context: sc, stop_other_threads,
562 status&: new_plan_status, step_out_avoids_code_without_debug_info: avoid_no_debug);
563 } else {
564 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
565 step_over: true, abort_other_plans, stop_other_threads, status&: new_plan_status);
566 }
567 }
568 error = ResumeNewPlan(exe_ctx, new_plan: new_plan_sp.get());
569}
570
571void SBThread::StepInto(lldb::RunMode stop_other_threads) {
572 LLDB_INSTRUMENT_VA(this, stop_other_threads);
573
574 StepInto(target_name: nullptr, stop_other_threads);
575}
576
577void SBThread::StepInto(const char *target_name,
578 lldb::RunMode stop_other_threads) {
579 LLDB_INSTRUMENT_VA(this, target_name, stop_other_threads);
580
581 SBError error; // Ignored
582 StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads);
583}
584
585void SBThread::StepInto(const char *target_name, uint32_t end_line,
586 SBError &error, lldb::RunMode stop_other_threads) {
587 LLDB_INSTRUMENT_VA(this, target_name, end_line, error, stop_other_threads);
588
589 std::unique_lock<std::recursive_mutex> lock;
590 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
591
592 if (!exe_ctx.HasThreadScope()) {
593 error = Status::FromErrorString(str: "this SBThread object is invalid");
594 return;
595 }
596
597 bool abort_other_plans = false;
598
599 Thread *thread = exe_ctx.GetThreadPtr();
600 StackFrameSP frame_sp(thread->GetStackFrameAtIndex(idx: 0));
601 ThreadPlanSP new_plan_sp;
602 Status new_plan_status;
603
604 if (frame_sp && frame_sp->HasDebugInformation()) {
605 SymbolContext sc(frame_sp->GetSymbolContext(resolve_scope: eSymbolContextEverything));
606 AddressRange range;
607 if (end_line == LLDB_INVALID_LINE_NUMBER)
608 range = sc.line_entry.range;
609 else {
610 llvm::Error err = sc.GetAddressRangeFromHereToEndLine(end_line, range);
611 if (err) {
612 error = Status::FromErrorString(str: llvm::toString(E: std::move(err)).c_str());
613 return;
614 }
615 }
616
617 const LazyBool step_out_avoids_code_without_debug_info =
618 eLazyBoolCalculate;
619 const LazyBool step_in_avoids_code_without_debug_info =
620 eLazyBoolCalculate;
621 new_plan_sp = thread->QueueThreadPlanForStepInRange(
622 abort_other_plans, range, addr_context: sc, step_in_target: target_name, stop_other_threads,
623 status&: new_plan_status, step_in_avoids_code_without_debug_info,
624 step_out_avoids_code_without_debug_info);
625 } else {
626 new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
627 step_over: false, abort_other_plans, stop_other_threads, status&: new_plan_status);
628 }
629
630 if (new_plan_status.Success())
631 error = ResumeNewPlan(exe_ctx, new_plan: new_plan_sp.get());
632 else
633 error = Status::FromErrorString(str: new_plan_status.AsCString());
634}
635
636void SBThread::StepOut() {
637 LLDB_INSTRUMENT_VA(this);
638
639 SBError error; // Ignored
640 StepOut(error);
641}
642
643void SBThread::StepOut(SBError &error) {
644 LLDB_INSTRUMENT_VA(this, error);
645
646 std::unique_lock<std::recursive_mutex> lock;
647 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
648
649 if (!exe_ctx.HasThreadScope()) {
650 error = Status::FromErrorString(str: "this SBThread object is invalid");
651 return;
652 }
653
654 bool abort_other_plans = false;
655 bool stop_other_threads = false;
656
657 Thread *thread = exe_ctx.GetThreadPtr();
658
659 const LazyBool avoid_no_debug = eLazyBoolCalculate;
660 Status new_plan_status;
661 ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
662 abort_other_plans, addr_context: nullptr, first_insn: false, stop_other_threads, report_stop_vote: eVoteYes,
663 report_run_vote: eVoteNoOpinion, frame_idx: 0, status&: new_plan_status, step_out_avoids_code_without_debug_info: avoid_no_debug));
664
665 if (new_plan_status.Success())
666 error = ResumeNewPlan(exe_ctx, new_plan: new_plan_sp.get());
667 else
668 error = Status::FromErrorString(str: new_plan_status.AsCString());
669}
670
671void SBThread::StepOutOfFrame(SBFrame &sb_frame) {
672 LLDB_INSTRUMENT_VA(this, sb_frame);
673
674 SBError error; // Ignored
675 StepOutOfFrame(frame&: sb_frame, error);
676}
677
678void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) {
679 LLDB_INSTRUMENT_VA(this, sb_frame, error);
680
681 std::unique_lock<std::recursive_mutex> lock;
682 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
683
684 if (!sb_frame.IsValid()) {
685 error = Status::FromErrorString(str: "passed invalid SBFrame object");
686 return;
687 }
688
689 StackFrameSP frame_sp(sb_frame.GetFrameSP());
690
691 if (!exe_ctx.HasThreadScope()) {
692 error = Status::FromErrorString(str: "this SBThread object is invalid");
693 return;
694 }
695
696 bool abort_other_plans = false;
697 bool stop_other_threads = false;
698 Thread *thread = exe_ctx.GetThreadPtr();
699 if (sb_frame.GetThread().GetThreadID() != thread->GetID()) {
700 error = Status::FromErrorString(str: "passed a frame from another thread");
701 return;
702 }
703
704 Status new_plan_status;
705 ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
706 abort_other_plans, addr_context: nullptr, first_insn: false, stop_other_threads, report_stop_vote: eVoteYes,
707 report_run_vote: eVoteNoOpinion, frame_idx: frame_sp->GetFrameIndex(), status&: new_plan_status));
708
709 if (new_plan_status.Success())
710 error = ResumeNewPlan(exe_ctx, new_plan: new_plan_sp.get());
711 else
712 error = Status::FromErrorString(str: new_plan_status.AsCString());
713}
714
715void SBThread::StepInstruction(bool step_over) {
716 LLDB_INSTRUMENT_VA(this, step_over);
717
718 SBError error; // Ignored
719 StepInstruction(step_over, error);
720}
721
722void SBThread::StepInstruction(bool step_over, SBError &error) {
723 LLDB_INSTRUMENT_VA(this, step_over, error);
724
725 std::unique_lock<std::recursive_mutex> lock;
726 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
727
728 if (!exe_ctx.HasThreadScope()) {
729 error = Status::FromErrorString(str: "this SBThread object is invalid");
730 return;
731 }
732
733 Thread *thread = exe_ctx.GetThreadPtr();
734 Status new_plan_status;
735 ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction(
736 step_over, abort_other_plans: false, stop_other_threads: true, status&: new_plan_status));
737
738 if (new_plan_status.Success())
739 error = ResumeNewPlan(exe_ctx, new_plan: new_plan_sp.get());
740 else
741 error = Status::FromErrorString(str: new_plan_status.AsCString());
742}
743
744void SBThread::RunToAddress(lldb::addr_t addr) {
745 LLDB_INSTRUMENT_VA(this, addr);
746
747 SBError error; // Ignored
748 RunToAddress(addr, error);
749}
750
751void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) {
752 LLDB_INSTRUMENT_VA(this, addr, error);
753
754 std::unique_lock<std::recursive_mutex> lock;
755 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
756
757 if (!exe_ctx.HasThreadScope()) {
758 error = Status::FromErrorString(str: "this SBThread object is invalid");
759 return;
760 }
761
762 bool abort_other_plans = false;
763 bool stop_other_threads = true;
764
765 Address target_addr(addr);
766
767 Thread *thread = exe_ctx.GetThreadPtr();
768
769 Status new_plan_status;
770 ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
771 abort_other_plans, target_addr, stop_other_threads, status&: new_plan_status));
772
773 if (new_plan_status.Success())
774 error = ResumeNewPlan(exe_ctx, new_plan: new_plan_sp.get());
775 else
776 error = Status::FromErrorString(str: new_plan_status.AsCString());
777}
778
779SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
780 lldb::SBFileSpec &sb_file_spec, uint32_t line) {
781 LLDB_INSTRUMENT_VA(this, sb_frame, sb_file_spec, line);
782
783 SBError sb_error;
784 char path[PATH_MAX];
785
786 std::unique_lock<std::recursive_mutex> lock;
787 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
788
789 StackFrameSP frame_sp(sb_frame.GetFrameSP());
790
791 if (exe_ctx.HasThreadScope()) {
792 Target *target = exe_ctx.GetTargetPtr();
793 Thread *thread = exe_ctx.GetThreadPtr();
794
795 if (line == 0) {
796 sb_error = Status::FromErrorString(str: "invalid line argument");
797 return sb_error;
798 }
799
800 if (!frame_sp) {
801 // We don't want to run SelectMostRelevantFrame here, for instance if
802 // you called a sequence of StepOverUntil's you wouldn't want the
803 // frame changed out from under you because you stepped into a
804 // recognized frame.
805 frame_sp = thread->GetSelectedFrame(select_most_relevant: DoNoSelectMostRelevantFrame);
806 if (!frame_sp)
807 frame_sp = thread->GetStackFrameAtIndex(idx: 0);
808 }
809
810 SymbolContext frame_sc;
811 if (!frame_sp) {
812 sb_error = Status::FromErrorString(str: "no valid frames in thread to step");
813 return sb_error;
814 }
815
816 // If we have a frame, get its line
817 frame_sc = frame_sp->GetSymbolContext(
818 resolve_scope: eSymbolContextCompUnit | eSymbolContextFunction |
819 eSymbolContextLineEntry | eSymbolContextSymbol);
820
821 if (frame_sc.comp_unit == nullptr) {
822 sb_error = Status::FromErrorStringWithFormat(
823 format: "frame %u doesn't have debug information", frame_sp->GetFrameIndex());
824 return sb_error;
825 }
826
827 FileSpec step_file_spec;
828 if (sb_file_spec.IsValid()) {
829 // The file spec passed in was valid, so use it
830 step_file_spec = sb_file_spec.ref();
831 } else {
832 if (frame_sc.line_entry.IsValid())
833 step_file_spec = frame_sc.line_entry.GetFile();
834 else {
835 sb_error = Status::FromErrorString(
836 str: "invalid file argument or no file for frame");
837 return sb_error;
838 }
839 }
840
841 // Grab the current function, then we will make sure the "until" address is
842 // within the function. We discard addresses that are out of the current
843 // function, and then if there are no addresses remaining, give an
844 // appropriate error message.
845
846 bool all_in_function = true;
847
848 std::vector<addr_t> step_over_until_addrs;
849 const bool abort_other_plans = false;
850 const bool stop_other_threads = false;
851 // TODO: Handle SourceLocationSpec column information
852 SourceLocationSpec location_spec(
853 step_file_spec, line, /*column=*/std::nullopt, /*check_inlines=*/true,
854 /*exact_match=*/false);
855
856 SymbolContextList sc_list;
857 frame_sc.comp_unit->ResolveSymbolContext(src_location_spec: location_spec,
858 resolve_scope: eSymbolContextLineEntry, sc_list);
859 for (const SymbolContext &sc : sc_list) {
860 addr_t step_addr =
861 sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
862 if (step_addr != LLDB_INVALID_ADDRESS) {
863 AddressRange unused_range;
864 if (frame_sc.function->GetRangeContainingLoadAddress(load_addr: step_addr, target&: *target,
865 range&: unused_range))
866 step_over_until_addrs.push_back(x: step_addr);
867 else
868 all_in_function = false;
869 }
870 }
871
872 if (step_over_until_addrs.empty()) {
873 if (all_in_function) {
874 step_file_spec.GetPath(path, max_path_length: sizeof(path));
875 sb_error = Status::FromErrorStringWithFormat(
876 format: "No line entries for %s:%u", path, line);
877 } else
878 sb_error = Status::FromErrorString(
879 str: "step until target not in current function");
880 } else {
881 Status new_plan_status;
882 ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil(
883 abort_other_plans, address_list: &step_over_until_addrs[0],
884 num_addresses: step_over_until_addrs.size(), stop_others: stop_other_threads,
885 frame_idx: frame_sp->GetFrameIndex(), status&: new_plan_status));
886
887 if (new_plan_status.Success())
888 sb_error = ResumeNewPlan(exe_ctx, new_plan: new_plan_sp.get());
889 else
890 sb_error = Status::FromErrorString(str: new_plan_status.AsCString());
891 }
892 } else {
893 sb_error = Status::FromErrorString(str: "this SBThread object is invalid");
894 }
895 return sb_error;
896}
897
898SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name) {
899 LLDB_INSTRUMENT_VA(this, script_class_name);
900
901 return StepUsingScriptedThreadPlan(script_class_name, resume_immediately: true);
902}
903
904SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
905 bool resume_immediately) {
906 LLDB_INSTRUMENT_VA(this, script_class_name, resume_immediately);
907
908 lldb::SBStructuredData no_data;
909 return StepUsingScriptedThreadPlan(script_class_name, args_data&: no_data,
910 resume_immediately);
911}
912
913SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
914 SBStructuredData &args_data,
915 bool resume_immediately) {
916 LLDB_INSTRUMENT_VA(this, script_class_name, args_data, resume_immediately);
917
918 SBError error;
919
920 std::unique_lock<std::recursive_mutex> lock;
921 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
922
923 if (!exe_ctx.HasThreadScope()) {
924 error = Status::FromErrorString(str: "this SBThread object is invalid");
925 return error;
926 }
927
928 Thread *thread = exe_ctx.GetThreadPtr();
929 Status new_plan_status;
930 StructuredData::ObjectSP obj_sp = args_data.m_impl_up->GetObjectSP();
931
932 ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted(
933 abort_other_plans: false, class_name: script_class_name, extra_args_sp: obj_sp, stop_other_threads: false, status&: new_plan_status);
934
935 if (new_plan_status.Fail()) {
936 error = Status::FromErrorString(str: new_plan_status.AsCString());
937 return error;
938 }
939
940 if (!resume_immediately)
941 return error;
942
943 if (new_plan_status.Success())
944 error = ResumeNewPlan(exe_ctx, new_plan: new_plan_sp.get());
945 else
946 error = Status::FromErrorString(str: new_plan_status.AsCString());
947
948 return error;
949}
950
951SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
952 LLDB_INSTRUMENT_VA(this, file_spec, line);
953
954 SBError sb_error;
955
956 std::unique_lock<std::recursive_mutex> lock;
957 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
958
959 if (!exe_ctx.HasThreadScope()) {
960 sb_error = Status::FromErrorString(str: "this SBThread object is invalid");
961 return sb_error;
962 }
963
964 Thread *thread = exe_ctx.GetThreadPtr();
965
966 Status err = thread->JumpToLine(file: file_spec.ref(), line, can_leave_function: true);
967 sb_error.SetError(std::move(err));
968 return sb_error;
969}
970
971SBError SBThread::ReturnFromFrame(SBFrame &frame, SBValue &return_value) {
972 LLDB_INSTRUMENT_VA(this, frame, return_value);
973
974 SBError sb_error;
975
976 std::unique_lock<std::recursive_mutex> lock;
977 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
978
979 if (exe_ctx.HasThreadScope()) {
980 Thread *thread = exe_ctx.GetThreadPtr();
981 sb_error.SetError(
982 thread->ReturnFromFrame(frame_sp: frame.GetFrameSP(), return_value_sp: return_value.GetSP()));
983 }
984
985 return sb_error;
986}
987
988SBError SBThread::UnwindInnermostExpression() {
989 LLDB_INSTRUMENT_VA(this);
990
991 SBError sb_error;
992
993 std::unique_lock<std::recursive_mutex> lock;
994 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
995
996 if (exe_ctx.HasThreadScope()) {
997 Thread *thread = exe_ctx.GetThreadPtr();
998 sb_error.SetError(thread->UnwindInnermostExpression());
999 if (sb_error.Success())
1000 thread->SetSelectedFrameByIndex(frame_idx: 0, broadcast: false);
1001 }
1002
1003 return sb_error;
1004}
1005
1006bool SBThread::Suspend() {
1007 LLDB_INSTRUMENT_VA(this);
1008
1009 SBError error; // Ignored
1010 return Suspend(error);
1011}
1012
1013bool SBThread::Suspend(SBError &error) {
1014 LLDB_INSTRUMENT_VA(this, error);
1015
1016 std::unique_lock<std::recursive_mutex> lock;
1017 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1018
1019 bool result = false;
1020 if (exe_ctx.HasThreadScope()) {
1021 Process::StopLocker stop_locker;
1022 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
1023 exe_ctx.GetThreadPtr()->SetResumeState(state: eStateSuspended);
1024 result = true;
1025 } else {
1026 error = Status::FromErrorString(str: "process is running");
1027 }
1028 } else
1029 error = Status::FromErrorString(str: "this SBThread object is invalid");
1030 return result;
1031}
1032
1033bool SBThread::Resume() {
1034 LLDB_INSTRUMENT_VA(this);
1035
1036 SBError error; // Ignored
1037 return Resume(error);
1038}
1039
1040bool SBThread::Resume(SBError &error) {
1041 LLDB_INSTRUMENT_VA(this, error);
1042
1043 std::unique_lock<std::recursive_mutex> lock;
1044 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1045
1046 bool result = false;
1047 if (exe_ctx.HasThreadScope()) {
1048 Process::StopLocker stop_locker;
1049 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
1050 const bool override_suspend = true;
1051 exe_ctx.GetThreadPtr()->SetResumeState(state: eStateRunning, override_suspend);
1052 result = true;
1053 } else {
1054 error = Status::FromErrorString(str: "process is running");
1055 }
1056 } else
1057 error = Status::FromErrorString(str: "this SBThread object is invalid");
1058 return result;
1059}
1060
1061bool SBThread::IsSuspended() {
1062 LLDB_INSTRUMENT_VA(this);
1063
1064 std::unique_lock<std::recursive_mutex> lock;
1065 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1066
1067 if (exe_ctx.HasThreadScope())
1068 return exe_ctx.GetThreadPtr()->GetResumeState() == eStateSuspended;
1069 return false;
1070}
1071
1072bool SBThread::IsStopped() {
1073 LLDB_INSTRUMENT_VA(this);
1074
1075 std::unique_lock<std::recursive_mutex> lock;
1076 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1077
1078 if (exe_ctx.HasThreadScope())
1079 return StateIsStoppedState(state: exe_ctx.GetThreadPtr()->GetState(), must_exist: true);
1080 return false;
1081}
1082
1083SBProcess SBThread::GetProcess() {
1084 LLDB_INSTRUMENT_VA(this);
1085
1086 SBProcess sb_process;
1087 std::unique_lock<std::recursive_mutex> lock;
1088 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1089
1090 if (exe_ctx.HasThreadScope()) {
1091 // Have to go up to the target so we can get a shared pointer to our
1092 // process...
1093 sb_process.SetSP(exe_ctx.GetProcessSP());
1094 }
1095
1096 return sb_process;
1097}
1098
1099uint32_t SBThread::GetNumFrames() {
1100 LLDB_INSTRUMENT_VA(this);
1101
1102 uint32_t num_frames = 0;
1103 std::unique_lock<std::recursive_mutex> lock;
1104 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1105
1106 if (exe_ctx.HasThreadScope()) {
1107 Process::StopLocker stop_locker;
1108 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
1109 num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount();
1110 }
1111 }
1112
1113 return num_frames;
1114}
1115
1116SBFrame SBThread::GetFrameAtIndex(uint32_t idx) {
1117 LLDB_INSTRUMENT_VA(this, idx);
1118
1119 SBFrame sb_frame;
1120 StackFrameSP frame_sp;
1121 std::unique_lock<std::recursive_mutex> lock;
1122 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1123
1124 if (exe_ctx.HasThreadScope()) {
1125 Process::StopLocker stop_locker;
1126 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
1127 frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx);
1128 sb_frame.SetFrameSP(frame_sp);
1129 }
1130 }
1131
1132 return sb_frame;
1133}
1134
1135lldb::SBFrame SBThread::GetSelectedFrame() {
1136 LLDB_INSTRUMENT_VA(this);
1137
1138 SBFrame sb_frame;
1139 StackFrameSP frame_sp;
1140 std::unique_lock<std::recursive_mutex> lock;
1141 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1142
1143 if (exe_ctx.HasThreadScope()) {
1144 Process::StopLocker stop_locker;
1145 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
1146 frame_sp =
1147 exe_ctx.GetThreadPtr()->GetSelectedFrame(select_most_relevant: SelectMostRelevantFrame);
1148 sb_frame.SetFrameSP(frame_sp);
1149 }
1150 }
1151
1152 return sb_frame;
1153}
1154
1155lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) {
1156 LLDB_INSTRUMENT_VA(this, idx);
1157
1158 SBFrame sb_frame;
1159 StackFrameSP frame_sp;
1160 std::unique_lock<std::recursive_mutex> lock;
1161 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1162
1163 if (exe_ctx.HasThreadScope()) {
1164 Process::StopLocker stop_locker;
1165 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
1166 Thread *thread = exe_ctx.GetThreadPtr();
1167 frame_sp = thread->GetStackFrameAtIndex(idx);
1168 if (frame_sp) {
1169 thread->SetSelectedFrame(frame: frame_sp.get());
1170 sb_frame.SetFrameSP(frame_sp);
1171 }
1172 }
1173 }
1174
1175 return sb_frame;
1176}
1177
1178bool SBThread::EventIsThreadEvent(const SBEvent &event) {
1179 LLDB_INSTRUMENT_VA(event);
1180
1181 return Thread::ThreadEventData::GetEventDataFromEvent(event_ptr: event.get()) != nullptr;
1182}
1183
1184SBFrame SBThread::GetStackFrameFromEvent(const SBEvent &event) {
1185 LLDB_INSTRUMENT_VA(event);
1186
1187 return Thread::ThreadEventData::GetStackFrameFromEvent(event_ptr: event.get());
1188}
1189
1190SBThread SBThread::GetThreadFromEvent(const SBEvent &event) {
1191 LLDB_INSTRUMENT_VA(event);
1192
1193 return Thread::ThreadEventData::GetThreadFromEvent(event_ptr: event.get());
1194}
1195
1196bool SBThread::operator==(const SBThread &rhs) const {
1197 LLDB_INSTRUMENT_VA(this, rhs);
1198
1199 return m_opaque_sp->GetThreadSP().get() ==
1200 rhs.m_opaque_sp->GetThreadSP().get();
1201}
1202
1203bool SBThread::operator!=(const SBThread &rhs) const {
1204 LLDB_INSTRUMENT_VA(this, rhs);
1205
1206 return m_opaque_sp->GetThreadSP().get() !=
1207 rhs.m_opaque_sp->GetThreadSP().get();
1208}
1209
1210bool SBThread::GetStatus(SBStream &status) const {
1211 LLDB_INSTRUMENT_VA(this, status);
1212
1213 Stream &strm = status.ref();
1214
1215 std::unique_lock<std::recursive_mutex> lock;
1216 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1217
1218 if (exe_ctx.HasThreadScope()) {
1219 exe_ctx.GetThreadPtr()->GetStatus(strm, start_frame: 0, num_frames: 1, num_frames_with_source: 1, stop_format: true,
1220 /*show_hidden=*/true);
1221 } else
1222 strm.PutCString(cstr: "No status");
1223
1224 return true;
1225}
1226
1227bool SBThread::GetDescription(SBStream &description) const {
1228 LLDB_INSTRUMENT_VA(this, description);
1229
1230 return GetDescription(description, stop_format: false);
1231}
1232
1233bool SBThread::GetDescription(SBStream &description, bool stop_format) const {
1234 LLDB_INSTRUMENT_VA(this, description, stop_format);
1235
1236 Stream &strm = description.ref();
1237
1238 std::unique_lock<std::recursive_mutex> lock;
1239 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1240
1241 if (exe_ctx.HasThreadScope()) {
1242 exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(
1243 strm, LLDB_INVALID_THREAD_ID, stop_format);
1244 } else
1245 strm.PutCString(cstr: "No value");
1246
1247 return true;
1248}
1249
1250SBError SBThread::GetDescriptionWithFormat(const SBFormat &format,
1251 SBStream &output) {
1252 Stream &strm = output.ref();
1253
1254 SBError error;
1255 if (!format) {
1256 error = Status::FromErrorString(str: "The provided SBFormat object is invalid");
1257 return error;
1258 }
1259
1260 std::unique_lock<std::recursive_mutex> lock;
1261 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1262
1263 if (exe_ctx.HasThreadScope()) {
1264 if (exe_ctx.GetThreadPtr()->DumpUsingFormat(
1265 strm, LLDB_INVALID_THREAD_ID, format: format.GetFormatEntrySP().get())) {
1266 return error;
1267 }
1268 }
1269
1270 error = Status::FromErrorStringWithFormat(
1271 format: "It was not possible to generate a thread description with the given "
1272 "format string '%s'",
1273 format.GetFormatEntrySP()->string.c_str());
1274 return error;
1275}
1276
1277SBThread SBThread::GetExtendedBacktraceThread(const char *type) {
1278 LLDB_INSTRUMENT_VA(this, type);
1279
1280 std::unique_lock<std::recursive_mutex> lock;
1281 ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1282 SBThread sb_origin_thread;
1283
1284 Process::StopLocker stop_locker;
1285 if (stop_locker.TryLock(lock: &exe_ctx.GetProcessPtr()->GetRunLock())) {
1286 if (exe_ctx.HasThreadScope()) {
1287 ThreadSP real_thread(exe_ctx.GetThreadSP());
1288 if (real_thread) {
1289 ConstString type_const(type);
1290 Process *process = exe_ctx.GetProcessPtr();
1291 if (process) {
1292 SystemRuntime *runtime = process->GetSystemRuntime();
1293 if (runtime) {
1294 ThreadSP new_thread_sp(
1295 runtime->GetExtendedBacktraceThread(thread: real_thread, type: type_const));
1296 if (new_thread_sp) {
1297 // Save this in the Process' ExtendedThreadList so a strong
1298 // pointer retains the object.
1299 process->GetExtendedThreadList().AddThread(thread_sp: new_thread_sp);
1300 sb_origin_thread.SetThread(new_thread_sp);
1301 }
1302 }
1303 }
1304 }
1305 }
1306 }
1307
1308 return sb_origin_thread;
1309}
1310
1311uint32_t SBThread::GetExtendedBacktraceOriginatingIndexID() {
1312 LLDB_INSTRUMENT_VA(this);
1313
1314 ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
1315 if (thread_sp)
1316 return thread_sp->GetExtendedBacktraceOriginatingIndexID();
1317 return LLDB_INVALID_INDEX32;
1318}
1319
1320SBValue SBThread::GetCurrentException() {
1321 LLDB_INSTRUMENT_VA(this);
1322
1323 ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
1324 if (!thread_sp)
1325 return SBValue();
1326
1327 return SBValue(thread_sp->GetCurrentException());
1328}
1329
1330SBThread SBThread::GetCurrentExceptionBacktrace() {
1331 LLDB_INSTRUMENT_VA(this);
1332
1333 ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
1334 if (!thread_sp)
1335 return SBThread();
1336
1337 return SBThread(thread_sp->GetCurrentExceptionBacktrace());
1338}
1339
1340bool SBThread::SafeToCallFunctions() {
1341 LLDB_INSTRUMENT_VA(this);
1342
1343 ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
1344 if (thread_sp)
1345 return thread_sp->SafeToCallFunctions();
1346 return true;
1347}
1348
1349lldb::ThreadSP SBThread::GetSP() const { return m_opaque_sp->GetThreadSP(); }
1350
1351lldb_private::Thread *SBThread::operator->() {
1352 return get();
1353}
1354
1355lldb_private::Thread *SBThread::get() {
1356 return m_opaque_sp->GetThreadSP().get();
1357}
1358
1359SBValue SBThread::GetSiginfo() {
1360 LLDB_INSTRUMENT_VA(this);
1361
1362 ThreadSP thread_sp = m_opaque_sp->GetThreadSP();
1363 if (!thread_sp)
1364 return SBValue();
1365 return thread_sp->GetSiginfoValue();
1366}
1367

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of lldb/source/API/SBThread.cpp