15ffd83dbSDimitry Andric //===-- SBThread.cpp ------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/API/SBThread.h"
100b57cec5SDimitry Andric #include "Utils.h"
110b57cec5SDimitry Andric #include "lldb/API/SBAddress.h"
120b57cec5SDimitry Andric #include "lldb/API/SBDebugger.h"
130b57cec5SDimitry Andric #include "lldb/API/SBEvent.h"
140b57cec5SDimitry Andric #include "lldb/API/SBFileSpec.h"
155f757f3fSDimitry Andric #include "lldb/API/SBFormat.h"
160b57cec5SDimitry Andric #include "lldb/API/SBFrame.h"
170b57cec5SDimitry Andric #include "lldb/API/SBProcess.h"
180b57cec5SDimitry Andric #include "lldb/API/SBStream.h"
199dba64beSDimitry Andric #include "lldb/API/SBStructuredData.h"
200b57cec5SDimitry Andric #include "lldb/API/SBSymbolContext.h"
210b57cec5SDimitry Andric #include "lldb/API/SBThreadCollection.h"
220b57cec5SDimitry Andric #include "lldb/API/SBThreadPlan.h"
230b57cec5SDimitry Andric #include "lldb/API/SBValue.h"
240b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h"
250b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
269dba64beSDimitry Andric #include "lldb/Core/StructuredDataImpl.h"
270b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
280b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
290b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
300b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
310b57cec5SDimitry Andric #include "lldb/Target/Process.h"
320b57cec5SDimitry Andric #include "lldb/Target/Queue.h"
330b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h"
340b57cec5SDimitry Andric #include "lldb/Target/SystemRuntime.h"
350b57cec5SDimitry Andric #include "lldb/Target/Target.h"
360b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
370b57cec5SDimitry Andric #include "lldb/Target/ThreadPlan.h"
380b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepInRange.h"
390b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepInstruction.h"
400b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepOut.h"
410b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanStepRange.h"
4204eeddc0SDimitry Andric #include "lldb/Utility/Instrumentation.h"
430b57cec5SDimitry Andric #include "lldb/Utility/State.h"
440b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
450b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h"
460b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h"
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric #include <memory>
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric using namespace lldb;
510b57cec5SDimitry Andric using namespace lldb_private;
520b57cec5SDimitry Andric 
GetBroadcasterClassName()530b57cec5SDimitry Andric const char *SBThread::GetBroadcasterClassName() {
5404eeddc0SDimitry Andric   LLDB_INSTRUMENT();
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   return Thread::GetStaticBroadcasterClass().AsCString();
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric // Constructors
SBThread()600b57cec5SDimitry Andric SBThread::SBThread() : m_opaque_sp(new ExecutionContextRef()) {
6104eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
SBThread(const ThreadSP & lldb_object_sp)640b57cec5SDimitry Andric SBThread::SBThread(const ThreadSP &lldb_object_sp)
650b57cec5SDimitry Andric     : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) {
6604eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, lldb_object_sp);
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
SBThread(const SBThread & rhs)6904eeddc0SDimitry Andric SBThread::SBThread(const SBThread &rhs) {
7004eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, rhs);
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   m_opaque_sp = clone(rhs.m_opaque_sp);
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric // Assignment operator
760b57cec5SDimitry Andric 
operator =(const SBThread & rhs)770b57cec5SDimitry Andric const lldb::SBThread &SBThread::operator=(const SBThread &rhs) {
7804eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, rhs);
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   if (this != &rhs)
810b57cec5SDimitry Andric     m_opaque_sp = clone(rhs.m_opaque_sp);
8204eeddc0SDimitry Andric   return *this;
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric // Destructor
865ffd83dbSDimitry Andric SBThread::~SBThread() = default;
870b57cec5SDimitry Andric 
GetQueue() const880b57cec5SDimitry Andric lldb::SBQueue SBThread::GetQueue() const {
8904eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   SBQueue sb_queue;
920b57cec5SDimitry Andric   QueueSP queue_sp;
930b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
940b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
970b57cec5SDimitry Andric     Process::StopLocker stop_locker;
980b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
990b57cec5SDimitry Andric       queue_sp = exe_ctx.GetThreadPtr()->GetQueue();
1000b57cec5SDimitry Andric       if (queue_sp) {
1010b57cec5SDimitry Andric         sb_queue.SetQueue(queue_sp);
1020b57cec5SDimitry Andric       }
1030b57cec5SDimitry Andric     }
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric 
10604eeddc0SDimitry Andric   return sb_queue;
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
IsValid() const1090b57cec5SDimitry Andric bool SBThread::IsValid() const {
11004eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
1110b57cec5SDimitry Andric   return this->operator bool();
1120b57cec5SDimitry Andric }
operator bool() const1130b57cec5SDimitry Andric SBThread::operator bool() const {
11404eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
1170b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
1200b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
1210b57cec5SDimitry Andric   if (target && process) {
1220b57cec5SDimitry Andric     Process::StopLocker stop_locker;
1230b57cec5SDimitry Andric     if (stop_locker.TryLock(&process->GetRunLock()))
1240b57cec5SDimitry Andric       return m_opaque_sp->GetThreadSP().get() != nullptr;
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric   // Without a valid target & process, this thread can't be valid.
1270b57cec5SDimitry Andric   return false;
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
Clear()1300b57cec5SDimitry Andric void SBThread::Clear() {
13104eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   m_opaque_sp->Clear();
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
GetStopReason()1360b57cec5SDimitry Andric StopReason SBThread::GetStopReason() {
13704eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   StopReason reason = eStopReasonInvalid;
1400b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
1410b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
1440b57cec5SDimitry Andric     Process::StopLocker stop_locker;
1450b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1460b57cec5SDimitry Andric       return exe_ctx.GetThreadPtr()->GetStopReason();
1470b57cec5SDimitry Andric     }
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   return reason;
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
GetStopReasonDataCount()1530b57cec5SDimitry Andric size_t SBThread::GetStopReasonDataCount() {
15404eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
1570b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
1600b57cec5SDimitry Andric     Process::StopLocker stop_locker;
1610b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
1620b57cec5SDimitry Andric       StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
1630b57cec5SDimitry Andric       if (stop_info_sp) {
1640b57cec5SDimitry Andric         StopReason reason = stop_info_sp->GetStopReason();
1650b57cec5SDimitry Andric         switch (reason) {
1660b57cec5SDimitry Andric         case eStopReasonInvalid:
1670b57cec5SDimitry Andric         case eStopReasonNone:
1680b57cec5SDimitry Andric         case eStopReasonTrace:
1690b57cec5SDimitry Andric         case eStopReasonExec:
1700b57cec5SDimitry Andric         case eStopReasonPlanComplete:
1710b57cec5SDimitry Andric         case eStopReasonThreadExiting:
1720b57cec5SDimitry Andric         case eStopReasonInstrumentation:
173fe6060f1SDimitry Andric         case eStopReasonProcessorTrace:
174fe6060f1SDimitry Andric         case eStopReasonVForkDone:
1750b57cec5SDimitry Andric           // There is no data for these stop reasons.
1760b57cec5SDimitry Andric           return 0;
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric         case eStopReasonBreakpoint: {
1790b57cec5SDimitry Andric           break_id_t site_id = stop_info_sp->GetValue();
1800b57cec5SDimitry Andric           lldb::BreakpointSiteSP bp_site_sp(
1810b57cec5SDimitry Andric               exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
1820b57cec5SDimitry Andric                   site_id));
1830b57cec5SDimitry Andric           if (bp_site_sp)
1845f757f3fSDimitry Andric             return bp_site_sp->GetNumberOfConstituents() * 2;
1850b57cec5SDimitry Andric           else
1860b57cec5SDimitry Andric             return 0; // Breakpoint must have cleared itself...
1870b57cec5SDimitry Andric         } break;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric         case eStopReasonWatchpoint:
1900b57cec5SDimitry Andric           return 1;
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric         case eStopReasonSignal:
1930b57cec5SDimitry Andric           return 1;
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric         case eStopReasonException:
1960b57cec5SDimitry Andric           return 1;
197fe6060f1SDimitry Andric 
198fe6060f1SDimitry Andric         case eStopReasonFork:
199fe6060f1SDimitry Andric           return 1;
200fe6060f1SDimitry Andric 
201fe6060f1SDimitry Andric         case eStopReasonVFork:
202fe6060f1SDimitry Andric           return 1;
2030b57cec5SDimitry Andric         }
2040b57cec5SDimitry Andric       }
2050b57cec5SDimitry Andric     }
2060b57cec5SDimitry Andric   }
2070b57cec5SDimitry Andric   return 0;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
GetStopReasonDataAtIndex(uint32_t idx)2100b57cec5SDimitry Andric uint64_t SBThread::GetStopReasonDataAtIndex(uint32_t idx) {
21104eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, idx);
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
2140b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
2170b57cec5SDimitry Andric     Process::StopLocker stop_locker;
2180b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
2190b57cec5SDimitry Andric       Thread *thread = exe_ctx.GetThreadPtr();
2200b57cec5SDimitry Andric       StopInfoSP stop_info_sp = thread->GetStopInfo();
2210b57cec5SDimitry Andric       if (stop_info_sp) {
2220b57cec5SDimitry Andric         StopReason reason = stop_info_sp->GetStopReason();
2230b57cec5SDimitry Andric         switch (reason) {
2240b57cec5SDimitry Andric         case eStopReasonInvalid:
2250b57cec5SDimitry Andric         case eStopReasonNone:
2260b57cec5SDimitry Andric         case eStopReasonTrace:
2270b57cec5SDimitry Andric         case eStopReasonExec:
2280b57cec5SDimitry Andric         case eStopReasonPlanComplete:
2290b57cec5SDimitry Andric         case eStopReasonThreadExiting:
2300b57cec5SDimitry Andric         case eStopReasonInstrumentation:
231fe6060f1SDimitry Andric         case eStopReasonProcessorTrace:
232fe6060f1SDimitry Andric         case eStopReasonVForkDone:
2330b57cec5SDimitry Andric           // There is no data for these stop reasons.
2340b57cec5SDimitry Andric           return 0;
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric         case eStopReasonBreakpoint: {
2370b57cec5SDimitry Andric           break_id_t site_id = stop_info_sp->GetValue();
2380b57cec5SDimitry Andric           lldb::BreakpointSiteSP bp_site_sp(
2390b57cec5SDimitry Andric               exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID(
2400b57cec5SDimitry Andric                   site_id));
2410b57cec5SDimitry Andric           if (bp_site_sp) {
2420b57cec5SDimitry Andric             uint32_t bp_index = idx / 2;
2430b57cec5SDimitry Andric             BreakpointLocationSP bp_loc_sp(
2445f757f3fSDimitry Andric                 bp_site_sp->GetConstituentAtIndex(bp_index));
2450b57cec5SDimitry Andric             if (bp_loc_sp) {
2460b57cec5SDimitry Andric               if (idx & 1) {
2470b57cec5SDimitry Andric                 // Odd idx, return the breakpoint location ID
2480b57cec5SDimitry Andric                 return bp_loc_sp->GetID();
2490b57cec5SDimitry Andric               } else {
2500b57cec5SDimitry Andric                 // Even idx, return the breakpoint ID
2510b57cec5SDimitry Andric                 return bp_loc_sp->GetBreakpoint().GetID();
2520b57cec5SDimitry Andric               }
2530b57cec5SDimitry Andric             }
2540b57cec5SDimitry Andric           }
2550b57cec5SDimitry Andric           return LLDB_INVALID_BREAK_ID;
2560b57cec5SDimitry Andric         } break;
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric         case eStopReasonWatchpoint:
2590b57cec5SDimitry Andric           return stop_info_sp->GetValue();
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric         case eStopReasonSignal:
2620b57cec5SDimitry Andric           return stop_info_sp->GetValue();
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric         case eStopReasonException:
2650b57cec5SDimitry Andric           return stop_info_sp->GetValue();
266fe6060f1SDimitry Andric 
267fe6060f1SDimitry Andric         case eStopReasonFork:
268fe6060f1SDimitry Andric           return stop_info_sp->GetValue();
269fe6060f1SDimitry Andric 
270fe6060f1SDimitry Andric         case eStopReasonVFork:
271fe6060f1SDimitry Andric           return stop_info_sp->GetValue();
2720b57cec5SDimitry Andric         }
2730b57cec5SDimitry Andric       }
2740b57cec5SDimitry Andric     }
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric   return 0;
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
GetStopReasonExtendedInfoAsJSON(lldb::SBStream & stream)2790b57cec5SDimitry Andric bool SBThread::GetStopReasonExtendedInfoAsJSON(lldb::SBStream &stream) {
28004eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, stream);
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   Stream &strm = stream.ref();
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
2850b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope())
2880b57cec5SDimitry Andric     return false;
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
2910b57cec5SDimitry Andric   StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
2920b57cec5SDimitry Andric   if (!info)
2930b57cec5SDimitry Andric     return false;
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   info->Dump(strm);
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   return true;
2980b57cec5SDimitry Andric }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric SBThreadCollection
GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type)3010b57cec5SDimitry Andric SBThread::GetStopReasonExtendedBacktraces(InstrumentationRuntimeType type) {
30204eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, type);
3030b57cec5SDimitry Andric 
3045ffd83dbSDimitry Andric   SBThreadCollection threads;
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
3070b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope())
31004eeddc0SDimitry Andric     return SBThreadCollection();
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   ProcessSP process_sp = exe_ctx.GetProcessSP();
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric   StopInfoSP stop_info = exe_ctx.GetThreadPtr()->GetStopInfo();
3150b57cec5SDimitry Andric   StructuredData::ObjectSP info = stop_info->GetExtendedInfo();
3160b57cec5SDimitry Andric   if (!info)
31704eeddc0SDimitry Andric     return threads;
3180b57cec5SDimitry Andric 
3195ffd83dbSDimitry Andric   threads = process_sp->GetInstrumentationRuntime(type)
3205ffd83dbSDimitry Andric                 ->GetBacktracesFromExtendedStopInfo(info);
32104eeddc0SDimitry Andric   return threads;
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric 
GetStopDescription(char * dst,size_t dst_len)3240b57cec5SDimitry Andric size_t SBThread::GetStopDescription(char *dst, size_t dst_len) {
32504eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, dst, dst_len);
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
3280b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   if (dst)
3310b57cec5SDimitry Andric     *dst = 0;
3325ffd83dbSDimitry Andric 
3335ffd83dbSDimitry Andric   if (!exe_ctx.HasThreadScope())
3340b57cec5SDimitry Andric     return 0;
3355ffd83dbSDimitry Andric 
3365ffd83dbSDimitry Andric   Process::StopLocker stop_locker;
3375ffd83dbSDimitry Andric   if (!stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
3385ffd83dbSDimitry Andric     return 0;
3395ffd83dbSDimitry Andric 
3405ffd83dbSDimitry Andric   std::string thread_stop_desc = exe_ctx.GetThreadPtr()->GetStopDescription();
3415ffd83dbSDimitry Andric   if (thread_stop_desc.empty())
3425ffd83dbSDimitry Andric     return 0;
3435ffd83dbSDimitry Andric 
3445ffd83dbSDimitry Andric   if (dst)
3455ffd83dbSDimitry Andric     return ::snprintf(dst, dst_len, "%s", thread_stop_desc.c_str()) + 1;
3465ffd83dbSDimitry Andric 
3475ffd83dbSDimitry Andric   // NULL dst passed in, return the length needed to contain the
3485ffd83dbSDimitry Andric   // description.
3495ffd83dbSDimitry Andric   return thread_stop_desc.size() + 1; // Include the NULL byte for size
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric 
GetStopReturnValue()3520b57cec5SDimitry Andric SBValue SBThread::GetStopReturnValue() {
35304eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   ValueObjectSP return_valobj_sp;
3560b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
3570b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
3600b57cec5SDimitry Andric     Process::StopLocker stop_locker;
3610b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
3620b57cec5SDimitry Andric       StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo();
3630b57cec5SDimitry Andric       if (stop_info_sp) {
3640b57cec5SDimitry Andric         return_valobj_sp = StopInfo::GetReturnValueObject(stop_info_sp);
3650b57cec5SDimitry Andric       }
3660b57cec5SDimitry Andric     }
3670b57cec5SDimitry Andric   }
3680b57cec5SDimitry Andric 
36904eeddc0SDimitry Andric   return SBValue(return_valobj_sp);
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric 
SetThread(const ThreadSP & lldb_object_sp)3720b57cec5SDimitry Andric void SBThread::SetThread(const ThreadSP &lldb_object_sp) {
3730b57cec5SDimitry Andric   m_opaque_sp->SetThreadSP(lldb_object_sp);
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric 
GetThreadID() const3760b57cec5SDimitry Andric lldb::tid_t SBThread::GetThreadID() const {
37704eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
3800b57cec5SDimitry Andric   if (thread_sp)
3810b57cec5SDimitry Andric     return thread_sp->GetID();
3820b57cec5SDimitry Andric   return LLDB_INVALID_THREAD_ID;
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric 
GetIndexID() const3850b57cec5SDimitry Andric uint32_t SBThread::GetIndexID() const {
38604eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
3890b57cec5SDimitry Andric   if (thread_sp)
3900b57cec5SDimitry Andric     return thread_sp->GetIndexID();
3910b57cec5SDimitry Andric   return LLDB_INVALID_INDEX32;
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
GetName() const3940b57cec5SDimitry Andric const char *SBThread::GetName() const {
39504eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
3980b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
3990b57cec5SDimitry Andric 
40006c3fb27SDimitry Andric   if (!exe_ctx.HasThreadScope())
40106c3fb27SDimitry Andric     return nullptr;
4020b57cec5SDimitry Andric 
40306c3fb27SDimitry Andric   Process::StopLocker stop_locker;
40406c3fb27SDimitry Andric   if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
40506c3fb27SDimitry Andric     return ConstString(exe_ctx.GetThreadPtr()->GetName()).GetCString();
40606c3fb27SDimitry Andric 
40706c3fb27SDimitry Andric   return nullptr;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric 
GetQueueName() const4100b57cec5SDimitry Andric const char *SBThread::GetQueueName() const {
41104eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
4140b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
4150b57cec5SDimitry Andric 
41606c3fb27SDimitry Andric   if (!exe_ctx.HasThreadScope())
41706c3fb27SDimitry Andric     return nullptr;
4180b57cec5SDimitry Andric 
41906c3fb27SDimitry Andric   Process::StopLocker stop_locker;
42006c3fb27SDimitry Andric   if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
42106c3fb27SDimitry Andric     return ConstString(exe_ctx.GetThreadPtr()->GetQueueName()).GetCString();
42206c3fb27SDimitry Andric 
42306c3fb27SDimitry Andric   return nullptr;
4240b57cec5SDimitry Andric }
4250b57cec5SDimitry Andric 
GetQueueID() const4260b57cec5SDimitry Andric lldb::queue_id_t SBThread::GetQueueID() const {
42704eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   queue_id_t id = LLDB_INVALID_QUEUE_ID;
4300b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
4310b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
4340b57cec5SDimitry Andric     Process::StopLocker stop_locker;
4350b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
4360b57cec5SDimitry Andric       id = exe_ctx.GetThreadPtr()->GetQueueID();
4370b57cec5SDimitry Andric     }
4380b57cec5SDimitry Andric   }
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   return id;
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric 
GetInfoItemByPathAsString(const char * path,SBStream & strm)4430b57cec5SDimitry Andric bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
44404eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, path, strm);
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   bool success = false;
4470b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
4480b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
4510b57cec5SDimitry Andric     Process::StopLocker stop_locker;
4520b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
4530b57cec5SDimitry Andric       Thread *thread = exe_ctx.GetThreadPtr();
4540b57cec5SDimitry Andric       StructuredData::ObjectSP info_root_sp = thread->GetExtendedInfo();
4550b57cec5SDimitry Andric       if (info_root_sp) {
4560b57cec5SDimitry Andric         StructuredData::ObjectSP node =
4570b57cec5SDimitry Andric             info_root_sp->GetObjectForDotSeparatedPath(path);
4580b57cec5SDimitry Andric         if (node) {
4590b57cec5SDimitry Andric           if (node->GetType() == eStructuredDataTypeString) {
46006c3fb27SDimitry Andric             strm.ref() << node->GetAsString()->GetValue();
4610b57cec5SDimitry Andric             success = true;
4620b57cec5SDimitry Andric           }
4630b57cec5SDimitry Andric           if (node->GetType() == eStructuredDataTypeInteger) {
46406c3fb27SDimitry Andric             strm.Printf("0x%" PRIx64, node->GetUnsignedIntegerValue());
4650b57cec5SDimitry Andric             success = true;
4660b57cec5SDimitry Andric           }
4670b57cec5SDimitry Andric           if (node->GetType() == eStructuredDataTypeFloat) {
4680b57cec5SDimitry Andric             strm.Printf("0x%f", node->GetAsFloat()->GetValue());
4690b57cec5SDimitry Andric             success = true;
4700b57cec5SDimitry Andric           }
4710b57cec5SDimitry Andric           if (node->GetType() == eStructuredDataTypeBoolean) {
4720b57cec5SDimitry Andric             if (node->GetAsBoolean()->GetValue())
4730b57cec5SDimitry Andric               strm.Printf("true");
4740b57cec5SDimitry Andric             else
4750b57cec5SDimitry Andric               strm.Printf("false");
4760b57cec5SDimitry Andric             success = true;
4770b57cec5SDimitry Andric           }
4780b57cec5SDimitry Andric           if (node->GetType() == eStructuredDataTypeNull) {
4790b57cec5SDimitry Andric             strm.Printf("null");
4800b57cec5SDimitry Andric             success = true;
4810b57cec5SDimitry Andric           }
4820b57cec5SDimitry Andric         }
4830b57cec5SDimitry Andric       }
4840b57cec5SDimitry Andric     }
4850b57cec5SDimitry Andric   }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric   return success;
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric 
ResumeNewPlan(ExecutionContext & exe_ctx,ThreadPlan * new_plan)4900b57cec5SDimitry Andric SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx,
4910b57cec5SDimitry Andric                                 ThreadPlan *new_plan) {
4920b57cec5SDimitry Andric   SBError sb_error;
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
4950b57cec5SDimitry Andric   if (!process) {
4960b57cec5SDimitry Andric     sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
4970b57cec5SDimitry Andric     return sb_error;
4980b57cec5SDimitry Andric   }
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
5010b57cec5SDimitry Andric   if (!thread) {
5020b57cec5SDimitry Andric     sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
5030b57cec5SDimitry Andric     return sb_error;
5040b57cec5SDimitry Andric   }
5050b57cec5SDimitry Andric 
506349cc55cSDimitry Andric   // User level plans should be Controlling Plans so they can be interrupted,
507349cc55cSDimitry Andric   // other plans executed, and then a "continue" will resume the plan.
5080b57cec5SDimitry Andric   if (new_plan != nullptr) {
509349cc55cSDimitry Andric     new_plan->SetIsControllingPlan(true);
5100b57cec5SDimitry Andric     new_plan->SetOkayToDiscard(false);
5110b57cec5SDimitry Andric   }
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   // Why do we need to set the current thread by ID here???
5140b57cec5SDimitry Andric   process->GetThreadList().SetSelectedThreadByID(thread->GetID());
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   if (process->GetTarget().GetDebugger().GetAsyncExecution())
5170b57cec5SDimitry Andric     sb_error.ref() = process->Resume();
5180b57cec5SDimitry Andric   else
5190b57cec5SDimitry Andric     sb_error.ref() = process->ResumeSynchronous(nullptr);
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   return sb_error;
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric 
StepOver(lldb::RunMode stop_other_threads)5240b57cec5SDimitry Andric void SBThread::StepOver(lldb::RunMode stop_other_threads) {
52504eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, stop_other_threads);
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   SBError error; // Ignored
5280b57cec5SDimitry Andric   StepOver(stop_other_threads, error);
5290b57cec5SDimitry Andric }
5300b57cec5SDimitry Andric 
StepOver(lldb::RunMode stop_other_threads,SBError & error)5310b57cec5SDimitry Andric void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) {
53204eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, stop_other_threads, error);
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
5350b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
5380b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
5390b57cec5SDimitry Andric     return;
5400b57cec5SDimitry Andric   }
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
5430b57cec5SDimitry Andric   bool abort_other_plans = false;
5440b57cec5SDimitry Andric   StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   Status new_plan_status;
5470b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp;
5480b57cec5SDimitry Andric   if (frame_sp) {
5490b57cec5SDimitry Andric     if (frame_sp->HasDebugInformation()) {
5500b57cec5SDimitry Andric       const LazyBool avoid_no_debug = eLazyBoolCalculate;
5510b57cec5SDimitry Andric       SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
5520b57cec5SDimitry Andric       new_plan_sp = thread->QueueThreadPlanForStepOverRange(
5530b57cec5SDimitry Andric           abort_other_plans, sc.line_entry, sc, stop_other_threads,
5540b57cec5SDimitry Andric           new_plan_status, avoid_no_debug);
5550b57cec5SDimitry Andric     } else {
5560b57cec5SDimitry Andric       new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
5570b57cec5SDimitry Andric           true, abort_other_plans, stop_other_threads, new_plan_status);
5580b57cec5SDimitry Andric     }
5590b57cec5SDimitry Andric   }
5600b57cec5SDimitry Andric   error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric 
StepInto(lldb::RunMode stop_other_threads)5630b57cec5SDimitry Andric void SBThread::StepInto(lldb::RunMode stop_other_threads) {
56404eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, stop_other_threads);
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric   StepInto(nullptr, stop_other_threads);
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric 
StepInto(const char * target_name,lldb::RunMode stop_other_threads)5690b57cec5SDimitry Andric void SBThread::StepInto(const char *target_name,
5700b57cec5SDimitry Andric                         lldb::RunMode stop_other_threads) {
57104eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, target_name, stop_other_threads);
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric   SBError error; // Ignored
5740b57cec5SDimitry Andric   StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads);
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric 
StepInto(const char * target_name,uint32_t end_line,SBError & error,lldb::RunMode stop_other_threads)5770b57cec5SDimitry Andric void SBThread::StepInto(const char *target_name, uint32_t end_line,
5780b57cec5SDimitry Andric                         SBError &error, lldb::RunMode stop_other_threads) {
57904eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, target_name, end_line, error, stop_other_threads);
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
5820b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
5850b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
5860b57cec5SDimitry Andric     return;
5870b57cec5SDimitry Andric   }
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric   bool abort_other_plans = false;
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
5920b57cec5SDimitry Andric   StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
5930b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp;
5940b57cec5SDimitry Andric   Status new_plan_status;
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric   if (frame_sp && frame_sp->HasDebugInformation()) {
5970b57cec5SDimitry Andric     SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
5980b57cec5SDimitry Andric     AddressRange range;
5990b57cec5SDimitry Andric     if (end_line == LLDB_INVALID_LINE_NUMBER)
6000b57cec5SDimitry Andric       range = sc.line_entry.range;
6010b57cec5SDimitry Andric     else {
6020b57cec5SDimitry Andric       if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref()))
6030b57cec5SDimitry Andric         return;
6040b57cec5SDimitry Andric     }
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric     const LazyBool step_out_avoids_code_without_debug_info =
6070b57cec5SDimitry Andric         eLazyBoolCalculate;
6080b57cec5SDimitry Andric     const LazyBool step_in_avoids_code_without_debug_info =
6090b57cec5SDimitry Andric         eLazyBoolCalculate;
6100b57cec5SDimitry Andric     new_plan_sp = thread->QueueThreadPlanForStepInRange(
6110b57cec5SDimitry Andric         abort_other_plans, range, sc, target_name, stop_other_threads,
6120b57cec5SDimitry Andric         new_plan_status, step_in_avoids_code_without_debug_info,
6130b57cec5SDimitry Andric         step_out_avoids_code_without_debug_info);
6140b57cec5SDimitry Andric   } else {
6150b57cec5SDimitry Andric     new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
6160b57cec5SDimitry Andric         false, abort_other_plans, stop_other_threads, new_plan_status);
6170b57cec5SDimitry Andric   }
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   if (new_plan_status.Success())
6200b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
6210b57cec5SDimitry Andric   else
6220b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
6230b57cec5SDimitry Andric }
6240b57cec5SDimitry Andric 
StepOut()6250b57cec5SDimitry Andric void SBThread::StepOut() {
62604eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   SBError error; // Ignored
6290b57cec5SDimitry Andric   StepOut(error);
6300b57cec5SDimitry Andric }
6310b57cec5SDimitry Andric 
StepOut(SBError & error)6320b57cec5SDimitry Andric void SBThread::StepOut(SBError &error) {
63304eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, error);
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
6360b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
6390b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
6400b57cec5SDimitry Andric     return;
6410b57cec5SDimitry Andric   }
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric   bool abort_other_plans = false;
6440b57cec5SDimitry Andric   bool stop_other_threads = false;
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric   const LazyBool avoid_no_debug = eLazyBoolCalculate;
6490b57cec5SDimitry Andric   Status new_plan_status;
6500b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
6510b57cec5SDimitry Andric       abort_other_plans, nullptr, false, stop_other_threads, eVoteYes,
6520b57cec5SDimitry Andric       eVoteNoOpinion, 0, new_plan_status, avoid_no_debug));
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric   if (new_plan_status.Success())
6550b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
6560b57cec5SDimitry Andric   else
6570b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
StepOutOfFrame(SBFrame & sb_frame)6600b57cec5SDimitry Andric void SBThread::StepOutOfFrame(SBFrame &sb_frame) {
66104eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, sb_frame);
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   SBError error; // Ignored
6640b57cec5SDimitry Andric   StepOutOfFrame(sb_frame, error);
6650b57cec5SDimitry Andric }
6660b57cec5SDimitry Andric 
StepOutOfFrame(SBFrame & sb_frame,SBError & error)6670b57cec5SDimitry Andric void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) {
66804eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, sb_frame, error);
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
6710b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric   if (!sb_frame.IsValid()) {
6740b57cec5SDimitry Andric     error.SetErrorString("passed invalid SBFrame object");
6750b57cec5SDimitry Andric     return;
6760b57cec5SDimitry Andric   }
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   StackFrameSP frame_sp(sb_frame.GetFrameSP());
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
6810b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
6820b57cec5SDimitry Andric     return;
6830b57cec5SDimitry Andric   }
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric   bool abort_other_plans = false;
6860b57cec5SDimitry Andric   bool stop_other_threads = false;
6870b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
6880b57cec5SDimitry Andric   if (sb_frame.GetThread().GetThreadID() != thread->GetID()) {
6890b57cec5SDimitry Andric     error.SetErrorString("passed a frame from another thread");
6900b57cec5SDimitry Andric     return;
6910b57cec5SDimitry Andric   }
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   Status new_plan_status;
6940b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
6950b57cec5SDimitry Andric       abort_other_plans, nullptr, false, stop_other_threads, eVoteYes,
6960b57cec5SDimitry Andric       eVoteNoOpinion, frame_sp->GetFrameIndex(), new_plan_status));
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric   if (new_plan_status.Success())
6990b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
7000b57cec5SDimitry Andric   else
7010b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
7020b57cec5SDimitry Andric }
7030b57cec5SDimitry Andric 
StepInstruction(bool step_over)7040b57cec5SDimitry Andric void SBThread::StepInstruction(bool step_over) {
70504eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, step_over);
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric   SBError error; // Ignored
7080b57cec5SDimitry Andric   StepInstruction(step_over, error);
7090b57cec5SDimitry Andric }
7100b57cec5SDimitry Andric 
StepInstruction(bool step_over,SBError & error)7110b57cec5SDimitry Andric void SBThread::StepInstruction(bool step_over, SBError &error) {
71204eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, step_over, error);
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
7150b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
7180b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
7190b57cec5SDimitry Andric     return;
7200b57cec5SDimitry Andric   }
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
7230b57cec5SDimitry Andric   Status new_plan_status;
7240b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction(
7250b57cec5SDimitry Andric       step_over, true, true, new_plan_status));
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   if (new_plan_status.Success())
7280b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
7290b57cec5SDimitry Andric   else
7300b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric 
RunToAddress(lldb::addr_t addr)7330b57cec5SDimitry Andric void SBThread::RunToAddress(lldb::addr_t addr) {
73404eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, addr);
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric   SBError error; // Ignored
7370b57cec5SDimitry Andric   RunToAddress(addr, error);
7380b57cec5SDimitry Andric }
7390b57cec5SDimitry Andric 
RunToAddress(lldb::addr_t addr,SBError & error)7400b57cec5SDimitry Andric void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) {
74104eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, addr, error);
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
7440b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
7470b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
7480b57cec5SDimitry Andric     return;
7490b57cec5SDimitry Andric   }
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric   bool abort_other_plans = false;
7520b57cec5SDimitry Andric   bool stop_other_threads = true;
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric   Address target_addr(addr);
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric   Status new_plan_status;
7590b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
7600b57cec5SDimitry Andric       abort_other_plans, target_addr, stop_other_threads, new_plan_status));
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   if (new_plan_status.Success())
7630b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
7640b57cec5SDimitry Andric   else
7650b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
7660b57cec5SDimitry Andric }
7670b57cec5SDimitry Andric 
StepOverUntil(lldb::SBFrame & sb_frame,lldb::SBFileSpec & sb_file_spec,uint32_t line)7680b57cec5SDimitry Andric SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
7690b57cec5SDimitry Andric                                 lldb::SBFileSpec &sb_file_spec, uint32_t line) {
77004eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, sb_frame, sb_file_spec, line);
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric   SBError sb_error;
7730b57cec5SDimitry Andric   char path[PATH_MAX];
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
7760b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric   StackFrameSP frame_sp(sb_frame.GetFrameSP());
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
7810b57cec5SDimitry Andric     Target *target = exe_ctx.GetTargetPtr();
7820b57cec5SDimitry Andric     Thread *thread = exe_ctx.GetThreadPtr();
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric     if (line == 0) {
7850b57cec5SDimitry Andric       sb_error.SetErrorString("invalid line argument");
78604eeddc0SDimitry Andric       return sb_error;
7870b57cec5SDimitry Andric     }
7880b57cec5SDimitry Andric 
7890b57cec5SDimitry Andric     if (!frame_sp) {
79006c3fb27SDimitry Andric       // We don't want to run SelectMostRelevantFrame here, for instance if
79106c3fb27SDimitry Andric       // you called a sequence of StepOverUntil's you wouldn't want the
79206c3fb27SDimitry Andric       // frame changed out from under you because you stepped into a
79306c3fb27SDimitry Andric       // recognized frame.
79406c3fb27SDimitry Andric       frame_sp = thread->GetSelectedFrame(DoNoSelectMostRelevantFrame);
7950b57cec5SDimitry Andric       if (!frame_sp)
7960b57cec5SDimitry Andric         frame_sp = thread->GetStackFrameAtIndex(0);
7970b57cec5SDimitry Andric     }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric     SymbolContext frame_sc;
8000b57cec5SDimitry Andric     if (!frame_sp) {
8010b57cec5SDimitry Andric       sb_error.SetErrorString("no valid frames in thread to step");
80204eeddc0SDimitry Andric       return sb_error;
8030b57cec5SDimitry Andric     }
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric     // If we have a frame, get its line
8060b57cec5SDimitry Andric     frame_sc = frame_sp->GetSymbolContext(
8070b57cec5SDimitry Andric         eSymbolContextCompUnit | eSymbolContextFunction |
8080b57cec5SDimitry Andric         eSymbolContextLineEntry | eSymbolContextSymbol);
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric     if (frame_sc.comp_unit == nullptr) {
8110b57cec5SDimitry Andric       sb_error.SetErrorStringWithFormat(
8120b57cec5SDimitry Andric           "frame %u doesn't have debug information", frame_sp->GetFrameIndex());
81304eeddc0SDimitry Andric       return sb_error;
8140b57cec5SDimitry Andric     }
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric     FileSpec step_file_spec;
8170b57cec5SDimitry Andric     if (sb_file_spec.IsValid()) {
8180b57cec5SDimitry Andric       // The file spec passed in was valid, so use it
8190b57cec5SDimitry Andric       step_file_spec = sb_file_spec.ref();
8200b57cec5SDimitry Andric     } else {
8210b57cec5SDimitry Andric       if (frame_sc.line_entry.IsValid())
8220b57cec5SDimitry Andric         step_file_spec = frame_sc.line_entry.file;
8230b57cec5SDimitry Andric       else {
8240b57cec5SDimitry Andric         sb_error.SetErrorString("invalid file argument or no file for frame");
82504eeddc0SDimitry Andric         return sb_error;
8260b57cec5SDimitry Andric       }
8270b57cec5SDimitry Andric     }
8280b57cec5SDimitry Andric 
8290b57cec5SDimitry Andric     // Grab the current function, then we will make sure the "until" address is
8300b57cec5SDimitry Andric     // within the function.  We discard addresses that are out of the current
8310b57cec5SDimitry Andric     // function, and then if there are no addresses remaining, give an
8320b57cec5SDimitry Andric     // appropriate error message.
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric     bool all_in_function = true;
8350b57cec5SDimitry Andric     AddressRange fun_range = frame_sc.function->GetAddressRange();
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric     std::vector<addr_t> step_over_until_addrs;
8380b57cec5SDimitry Andric     const bool abort_other_plans = false;
8390b57cec5SDimitry Andric     const bool stop_other_threads = false;
840fe6060f1SDimitry Andric     // TODO: Handle SourceLocationSpec column information
841fe6060f1SDimitry Andric     SourceLocationSpec location_spec(
842bdd1243dSDimitry Andric         step_file_spec, line, /*column=*/std::nullopt, /*check_inlines=*/true,
843fe6060f1SDimitry Andric         /*exact_match=*/false);
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric     SymbolContextList sc_list;
846fe6060f1SDimitry Andric     frame_sc.comp_unit->ResolveSymbolContext(location_spec,
847480093f4SDimitry Andric                                              eSymbolContextLineEntry, sc_list);
84806c3fb27SDimitry Andric     for (const SymbolContext &sc : sc_list) {
8490b57cec5SDimitry Andric       addr_t step_addr =
8500b57cec5SDimitry Andric           sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
8510b57cec5SDimitry Andric       if (step_addr != LLDB_INVALID_ADDRESS) {
8520b57cec5SDimitry Andric         if (fun_range.ContainsLoadAddress(step_addr, target))
8530b57cec5SDimitry Andric           step_over_until_addrs.push_back(step_addr);
8540b57cec5SDimitry Andric         else
8550b57cec5SDimitry Andric           all_in_function = false;
8560b57cec5SDimitry Andric       }
8570b57cec5SDimitry Andric     }
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric     if (step_over_until_addrs.empty()) {
8600b57cec5SDimitry Andric       if (all_in_function) {
8610b57cec5SDimitry Andric         step_file_spec.GetPath(path, sizeof(path));
8620b57cec5SDimitry Andric         sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path,
8630b57cec5SDimitry Andric                                           line);
8640b57cec5SDimitry Andric       } else
8650b57cec5SDimitry Andric         sb_error.SetErrorString("step until target not in current function");
8660b57cec5SDimitry Andric     } else {
8670b57cec5SDimitry Andric       Status new_plan_status;
8680b57cec5SDimitry Andric       ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil(
8690b57cec5SDimitry Andric           abort_other_plans, &step_over_until_addrs[0],
8700b57cec5SDimitry Andric           step_over_until_addrs.size(), stop_other_threads,
8710b57cec5SDimitry Andric           frame_sp->GetFrameIndex(), new_plan_status));
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric       if (new_plan_status.Success())
8740b57cec5SDimitry Andric         sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
8750b57cec5SDimitry Andric       else
8760b57cec5SDimitry Andric         sb_error.SetErrorString(new_plan_status.AsCString());
8770b57cec5SDimitry Andric     }
8780b57cec5SDimitry Andric   } else {
8790b57cec5SDimitry Andric     sb_error.SetErrorString("this SBThread object is invalid");
8800b57cec5SDimitry Andric   }
88104eeddc0SDimitry Andric   return sb_error;
8820b57cec5SDimitry Andric }
8830b57cec5SDimitry Andric 
StepUsingScriptedThreadPlan(const char * script_class_name)8840b57cec5SDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name) {
88504eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, script_class_name);
8860b57cec5SDimitry Andric 
88704eeddc0SDimitry Andric   return StepUsingScriptedThreadPlan(script_class_name, true);
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric 
StepUsingScriptedThreadPlan(const char * script_class_name,bool resume_immediately)8900b57cec5SDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
8910b57cec5SDimitry Andric                                             bool resume_immediately) {
89204eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, script_class_name, resume_immediately);
8930b57cec5SDimitry Andric 
8949dba64beSDimitry Andric   lldb::SBStructuredData no_data;
89504eeddc0SDimitry Andric   return StepUsingScriptedThreadPlan(script_class_name, no_data,
89604eeddc0SDimitry Andric                                      resume_immediately);
8979dba64beSDimitry Andric }
8989dba64beSDimitry Andric 
StepUsingScriptedThreadPlan(const char * script_class_name,SBStructuredData & args_data,bool resume_immediately)8999dba64beSDimitry Andric SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
9009dba64beSDimitry Andric                                               SBStructuredData &args_data,
9019dba64beSDimitry Andric                                               bool resume_immediately) {
90204eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, script_class_name, args_data, resume_immediately);
9039dba64beSDimitry Andric 
9040b57cec5SDimitry Andric   SBError error;
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
9070b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
9100b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
91104eeddc0SDimitry Andric     return error;
9120b57cec5SDimitry Andric   }
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
9150b57cec5SDimitry Andric   Status new_plan_status;
9169dba64beSDimitry Andric   StructuredData::ObjectSP obj_sp = args_data.m_impl_up->GetObjectSP();
9179dba64beSDimitry Andric 
9180b57cec5SDimitry Andric   ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted(
9199dba64beSDimitry Andric       false, script_class_name, obj_sp, false, new_plan_status);
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric   if (new_plan_status.Fail()) {
9220b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
92304eeddc0SDimitry Andric     return error;
9240b57cec5SDimitry Andric   }
9250b57cec5SDimitry Andric 
9260b57cec5SDimitry Andric   if (!resume_immediately)
92704eeddc0SDimitry Andric     return error;
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric   if (new_plan_status.Success())
9300b57cec5SDimitry Andric     error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
9310b57cec5SDimitry Andric   else
9320b57cec5SDimitry Andric     error.SetErrorString(new_plan_status.AsCString());
9330b57cec5SDimitry Andric 
93404eeddc0SDimitry Andric   return error;
9350b57cec5SDimitry Andric }
9360b57cec5SDimitry Andric 
JumpToLine(lldb::SBFileSpec & file_spec,uint32_t line)9370b57cec5SDimitry Andric SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
93804eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, file_spec, line);
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric   SBError sb_error;
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
9430b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric   if (!exe_ctx.HasThreadScope()) {
9460b57cec5SDimitry Andric     sb_error.SetErrorString("this SBThread object is invalid");
94704eeddc0SDimitry Andric     return sb_error;
9480b57cec5SDimitry Andric   }
9490b57cec5SDimitry Andric 
9500b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
9510b57cec5SDimitry Andric 
952480093f4SDimitry Andric   Status err = thread->JumpToLine(file_spec.ref(), line, true);
9530b57cec5SDimitry Andric   sb_error.SetError(err);
95404eeddc0SDimitry Andric   return sb_error;
9550b57cec5SDimitry Andric }
9560b57cec5SDimitry Andric 
ReturnFromFrame(SBFrame & frame,SBValue & return_value)9570b57cec5SDimitry Andric SBError SBThread::ReturnFromFrame(SBFrame &frame, SBValue &return_value) {
95804eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, frame, return_value);
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   SBError sb_error;
9610b57cec5SDimitry Andric 
9620b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
9630b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
9640b57cec5SDimitry Andric 
9650b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
9660b57cec5SDimitry Andric     Thread *thread = exe_ctx.GetThreadPtr();
9670b57cec5SDimitry Andric     sb_error.SetError(
9680b57cec5SDimitry Andric         thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
9690b57cec5SDimitry Andric   }
9700b57cec5SDimitry Andric 
97104eeddc0SDimitry Andric   return sb_error;
9720b57cec5SDimitry Andric }
9730b57cec5SDimitry Andric 
UnwindInnermostExpression()9740b57cec5SDimitry Andric SBError SBThread::UnwindInnermostExpression() {
97504eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   SBError sb_error;
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
9800b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
9830b57cec5SDimitry Andric     Thread *thread = exe_ctx.GetThreadPtr();
9840b57cec5SDimitry Andric     sb_error.SetError(thread->UnwindInnermostExpression());
9850b57cec5SDimitry Andric     if (sb_error.Success())
9860b57cec5SDimitry Andric       thread->SetSelectedFrameByIndex(0, false);
9870b57cec5SDimitry Andric   }
9880b57cec5SDimitry Andric 
98904eeddc0SDimitry Andric   return sb_error;
9900b57cec5SDimitry Andric }
9910b57cec5SDimitry Andric 
Suspend()9920b57cec5SDimitry Andric bool SBThread::Suspend() {
99304eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric   SBError error; // Ignored
9960b57cec5SDimitry Andric   return Suspend(error);
9970b57cec5SDimitry Andric }
9980b57cec5SDimitry Andric 
Suspend(SBError & error)9990b57cec5SDimitry Andric bool SBThread::Suspend(SBError &error) {
100004eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, error);
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10030b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric   bool result = false;
10060b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
10070b57cec5SDimitry Andric     Process::StopLocker stop_locker;
10080b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
10090b57cec5SDimitry Andric       exe_ctx.GetThreadPtr()->SetResumeState(eStateSuspended);
10100b57cec5SDimitry Andric       result = true;
10110b57cec5SDimitry Andric     } else {
10120b57cec5SDimitry Andric       error.SetErrorString("process is running");
10130b57cec5SDimitry Andric     }
10140b57cec5SDimitry Andric   } else
10150b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
10160b57cec5SDimitry Andric   return result;
10170b57cec5SDimitry Andric }
10180b57cec5SDimitry Andric 
Resume()10190b57cec5SDimitry Andric bool SBThread::Resume() {
102004eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric   SBError error; // Ignored
10230b57cec5SDimitry Andric   return Resume(error);
10240b57cec5SDimitry Andric }
10250b57cec5SDimitry Andric 
Resume(SBError & error)10260b57cec5SDimitry Andric bool SBThread::Resume(SBError &error) {
102704eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, error);
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10300b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10310b57cec5SDimitry Andric 
10320b57cec5SDimitry Andric   bool result = false;
10330b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
10340b57cec5SDimitry Andric     Process::StopLocker stop_locker;
10350b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
10360b57cec5SDimitry Andric       const bool override_suspend = true;
10370b57cec5SDimitry Andric       exe_ctx.GetThreadPtr()->SetResumeState(eStateRunning, override_suspend);
10380b57cec5SDimitry Andric       result = true;
10390b57cec5SDimitry Andric     } else {
10400b57cec5SDimitry Andric       error.SetErrorString("process is running");
10410b57cec5SDimitry Andric     }
10420b57cec5SDimitry Andric   } else
10430b57cec5SDimitry Andric     error.SetErrorString("this SBThread object is invalid");
10440b57cec5SDimitry Andric   return result;
10450b57cec5SDimitry Andric }
10460b57cec5SDimitry Andric 
IsSuspended()10470b57cec5SDimitry Andric bool SBThread::IsSuspended() {
104804eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10510b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10520b57cec5SDimitry Andric 
10530b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope())
10540b57cec5SDimitry Andric     return exe_ctx.GetThreadPtr()->GetResumeState() == eStateSuspended;
10550b57cec5SDimitry Andric   return false;
10560b57cec5SDimitry Andric }
10570b57cec5SDimitry Andric 
IsStopped()10580b57cec5SDimitry Andric bool SBThread::IsStopped() {
105904eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10620b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10630b57cec5SDimitry Andric 
10640b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope())
10650b57cec5SDimitry Andric     return StateIsStoppedState(exe_ctx.GetThreadPtr()->GetState(), true);
10660b57cec5SDimitry Andric   return false;
10670b57cec5SDimitry Andric }
10680b57cec5SDimitry Andric 
GetProcess()10690b57cec5SDimitry Andric SBProcess SBThread::GetProcess() {
107004eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
10710b57cec5SDimitry Andric 
10720b57cec5SDimitry Andric   SBProcess sb_process;
10730b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10740b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10750b57cec5SDimitry Andric 
10760b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
10770b57cec5SDimitry Andric     // Have to go up to the target so we can get a shared pointer to our
10780b57cec5SDimitry Andric     // process...
10790b57cec5SDimitry Andric     sb_process.SetSP(exe_ctx.GetProcessSP());
10800b57cec5SDimitry Andric   }
10810b57cec5SDimitry Andric 
108204eeddc0SDimitry Andric   return sb_process;
10830b57cec5SDimitry Andric }
10840b57cec5SDimitry Andric 
GetNumFrames()10850b57cec5SDimitry Andric uint32_t SBThread::GetNumFrames() {
108604eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric   uint32_t num_frames = 0;
10890b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
10900b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
10930b57cec5SDimitry Andric     Process::StopLocker stop_locker;
10940b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
10950b57cec5SDimitry Andric       num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount();
10960b57cec5SDimitry Andric     }
10970b57cec5SDimitry Andric   }
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric   return num_frames;
11000b57cec5SDimitry Andric }
11010b57cec5SDimitry Andric 
GetFrameAtIndex(uint32_t idx)11020b57cec5SDimitry Andric SBFrame SBThread::GetFrameAtIndex(uint32_t idx) {
110304eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, idx);
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric   SBFrame sb_frame;
11060b57cec5SDimitry Andric   StackFrameSP frame_sp;
11070b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
11080b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
11110b57cec5SDimitry Andric     Process::StopLocker stop_locker;
11120b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
11130b57cec5SDimitry Andric       frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(idx);
11140b57cec5SDimitry Andric       sb_frame.SetFrameSP(frame_sp);
11150b57cec5SDimitry Andric     }
11160b57cec5SDimitry Andric   }
11170b57cec5SDimitry Andric 
111804eeddc0SDimitry Andric   return sb_frame;
11190b57cec5SDimitry Andric }
11200b57cec5SDimitry Andric 
GetSelectedFrame()11210b57cec5SDimitry Andric lldb::SBFrame SBThread::GetSelectedFrame() {
112204eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
11230b57cec5SDimitry Andric 
11240b57cec5SDimitry Andric   SBFrame sb_frame;
11250b57cec5SDimitry Andric   StackFrameSP frame_sp;
11260b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
11270b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11280b57cec5SDimitry Andric 
11290b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
11300b57cec5SDimitry Andric     Process::StopLocker stop_locker;
11310b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
113206c3fb27SDimitry Andric       frame_sp =
113306c3fb27SDimitry Andric           exe_ctx.GetThreadPtr()->GetSelectedFrame(SelectMostRelevantFrame);
11340b57cec5SDimitry Andric       sb_frame.SetFrameSP(frame_sp);
11350b57cec5SDimitry Andric     }
11360b57cec5SDimitry Andric   }
11370b57cec5SDimitry Andric 
113804eeddc0SDimitry Andric   return sb_frame;
11390b57cec5SDimitry Andric }
11400b57cec5SDimitry Andric 
SetSelectedFrame(uint32_t idx)11410b57cec5SDimitry Andric lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) {
114204eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, idx);
11430b57cec5SDimitry Andric 
11440b57cec5SDimitry Andric   SBFrame sb_frame;
11450b57cec5SDimitry Andric   StackFrameSP frame_sp;
11460b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
11470b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
11480b57cec5SDimitry Andric 
11490b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
11500b57cec5SDimitry Andric     Process::StopLocker stop_locker;
11510b57cec5SDimitry Andric     if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
11520b57cec5SDimitry Andric       Thread *thread = exe_ctx.GetThreadPtr();
11530b57cec5SDimitry Andric       frame_sp = thread->GetStackFrameAtIndex(idx);
11540b57cec5SDimitry Andric       if (frame_sp) {
11550b57cec5SDimitry Andric         thread->SetSelectedFrame(frame_sp.get());
11560b57cec5SDimitry Andric         sb_frame.SetFrameSP(frame_sp);
11570b57cec5SDimitry Andric       }
11580b57cec5SDimitry Andric     }
11590b57cec5SDimitry Andric   }
11600b57cec5SDimitry Andric 
116104eeddc0SDimitry Andric   return sb_frame;
11620b57cec5SDimitry Andric }
11630b57cec5SDimitry Andric 
EventIsThreadEvent(const SBEvent & event)11640b57cec5SDimitry Andric bool SBThread::EventIsThreadEvent(const SBEvent &event) {
116504eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(event);
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric   return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != nullptr;
11680b57cec5SDimitry Andric }
11690b57cec5SDimitry Andric 
GetStackFrameFromEvent(const SBEvent & event)11700b57cec5SDimitry Andric SBFrame SBThread::GetStackFrameFromEvent(const SBEvent &event) {
117104eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(event);
11720b57cec5SDimitry Andric 
117304eeddc0SDimitry Andric   return Thread::ThreadEventData::GetStackFrameFromEvent(event.get());
11740b57cec5SDimitry Andric }
11750b57cec5SDimitry Andric 
GetThreadFromEvent(const SBEvent & event)11760b57cec5SDimitry Andric SBThread SBThread::GetThreadFromEvent(const SBEvent &event) {
117704eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(event);
11780b57cec5SDimitry Andric 
117904eeddc0SDimitry Andric   return Thread::ThreadEventData::GetThreadFromEvent(event.get());
11800b57cec5SDimitry Andric }
11810b57cec5SDimitry Andric 
operator ==(const SBThread & rhs) const11820b57cec5SDimitry Andric bool SBThread::operator==(const SBThread &rhs) const {
118304eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, rhs);
11840b57cec5SDimitry Andric 
11850b57cec5SDimitry Andric   return m_opaque_sp->GetThreadSP().get() ==
11860b57cec5SDimitry Andric          rhs.m_opaque_sp->GetThreadSP().get();
11870b57cec5SDimitry Andric }
11880b57cec5SDimitry Andric 
operator !=(const SBThread & rhs) const11890b57cec5SDimitry Andric bool SBThread::operator!=(const SBThread &rhs) const {
119004eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, rhs);
11910b57cec5SDimitry Andric 
11920b57cec5SDimitry Andric   return m_opaque_sp->GetThreadSP().get() !=
11930b57cec5SDimitry Andric          rhs.m_opaque_sp->GetThreadSP().get();
11940b57cec5SDimitry Andric }
11950b57cec5SDimitry Andric 
GetStatus(SBStream & status) const11960b57cec5SDimitry Andric bool SBThread::GetStatus(SBStream &status) const {
119704eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, status);
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric   Stream &strm = status.ref();
12000b57cec5SDimitry Andric 
12010b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
12020b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
12050b57cec5SDimitry Andric     exe_ctx.GetThreadPtr()->GetStatus(strm, 0, 1, 1, true);
12060b57cec5SDimitry Andric   } else
12070b57cec5SDimitry Andric     strm.PutCString("No status");
12080b57cec5SDimitry Andric 
12090b57cec5SDimitry Andric   return true;
12100b57cec5SDimitry Andric }
12110b57cec5SDimitry Andric 
GetDescription(SBStream & description) const12120b57cec5SDimitry Andric bool SBThread::GetDescription(SBStream &description) const {
121304eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, description);
12140b57cec5SDimitry Andric 
12150b57cec5SDimitry Andric   return GetDescription(description, false);
12160b57cec5SDimitry Andric }
12170b57cec5SDimitry Andric 
GetDescription(SBStream & description,bool stop_format) const12180b57cec5SDimitry Andric bool SBThread::GetDescription(SBStream &description, bool stop_format) const {
121904eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, description, stop_format);
12200b57cec5SDimitry Andric 
12210b57cec5SDimitry Andric   Stream &strm = description.ref();
12220b57cec5SDimitry Andric 
12230b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
12240b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric   if (exe_ctx.HasThreadScope()) {
12275f757f3fSDimitry Andric     exe_ctx.GetThreadPtr()->DumpUsingSettingsFormat(
12285f757f3fSDimitry Andric         strm, LLDB_INVALID_THREAD_ID, stop_format);
12290b57cec5SDimitry Andric   } else
12300b57cec5SDimitry Andric     strm.PutCString("No value");
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric   return true;
12330b57cec5SDimitry Andric }
12340b57cec5SDimitry Andric 
GetDescriptionWithFormat(const SBFormat & format,SBStream & output)12355f757f3fSDimitry Andric SBError SBThread::GetDescriptionWithFormat(const SBFormat &format,
12365f757f3fSDimitry Andric                                            SBStream &output) {
12375f757f3fSDimitry Andric   Stream &strm = output.ref();
12385f757f3fSDimitry Andric 
12395f757f3fSDimitry Andric   SBError error;
12405f757f3fSDimitry Andric   if (!format) {
12415f757f3fSDimitry Andric     error.SetErrorString("The provided SBFormat object is invalid");
12425f757f3fSDimitry Andric     return error;
12435f757f3fSDimitry Andric   }
12445f757f3fSDimitry Andric 
12455f757f3fSDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
12465f757f3fSDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12475f757f3fSDimitry Andric 
12485f757f3fSDimitry Andric   if (exe_ctx.HasThreadScope()) {
12495f757f3fSDimitry Andric     if (exe_ctx.GetThreadPtr()->DumpUsingFormat(
12505f757f3fSDimitry Andric             strm, LLDB_INVALID_THREAD_ID, format.GetFormatEntrySP().get())) {
12515f757f3fSDimitry Andric       return error;
12525f757f3fSDimitry Andric     }
12535f757f3fSDimitry Andric   }
12545f757f3fSDimitry Andric 
12555f757f3fSDimitry Andric   error.SetErrorStringWithFormat(
12565f757f3fSDimitry Andric       "It was not possible to generate a thread description with the given "
12575f757f3fSDimitry Andric       "format string '%s'",
12585f757f3fSDimitry Andric       format.GetFormatEntrySP()->string.c_str());
12595f757f3fSDimitry Andric   return error;
12605f757f3fSDimitry Andric }
12615f757f3fSDimitry Andric 
GetExtendedBacktraceThread(const char * type)12620b57cec5SDimitry Andric SBThread SBThread::GetExtendedBacktraceThread(const char *type) {
126304eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this, type);
12640b57cec5SDimitry Andric 
12650b57cec5SDimitry Andric   std::unique_lock<std::recursive_mutex> lock;
12660b57cec5SDimitry Andric   ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
12670b57cec5SDimitry Andric   SBThread sb_origin_thread;
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric   Process::StopLocker stop_locker;
12700b57cec5SDimitry Andric   if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
12710b57cec5SDimitry Andric     if (exe_ctx.HasThreadScope()) {
12720b57cec5SDimitry Andric       ThreadSP real_thread(exe_ctx.GetThreadSP());
12730b57cec5SDimitry Andric       if (real_thread) {
12740b57cec5SDimitry Andric         ConstString type_const(type);
12750b57cec5SDimitry Andric         Process *process = exe_ctx.GetProcessPtr();
12760b57cec5SDimitry Andric         if (process) {
12770b57cec5SDimitry Andric           SystemRuntime *runtime = process->GetSystemRuntime();
12780b57cec5SDimitry Andric           if (runtime) {
12790b57cec5SDimitry Andric             ThreadSP new_thread_sp(
12800b57cec5SDimitry Andric                 runtime->GetExtendedBacktraceThread(real_thread, type_const));
12810b57cec5SDimitry Andric             if (new_thread_sp) {
12820b57cec5SDimitry Andric               // Save this in the Process' ExtendedThreadList so a strong
12830b57cec5SDimitry Andric               // pointer retains the object.
12840b57cec5SDimitry Andric               process->GetExtendedThreadList().AddThread(new_thread_sp);
12850b57cec5SDimitry Andric               sb_origin_thread.SetThread(new_thread_sp);
12860b57cec5SDimitry Andric             }
12870b57cec5SDimitry Andric           }
12880b57cec5SDimitry Andric         }
12890b57cec5SDimitry Andric       }
12900b57cec5SDimitry Andric     }
12910b57cec5SDimitry Andric   }
12920b57cec5SDimitry Andric 
129304eeddc0SDimitry Andric   return sb_origin_thread;
12940b57cec5SDimitry Andric }
12950b57cec5SDimitry Andric 
GetExtendedBacktraceOriginatingIndexID()12960b57cec5SDimitry Andric uint32_t SBThread::GetExtendedBacktraceOriginatingIndexID() {
129704eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13000b57cec5SDimitry Andric   if (thread_sp)
13010b57cec5SDimitry Andric     return thread_sp->GetExtendedBacktraceOriginatingIndexID();
13020b57cec5SDimitry Andric   return LLDB_INVALID_INDEX32;
13030b57cec5SDimitry Andric }
13040b57cec5SDimitry Andric 
GetCurrentException()13050b57cec5SDimitry Andric SBValue SBThread::GetCurrentException() {
130604eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13090b57cec5SDimitry Andric   if (!thread_sp)
131004eeddc0SDimitry Andric     return SBValue();
13110b57cec5SDimitry Andric 
131204eeddc0SDimitry Andric   return SBValue(thread_sp->GetCurrentException());
13130b57cec5SDimitry Andric }
13140b57cec5SDimitry Andric 
GetCurrentExceptionBacktrace()13150b57cec5SDimitry Andric SBThread SBThread::GetCurrentExceptionBacktrace() {
131604eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13190b57cec5SDimitry Andric   if (!thread_sp)
132004eeddc0SDimitry Andric     return SBThread();
13210b57cec5SDimitry Andric 
132204eeddc0SDimitry Andric   return SBThread(thread_sp->GetCurrentExceptionBacktrace());
13230b57cec5SDimitry Andric }
13240b57cec5SDimitry Andric 
SafeToCallFunctions()13250b57cec5SDimitry Andric bool SBThread::SafeToCallFunctions() {
132604eeddc0SDimitry Andric   LLDB_INSTRUMENT_VA(this);
13270b57cec5SDimitry Andric 
13280b57cec5SDimitry Andric   ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
13290b57cec5SDimitry Andric   if (thread_sp)
13300b57cec5SDimitry Andric     return thread_sp->SafeToCallFunctions();
13310b57cec5SDimitry Andric   return true;
13320b57cec5SDimitry Andric }
13330b57cec5SDimitry Andric 
operator ->()13340b57cec5SDimitry Andric lldb_private::Thread *SBThread::operator->() {
13350b57cec5SDimitry Andric   return get();
13360b57cec5SDimitry Andric }
13370b57cec5SDimitry Andric 
get()13380b57cec5SDimitry Andric lldb_private::Thread *SBThread::get() {
13390b57cec5SDimitry Andric   return m_opaque_sp->GetThreadSP().get();
13400b57cec5SDimitry Andric }
13410b57cec5SDimitry Andric 
GetSiginfo()13421fd87a68SDimitry Andric SBValue SBThread::GetSiginfo() {
13431fd87a68SDimitry Andric   LLDB_INSTRUMENT_VA(this);
13440b57cec5SDimitry Andric 
134504eeddc0SDimitry Andric   ThreadSP thread_sp = m_opaque_sp->GetThreadSP();
13461fd87a68SDimitry Andric   if (!thread_sp)
13471fd87a68SDimitry Andric     return SBValue();
13481fd87a68SDimitry Andric   return thread_sp->GetSiginfoValue();
13490b57cec5SDimitry Andric }
1350