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